From 75dc42032976d9b2b2ac5f1bc00b7372857eb2d9 Mon Sep 17 00:00:00 2001 From: stansmith Date: Mon, 14 Dec 2009 19:31:42 +0000 Subject: [PATCH] [OPENSM] Wof 2.2 build 3.0.0 version of opensm.exe for failback purposes. git-svn-id: svn://openib.tc.cornell.edu/gen1@2637 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86 --- .../ulp/opensm/user_3_0_0/README.opensm-build | 24 + branches/WOF2-2/ulp/opensm/user_3_0_0/TODO | 16 + .../WOF2-2/ulp/opensm/user_3_0_0/config.h | 71 + branches/WOF2-2/ulp/opensm/user_3_0_0/dirs | 5 + .../opensm/user_3_0_0/doc/OpenSM_PKey_Mgr.txt | 79 + .../opensm/user_3_0_0/doc/OpenSM_RN_0_3_1.pdf | Bin 0 -> 83938 bytes .../opensm/user_3_0_0/doc/OpenSM_UM_0_3.pdf | Bin 0 -> 223001 bytes .../opensm/user_3_0_0/doc/current-routing.txt | 202 + .../opensm/user_3_0_0/doc/modular-routing.txt | 78 + .../doc/opensm_release_notes_openib-2.0.5.txt | 487 + .../ulp/opensm/user_3_0_0/doc/qos-config.txt | 45 + .../ulp/opensm/user_3_0_0/ibtrapgen/Makefile | 7 + .../ulp/opensm/user_3_0_0/ibtrapgen/SOURCES | 64 + .../opensm/user_3_0_0/ibtrapgen/ibtrapgen.c | 442 + .../opensm/user_3_0_0/ibtrapgen/ibtrapgen.h | 313 + .../ulp/opensm/user_3_0_0/ibtrapgen/main.c | 465 + .../user_3_0_0/include/complib/cl_byteswap.h | 547 + .../include/complib/cl_dispatcher.h | 660 + .../include/complib/cl_event_wheel.h | 493 + .../include/complib/cl_signal_osd.h | 127 + .../opensm/user_3_0_0/include/iba/ib_types.h | 10684 ++++++++++++++++ .../include/iba/ib_types_extended.h | 2809 ++++ .../user_3_0_0/include/opensm/cl_dispatcher.h | 673 + .../include/opensm/cl_event_wheel.h | 497 + .../include/opensm/osm_attrib_req.h | 119 + .../user_3_0_0/include/opensm/osm_base.h | 823 ++ .../user_3_0_0/include/opensm/osm_console.h | 58 + .../opensm/user_3_0_0/include/opensm/osm_db.h | 455 + .../user_3_0_0/include/opensm/osm_db_pack.h | 255 + .../user_3_0_0/include/opensm/osm_drop_mgr.h | 259 + .../user_3_0_0/include/opensm/osm_errors.h | 181 + .../user_3_0_0/include/opensm/osm_fwd_tbl.h | 388 + .../user_3_0_0/include/opensm/osm_helper.h | 620 + .../user_3_0_0/include/opensm/osm_inform.h | 305 + .../user_3_0_0/include/opensm/osm_lid_mgr.h | 322 + .../include/opensm/osm_lin_fwd_rcv.h | 255 + .../include/opensm/osm_lin_fwd_rcv_ctrl.h | 233 + .../include/opensm/osm_lin_fwd_tbl.h | 379 + .../user_3_0_0/include/opensm/osm_link_mgr.h | 271 + .../user_3_0_0/include/opensm/osm_log.h | 474 + .../user_3_0_0/include/opensm/osm_mad_pool.h | 405 + .../user_3_0_0/include/opensm/osm_madw.h | 1160 ++ .../user_3_0_0/include/opensm/osm_matrix.h | 454 + .../include/opensm/osm_mcast_fwd_rcv.h | 259 + .../include/opensm/osm_mcast_fwd_rcv_ctrl.h | 235 + .../user_3_0_0/include/opensm/osm_mcast_mgr.h | 339 + .../user_3_0_0/include/opensm/osm_mcast_tbl.h | 484 + .../user_3_0_0/include/opensm/osm_mcm_info.h | 237 + .../user_3_0_0/include/opensm/osm_mcm_port.h | 269 + .../user_3_0_0/include/opensm/osm_msgdef.h | 208 + .../user_3_0_0/include/opensm/osm_mtl_bind.h | 144 + .../user_3_0_0/include/opensm/osm_mtree.h | 378 + .../user_3_0_0/include/opensm/osm_multicast.h | 769 ++ .../user_3_0_0/include/opensm/osm_node.h | 957 ++ .../include/opensm/osm_node_desc_rcv.h | 256 + .../include/opensm/osm_node_desc_rcv_ctrl.h | 232 + .../include/opensm/osm_node_info_rcv.h | 305 + .../include/opensm/osm_node_info_rcv_ctrl.h | 261 + .../user_3_0_0/include/opensm/osm_opensm.h | 440 + .../user_3_0_0/include/opensm/osm_partition.h | 256 + .../user_3_0_0/include/opensm/osm_path.h | 267 + .../user_3_0_0/include/opensm/osm_pkey.h | 755 ++ .../user_3_0_0/include/opensm/osm_pkey_mgr.h | 90 + .../user_3_0_0/include/opensm/osm_pkey_rcv.h | 253 + .../include/opensm/osm_pkey_rcv_ctrl.h | 248 + .../user_3_0_0/include/opensm/osm_port.h | 2122 +++ .../include/opensm/osm_port_info_rcv.h | 274 + .../include/opensm/osm_port_info_rcv_ctrl.h | 261 + .../include/opensm/osm_port_profile.h | 291 + .../include/opensm/osm_rand_fwd_tbl.h | 354 + .../user_3_0_0/include/opensm/osm_remote_sm.h | 212 + .../user_3_0_0/include/opensm/osm_req.h | 354 + .../user_3_0_0/include/opensm/osm_req_ctrl.h | 228 + .../user_3_0_0/include/opensm/osm_resp.h | 279 + .../user_3_0_0/include/opensm/osm_router.h | 323 + .../opensm/user_3_0_0/include/opensm/osm_sa.h | 500 + .../include/opensm/osm_sa_class_port_info.h | 269 + .../opensm/osm_sa_class_port_info_ctrl.h | 261 + .../include/opensm/osm_sa_guidinfo_record.h | 279 + .../opensm/osm_sa_guidinfo_record_ctrl.h | 230 + .../include/opensm/osm_sa_informinfo.h | 299 + .../include/opensm/osm_sa_informinfo_ctrl.h | 261 + .../include/opensm/osm_sa_lft_record.h | 281 + .../include/opensm/osm_sa_lft_record_ctrl.h | 233 + .../include/opensm/osm_sa_link_record.h | 276 + .../include/opensm/osm_sa_link_record_ctrl.h | 261 + .../include/opensm/osm_sa_mad_ctrl.h | 352 + .../include/opensm/osm_sa_mcmember_record.h | 420 + .../opensm/osm_sa_mcmember_record_ctrl.h | 262 + .../include/opensm/osm_sa_mft_record.h | 280 + .../include/opensm/osm_sa_mft_record_ctrl.h | 231 + .../include/opensm/osm_sa_multipath_record.h | 273 + .../opensm/osm_sa_multipath_record_ctrl.h | 260 + .../include/opensm/osm_sa_node_record.h | 275 + .../include/opensm/osm_sa_node_record_ctrl.h | 231 + .../include/opensm/osm_sa_path_record.h | 274 + .../include/opensm/osm_sa_path_record_ctrl.h | 261 + .../include/opensm/osm_sa_pkey_record.h | 268 + .../include/opensm/osm_sa_pkey_record_ctrl.h | 218 + .../include/opensm/osm_sa_portinfo_record.h | 280 + .../opensm/osm_sa_portinfo_record_ctrl.h | 231 + .../include/opensm/osm_sa_response.h | 255 + .../include/opensm/osm_sa_service_record.h | 298 + .../opensm/osm_sa_service_record_ctrl.h | 230 + .../include/opensm/osm_sa_slvl_record.h | 281 + .../include/opensm/osm_sa_slvl_record_ctrl.h | 231 + .../include/opensm/osm_sa_sminfo_record.h | 262 + .../opensm/osm_sa_sminfo_record_ctrl.h | 231 + .../include/opensm/osm_sa_sw_info_record.h | 306 + .../opensm/osm_sa_sw_info_record_ctrl.h | 259 + .../include/opensm/osm_sa_vlarb_record.h | 280 + .../include/opensm/osm_sa_vlarb_record_ctrl.h | 231 + .../user_3_0_0/include/opensm/osm_service.h | 241 + .../include/opensm/osm_slvl_map_rcv.h | 265 + .../include/opensm/osm_slvl_map_rcv_ctrl.h | 261 + .../opensm/user_3_0_0/include/opensm/osm_sm.h | 566 + .../include/opensm/osm_sm_mad_ctrl.h | 339 + .../include/opensm/osm_sm_state_mgr.h | 353 + .../include/opensm/osm_sminfo_rcv.h | 291 + .../include/opensm/osm_sminfo_rcv_ctrl.h | 232 + .../user_3_0_0/include/opensm/osm_state_mgr.h | 518 + .../include/opensm/osm_state_mgr_ctrl.h | 233 + .../user_3_0_0/include/opensm/osm_stats.h | 125 + .../user_3_0_0/include/opensm/osm_subnet.h | 1161 ++ .../include/opensm/osm_sw_info_rcv.h | 304 + .../include/opensm/osm_sw_info_rcv_ctrl.h | 261 + .../include/opensm/osm_sweep_fail_ctrl.h | 239 + .../user_3_0_0/include/opensm/osm_switch.h | 1552 +++ .../user_3_0_0/include/opensm/osm_trap_rcv.h | 326 + .../include/opensm/osm_trap_rcv_ctrl.h | 232 + .../include/opensm/osm_ts_useraccess.h | 54 + .../user_3_0_0/include/opensm/osm_ucast_mgr.h | 328 + .../user_3_0_0/include/opensm/osm_umadt.h | 143 + .../user_3_0_0/include/opensm/osm_version.h | 63 + .../user_3_0_0/include/opensm/osm_vl15intf.h | 417 + .../include/opensm/osm_vl_arb_rcv.h | 265 + .../include/opensm/osm_vl_arb_rcv_ctrl.h | 261 + .../ulp/opensm/user_3_0_0/include/opensm/st.h | 107 + .../ulp/opensm/user_3_0_0/include/unistd.h | 38 + .../user_3_0_0/include/vendor/osm_vendor.h | 78 + .../user_3_0_0/include/vendor/osm_vendor_al.h | 372 + .../include/vendor/osm_vendor_api.h | 519 + .../include/vendor/osm_vendor_sa_api.h | 879 ++ .../include/vendor/osm_vendor_select.h | 76 + .../user_3_0_0/include/vendor/winosm_common.h | 251 + .../ulp/opensm/user_3_0_0/libopensm/Makefile | 7 + .../ulp/opensm/user_3_0_0/libopensm/SOURCES | 62 + .../opensm/user_3_0_0/libopensm/osm_helper.c | 2534 ++++ .../ulp/opensm/user_3_0_0/libopensm/osm_log.c | 327 + .../user_3_0_0/libopensm/osm_mad_pool.c | 302 + .../ulp/opensm/user_3_0_0/libvendor/Makefile | 7 + .../ulp/opensm/user_3_0_0/libvendor/SOURCES | 60 + .../user_3_0_0/libvendor/osm_vendor_al.c | 1533 +++ .../user_3_0_0/libvendor/osm_vendor_mlx_sa.c | 879 ++ .../user_3_0_0/libvendor/winosm_common.c | 249 + .../ulp/opensm/user_3_0_0/opensm/Makefile | 7 + .../ulp/opensm/user_3_0_0/opensm/SOURCES | 62 + .../opensm/user_3_0_0/opensm/cl_dispatcher.c | 405 + .../opensm/user_3_0_0/opensm/cl_event_wheel.c | 663 + .../ulp/opensm/user_3_0_0/opensm/main.c | 1158 ++ .../ulp/opensm/user_3_0_0/opensm/opensm.opts | 139 + .../ulp/opensm/user_3_0_0/opensm/opensm.rc | 46 + .../ulp/opensm/user_3_0_0/opensm/osm.mc | 29 + .../opensm/user_3_0_0/opensm/osm_console.c | 226 + .../opensm/user_3_0_0/opensm/osm_db_files.c | 796 ++ .../opensm/user_3_0_0/opensm/osm_db_pack.c | 172 + .../opensm/user_3_0_0/opensm/osm_drop_mgr.c | 721 ++ .../ulp/opensm/user_3_0_0/opensm/osm_files.c | 99 + .../opensm/user_3_0_0/opensm/osm_fwd_tbl.c | 115 + .../ulp/opensm/user_3_0_0/opensm/osm_inform.c | 763 ++ .../opensm/user_3_0_0/opensm/osm_lid_mgr.c | 1494 +++ .../user_3_0_0/opensm/osm_lin_fwd_rcv.c | 160 + .../user_3_0_0/opensm/osm_lin_fwd_rcv_ctrl.c | 125 + .../user_3_0_0/opensm/osm_lin_fwd_tbl.c | 102 + .../opensm/user_3_0_0/opensm/osm_link_mgr.c | 514 + .../ulp/opensm/user_3_0_0/opensm/osm_matrix.c | 156 + .../user_3_0_0/opensm/osm_mcast_fwd_rcv.c | 181 + .../opensm/osm_mcast_fwd_rcv_ctrl.c | 125 + .../opensm/user_3_0_0/opensm/osm_mcast_mgr.c | 1726 +++ .../opensm/user_3_0_0/opensm/osm_mcast_tbl.c | 302 + .../opensm/user_3_0_0/opensm/osm_mcm_info.c | 102 + .../opensm/user_3_0_0/opensm/osm_mcm_port.c | 127 + .../ulp/opensm/user_3_0_0/opensm/osm_mtree.c | 137 + .../opensm/user_3_0_0/opensm/osm_multicast.c | 403 + .../ulp/opensm/user_3_0_0/opensm/osm_node.c | 335 + .../user_3_0_0/opensm/osm_node_desc_rcv.c | 182 + .../opensm/osm_node_desc_rcv_ctrl.c | 127 + .../user_3_0_0/opensm/osm_node_info_rcv.c | 1090 ++ .../opensm/osm_node_info_rcv_ctrl.c | 127 + .../ulp/opensm/user_3_0_0/opensm/osm_opensm.c | 320 + .../ulp/opensm/user_3_0_0/opensm/osm_pkey.c | 547 + .../opensm/user_3_0_0/opensm/osm_pkey_mgr.c | 596 + .../opensm/user_3_0_0/opensm/osm_pkey_rcv.c | 220 + .../user_3_0_0/opensm/osm_pkey_rcv_ctrl.c | 116 + .../ulp/opensm/user_3_0_0/opensm/osm_port.c | 936 ++ .../user_3_0_0/opensm/osm_port_info_rcv.c | 870 ++ .../opensm/osm_port_info_rcv_ctrl.c | 128 + .../ulp/opensm/user_3_0_0/opensm/osm_prtn.c | 399 + .../user_3_0_0/opensm/osm_prtn_config.c | 447 + .../ulp/opensm/user_3_0_0/opensm/osm_qos.c | 451 + .../opensm/user_3_0_0/opensm/osm_remote_sm.c | 90 + .../ulp/opensm/user_3_0_0/opensm/osm_req.c | 298 + .../opensm/user_3_0_0/opensm/osm_req_ctrl.c | 136 + .../ulp/opensm/user_3_0_0/opensm/osm_resp.c | 227 + .../ulp/opensm/user_3_0_0/opensm/osm_router.c | 124 + .../ulp/opensm/user_3_0_0/opensm/osm_sa.c | 1207 ++ .../opensm/osm_sa_class_port_info.c | 280 + .../opensm/osm_sa_class_port_info_ctrl.c | 126 + .../opensm/osm_sa_guidinfo_record.c | 611 + .../opensm/osm_sa_guidinfo_record_ctrl.c | 124 + .../user_3_0_0/opensm/osm_sa_informinfo.c | 922 ++ .../opensm/osm_sa_informinfo_ctrl.c | 154 + .../user_3_0_0/opensm/osm_sa_lft_record.c | 515 + .../opensm/osm_sa_lft_record_ctrl.c | 124 + .../user_3_0_0/opensm/osm_sa_link_record.c | 777 ++ .../opensm/osm_sa_link_record_ctrl.c | 128 + .../user_3_0_0/opensm/osm_sa_mad_ctrl.c | 651 + .../opensm/osm_sa_mcmember_record.c | 2383 ++++ .../opensm/osm_sa_mcmember_record_ctrl.c | 132 + .../user_3_0_0/opensm/osm_sa_mft_record.c | 547 + .../opensm/osm_sa_mft_record_ctrl.c | 123 + .../opensm/osm_sa_multipath_record.c | 1652 +++ .../opensm/osm_sa_multipath_record_ctrl.c | 128 + .../user_3_0_0/opensm/osm_sa_node_record.c | 600 + .../opensm/osm_sa_node_record_ctrl.c | 125 + .../user_3_0_0/opensm/osm_sa_path_record.c | 2006 +++ .../opensm/osm_sa_path_record_ctrl.c | 126 + .../user_3_0_0/opensm/osm_sa_pkey_record.c | 590 + .../opensm/osm_sa_pkey_record_ctrl.c | 113 + .../opensm/osm_sa_portinfo_record.c | 878 ++ .../opensm/osm_sa_portinfo_record_ctrl.c | 125 + .../user_3_0_0/opensm/osm_sa_response.c | 175 + .../user_3_0_0/opensm/osm_sa_service_record.c | 1204 ++ .../opensm/osm_sa_service_record_ctrl.c | 125 + .../user_3_0_0/opensm/osm_sa_slvl_record.c | 557 + .../opensm/osm_sa_slvl_record_ctrl.c | 126 + .../user_3_0_0/opensm/osm_sa_sminfo_record.c | 583 + .../opensm/osm_sa_sminfo_record_ctrl.c | 125 + .../user_3_0_0/opensm/osm_sa_sw_info_record.c | 535 + .../opensm/osm_sa_sw_info_record_ctrl.c | 123 + .../user_3_0_0/opensm/osm_sa_vlarb_record.c | 577 + .../opensm/osm_sa_vlarb_record_ctrl.c | 126 + .../opensm/user_3_0_0/opensm/osm_service.c | 202 + .../user_3_0_0/opensm/osm_slvl_map_rcv.c | 232 + .../user_3_0_0/opensm/osm_slvl_map_rcv_ctrl.c | 127 + .../ulp/opensm/user_3_0_0/opensm/osm_sm.c | 824 ++ .../user_3_0_0/opensm/osm_sm_mad_ctrl.c | 1049 ++ .../user_3_0_0/opensm/osm_sm_state_mgr.c | 872 ++ .../opensm/user_3_0_0/opensm/osm_sminfo_rcv.c | 768 ++ .../user_3_0_0/opensm/osm_sminfo_rcv_ctrl.c | 127 + .../opensm/user_3_0_0/opensm/osm_state_mgr.c | 2986 +++++ .../user_3_0_0/opensm/osm_state_mgr_ctrl.c | 127 + .../ulp/opensm/user_3_0_0/opensm/osm_subnet.c | 1272 ++ .../user_3_0_0/opensm/osm_sw_info_rcv.c | 681 + .../user_3_0_0/opensm/osm_sw_info_rcv_ctrl.c | 126 + .../user_3_0_0/opensm/osm_sweep_fail_ctrl.c | 133 + .../ulp/opensm/user_3_0_0/opensm/osm_switch.c | 550 + .../opensm/user_3_0_0/opensm/osm_trap_rcv.c | 771 ++ .../user_3_0_0/opensm/osm_trap_rcv_ctrl.c | 126 + .../opensm/user_3_0_0/opensm/osm_ucast_file.c | 413 + .../user_3_0_0/opensm/osm_ucast_ftree.c | 3141 +++++ .../opensm/user_3_0_0/opensm/osm_ucast_mgr.c | 1277 ++ .../opensm/user_3_0_0/opensm/osm_ucast_updn.c | 1281 ++ .../opensm/user_3_0_0/opensm/osm_vl15intf.c | 544 + .../opensm/user_3_0_0/opensm/osm_vl_arb_rcv.c | 240 + .../user_3_0_0/opensm/osm_vl_arb_rcv_ctrl.c | 127 + .../WOF2-2/ulp/opensm/user_3_0_0/opensm/st.c | 625 + .../ulp/opensm/user_3_0_0/osmtest/Makefile | 7 + .../ulp/opensm/user_3_0_0/osmtest/SOURCES | 69 + .../opensm/user_3_0_0/osmtest/include/error.h | 57 + .../user_3_0_0/osmtest/include/osmt_inform.h | 88 + .../osmtest/include/osmt_mtl_regular_qp.h | 187 + .../user_3_0_0/osmtest/include/osmtest.h | 517 + .../user_3_0_0/osmtest/include/osmtest_base.h | 72 + .../osmtest/include/osmtest_subnet.h | 349 + .../ulp/opensm/user_3_0_0/osmtest/main.c | 678 + .../opensm/user_3_0_0/osmtest/osmt_inform.c | 961 ++ .../user_3_0_0/osmtest/osmt_mtl_regular_qp.c | 447 + .../user_3_0_0/osmtest/osmt_multicast.c | 3500 +++++ .../opensm/user_3_0_0/osmtest/osmt_service.c | 1833 +++ .../user_3_0_0/osmtest/osmt_slvl_vl_arb.c | 570 + .../ulp/opensm/user_3_0_0/osmtest/osmtest.c | 7489 +++++++++++ 282 files changed, 139653 insertions(+) create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/README.opensm-build create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/TODO create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/config.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/dirs create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/doc/OpenSM_PKey_Mgr.txt create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/doc/OpenSM_RN_0_3_1.pdf create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/doc/OpenSM_UM_0_3.pdf create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/doc/current-routing.txt create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/doc/modular-routing.txt create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/doc/opensm_release_notes_openib-2.0.5.txt create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/doc/qos-config.txt create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/ibtrapgen/Makefile create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/ibtrapgen/SOURCES create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/ibtrapgen/ibtrapgen.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/ibtrapgen/ibtrapgen.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/ibtrapgen/main.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/complib/cl_byteswap.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/complib/cl_dispatcher.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/complib/cl_event_wheel.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/complib/cl_signal_osd.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/iba/ib_types.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/iba/ib_types_extended.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/cl_dispatcher.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/cl_event_wheel.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_attrib_req.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_base.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_console.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_db.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_db_pack.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_drop_mgr.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_errors.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_fwd_tbl.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_helper.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_inform.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_lid_mgr.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_lin_fwd_rcv.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_lin_fwd_rcv_ctrl.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_lin_fwd_tbl.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_link_mgr.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_log.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mad_pool.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_madw.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_matrix.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcast_fwd_rcv.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcast_fwd_rcv_ctrl.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcast_mgr.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcast_tbl.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcm_info.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcm_port.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_msgdef.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mtl_bind.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mtree.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_multicast.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_node.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_node_desc_rcv.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_node_desc_rcv_ctrl.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_node_info_rcv.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_node_info_rcv_ctrl.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_opensm.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_partition.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_path.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_pkey.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_pkey_mgr.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_pkey_rcv.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_pkey_rcv_ctrl.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_port.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_port_info_rcv.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_port_info_rcv_ctrl.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_port_profile.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_rand_fwd_tbl.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_remote_sm.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_req.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_req_ctrl.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_resp.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_router.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_class_port_info.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_class_port_info_ctrl.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_guidinfo_record.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_guidinfo_record_ctrl.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_informinfo.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_informinfo_ctrl.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_lft_record.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_lft_record_ctrl.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_link_record.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_link_record_ctrl.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_mad_ctrl.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_mcmember_record.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_mcmember_record_ctrl.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_mft_record.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_mft_record_ctrl.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_multipath_record.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_multipath_record_ctrl.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_node_record.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_node_record_ctrl.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_path_record.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_path_record_ctrl.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_pkey_record.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_pkey_record_ctrl.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_portinfo_record.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_portinfo_record_ctrl.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_response.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_service_record.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_service_record_ctrl.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_slvl_record.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_slvl_record_ctrl.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_sminfo_record.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_sminfo_record_ctrl.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_sw_info_record.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_sw_info_record_ctrl.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_vlarb_record.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_vlarb_record_ctrl.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_service.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_slvl_map_rcv.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_slvl_map_rcv_ctrl.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sm.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sm_mad_ctrl.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sm_state_mgr.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sminfo_rcv.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sminfo_rcv_ctrl.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_state_mgr.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_state_mgr_ctrl.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_stats.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_subnet.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sw_info_rcv.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sw_info_rcv_ctrl.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sweep_fail_ctrl.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_switch.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_trap_rcv.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_trap_rcv_ctrl.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_ts_useraccess.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_ucast_mgr.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_umadt.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_version.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_vl15intf.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_vl_arb_rcv.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_vl_arb_rcv_ctrl.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/st.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/unistd.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/osm_vendor.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/osm_vendor_al.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/osm_vendor_api.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/osm_vendor_sa_api.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/osm_vendor_select.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/winosm_common.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/libopensm/Makefile create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/libopensm/SOURCES create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/libopensm/osm_helper.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/libopensm/osm_log.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/libopensm/osm_mad_pool.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/libvendor/Makefile create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/libvendor/SOURCES create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/libvendor/osm_vendor_al.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/libvendor/osm_vendor_mlx_sa.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/libvendor/winosm_common.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/Makefile create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/SOURCES create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/cl_dispatcher.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/cl_event_wheel.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/main.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/opensm.opts create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/opensm.rc create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm.mc create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_console.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_db_files.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_db_pack.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_drop_mgr.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_files.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_fwd_tbl.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_inform.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_lid_mgr.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_lin_fwd_rcv.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_lin_fwd_rcv_ctrl.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_lin_fwd_tbl.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_link_mgr.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_matrix.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcast_fwd_rcv.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcast_fwd_rcv_ctrl.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcast_mgr.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcast_tbl.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcm_info.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcm_port.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mtree.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_multicast.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_node.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_node_desc_rcv.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_node_desc_rcv_ctrl.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_node_info_rcv.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_node_info_rcv_ctrl.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_opensm.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_pkey.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_pkey_mgr.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_pkey_rcv.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_pkey_rcv_ctrl.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_port.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_port_info_rcv.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_port_info_rcv_ctrl.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_prtn.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_prtn_config.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_qos.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_remote_sm.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_req.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_req_ctrl.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_resp.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_router.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_class_port_info.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_class_port_info_ctrl.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_guidinfo_record.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_guidinfo_record_ctrl.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_informinfo.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_informinfo_ctrl.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_lft_record.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_lft_record_ctrl.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_link_record.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_link_record_ctrl.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_mad_ctrl.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_mcmember_record.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_mcmember_record_ctrl.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_mft_record.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_mft_record_ctrl.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_multipath_record.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_multipath_record_ctrl.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_node_record.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_node_record_ctrl.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_path_record.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_path_record_ctrl.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_pkey_record.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_pkey_record_ctrl.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_portinfo_record.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_portinfo_record_ctrl.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_response.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_service_record.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_service_record_ctrl.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_slvl_record.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_slvl_record_ctrl.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_sminfo_record.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_sminfo_record_ctrl.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_sw_info_record.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_sw_info_record_ctrl.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_vlarb_record.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_vlarb_record_ctrl.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_service.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_slvl_map_rcv.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_slvl_map_rcv_ctrl.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sm.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sm_mad_ctrl.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sm_state_mgr.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sminfo_rcv.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sminfo_rcv_ctrl.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_state_mgr.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_state_mgr_ctrl.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_subnet.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sw_info_rcv.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sw_info_rcv_ctrl.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sweep_fail_ctrl.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_switch.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_trap_rcv.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_trap_rcv_ctrl.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_ucast_file.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_ucast_ftree.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_ucast_mgr.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_ucast_updn.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_vl15intf.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_vl_arb_rcv.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_vl_arb_rcv_ctrl.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/st.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/Makefile create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/SOURCES create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/error.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/osmt_inform.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/osmt_mtl_regular_qp.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/osmtest.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/osmtest_base.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/osmtest_subnet.h create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/main.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmt_inform.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmt_mtl_regular_qp.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmt_multicast.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmt_service.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmt_slvl_vl_arb.c create mode 100644 branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmtest.c diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/README.opensm-build b/branches/WOF2-2/ulp/opensm/user_3_0_0/README.opensm-build new file mode 100644 index 00000000..cccd07a1 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/README.opensm-build @@ -0,0 +1,24 @@ +##### Begin svn/gen1/trunk/src/userspace/osm/README.opensm-build + +# How to Build the OpenSM Subnet Manager +# ---------------------------------------- + +# This file is arranged as a shell script so you can paste or execute +# it. This is for building from the SVN source at openib.org. + +# 1. Complete steps outlined in README.kernel-build. +# 2. Complete steps outlined in README.user-build. + +# set TOP to wherever you've checked out the openib repository. +TOP=/usr/src/openib + +export TSHOME=$TOP/src/linux-kernel/infiniband/include/ +export MTHOME=$TOP/src/userspace/hw/mellanox-hca/mthome/ + +# Add util dir to path for makedepend +export PATH=$TOP/src/userspace/osm/util:$PATH + +cd $TOP/src/userspace/osm +make VENDOR=ts + +##### end \ No newline at end of file diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/TODO b/branches/WOF2-2/ulp/opensm/user_3_0_0/TODO new file mode 100644 index 00000000..684ef454 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/TODO @@ -0,0 +1,16 @@ +Support new HOQ value for the ports feeding HCA ports + +Support Static Lid assignment with a flag for specifying a file with guid to lid. + +Support PKey comp in Path Record +Support SL comp in Path Record + +Support VL traversal in Path Record - compute the SL accordingly + Make it a runtime option, So we do not pay the price if no SL are used. + +Support a fast Path Record mode - if the fabric is totally uniform in rate and + MTU. No need to traverse the path at all... + +Improve the MinHop routing algorithm such that it only calc the min hops +for switches, then + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/config.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/config.h new file mode 100644 index 00000000..5d7c42de --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/config.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ + +/* + * Abstract: + * Windows-specific definitions + * + * Environment: + * Windows + * + * $Revision: $ + */ + +#ifndef _CONFIG_h_ +#define _CONFIG_h_ + +#include +#include +#include + +#define chmod(a,b) _chmod(a,b) +#define S_IRUSR _S_IREAD +#define S_IWUSR _S_IWRITE + +#define snprintf _snprintf +#define fileno _fileno + +#define stat _stat +#define fstat(a,b) fstat_alias((a),(b)) + +inline int +fstat_alias(int filedes, struct _stat *buf) +{ + return _fstat(filedes, buf); +} + +#endif /*_CONFIG_h_ */ + + + + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/dirs b/branches/WOF2-2/ulp/opensm/user_3_0_0/dirs new file mode 100644 index 00000000..cbfc709a --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/dirs @@ -0,0 +1,5 @@ +DIRS=\ + libvendor \ + libopensm \ + opensm + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/doc/OpenSM_PKey_Mgr.txt b/branches/WOF2-2/ulp/opensm/user_3_0_0/doc/OpenSM_PKey_Mgr.txt new file mode 100644 index 00000000..df4031cd --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/doc/OpenSM_PKey_Mgr.txt @@ -0,0 +1,79 @@ +OpenSM Partition Management +--------------------------- + +Roadmap: +Phase 1 - provide partition management at the EndPort (HCA, Router and Switch + Port 0) level with no routing affects. +Phase 2 - routing engine should take partitions into account. + +Phase 1 functionality: + +Supported Policy: + +1. EndPort partition groups are to be defined by listing the + PortGUIDs as full and limited members. + +2. Each partition group might be assigned an explicit P_Key (only the 15 + LSB bits are valid) or the SM should assign it randomly. + +3. A flag should control the generation of IPoIB broadcast group for + that partition. Extra optional MGIDs can be provided to be setup (on + top of the IPoIB broadcast group). + +4. A global flag "Disconnect Unconfigured EndPorts": If TRUE prevents + EndPorts that are not explicitly defined as part of any partition + (thus "unconfigured") to communicate with any other EndPort. Otherwise, it + will let these EndPorts send packets to all other EndPorts. + +Functionality: + +1. The policy should be updated: + - during SM bringup + - after kill -HUP + - through SNMP (once it is supported) + +2. Partition tables will be updated on full sweep (new port/trap etc). + As a first step, the policy feasibility should be + verified. Feasibility could be limited by the EndPorts supports for + number of partitions, etc. Unrealizable policy should be reported + and extra rules ignored after providing error messages. + +3. Each EndPort will be assigned P_Keys as follows: + + a. Default partition group limited membership as defined by rule #4 below. + (only the SM port will get 0xffff). + + b. P_Keys for all partition groups it is part of as defined in + the policy. + + c. P_Key update will preserve index for the existing P_Keys on the + port. If port has limited resources that will require reuse of, + on index a message will be provided and some of the settings will be + ommitted. P_Key indexes will not change under any circumstances. + +4. Each Switch Leaf Port (a switch port that is connected to an + EndPort) should be configured according to the same rules that + apply to the EndPort connected to that switch port. + This actually enables unauthorized port isolation (with future + usage of M_Key and ProtectBits). + +5. Policy entries matching a non EndPort will be flagged as + erroneous in the log file and ignored. + +6. At the end of the P_Key setting phase, a check for successful + setting should be made. + Errors should be clearly logged and cause a new sweep. + +7. Each partition that is marked to support IPoIB should define a + broadcast MGRP. If the partition does not support IPoIB, it should + define a dummy MGRP with parameters blocking IPoIB drivers from + registering to it. + +Phase 2 functionality: + +The partition policy should be considered during the routing such that +links are associated with particular partition or a set of +partitions. Policy should be enhanced to provide hints for how to do +that (correlating to QoS too). The exact algorithm is TBD. + + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/doc/OpenSM_RN_0_3_1.pdf b/branches/WOF2-2/ulp/opensm/user_3_0_0/doc/OpenSM_RN_0_3_1.pdf new file mode 100644 index 0000000000000000000000000000000000000000..4eaacf87aabeba3261a395dfc2be991e5a4355f5 GIT binary patch literal 83938 zcmce8bzD?i*YKbs0uqXJjnd69w4{`DcgN7(NQn|k3JOYhcQ;5&cS$z_(k1!Lpm?v> zd!OgN@9+D)=MR|Kv(JjXYOl4|IbUrX4T|rtI5%#IkI>f@v_#0jp=HJ)(%7Xra7sLko(^}cv>YA8CY@xP@!XOW|LLf6M7==O9($EUX z4AU#19Mr<(tgP&zU!h{W`YK}!afI0%R5sA5g6dp`x{MHZeFF|dRtN`^fq@~Ig#~2D z%w`DUU}R@zG34O+?=v)^){A0iuWM_6WrB<-WMo3p!r$!}YLGD0KV61`i!}tuAfRin zYi?x(B|%2l2x14N56adRebNs0=1{K!9fC>XYDmG@7NTnan*?3As}U((i>nz>Ie)*& z8e++>Z*O8{3H3ZM9|Rj_P*GI_S~{4U|LG6R8No10S{Xp8P_%>mME7S0^c@k5WOX2v zeyH?eSTwKw)Ax~|9Ek#T1pmBI5MpN! z;|i)Zf1St*W8ud{26-R|YQa$N$^=~is0U?&f@TmlF}H`-&8dpbJk zV=gcGOEPp{)K`9JT{w?=Z$wlPfro{MBp+vW@NH$<^rg{+wp;K;k)2iPPVv`#|Kxh5 zymN<@&+$%o8}AYF^?fw%{|M~=*w>H%mrBBSOXQ~SI3LC^F3yN8oCyao0%2mV>tj=y zm)Fuu)IoSOLth#4o07|jBX4Uiom5!fZe^C4vreIY5l_D0Pq^^l2PzhpdVrZhT zdu7AI=2lLBB8!P08YP+8SpJr-D}TleihcO?<)i#4pxr8 zWBdmK*uDqmPJgV!-z_+7%3tw;fr^%P4%XIIw)W6XlIRnlfR%-{xrwf&z6($uCV2~( zQvD%<@1(FXG5-fru3h;LQvQzhUtR8Z*Te)Ax3qGy1d7_(IsDE&bXWEtP+p7u2g)Cd z@r!GNP5CSLAfU7(#MaRS;`A2|S=cz({{y;ft@?rPn&E5Z|KX5-C_nRc6!@-m%zsfj z*yP{nq6Yz`AWlGGh_1bZ?eB{L27&)f-LKp;|Awx=x*{|32 z7e0USOFx_nG(P~!TN&CrLAe78LZB|j0Ai_c@^{Pni_m|?4!)M^5A1)(`QN!TIp}_d zkseGB^A3OZV{ELyDD)4N`h}Ta{Sh<(T$3R4a}xpGKS6ytbYl#L1``%$4j>D3^9yt7 zN>B%X9SEeLpZ~@ru73Y1C>h|jlez{8g$jen21WY=B5b4n-OKz8AFveZCt<%(|BJhk zfhJ(zZ~Z~<@4&A&B+%3g>P>&l{wLtSI1m}&HK+d!{0IM6z^?`SPrzZn|7l%7Kb+}5 zuggzzVWeLR>7StgV(`#)xu)iyX}_KUg$_#{t|age(64^~6YWgbHuKNWujz$BzZTLz zL5KbRXXw|f`j60m(hGxrP0K$)|HXJ^fIrp!pP^sV3xj^GoBss;7vqF#`!zNH4E=fr z6#7qF`X}hW*s6@JmA*X09%`8k&;kW?^9|daFo;?}_j6CKY)KfpTf5qp3o}6}|GtV0 z!eHpY^SA?q{g`Dk0u7dRyND+DH&n(}i z3j6ubMtQY2{2@SwAG>i@Mz+7-uETEpV|#9|&}k_TLZ3RNsj1P@Xajp#$x_`wMBm?} z#!`Hj#_s~)@9SMTws}iU)zN6jZPXKJ)YH5wVM~X#wP{TN-yZZJl(~(R`?1BWL%*@D zZAt9PA3vyV!|SF%g8S7k94~oUx7uB1 zv4rr@v_xsp+Bm+~bdm3)Bz5u!+&c5N!3zK{CyV)GkEwb#B&xx?yjfO*2s@7V(;SHM zOWvix4^@5kc|iZnT{vZcg8E~ClAl{r#islxPTdD138B7Px*y=^nppTv@LwcJGZh>< z#Aq;84v8128m+?7u@$v;xk$sF!daq!*6GTo(#X2e7pKlRs z=iozWW*j(xpuuRWz1ci}9=zDi?`HC-P?B`StS5BIE%-h5E&50Jq~KdU!CA)J)(Xb{ zdI{lQ9$SX_yvPdcYyTpwQ*|(1DL470N`-v*V-hvrQ+(pDoqeXV4U=enGS3y_vW4%+ zqim9?lSMsCn_ajxR_b8WeWB-^_3pH(EUXCiVGGTG0EG|#D1AMU0g}yyrX2hSsl&9GePLyc-Xz0SoJ5WCRnATm;H3 zvaDNgsW$~sPI42O(@PUeBOrsa zi6y_KoypGuXsQFvBd+d)X28&-obHL0xq&D&xi``Oi)H*0QU3qo`&(SU1epJSxa6!X zbS?kF)-TcKJE}k21#~U>frh%~&{PZhQ4+dOVPt}SQh*jGM4@{mdlP$?U%_2@oooN` z9on^L`a>*NehwxJ18A-ff<^#_rw|h(V`zrR$O2?|Vq$M61F?nW8CI6CycSmI5wJ41 zvX!^i)rVF+1R;(l`VbLYT^HcBivqJlD-%CU3W5R(KMD$e_E48&mzw}oerSaj0x)DkjQZ6il4^sHpdG2(YlQv9Jj6F|nZ+CO$s!A<07^J`D{$ zJq-;HH#avA-_PsvBLMjhzyuHh2lohYIR&@{K)P%OBmn?$@Nicb3={Oa34ptC3;s63 z9YiE#bO78fxSKa_-GE29eFy<`(Nr#=V=j9^MDR^ULaDJhJg(y8R$DvG55ADW+V5 z9+=toMZW+7S(yCx+>X8-3szFmOLD=t3I;-r$@Z++1B&yI-D2;iL5GDsVTyMtJ|*GJ zLyP;Vr7got2TF#Hz7c6s^O}X-Z|27sMJyoFYxOe4kCWzS9O_Cp&3y6)oLHLCb5{xMv$35O^vI z@Ir~BIFHGb&KRRxee%(ucFXnkvL-6V?nA|s#P^59MI-a@xL@HK?JahhMj}O8{3;JwOrv^CjS0xn?i=S^D@Jk>>@c2<-($JB8);n;%5!@(!!shkiOh zj#c-IrZw=Hv?oeBn*^=%btIgq0zFPW*rvFV(8ArQdRFPfQ89O*!R@Wts| zZsMeV2xb475=z8~xJK`kodkD1NyhF&iRf}UtBoe+IZ zEo9I%>xzSNf!gB&)eVT}K~=filGaIUYjG+|5cMmzzA&kS>TD6LpTkdFV!vq%QKe%b=R`^#dxyOl220E4tGBnFn;Z)LbkjpNrY_$Z``+ox{r7NZ5v5))JLi24B9awr2~+r^MUUSMC|{1O za^}((Co^?4Pxy~4D(_@Yy!ux5B!|exvUSZqG96f!T?7AIh=E7iWXwZ6Cuw9tU27(3 z?ja^=nCK%N(LVTYwXM(R8sHd-M-#M!F`Fj&TSxI5`In=sxE%2+PIg+DmPMWsmw>*} zV+2fw+#8(M#F%K=4$o$kcFYK(f@faYy*iVrvV6>RVyGUX;#+1|+naX$qlOM?~-w39i*&_Dz1l zIT#Om-(Te3ol)n9daC9gOgv`yRGAZ1v$U!w{+$sCVM{P?4d0ucC4Ki9TulHIRM16L zhtAE-w8jiYpUhM^Y-~P{psiQ5P5bx+K68?OxX5#EQP(?Nc^2=z$`x*v?Xa12)|A;* z+2VJBl;5v>)If9D|AnXY)koqR@oRo(K0fCHmjHz&q_(lTBF;RTp4@KY(fs|KOF+^J zT3CpZ*@>ZprrsM#i-^S%4+p7{h8=S&;+ylORq=|3*peKILS^cuAA%6XX^X$rzqeb= z+?Tlb`W2ymxw`qdMf!Wo$CG>K`uUUD?pg?>iw@W*wi^yX7ug}jmw=mQioAI*m`+3v za?b+Q$2_|hE&=k#IcJH73^|hJ{(D)dyrbFsR+oT;Sr75cfiG24^sPmC`O4+}{=1(p z0YXd@yz7>ub2MfcKy7hzJZX}T!A}ap#28%7^yBtWj7j5xm0g-s(plrtI_I}B0?e%R zUG7~1yqMb#UJIYJxUPOl4fo`BDl0roM{o5UuvTNo$!%#%$BlpD%UXCIicGU^wND(X zeL48WBmENa$ys}d_drT~U0hSZ=H%_I>U&>H+FstRa2wMo%}cAPF=9kl+eRkrjTT$1 zQj~7*u_PNo(A!^8>*7q;Oz<+fkkRFdmiErwtai=#g1rH52lFLgI0a?~i!Ht=-xso3WxsHc8c26b*01@fiNl1EQs_}& zIMxbA#v**{8r3l|;aV5?jTL!nk!v_E-bag^Tcy;r!`qUpvQ3%mTg6&YRlxY$(H&#E z=jm8h1z~`5bYF=}KqK$AnrGQFN#Y(uMIN|`kaJv>dKJz%Y?-!w8`=ZHyy~aKF5+t! z?(V#43wjy@>!v2CbU{TLQr>6Em&0p&cA32`?&L{u7?}vcB3;zy#MGxJ#N#yOgY7B2 z=rj9eRmFw*!7B!s)E>D-#r|jN=QN-@WAoz?=h%$vO;HYe!y>uy+F7&v%aITK3{-gE zZ9#1tJ3NaiQgk@QtC`+)9jrN&-%w6qfs?xYaSveDW@dE?mv=_yQxtD+dqve2umnfU5k^9V5 zXB;+WF76cHM$p*tqnEKSM>bC^^_g}e%`^ys;(oUU{m|A?6oefYPccVF01@0vwIUvpSxPwL=Zxx8i+frc95mldPk(<4J|(GzZGJ5oR!uHXY3Nz z8i(2z%NyqQ9=ctym>$oe ze!BK%;=U=TBbmLdihjbg-m{e|7J8=^i((wOEXvH}qBmwD1_>12-}e(@H!PAH1V;wP z`G=UdE2VR16hmYaw0-0~rbhvq54|?HwkSSqRLpz}Kkz1A{%~hDK>d8Zf8tdA!h*As zxKxN(upu&Y2)6q$%27?gM^@9o{r+-r^Q1?! zf|~}+^aiEkfTtC~lq^XwX;$kj=B{}FkY_Esu)n!7v6bgQ*XUqlqRLaGt2^PQB{yUP z_5L^!iI5dmn`VGyUeE|A&)$X}@J>-IX06E1)>=rZ^f=LHgxg!`>%4pLW}wXniN+6^ zi9WUdi*+@i(Z&4})%`DqQtBi}8Twi?pXx7%D8zal+?9EA6*GIAyFR74Q5LY)H)P6( z4x6u@3r=rT+b})T&v&o1AvQkS5=QH@c6?R7to`C_Bge_SD(|(w%GM33@o!?TTWgv; zb@>9%e1)d{q|#2b^_RL_dn;Z%__{_Yom!s55?OA5rK`WFwEoHlQcf6bXAeMeR?5id zj&RTlIThQbY0jn&tk!18YD9FZm)50QXwW=~jSn9#+~rJ@oQO4>khf_{Ek%lg1I_O` zQLN7#C!bVb0`NmG0dXU;YutJl_3jmI)C~b~lk)QV8!vGH6Kw4#&pJXmRBI{Lu@ydb zl+L>6iRvho0)Q=1dfN8Y#YB9h5ICIGM{Yw%!?i zl5=2LIAkNOwVz*PYKcq<=uKaLK3e(wh$%sPbYjqU&1%Azo<~x8diSmDtu(i7z#(N_3rJn@zsN=zrhJX-D?Bb5`YS)cJ$f>O)x*lr@TdDlud^qpR{>qhp_;l88Tl;e4%g#mmoV>6keS6)OHo@G;DFI^I3!}mO ziEoO2?y3zg)kCh+6Fays4#NQB+NgN$WLou^$3f}z)l9n#juv-Y%Q^`LW?P9ZXG}|t zhHLP1I^6SICn5v8#8rVP;pf>Dk4YGCd-QFi)uA<+!Kl`enmds}4~jVzaU;i6%ecFX;d&h`%=sBC2P@^u*Xl59 zC03#>?mFbO7o)R3qpvGODR>q6EyW{8|5>bnq2%zw0qYoj3o6kE_rki77d#RE(kG?9 zmjF47;{6JebRynps}-C5_m`s^BEwx6`ZN0R`sPiRH`ht|Gi&#WMU~Rmf(e}~oevFW zT=%FgL3M364&{22T3z*pXt%PQRU^vUv>hZJ6#K(9E#b;Xm2$95zG3qoWW$XZ8OnwP zMRXRew?Q6-R^tN;8&TfO7^QKIiaQP0(1ymZSFRksrMCEp&Wa}p>Kcq37S7Lp5~H4# z%}Z9P%8G2&gKCwvJFAoiWfB7a+@z1MVkQwg%8fh3|*tjIin~4BU^y`d@3t ze^=FoG5SBL<}wJg0Dl}MU6K7qF$UJ9@t(^17BJ9%lx}mB z#%(b~9=ONnueNQH4(``2q6h$GKr+U1nGd!TK0Uz-B@<%;xyfBHtvDV9LLN)WiTXDV zc1~?^lsholqs6hOjc?Z>Go2DdHrAKjm0cqM2lRY04%BZFN*~K|-L_8~UweK~kie@< z$fkGP=gy{c^x!hSsTCoOR3Yz!(#E@5m-I2!^zkSMS@C>~Kw;dMy4bN!Z@4(eB_6SM zCOln?=tNix_0On=}5?c%RsIy7Ru|uX)hT(kkS> zbY|m9KY1ui`te05&$=2vnWo+;`yu{WU*7F?ug$y^nh%FJByFPUm|tuxLDX z{MCxs7-#VFZNtC_<68P!5p!ctlgIuqgJ~jj+H(}TZxDw(UX<^N-HXs99u!MWdg|l- zDxyQgHAhXUDuRdwl_{}V0s8?M!O1)q2QMmpcEQ~+;>I@_=?vnPmPN;MD&e5J4_h7! zJ9QiPI0Z(T+LdY{`8kfpN$$5(3ZcSlTd1DgBdJru^HF0x`H1BeWPXl%$Aym2(_6^P zKk+%Q$9TT7gNw&&{FQrkvK_-su-Y}?oi}Mv9PU~C} zQXI07Pe!XFqxPWqwWQoa+%>#0 zGt_$~bH{{I2x)K+JE?8sbp{-~WH>n|LtD?uXVvYe zu97u>o5#2l+{F-aqla4({&N^OyTDo2TO?82yYRu>#e}DSp3XhHR}XHIV&+~f!@J9zEtf-<5FmufOCk5bhcK}^CLGo09sm_!Ei=O!lqvE7mGe~io&}zW1Xe4* zXyzJQGTY*zTtZ`I7uQCaQOo-|*RV$R1>V;mWPDv}FXdwHY7>GD$?xX_>SHimjCpt; zWyd|&)+x!Cv8YCD2+~8#&i`1fjA=DZ_)Ru5D43Wm$fU`rsOARWvrbi0A^8HI)ac{k z;qX^{H$fyyrct~0fUKxjaEus|uTWnF_Pxe6${>r6?nvqw0Q1WjW2U(v%l9mY-s!Jg zv*RNyPIV+vL?BS^n`|-b@Wx!;nH^_O8ZOtWU3zD{EJdbk5>tbzpweiWhah{P*v!dU zFr;K_&r8W22f>$3UkkumTtnncU!6*^-$G{9mpXo9HF2!GGh!WEn-sm zSHe@U-|z9^l#O>zKLpj>KAm1HIz(WW9fC z?A~@|uZ0ncMJ%zW!UYH*BkN85do+Zd3;*R1;lD>i(Dk|B&u|E9D7`v${TK1@d;I%; zjQ9Nj@B2|4w4E3R1J-v7{r5+_{66!46E9(yelqu?wcx5h=STO-zlwe*6(d+{}wB(=Nkm=jb?^Q_`fdjm7)E_`nQMX zFc|+Q+p8-R|3S<3{tCnW zx~F&Qb)V`r{T&@j{{fyQ;;`<^<$cJ<0JrR1Oi=k|+~#1qs}_S{y!-HjGL^|Ly@p z>LT4MpU36zT;i)7i_0qKQNOAPjATBDY19vr%f18T&`D+v=U5oB{wukOX5syYlm8^yE> ze(<0+vZ0%6hPeT|&EzDD<6YX;`x1B_#P)ciB?fU<59TJ7)-0A@0vz=gde-y-mA)q| zEpI%;yYO}#mhm#+Xg5_B84qcP6hUQQeEMX49H)>Ir3|JmM<6!~5RE+$rW!^VYmnjj z)?P->cIy@P4AddeTIi$RTEd#m!5xgvLX}Fj&UI z9ero3151Tsm4uMe|CJYH&$egyd*yvS8KA%fwoS6*zkQ&d-wr&Lj(^<{hYa z^rH3(lJy7oF}A(%LzheQKQG_%i--xdUqE?oAGBSvt$!a;aS*HeV8eI&T+VbNbVxpN zxwa!ZLV;-0@=_))*93oTMevc|Q;_|0{jhOD*7bA=jAsUN?-EAS?1V5FITv5~O7IqI zCpm>X6?XF5W!dn1FL^0{(CuD^^V*rtX#d^1(gPsA0?+~qu8e-u>DNjK zu^1k@cpK_xrz)`zR(MaiEV9JBJH3+ZnL~~Xi^$?v51bTtdOn08$FsTuqlPFR77$r(7a4(EZ^36is?o*mTY{FG<_6giY+Q&J*^illriP|aPEdfQFV@=158 zaQfV&D`IAU&9|vS{?bjVNxFABrsBUyWu=ShsSAV1$T1`b<)yNV% zHvgnM*dpa_Kdl(@A}^wyJp-nNNa$xPg~7I(B1-j+Ofy+wFKeYLEm~}2gR+e=4{vlsop+e;;MM;1eRIq7m(b^(tnqXIfy)C zvPn6u^A>+Smh>&c zh2@NgCs`67xfP|NKTNGk0zx>8-iY>!!rczmb_J0kx~IBH_{%R#r4vLS zO}}Q&9n&&p>ItrOlSs8BId#a1S?@wUqk61tRw#{2zl71`a*1e&$`e=7NbOs?YWs~J zAHpM3i!y!o@z%s05R=@!?bb5{%qP#D_R-A?E>$MavvSc3@m*5ebw%%}q4I_yCsp=F z9b(LXo*l%UujoEQF7;t}y!>vP;3knkK-Jf(&WLf@bma9_gmU(qjh$LOBcyaEV3VBM zM_=s>G)v$$#*a5|@JudqnCwaEQMwa3xWsO&>iNz~epYL~8|GDh7(&w;TBi4~Y1T5# zWbVd!9n>wZ<6)HVVtIW7jRvs>Nr_b^ z+ti`0irUcA0$nQN;&*7N2o?5<{)RD9>(*o09Pue(6qAnGB9@&eD)VnexwrxZf}FH` zJzZ@ld_j6t@!Gu8{@ihQ!l?)M)Ra=5m8*i2y|zl<9ZWcAt$L6grxzY6+!Up7m<-(3 zXR3JW_5NabX>mcTxD(Mjxtis%cNJT*K?~^%u_vCbi_#qWJWDyvbQP4@nB~|8mS(kG zM%wU+!~|RBql}k}TW254W$d1qGQ|!{X=9cpWx#ug!9OE%5136Tb-rJ;s*{=PW1N$M ziQuj+$FQw(Kf{qS?_Cs{r=ag!I&W5DxilsBQIE%B6kcri!*5FMe#m$qfz%Z%N)sr+ z_>A-|LH$M28+;c>0rdAeg|t&{6kD7fzOhIKs=(@!UiBo|ThAp@?>tFp8s_xW>}>SSHHtw; zJpYn#eCr`qDF-Dz0Zn;$IdQGnYCm2ELG{>9bQ8-wkKT&Ox__+XR*G!3@pfx$nl6n+ z8Tg5gRwUVny3vqYOLiin%)*^mcJgJZDO{5*Yj0|y2L`*1nwbo={l~#!5+|ARLQTgp zEKlVq_Jl+gb_uojER?D~XVwW|iL-9(GJUY@a{8PdtcX?fu3IfSxAKJDW${QtlaW5@ z+v%y3wpilp@w2&v4#x$){7~}{L1RyYib2!~Y67&Aj!6rTh01oTf%pz(y$~$qXu?U+ z+K_?w#}XnaV(h9V!`PeKN@h|b!3jat-Tb#QZ-0IHvQLAAXmNB^3z9<$AEVlVc%UPP z#yYuumPNPtxKoFWWBjF;&})~s8%{1;U-H~uH~Ci9vMjDhiG4_E)Zog!O=u9q-FXx_ z>AI=1=_HHaNqzeMlM1yWkY2)qtjw;lur6=pAz9(oNF~iL?sY*M#-1ltFPAfM7zM9^n zaeLB}IO6flDa7XyJmM`%%p(~xOw;HDxvUGf>FDv&!4w3kGB%7YXUApt)weHB@v#zg zA2A!1K^|qHM=|%t+zLx{OW5WuvHRdPft-BX(6xVPR4rjCVGdA|aEFh-o&LuDx zfFtFix=^H{^|`VHg7dahEr&H~EFZV18cTr$x+Y@paT}A1B1zHod?tUhe9!>M+|+#m zF@7&wL;(3UXh+}J*oxXUKSI`^o~&3SEI&*_R$)qbF7w61`&3CXm9qOfcw1xs1jHqI zUD0p2)zB4t&V3#G3q|TXk?Tb*(HlTPPk7r?BV;lV-N$vfkgMGhMXTLao)O|XtB}z* zlK2+96r`V1QPKo&()C)+@jJ-N|`2HLkm$88ub*ep;Qp@9mD7; z{-h#YYkaURjj!n>SIg<>A;Vlu{qR*7j{@u4ws=~4_ES~$%SKV7W^@X|zOKblh(i*W z(W|F(mD05N*!4I8MAg_RbV5^;lZAAWb4r%8ftAxk*%rl)-h7#^#vzNG3vN!H-gjLJ zaPL_(!0!tge&R}JNuld{*w5z?JV<|FGY#nuk~ep`weS7}QcIb*D1OgH|3w|=dnpFiUHIeK zIMDZE3v}ckAC3EYt^s?H^_N1;_hJq#A^o2|E_Vg$C;5M_B(SkE{_CO%m>v2MAM~+U zW=7~U8PLb5|9g73BJskS$k;Ra*xD`R$y}GUZ z5AuwJI<12tU)n;;a5;hv5Y=wq0iN=Siu7I@q}H#Cd+I%;TruUh#SWzYDuytPMvgU#?mYh^w2p2|u0mt45+ zF8TNKtEcgSgz}z}s7}w8M$T+^7uJq%*=o&Riewy{u?5lF$3K4TkYD9gFEP~?{*}H8 z)83KF>0vOKxn8ZiE)e2r-Hx2PNbhs^U@95^>ta7<4dY%1Tz6_8splslsbwZ9FQ<`g zE9tmG(?u(4U<;UJ8mQ!R?^H+1!-u!#q^UQVrrqJI6FXNyUxym;>O*n!MoTE z%d;#&GeS-GemCKu|h`L_W=+TpXiA$KIKq{tZ1z z{pEVW@?+-I9-l&$6?N;k*%n>Xk0>qptS@?Gdit#N-aSeav6ADBY7qHUq^NX2u$g*a zNJ+Dbga3nb&qR(#R8G8N2hH1i+ku{ox7^1)q{>Ipq8_6zmpBfH69?+Ey1&5IXq?jZ z)f+Wj>#eNsI~QhP0e5BLG3Ack7c4Kc^nHq@itC>AOmBiJ%fpem^5{)qpJSJ)OzXwP za#~)VlM^F{5NZMBGL)^-`Q;YI{gd5&R2qcr*!J4>Da9#b_DrBw_S{<07c68w4!_FC z9>u}hx^bN7*@WE0l+w8ikmBG7ejZqIlNJNNb*jOY@L$Rk+}&cFV(3wX%Nq5 zKO&GX^^W^k(vZ#IE}l=6Rb}7*l7@?S#3qcA@MNieg z);%7oRUT=hkg#7Xq_fI>Q zbo0I()iG7nT$sxViuEN+gLP~SNV$3vIc(|IK4H97rIy+`1|U?vAQmipfZ=Z|xqK`4 zwxs_pPlTF9t^AoujrALIs~Mk{^+}xVGAYszI#sJhPoGA7GLs9hAI?YqW=5Lvk^#3U znlQKC$U&ANp6zXJQ2E%U%|r=$L_mU4`-5~d-PfOT=A*)^;G{mtJaUX4#trxsR`(h= zn^Nh0K@>x~UzbY_w*(f7_wg9KWc*_nElx8g zUoNRpu>js7&OB$U`nGiLIS;Zfv^h|xL)*Y3hS)3po@Oarg?iq% z@ZHYf5KtdltD&KPx;yvYmtBb29sqwMTwFptMO(*^E2Rp@#)}M@ELq~d#OACx``AQP zZ}<|B`rDG*F7MHSF$&%Nyc#Bn^1w&Qr}06!VQ8w>FEmu*VvPu?!_9IgiEQ56sc%Wo z?|BjVS-c8vPyMU~{2X0+`!RB}YZ)$Py8Gozs^(jyQEe}^@YI_XA}Wh(J&i|$B|_`i z`{tz*Z(0bph6v3`ft7<%Y!fd&-o#no$y>E#jQF&g=y9%d@X{w2RXlxdgy!4+6d>jk|`+Vsea5h4VM9tdrz*(H{ECzpBlDq#6F9 znUunFxXk)BbN0bY5Ovs#X4O0_z?nZhfxS=y zO$$x&#^i?Tu?xmF#Tj)=X z=ah)SDZY*tqRSAa?MpkFryw*-G(N4_XKz^Fus&>VB7aFYkn;rrj)dl8F4@_OcEm|v zUDAidc#up4lJEd#6mrfUQYi`oml*m3#pEuQUs1&JjA*6U85_q zC@K@-=j7(}6|q`fae{H?3!gnvub%p0h65Y* z6u$z0WQ)=UKWSQIs)eu`5;~+2?MwE8^osnPuDyoVs4tG@GzO0l9#ynjkfk-eQoYIPxPlD z&z|9Pmr$pmdRLp(>eBMX4QZx6l#qn&^flsIxN~T#HH`CNRryaMx8Zx5 z2b9$)PV~nFqumoOHn0vT#Th0bCZwj!{B+%Vd!-J_pe>3oJZW`t zleQarWN~DK6mLWYPHxHLJo^oC5=N&ko?vq9R0NXe@zE_R*3Q-j zx4r;1JrduHhP^EotOpNZlSCYh?z(19ddMYtDiM9|(0P$EeLq<&S<1=xTm3ES8fM-d z`*Ggak;WEwg_zi`L4w#gMz0<+w3~gCP||pe`6wZqP2e0ezV~wu9I@sU;wcTun|A@d zSp{Ed!rA0wkx7eE(Sf|h=Z|V1gfDYbQ`xHImWCqcX1s$BFBwRpdW!NkOixZuu;WDt zSFZY#`zq9wKDWh+hfLHTihov3tzx5XL6h8<#q2hSc=UC>HZ<3wOO+sIDK^I~=leqr6hhuq#y)Pc8Ufm*t@G#`htd|q2MXVp$<4Wc)vqFtbcz?n)0F^2f@jI`9ON?75^!}7|wX(#Kbu5ZVC z4$+w)tWl7hrxvV8O!(of_;3^i#fHeu)eA+MGgP$q5!ZL;c>|R@Ef*N?)~wLDNuVK` z*U}OO0R7<0_?{nP7o~5Mt!Bp0;EI(Pv(X(6IdYY*K4c+XUodbTDq9uRg-gYFM8-yq(RQXCNf$z5Vhe%nE#B=Gb6$#mwn6walkj?w zMy*1wLY27UfRJ*hRo97>V<&JT`Rt~~dn(u5#54JkW$ulnX$YSGjDNTrl6s+Oi88AS z$w)&`5e^(Cw%vfR9X)2ua7xG*CHi_-CEKFV5ThjpNu&TOhb(V8)sxnQ}`Tq1b2%FuzPJt(A z(%T>Ekt!Y~w^&a+)BxH%RUu0g^naA6V~*24cZU&Ez=Y4}mR2CaU7>qTqMsOhHX0}g zl3fg++il!yq7H#m$H_n4_Lw?Xy<-e-60?Plb4joxWL$;2K-1eU;+K~CDc4Sz9dOZa zjW@snBJoPZ34Y|;swGl7vSM-GLW3dF2vh^!zaU0f@lT1*9q^a3Y&LBZpTc!$rz4O)eiQ<+X^DO_%zR z8wagFpuAF{**f7_;mp)?4|Gy(4C(@Ol|8aC3F=0q%Lh6DZNo=6f0GvfaxDID(_*IU zN63Gs#Z1?aQU9B?_Df8f{}l9=*+|h00<9um*gxh<;BxUrY#nx0Oy2J|>2h9A>( z&U)K4EM$A{RDC7J8=qz&=F!YNw48bRF!i;C=S|bgNsZ!8I&Df4T72O=%<6gMuZ7hg zM>!M6u=8TJ&1aFR2qvs4I9X|r2$+I1IGuIJh&5h+BpC&Q(*%n<%2aMCB7jQH}_t(Gv8uMMaOK)M6Gi9%-&m-BiK@Zet_7 zqAZ)-DIwHSN*73us0oKSbUUfxEG8OCIgA&_$=r+t(t@Zs`mDxpZf#dD1^}L_%F}b> zQ-xw(5Encz7SGG@{z!Ni`7}LFN_Cj-D`Gr-tsG5I7o4ORIj4z8o{n=Zs1Y^M3@NgdcF<$_#rsQ)SigNO zfD+r`cj%Kr{^~1#LRodZq5-dx(5#6&*!Af%N)7#lx<%WVSoTTm(EG=EX~mQu9INMq zF3JZhvUH~v>B`p$@$lw{c!IgH!PVo1=}894B{}J!qiS%VZBFh7@^xHS^Gw2{$m|QWZQoABHpKF*7b?55+Wrb`(1K!q_gdoVc5+Me2sPQ;JaQ5%h6aIVamQ%kceB+^Yj zy{mOZ9T0zD(G2l+V~}y1)v3mhQhz4W#Yl9ga*tanLhOFj!i~dLWGnX!Y+N`F%Wn$t zAxm-qYI~}?RcFQk4gcj-aU>zu3Zg9Oj>a2@`LWO1uoE0s?45hDG4&3YVi=njg!uy0 zX&F0*{Hph>(_NmrkUPgSLd;Ww`v}?Vd6T-lIiuZb$R!o<6=$bY`VkQ^wKW)TS@jG1 z;dmG4@!-8=lm+r-6v7u$H z;gMqvZ%JI*)_Sa)`Hn=qAYT<}=~I{{?;LyU?hHVtwY}%}Sbg;(mY-4QU&rd}SI_(r ztFK>m^Dkock2m-IjMYD0#`3?3)mNZ?lKf#BvIx@6$$L!EGilO6;sti!k zoW+moh#(HM$WlQy)KZqLWRV;W7x2`#PEXW?_J(z`wJK#2yl%>UGx>oRtG?%=?s?4U z@ez%}ncPq~a*KfO`h3#yzKEtqk9i@LVc&Ra*_}eugl`8qJDS6UY-NId4i=$LkPoI1 zg{Cy@%*-CD;faiw2tUxc@wLWFFFCUlGncK1$eXe{@!oKZ9}!`88gDVa+}CW@n1ue& z>`*)0Q6O&k7v7w^m_?u~-eZh?YMtr*859y_CrbMwslnXRrcu(72z zwNHT-D1@mAMF&r;={=Ba{lE@27hNMlThv>6?={hki^;c51Ge)}zWK-C>$zB<@0M-U zzhM*M;dtXqI7)lS*caJuU?YCYok2}g4^g+=3KZ1a1jH(_b82U*l8oqEJPB}R{6a5QmW$OIUEhG##>|NEALAL%kL>fi zyeT=O*N-yr?XO5*)czeyK3T&i*TumB%)tom5LD>pS|O50W~X2v0^ZOz={#=;u`$jI zu(T&Meg&TKkGxd3jZO}<7$~{{Gx^f|p`MlU-M1%=?|A z)=`Z*{Sj1|ba0-x0EeAB#!a!x2vuxP&h-YNSiPE-!Nu>3e6FS5Wpoy>mQ!Z8+UsWI zih-AYY@j{gIy!{b4`lSQGEkDjnMa_x?z3I5#&`oeJfx^#u|XhR3KQ?ts3*kF;w*z* z$v3!z>*hU(y5uQTfk@yCd^j>hJw(}1ov!#s;#3`yVauKlz=8pM8LIV!1n<49P?i76 zS1u$#T~Zcc&;qZAke26d+O2n40y`?r>AEB7uo6ntE`dvovZ2sdh#b1rN3W3$+l$f> z+9VpjKycyNKp27)gi1glq7hB>|89BTUaUOk$Cpg46#8sTgd;HQLM+IkfH&K8xJXWw1e}Y(66i*wF z5fbtO=bczOKl{0Kk~kAM#W7LVMxM&`CtlHv@jw9#(hfcqqJczDo{Yh4OdIef-jmB% z&_yx}i25gT5IsRIpyQ1cpJ!x<40h@klPlfWKI686q6faX%!IRE>fG}7IzU0tax4=W zQdd5*Lmk|v=!YX$pq8V2Ht#-)+kP}*Pa<|aOpK@E8-`6d^(W31gzYEq@S0;XR89p; zvdq>4prwPGsaB{Juk^`vO-gDLSDY}_F#bDtK4VtF0dj{#nz6}`DZ_C*1DdN)L4dd+ zS&Rm^huzLs0ES%>zhr;inm)$0!-S)UDOhsOMKz*MP>O0JZw zuz!MdQvJK>{8m~@|A>&#%Vot6Rpu75BZH`KD`Qh)eA2>9j*Ob(n{S*A zYFNEI5M~BB%_lx3!cr9cPIvYmQ#;Y|@@3zz8|$%6-_(Yr4Q_pot8dYqLHrn0$ny5tP4_f5I9?a|H;Jxm;t?h+OPOaX5l!NyNoxXZOP}3DMJ30)Oa>0<5YCm|PkybJ zo~<;V$OuAb-SI8rQDHXmPS(iO=VXPu!o45q`0gvp6$szz%j8zdh{bV4CrM<9KF#b^BRRQ$cZA@u8wT_@1)ZpeHJ91DC&WjErhNMgPs zNTM~V1iag5b(ja%T$Ll=wpe#7NBYZ5iz=7D`lm_VqU2+Agi+l-CXQ^z`(YK9oTit( zPEub2M^q&mUe8AI^hiB~lAo~{Xs+-0xu@P%+6Y~g5wuUrSXFm2J*NT;)E3tWM+dHV zzbwB~fGN=^5fve<=K>)%MRetoxSIH?)uUT*CWj#k3@=0Xr;hZZAyMC5l#=;!O))wC z4cd0;z$j(GlT*RzpvO2MZt@VF2J4XI>X-_WR7Yt!E4g>a$$QFkr7qLrf+q*VH&Es% zZ$OMfe@;XdobHz#Ri+%`YsR;=jiog*vCT!X+bjH*Xg0)61g+in_Kk|-%eXgS_MQ!7 zKKW>>12I?5ta}nPG3crEUnu=LT^^$lmBDVz5f?FbSn%eXj^aYFY)UeR*e7VAySfzfxG`r!Esvl)GE(pG?FHnRl$qh~F9HVf%A zvB%-eJab^p=%*q_{FiA+`56g}AHiG1c($*-Z173E4~ofxV>C(OPa;C8prd)mHt-%% zJisBzd(U*NAX=)F2o9N0`Ch$3Cd97blHyV;h+P%wP7&RGNY)&Me(>2$1 z*cg~r37eCAW(hP#1|al%G-mM5b+jHN8kcA$tNS0=cTp{;om5iwi3ap3nKWoo4-a}} zW_T-ITnuv=)bll^GY=9aLpasC;d3LbuJ*#OkzjQ#Eu#CGsmAU~KG2%wN6#I%Zth|? z=d_*2d|m=7ZMSDuVph8Aj@+u=rLPS}oPCY-TMJ(suq-`WC!Y4tuQvml=Zib%QR;g4 z43!@@Dd5GAI`m5)+h?m;`{xw|X@<-8T+T3~Z#uO@9UzOMO4i6*v`NX0i`&oe7Kr(( zBflF^UFCt+&u_%SuNK(FW(Yc)9!L>**J&R)o!srq@qAEf`|-P{y8N9FPd~)xQdNS< zmAW-tq*)=C!hNf}z2M&DYHD=~NjV;lK~V6c*lWGoI9H1`zoLX!0goyr)UAEk8W4s( zP$Kl{kIM3VL|S+FM903jZ#aiIOL#QbpKoAk&eur=MP*;6L2G%xJ;p8nm=*e{br%(TMiSNV0*)CfCue=uI2f4YA#8xq0%m?Zx$0V+{wa75>2MePez>h<%zE_mj=*<{tK&UYo3&)wnD3 zC)!n;KAlB?-d9zsUEzvLum@FNvvldY>Z zh+WO9@6fKj^{1hpa>&nD~u0GNn4mS1qTanKz~N@CVV?vcD;>& zTP&&sz9a$q^0QYRZ&_g9-M_X{6R~EK9x!i&5dIw;nadd}a@8 za9cDh^;O06**V4PA}kOvSVQheX4-8l!tn`;v@&TF`klNNHTyc^&lkvsyijj*XJ!;= z?Kg^B-d0v%=dOBv!B1WN)t=+3RE&RLp&r%5`M5}KE3T+yv1ITbe2E)NQ{)%4ak|ZK zjX~o>;#SAaJ$PFT$MS~IpZ)D!B3Xk~`ZOG4#JK_M*Wz-yXdP-$QU!b?MHFwtFUv;-}hc-vN~`7z?F0T=**%~qzvR*mW8xS zQ?3fn$D6vQM&XSUP$0-y#$frRbKh)U3vM6vLQr>fcDl!%>cBe40Dl)^gByauOq&wR09K85a-6d(^G>*j0P>-mxiirtwu)rGqU(Zrlv_ z+OR424*77%c-N@VquQh9N3$;nzqHB2oAcGLGHzQ1w+iqw{@% z`qFAeGK!0q-(Y*vzcd`9R=HnWB&#B;6^{jg%HVCm_yn*Q)1b$#w>02287?~#=nS9H zd^B#QummK~oFz?X$yM^exPR1o2>^axMSOF;RS+lJH^`qV0wsB6Dk%3#4aDL^=#fd9e(Q0T4myPq8sLK#{y~~2cqbYm&xdcU{Q=)YaW<4o3F7_fJ8Ueuyz8= zA6@$%qEgY6Yg3JJVjYU6LRBC+rBEzBV>LKKEc(5;T#xydJqF_VPgh=^o?pEADQ&d6 zhoj<$9%PfFTyd(xI`ln`oD%%9x^DUG#{0!~NUzCjx29@@M3|I zzE8SsXsNqIYiKczO{D*?djggdi9R)WBIkUsgaUD*W+jn?4yKmjr{^)jU&3T~Q7dDD zB3tx>4m3v8q9kUl)%@RYl7l2Fh5*J$+MIu=->F!96IfA#Z{Oox&QbL_!!-nAMWn)O zwm$5Ej_b2w|BII9f8tC3aZB@G4DP>Ex&Mky`QNuR{|>D9A9m{htM=u8T3h~anECyO zN$tOHm$Lqqar6&nem~W9o!5upeU@u>h&@V7TJ=eu>Lk}>*4idlPLbmMJS#dYKTJpZ^qll&c(t!_SeOpn`2-m4QGaoi~kQxH5 zn)oEDsZO|!njh)W{hRt&rl;ICa}3apQfzgHgcU>Nr2fwM<@orKb>30(#h(!7XXoPH z*$bmv*HA91mhcU?{sNY^1JOv;OG0OIYoZ%*VaIkcWNJpysVQIDL4z{VLwn+@z?)+< z3^qBsYI3f@yVYRi7i0BkCF%MS_L9i*FC4`gNp)S z<@75z*l-0Ip|h#jTYAuR`4*+oDuCu6ad(f)K(T|ujsmC&2LmFHN^WNI*0;9#gK z{C-UGTDfK0WAdD0^3bzX8EQ8Bde=1=8}Ow146cl9%y1l%gl;WzhbHaCAL2N$=;j49 zZv%!s!e~Fr{FtgZO|hDy{)}UxpJmc(3to z-<%R#I)J4ZE#K5oQ35-XUvnGPG%qe%G<$o;hx)1$st5?oagytnxZe6TaYxwj7gLSy z;tMkl7g+jOG&s~8Yf(udM{_~`t*+a#x%JLl(-NJ~S*sGf#mxOX+Xkwsa7!Egm_+P{ zUJkK$%L}kZt;%yz-TgVhRn#3J?v=oNn}7xPgd5mf$*a zqamOiN`)|yF`4_ZWx5JM(%@8h9+#9M2TS98<8DM|BuXVX68a+@WSc{qbA2EfrXnx1 zkXVc=TH*E!Q#l{!YlC9FM0Cd%NO3oj{0l~@6 znm%U$*``Oy*ar@vZqV2MeKECWX`~gB&2BWh?I$CL-&EHbYiK)&m8+=cacH6v$fR7v&&QiP*==c!NkVv0U!TEO2?Ly0*?BG9pO_ zsw3f4HLdcM>s<6Am*XO=PlGl@rA@Jtwt2$2$>>Sv;(O)@#%!saGPu>z%UCYUL}#mT zb_kgEcf*^{6R)W#y|uv@lGQThe-(W&BQ!h7bz=YaYga+clVFo-54sj|iyigwmG*pa zRgjm(F|j9u_-T7WGF%M<;Y`5+6Mh7d-p4q=NOJT@&vttZRm2p(%`#Dfr zj6jjHTANPpg33cHf@v*oA40*N^I&*1!wopg%z4k3iR_H*%tG&T=F~_y0`;O+3zHa2TayB^#G19~ zOe>(HDVh1qH-N*eo_Ot_tRiUNbC|u!R$&F$znhzY24QGa{A|1P3gB?vC?35tWL<4X z4>%KSdLXB+ypk&319$r{F`=D~e{k|0GZEOYmBT*8bA|1K)=F}e`9WeADHs*24ab_A zHU6cY7yKHu=Bc`QG_t@rI;GtkmuLkTf=SF#4r$x1Pu{BuNThZ|QZ>15@=#Z>q(8Wp zo8G~k-L?b!9-6oZo(gB&OMaKQHwX(mr)RO!VQ%tB)QqMV_U@>O=)9eU94AOo059k`8mL0r#yF zTYOH7wr7^?F0~DDJgxJ-pbdsWJJOm?_`blLJi>OhcAjdF0?c zzz()VqPRWU>G!)|VpZ}}d+1ZZ5wHY-vi5>3gkEBY+$psTtn6~d}BF#iOYrFhmQM;2X{N zm?fHxI?LuD%1kxt){ilQmcbtEOi+jC=z;<+;PIJdNHj{jg+thT1^sqLo7y=5o9Fzh zZr>%tXp~%2pv+a~?su4hr7`+?kXX7oaw=3qnk&Fmrjoo5&zb-IQ-9p^%N}2VXDBFf z!FZ@ZO&T3z?1vYSxImx!YvBcQXtj~=D)LIES&Hk)CzSJ*_M1iR zTWQ#GiAyOJCUqgGOxEM1ztaXc{H6J&`6LEwM#;NPAr#g|xl^WwNG>VAl?aL}2QwO^ zDo-DUy*k%^ZhVnbTRk}V4dU-;RWJsT5|sy2U~^OlCoHx%$Dp`EETXly7@|*q>`fqu ztYlzfqKw;(gtuJC%t59jS{E?o?RK*z$s;_K<~j!o@hmMFINqt1!T|Yh=Ft0m1yl}M zNXE}MHv+-E>o&=1@oLV>nV8mR$M?I`;A@Y~x;mR65)B3JPIP!grwhR6KDG}I2mRn} z*mwvBd)q27a-Kw~n*kB|kc+Rqxou(+Xd3vr`_YxvvFrU5mZP4izSkKt3$ermh1phy?(j{9lDc`4K0E1osd0}F8hTGv`_ z$H+Wo(((^*GMQEM6LT*((qh}O-)zouL4q2N8I$rnbF6x~S|si${(XwpD5*cUq` zkrArBzg01$rRb1Wsu+xw!d+zs`Kn(E_u7*c4Uwq9u{5mqgk+!fVxo=w&0&>EIZT-x zKl>U@*dRpa@!OIQlDt!Jf7a4f?-Kg$pz??=A>euXhZ3hKPp`gAVol zJ^B5JX7LM=0c4MFNBsF*DC30`Sj9b=C_bTFlc@WgXE2={)=AzlOcaaMygb}oTV+V> zf$`u#WSUIL`RDKU?$)W90$?>5pqx0+;{&+#>ZZ6I2jg%9r&YI-pu2@!hbYq?Iv)R@P=A!-~-~z*_So z@u`Cop6^WkV8&*20}~-=#cYWyHWph1DP1k!joBmRil+2*F|Vwd{CTB%X>s3hWpTqV z1RO0H-hRs4o;UJiw$|-fr*7~)Nt28b_3MrI!=0E@=h%AQd;i%;(=dWWaxE_wj);o_ z6}h_Dl}A1h&l4iIf7uZ@JaS{ZJuLZIGE5aDWx1e+vg+s5yg8+%G6|#VHmu8)(>f>b z`pIi?ZsB6KbH^9isiS`hvN7yPIn6%O`9`4Wcp_|JTdG0uNQdT5sFoVxR2~wrV~Y?( ztsU0qmUPfQIIonuEWN!Z#Vi^=4K?M{8h}BzkY!%|IOUyJrzn-pp%Fm@_of#0lMP5i zQMtxY*FuAI;h-pnle+rn!8#4nF7sYj=@JBx@j`W|WYIgU?5fr^lcS%a)rIGQc~Kjy z*2ic5Acf55U~I&Tl|5_L9e4c>$~8!6BLaEbA`rVa!`_EuLqP{@cY$k>aZ$NqOxtMs ztOoe4?Y;^A{F_lN{*HnrG2!-;795pu*Iv+LfDjhJpilG&>4_;TTp1$v(+Y|p9?MVC z%MgAmpsPw7kC#cjv{iKIK<;a$Z+nH718Myi7TaaFu?tF%C{98_L50Q z5uGRN&_oF1;8^`Ofq2uJB)*abS>%2Dqu3uWWL0EQL_CTH)f$Lvbu-AoI(7HjHU+FK z&R&Qbk#;jc>-JY`@cKCC5q0R(yh5-Q<{PMkfe1-_-)w@rE$lLWl4h9c=4}AjrVU#2 z`_$bm9rYhg%2Vlkt{~@kSt?vWo}c^k1tr`NL9~hiRs8jA!xD-IOG*}5fs;Dh;3?b? z8PqIOG?$73vzf~q-3LcmtbnPqr6E^Ix{>gdAedwN6pNB3cM|J!5HS0515+IM{%4I} zRw_(FaQSNIS;;41yGy$oXC&KZ5m5Ni)D@yw0`z4lR`E_Xs_CWSl7^s8%semHzkt)! zqx}7;2MPCCHCNl|9yz=Bw|{?l6$|&(V1^Fo`qLJU|H#jh?)g#TfC{bvDwF=2h5_3= zt%cK;FJlKPyfItd%V*7L!(~Lb%+fu0)0gr9nA1UJtAy;9~-{!61}=U>)@~S zqQD}8VR(6$G@2C(l6xj(!qjd*TRIz88frA(0{JT6LuQwa9Pl5cl5{AXT&HQ9c_&a( zP_SUt_pPQ$ovAK-+3nfAw?pw@x4zqe`fTc@^ zZ1HqN9-gG+R8P!DM;-6w-bu@+rqluF*zH)J)GIwTIXy~b8nh3k!0um2X^Jg^wc(UI z%zJCM+8#QiTlczKwgyDOnl}tx9*@Tlt3S!4cc=p`S>O`w=0GmQJD!bv_5M^u9zfsD zWR&RXt6=)_n_H2?Ds2Zed)2#Z307eqG!?n`Z(&xRvdNjWYP@-pz>bTW8QEqhdT7+y zyG=C3blyZHD|+IotsS%A+BeXRnqFB;Xbo4$VB7vmNovygC7jdL(@9}T%P61h!lZU( zN^--5K0DJqGLcZ1(J{`Y&W0PhzZTo?Jafwi;@@)njriyO3k=DtU1eF(pwI)SSTAgaR zQAJ1u`}G5Cg6~8IT6n$z1cchbCRm=299z4oT{p#4m0477JB88GmLtfU)L=4e=KGtE z=sj&_^WCRowX?DGJAEwusOp(W_1@>t;o(j^OWZrqx3GvaTgFWj;+fxLiz4_e)!IT} z(b;}xX0=s&?m8X)qZ~jCkrZ5Z!K0df7YU!b9&Qur(25@S^8*SjVQX};9k8yywuqUlwC#RMS9vTxA~i*0b*Qc=2AdG= z?~cNi!KGj}G-!;21?BUVqiI#EryK<~hN{PWfxyK!g(S#f&10^4Z8>MR>r4G%^ zb;V=A{XH4s)kfJCK*3EZ!-xkk$}BwlT=gI-&D<~Mbf`Wdv%iaGLa;Okkklcgj(<7n zigQBsGkgoJ0h3*8dg{i2A7~mptFc!?am5WrLW@t|Zr_wZkM|Tc<~(tdJdZZVBc>rj zZjrMg*A=M`<(6v;U&v*`FX{*1-#OIlLPd)YnH_SN6D48Ldfn3yIdxb6>*bn}lQY|; z^&oouTdvff>p39(enm+vIdu7=#h31Sf6x%sXcg7u0ur_<(Pqj%|HNZQG7g6P7ej^r zv=sDDhYEj~;=g1a|3UTfcb@j&@BD97AOAK~_<#N7|EF4yzd!U}O!WW%LxsP8;{OCB zGco^(`2Gh&g${LT=XJ5~U3cm`;j1u)6JCeMC1ayh&7_xl=Sfio6cLm#DkMrVUp`%z zIlz=_j;8e5beLIU^88)CdxJK&=h4W{G&bimLhxai zXey!e3V}@!R$L{pwx&DfH1hPe%U9VBC(-B>Kcp-~&uZu@v7(S7iyO3pvy95VrL~i56-Y zY|4z(BhZ{u$%S*4b}$9QxdnxM>y3#j`Vz`jbPNeDx3*6StJBJSwQDtv>X9cf@jlt>+qWuZTKZxVsE2`Y&N#kqJx?jBZG zkA!%`7QaT;l7?YKx>)Gl}tJD^CUSqmbUx9A2KHNw$V$CDLGxrIao=UZF zg#m`Nj^Fc2Q4z^%Z9L@fsGIcTpTrV}Qc?Jpt@xAKJDD&A1zIG2SDu(WlIKYxxFir@ zMA~#Y5v+5JmyMgth$J|+U!W+_$rVjqB=6#LmnokjMsC6Q|?h%cagB zy0|n#RI`H2h;NX?LShe5HiEsdqg{?lQuUC&j&I#|NRA;Iek!nehDd+#m_dKNDSt8Qw{;7dV5i@Sd(3Og zBj;~C$xmb4h=vuXq00h(rs(8H3SKX;D(l=Qb@W+cwRF4W#6FQgp)>eQB7Jd1F+{CX)h9T!gEKDr*C!d8R zo-j$y%t-geq?cK+;J8ecW?A%{0#bsj zCXGa|rnl7$c`z!mBK7!F-^~lU_d}jp7Yv%*8ZJF&iYIxC)%JOQX{odEbsPVkm)oz@WjJT*9B!z>RO0By0)>$avW%O&{3%^^anv+ zZU>ogop%tnZjoyNKM}UVby=~okAqT)3<^aIiodfOX0XllbAwmSJisEUU6;@tMjUFM zSX_213%cRF3>6e`@+ZsoH*xO_CmOn||6qH<7}0VPbJnH;(WjyZSUqRTIz7(>CT~zL z!NIOFcP+gg)r;GQc+lCmEdJOZZ!tLBogU8DAadx;0ggJ(JcI5}%2;`;9)_sCY2;(M z*IXLj*q|p@PegARZD8*b+|-lx51fh*pyOvP7xK!@jB`c*K>=zRe)w`(-}7N6>nfs8 z82J=IFYab>?uIrlz)E5;7;) zUD2F>ig|!bEGPN6Aan1_Q6bI@m$F>>z+XGRhur%}=rcXFm74QxMd>x%FSPXK#pNV? z?9rZcd)Phr8b_tr47CZrILBCEaH{L94Gpg=qrG04Yhe4mP9<`@G)IOfECxot=-dOR z3+OcuK}B^;Z<(_!*4I9EQllXN$3`AR-4F_Te()Ke;fI7oera7N9_3m5AOzwbp>+Pa z=8UDXR2WT2z4^(Taf%S8CJ)4Sz++C4(j!gUPAC5XVqXq$NMb$b0Yy@Lkx{4lYM~$B zi#5>5F%s+lTFm~PG5)U#@gEnn|4JM9cS7cmp#OiAxBnl-?7v<4e?!PH|8?oVzUqHN zG5a4j{r;VhVPgNI>;DJEthc(Z{rb@NzX=&=ow^NqCw%P26Wf4B0h%2?Fws1TqysH7 zTTmV7$RVFx<8Sclw86LV`1ySpzoT&Gg z(LBA8Mi7wYyOwCbq!Omf0~plmF2~H}ewGWv8#C-1GNFkz|Z4OgNP|n0QyC@0=-poOuBQUF0LI9CQi#l>&0i$d@MUMssY4 zC~k;_sIi;|bq@X}?7@c>0cur)6_B!31L#E0$MGkq)`aB$-d@ZPj310-y7jy5j-2Bj z#Uu$E7HAG`Zk{lv%A(XqedDPCZud>eI#uGV>@PM3xtm+%kArY$_|59_#{Y^I zZ`vi;LFqP;>meW5HTcKnK+*wNhxPM=IiImhvm0A+77+GeHh8=||if zzetoWz}LGiMIY4TBBBa@9A-BhkowUmSya<&4lxFg@C;OuucPKHSw_qt=(u@1IHia(VS9pG;F!e$c*x|K!WX2i&V-?{DNxt8NyPUh zmPp=Q+Q)5No`?wvV8U9O=czdYXX9bXJXh3b@mM%LKplW=mrhWoMZ;NzN^x&%j_#w9 z`s^~{M6y)dV6t2~ov!-@_7u+^cig7Us6yHV>K#)A&S$UM8F0g?+1mtZyymkV;bP4o z-@dVLx1f=s8T^myTY4^Rnv_@_5sUl5AW?!#y9CLRCIhgVp7ZXj$AWQr_mBId%(C`-}`Pg zr-bFWDbHt}V|&&M&(Gx9A}iW*aHo0~u4Q{o%B~<2ms2XRR|(H&5nU9XZ9`)ek2ON! zIj{Bay+t4-87A^r_~uq1e?)3q_@g|xB9Ax9s6d4}0BpP0PNsHc_VTU9wRe$C)JRgq zwZM0G4T6bEJ1$dV+bmIZk3kp6tTOPN z-mApEHlj9OFaTl!hv0yKms2(&$X|>^4+yXl>@gZv_AX`&KZX z0w~8E83|ZFo>D_-22^$G_fmXE9VJ3K8pyhqE%U>SiQO|bl?^qOQJ|300w$pT@=_cb z5fUD6PT&T^T8LrDH!fK@=&9tdLWRPYN8zazR0_RIR!ga+^5rBRtAxhqN(p{drDYnS zFv$6%^GjcJ+GomM9E)-nW4kzg_15=(Bwad_n|&`Bj0TS7^wG};`n5w zA@Id0=1q1#v;>EHrX9O2&h0amf!v%$2Pk0?;dWhXp*v!p5a@!e4r`{s8GI zi2@WZqTZ57c!|kgu>zvksQf<|{xgg_1ID;Eq|f&88$~8w`G92NU=Dkxq-2eJypIa1 z#^Ck$v4;qsVu~9e7K--J4&I7s`8IlkV1qc3VgXP2Bq+8xK>d~=pv8+VF14jCE7o&| zGqhgH&Q@ zn+d1j!MH_(Vx}m?@CkXEk_0-B9)Td7-@F*_X|c6F^TH#ZPfTPYuiajrX}75(zMB#- z_dP>>ZLT-XV$@7LGb2ubOMfJvjWI!l+s3%>fV>KJPFT0YFR;JZ9;_Dbd&Nl#J>M&s z)omzSydkd>nC(ijwE^h~AnMRLbP=-7WdlB3T29g8m{#YObZgLSf_rWdPg^f*mmHfS z3x@@#>OSRKu3a)!4=64JiAqFYoHZrfc{U0_4ub{73m63*07x!KEm zxTs$}&jC@szsFxMY?o)A5zHWHZD_cKgRXGJtX!)UeXb{#>Kvllw+Q=O}FiS zwWD98bAB4xj$Gkb4ZjaGli?3VH!dQF+0J?J>gUt_E_1}n z$cZ1pE!>skWe*O2Yx?A%=aV*$@X#GeTd&-rqqLuH&G7IS`mntNLEx*3G2sa@5PE2x zGhG0{3$LrB2~sF0^-N3rwD?kI6<}5`xn>0nkU3-i^igYyuh5kKK_13``$zjqmlvsl zPA2}~F_U<5c1tkr>m;HgGxxp%h;`4kADH&NJ>Nb*`>}hb1<&k*5llMVFG(bCZjK9o zDM8~1IDVKM-<%lVq&XPWPB$`gqb}1$62u`f{-%C?& z{Bck$mKpe(itI)~mQ?`;QFos4+#h&a_qt3EOHUGX9Uqvy_fB&R8ik#9mj=*p@i{(UVL$z|BG|PU(%0%73cr>9Pz)9_RRn0u>ME>YvzBm zXa9AU_`6a5CmihGec1oUjq?ArDDWTUA*`%yoc~nx^(VWN?XM)QKe<+H|0GF^`M;U@ z|NCbDPwjaY&OgCp|KLRPOI_Rkk1xdcFXq1_9AhfmdxA~27WQ}VP+yk`dI*u?cXp<- zv3i`R<);lZ7w0vQ5W{es9M0vd4c`peEnkNaI3@B7e)2x*|u;!b+$C4 zM~1Sfhl7h@FWpLfa#z*mW=bXVffNXKSx&0R7bKlMe0 zf}7PJ#lZ%Zev>J?pNhlqepy6*JzzVz+K7`V3^b9aoZqZl=93MS6My#$UEyZBp!z3u z4y-P^`(P^nsS)R_sJ@JVIdW!S$XL)J0TSPj-O zmUt+Q->;6^2$KgRMsLY8)vB)RW0_DsWIkVL4Tkgc8yc376;^H7Fv00Xd>zsW(^!!nK- z^Yh4QVLr+d5SImK_b-VBGy9kzNoOL+9C7g-;`q=<0YPE~--8NgE<}4yNzZy9u~R5= zpb$y!ACV29HtTlQd$v+mVe0HNC&p=pQTYsMpra&6AU3JJTl>Wj$Jr^)CXOq;V~wB? zIPA~G80p%fx_nJLo1e2>yV$gBR<_e5awNF$(iahMgV|=tZ@^{vxav_g>V)S20J4<+ zS67D9(0ri+r*WyGOcgwr?)$!wdw+RZiiE-e{w)r^@K8+OV z5u#gqy_JV`XNKNTJ{lMY#lJHjAlli9*fVGETES*gq=7mdBVIBGRIB0C55toSW=HH1 z6b6_Ei|WT+^v}1lM!!dQJ1WPH?y8J21h+G0l{=d!PITc9MDK)D!Q zq(7uG#n=SY?vKxi=(h;UteZ$9Gac}}`O?3GQS3EV&5#~Ue)j!H#OuaJD$4`A88mAB zKHw1}w!|2xAf)EpX2d%sB?c3dgn8ApB-^CaVCYX_# zLF~IA_9bJ9*q0CzK@h|idq_kQu_h7YLn4Hb#QMKgz09q9Zr%3$dA=`?9QEEhb?U8C zr%s*QcWTu9rM5v$7S%7M?H?Q0@$jtVKPQ}8^wo2X^V@R$QE}w)b?+5g)Ohiio3_kp z_QwYYCVun3hN;~bG~4{^*@CVdMQ1;p5i?_xyB)dz=WBL3vhZ$FREhVi=ZHD7;Pdx~ zZY#IuMo)G2(Q1eC58SZ#bg4IMRCLt(yL{O{a^z_F^e>pbZ$Y0+e>tzu znfrE!=iWay^6{3#ajv%>jJxFMvGnUw>c>;hlv~!M?(r@Cp3JEtlonm^NZdc^O*$>_uGX2Sf=T>FJAAKV&e$(cfe{^5ApyHb0%X8d&VcYRs zNmZ4M&RyO6=FRq%Y!_2)MV3;xP7f`&=hJL^6E7uAET1th=2~*bza8rxot=B!{OUg@ zw*T9fdqU|=AMHDr`|RqsU#xk)SiTuR= zzW*&gd@lFvYfh}6w>x)*J6opIx4FJ+*{g1?iX&V6H7VxmwcMMc`VOnmu1Uj$Z}T$L&8hZYP~_(m2Uj+&@xrt(4!%*M+)LwguS{t&u1MpB`R+Z6j&5GG-QrTUKddox za>eE8FPz_+es#nrHGj)FvBT`~FXjDuDV*tq4_fC)s`F#-s3YHB|9x$ztQWr@dMJH; z({+V6jd}OI&V833ifMoPYSujCuK8N;+di?=)+0^IKYg>ITD0M&1Kk%7Jd{zR%BL}l zv)-Tm&9yS!zG#`A&p@rirfA(wHmyQ;!_hr$oSF6@h23E83l7Cjjw&YOyP_@9sZoxa>b|V&mZ}|%R?oq z`^1q~^4GlGCdXeBeZy`H_e~yM>`1-??|o6H^xs=LHEnn~W>(qKz6tAMmi}4mV4;|V zma)Z#AHK2oz_~mHd;d49S1Y`0xO@4?rZZF9wCNs`)bxCn-N|?M{XRa>XDe05cqrXA1y zRm5{*)mK*w)c>e(y{$VdO)b%@V%eBVAJ>2RLZR_n>QuU1=iR&I=jEXSLO_v{;5<+s{3H?58P`rBhSN0r{tY;?QB1@f-h-mc4|Kk_UpoUB~QesS5m z?tc=;Pj4E#@q?S+WFJ>$)u*Gf)F@H^_MRsN?#1@}scpS#7vApj!rKcUUAfe3<_?v@r$O0Rso?A;-8RbOgl`@GVW-3v!wy3r_V zSKrz7YdhCvTz&7Ub8JSI-}X(rd~WW@@;j&8KlJ_38wZvgc`p8oE~BCuD`A zKh<)*TA;%S;*F;P*!9)$SGk zZ2pWx*DrpvbNSeg%ch)La3l8h{{Ot%q|Ln7x9r%S^~{B0)v|q*Q2b!Azgk^Be_;26 ziYN9Idu>4K2M=~M_`OB(qji>TZeIWOyF;%3@6t*CsRypOdu?WP?L4!1baJ&==fj4> zn){u(mJ}^rYGbwBefq|aFY)~Oi6yUWJJ_h;)A;YNw46V!WW$r?R=rg*BYTN^U5n#) zmIhAH2Jc*TJNNH>N-p2nqVS$7Up;Pca^!cHS{Ha{Lf-Fx&)>Y!ieFAQD%q&aheswX zjxMx%)K|{4{%tizt|&Nc(xGl+hP_{-!Q#e+wkr2`e{o__t`q&X9)CE0VvcP^H!m&z zLB}EAy|VJt^$Fjd8d5Y{s+M&-$|D%Js|MulK#3y<+|ucOJF8_4>n;N1SVqfh;u?^L$CJND0ce{;)!lfJUW zr+N6?h@`b6cxj70t%RO0k%~l}GhAF2~U;VZAi|6CN zjsHF0rB{xwZ`jp#cKyh^Uv>DU`1HQT;@&KIt5vlEefRFX-L}T=V_%K*e_VLWzF9fr zN-tJRPe@hmqA$d}{j0Ceq|^I7oAyUt?pWfTPonzPn!T`8 z!{}4rxn|!PHGf05EpOb-TcURkchx7!N&Eim`(@oK=?5IszdV{@TOW7)d|H9Ni^s*} zd;i{!ZuwkO9zMvH*sI6g{Lh^^@xPDnq)y*|zGf`mF#b$kQ+?~r3AXf(zjRu2rS7(u z2cH|XWL1&e6T3xgRh}Af_?t_ zQJvRzDl%vDa{TU5kMwum9aX1bVSBbg|NgNm-1oVRxO zbd-26%k~@9^?0;L19?v#H`Jz{W*W1=Q{&UWQ zmo6yIJU3RaYojavl>-uHhTHOy|H&z&f0qC=jGYkPgzxbYK@r2 zt2R{5$acQgu6KXS_w&XNzpK0V?$hFv-+8U=goKYvJbA9g^xmVlE^5%I?Ug<`PnKSM zHt*wMy(VYR^>pEbbN)&z_q6J>=3q1Xf*cv!e;bEsfwH^fujMXe{mEB- z;dgc8zj(6cZ0XHSro9k1*M7dolN~2MPtLa``<0DdU5Qt0YtHx&j{2wn;g8FgKelR; zdsY0ErtSXP)_3I9dzCh>-?8F@bM}XyTzKl(oN?&2@^z0d8NFi3n>TM>JN&SwvT(?+ z3zOHzXRL@HzWSr+%2TSXOD?wagZ{^kEvcAu=ZF;-JDk7T_twcD5AC`h6MgSY-h}+z)qViyqo_rE5ixlYRQ0`Kf5d(sx(P9a6A;tEAmU+G^hrO5ctJMLbhZU{U0jFXKa0Y^7tEZ2eZ|9H1mtimFy3Ba@ALdwIYwwuHZQGaG`lc_c#iB6@HKV#+v2{IH{gw(?Vh73rE;$J9mAwya}sYi0p#H8L))!Qc~MJJ^uh6Tu;#-}E5T=h1I{S#8F z#U%IZ8D(RiyGuyw$?}6LD_#y~ck8jQDg>*St9R(wDJp4Tzka%ZAt9^BvQIbsf3d9e zS&nsU?kJBI=-JSzP%A`OHY&kG%v&sY9|c`u(P=3Vbtk2$l;lHILLt)mv zs;Q11LK$6WZjUz#KWW4HDiX#+2&03^>4GUW5L5?a7QwHQoApM>BEmGE*A!+&74)WI zJ(%@o#S;d@@0^>#B9TNhpMVG?@t}^&q&JPY7||rE*Br)L2`mX*0!3auu+{$;Nw}ix z)8$m66mx@Wge=d9BW%&(@G^y}nVW{N<=J3_Ee04qb!#?%ge}hoBW%&Z@F`iZYC1Ns zRz7(aFe|pORrGHfCu_MKZPsEKwBG zJsh9bvhK}gIyS!*OI%o1iUemx6SoiBfCLwTCk$#b1%4}@Fg4wN^Wj+$h4m%FSuut8 zhyBbhB zD*FEyNob=VB$lpZ^J3aqbjjAdL{&l@eTN9@CHt4lNtmMt%6BjqzEoqaDJp(U80T_Y zQiqwwEg7OEaTpM#Jf=NbG6z5n8>AV~Wyu@{H22#soH{LR<5E#_Btu#fhaHKeNK59Z zI6+I1mfT^(G4x|)WypvWlAI`A$iqg`RuZ?FB!&%+T9qLqQ%Hu4Od*tTn^DLlMQqeo zhKx)h88RY;aG)?%HZp~9h%rS*rjQI7nL;w8C55n36v>8dk~P-N30o;rq$PvcN|7Qh z8N?id6lv*%*f7mAxh|SH*85sMOvz5KSrUj3Q--u;5Fe%tX~`h2tz@UyEE&YLl_4z| z#I=(g4D8{2Qq#})*674oCh*m z)<6$lz%m^qC6L&orkN*8kSen7QIo7`ns*k=irZr;l4&NM#tgbjQb{!VOuCdHY5rM{ z#7t_)i<#LKRJPF7#YQPZMk0>~cW9BE(kAuZ{{lr_JLchh{dU>{~#8Pd}GaAjpkOW(tkHNUrZ z^L<0uyojg0ialwVfMVcLdH# zk(Ta<(Ljo{BoI>;+pXCGL&ZiUWo1Z92gH??AuS2Slr=9uann?^oIm6afA9-7PvPP%3WLJ5|Yf!Hu*eMTaXTe4B3n$4n1*vGAzuW1}~A^;@|lm94& z<(?qbH6nl9lHHbOp@k`dVWoXi{xB_`C1iKgJTzj-FjgM2yJ;HwS%H*5x*jo`lHxfx zEmGF^2%s#qq&a9K5W%Mz*OB!%@<&wFBiZ?IMPUJCbwE-i>p*0lu1h!8trSW9j}8g* zc+5+P+$i6)=#ncdLsI{v>yj%gLDCeoVM;vsZ?h@UEZM`Al_9D7F)AxVQvahv!m_IQ z!QV|Y(E3p_Wu-_<0x`=;KF~~A{FTKh zxw0~(C4soIGGs&osphqdZd%l==K;o|Nc;%RKkI>Pm{Md!0!fjP2&70hOybUv?LHy7AIpXS~?(Z zSs9WNh}rsCj>QU!fsMx1VKGq2dr69mx*!p#;lkW>Iw^y6KxQE+lC={fejSooNQN{? zL+g+jrH1#3&6G7sL+gNCSs9WtNQdOg%8-;oIwVup{CyRcj1S5}6!WDr+YhK$4? z4R<7_mbK&$S5}6!BoJ3thGce>5(t*{;9}QIS(7xhZc3Q4QY3XjIwVt8inJsUQ`YyytpY1m}*k~aLY=N zm}d(lS5}531mYiMc_!zM8)!qXdaOL>snA69vjPc&^gx(alJit(BH93yKkN8nuFFO-8kb*k(Tsf%9>~C*%gk( zD7msSB-y`+vNB{O_IS+Sz*lG*THhsCR)!?|mmbM2D?<|hqen8!n%{{lG!3l>a%E*m z;(zo=uB-$})6jY(Q`Y=WT%l=bJ&-FaLs}AuD=R}<5(vtw=Jk>aj!6+XD@Bt1OFvAe ztQ2WUAf~K&!a+e*VoTn z`?TJ{KwHI}L+safBK2v`1eN|a2eFVj6I5CbO_1hHP-!k&kHk_@ki9cCP(&{zMOubI zjJA@?LY3yC^~!Rjd6HJ8ztEvaVwi68TM%~D9$_}6NJ|E>F3sQeRr$MLmaasKv~)tO zOY@CErFm$*d6;3PNMRdmlGr~nEfuAgm1AA@$_?BOms@q=2Y&4AJ5bHy@%yF0zvJb7 zt^A6>3G=%>iXE?o>LebI$IcI? zA(-Ezx$LM6(6{lab{kLAWH$1<;0f{%817>RWfe20pk@-jtUmz@^| z>Lk#SIfqP%&u8b!p0LF0R4_EgoJ^7CwFkeR6|ktHu+g#)Sp`}#D>Io2SpaFvZ0LtD z)Mv1v=7cP;t%ck9+;;xPBQ0YESF*?EzPUgWp)m^~!Iit#}dcz#e3$ov{Q z4H-Yc3&o|_dBm0pRa`zh52^Gbn3lgYrjxlfJ3M~o@KqNKVCUhDu9c$NdEC+}Dy)a1 zXm%cv=$rZMJk-#MRHvQC5PFf@Zu9Fci9S_4Om9dg!ov*1RM{K^xEa<1KeTCg83vD^ zC9=DPiNU%ALj&)uWU8WpH8%DWx%%;Iey82d{iCiSjPB;1PcQR9CeQ>c)XBi&;PC58 zkcmU_I-w1}ddhsD7Yo+r=0BOE7orz_?W2>q&`Ge?G(a+R>_R8_8CEuuux-39^um89 zMi0hNg7?pvVAhFf2Cv%*ZSZ|Jy=}a1^b-6{dSqG{)Kxu@g`8fno$AH-!|p01 z^rNA{CK`qi_E^Do8Xm|~PWst^`(eN3EEv@1f-K~vf?)WIKqaDX)_hDGR85OuXv5Pl zx`uuRHfZRFHrTTmHar_XIO9N_TPE1&goXwm zu>ZLY4%6qwPz)Z^=VhIU6!F0mLL0+SysQ_)tS}<-BZ{NtZ6ss3|mlE7X!)EZi?6yFKiLMtgRxvnh9~i3`e2UM{Ith#<(>8wAi#Qa&(*>D0 zD}F=+fdY)oj{R5xHpSr8{a6C*7cKQ%@?!~Lixp)qbP{y*VQu`_hXVx#x?Wru3ioAt z8SBKLp$jZ#fxghQ8@=$mdmR}5Rxx;gL~W26yg&1bfxC3-TUp=Xz?k?}zuO=3tsX^l zoBCGP2BDIuuENw68R&*8UHD}3DG!$3m} zO|*fEj}Jg5EI7#ESCw$o9|W_-C2sI&$T|`12N~-`^c|{)EiQ3`hYUjzH+aawFkG^kb+)JeBh!vvzeEz62l<_wNi-R#1#P<$SSg5^|M%6TuvSr-vGt62(xXysbX!G(We6G3;9$W2sAUF%GPC^Gp+`(RK5Zd7ktpr_LrZ%9YBA#e*i_Ur$)&gW2WP&q-jAw7*Ho@>KQyUhvi18O1LPIhBf(#mp;TL3>sX*dbX9pJDi18O1 zBB{ZXz4~^3$O7yQYop=R8OYFPHq_v#RWbhZXgG-mva0%a@T-A@sa~j}p-4ph$_iwn zu{9^tP~82{3sX^?0S!miK+;jy378#7C+cM^k7QWd8mNtgfWQ%afgCcCHyVztYS0B_ z+6G6~KvquI3y!CX!5w*FZ1F^c>p12QVeN^o*5kv>yM?Te3K^pDVAdzB4D+ij z!>(t$pOIKR8)&dIk{ZH@@%a*H;}Um#2z_WMOcd@|k(Lry1!Qi>#EF6si7s)eK!)^^ zxKbcPCq@kwqz7E$^3m|K`e0qASQHLn=V5UNyQ_Wcr+8 z*Q#P~HAw~VHmp`&XL-n=hM4Jr3}Y3~1jyB}v5KUG5Mvcd2^q#Jk`gl3iE*sh)LdeW z=XGLJbBQS-$k+n~zCZ@|;Sx^|5aNO2;Q{F+Xee%Ukl}&B!$YR!HK-UoJp@AquM@j7 zQqH2iyzGI(7K?U_m14{fA=5^16<(*0J1BbQ2&>$2Rm>1eXCJqG;v%AFT6xlb%8!% zWdWA}nYdK2sv!%|AyXUdSuS3F7>1V+@+Qzm95WIS=vf>xQUj2QL&hBtOa)Qg;#t?rjTg54BY_te=p_&Q(=og>XD>zu!dPr(o zLjTk*Hc&7$75t$Xze}MHb>X4Oz0wB9rzAM)B@Dp#A`_B&BqpTVgHGF4Ie^wsYfaIb zgLR$Mx~ZdS{9DN>4j#Zjk>sRQOm1LR2A_cJh~{^^kr2;5VhMJsy1~RIru1(Q4Pdn( z|9Gc34M61}#N|*NZIe>N251=LsGHn>K)=NJq#i>Yt<&N$?1ZGWR7UpT{0APQY95nu zd!c!1|27G!X^wUYDZLVVaIGD&{gMac5lZL=Gw=v6@*0_Xcre(+BnC?~;FOTN<1pkn zoN6Y_>xdcHJJk`J_ztG8`w&N)K8dN0RtfzQ@bOOc7+Rqm3Tr#PnNXLb`JjZ9L5T^2 z?V;^3)Xb;1smswUVXz}MAwF$j3Z~E&a-h61HY=yTv7(!RFq`b5usM|K<9)PA?xAVy#KMF6;6f7q#)EU2E940>{|1Lg9~L<7MuR(33kN$*26is| z8K>lsiCZ{uz6!eb77oQ8%89jb;LbSEr41VhHm}futAzt@HFQpH;b2ZX$mbRgIF(Qi zhiy9S6N4-?u^BflwrIkeR^!B;tQrEBpuBP5=CBq1JHT+9hXV3oEX;nQf<4suOcvdQ zpV=ZMx#z$h2`N#PqkE(zcaKkts+X9Wme{W!M5+VV6>uw2_{MBcz7ncO4@~O=LFGR2 zNr`qFJ}?W16jeE}>f>59i*v>)aZX3~tP{ARjyY98v)MVFf-1YZdVnj zyOPsc2~FyzfSzy=v>g(Rh~okcSdXzOCMkVB8&w!PtqbZt}pSG`vqLd=~eel!RV3R0#rY zbB6!HYl=v@MfI}f4T${gO9=drQAuGL`?io#=3^%k_K&WepZQ=xhNBvzmqCWSFp+62 zur##uvgp+y!@V4lAs=d#p=^LW4;S_1dC2h*8L|yTKMki*V;^`Ak+$Qvnxf8rFFV;9 zWVjkL$Us20JcM?jBU_Q83}+GJ*pOLezSGbSIS!)?xmqGar3Arxd5|bR&&%%%1sN`S z$h_fFhdd8=I_xkZV)4;m<6I(-&ms%4oyKoSMVX%;SPU|Lon(;VD!}+WKl`Q*YnI7f z6`wRUatPrw^Ld7L*kY)Rd0Im|KU=d#84Jcmna9c2uTjP_K?WH=-5F%Ou*N83M;qBHx=Ya>=8bFO;4?6hv^1H}$h#sYgoJ3rf6j56Y{ zRIFcOdz>H0yx|oN+n%AFYNE4;asx30;VG_{sD2vT z@eO@Ye~QX)mPai_a8L&KwX^`<_q(R0D9E>tL zA6UM$U!1~-&K|Nas9q0?>!m)-=QGj8$5QnMte>tKKbjcZp)!To+0XOE;`6XPh|Ydw;K=iMJ(2;-Z}AN>e&=J9 zQUB*R;jY>KhR}?TLnE=7>NoMleji;&ejnMVaRp5|iRx#gzw#i^Hrfhjed1#wBYPR% zDJA?i${3dl%ZdKS8b4~)b>aR z6Wb$6PjzN5`x(cElQWSaJ3wV5uJa)MPUaF>buyQ@10$S7@J)0^-7?_|VrtR{3&@T7 zp{#-SLH9CNp+W4zUO6Do!!AW+G|ooR47&&v=LmPHbR4)XBJI4?_Ne-#&+}2+;~IcI z&(AI(MO{#GNVtXyL1I&sViB97{Ep~?ayI%rUKwWSmzM|_WJr(`{ZIr&Wh|3xz-sJd zZj@0TAX!WM@R7a8gWC*ZKU`)|`<5hY6wKz7Fo+~^m z&rciLsq7BXC}UUP1{wRFk5Pueoyw?h!gU3Go|o6J@ls;ZE=bT28=%ODK99Y}X|SJ%{TMKjk=P6sM&zu^s*Z>s!dZLKXp(vSiFAA(kI~Nhz)$a_RE09O%l-sPKU}U z4}A2zfXoApoA9OswSkZBmp+=eMO_v-t3gK2u&4y2Jn-|&LUFu)nvaFcp*%ph#0IF1 zCpPu-`Y=Nu$P^mw=f}x{%IF@20(G*sP-9M?=cRj;-%EJ_Q_<()tqG!wpYQ;yi0o02 zkv$5xPsBGtMtl>>8Oa`noty9gGO|a(-IF~EGQtDAvr1wW)CG`O1v26faH?Q6Ucy{L zM$YW0q9pzRGLqv#>X7UU*rJF(fQ zvM=BYgZKl;h(EwqOZElGh(AF3p7;aQhmvy?WF&Wk)j|9LWMp4JI+nx-*l9_802w() zX(%@*JV0r=as6s2)h0GY@sx3GAp<};iOL1z9)NT)iB)h~AZI$r$e9k|3yD=ABlmO~ zUa~XpgSa|jwZkIsaV1B_i({y9AJp)Qm(jmyNC}eX;r%J&9-yHNhu8onrO%`Jab#K9 zZKLT!&CdD^d!+8$-;qz@E~lW`!eN1lhuYho81 z_lceHW)PV-mF5#s(`%v&y^}*|OL>6nGQxXY&=B4OO2?*A--Hwe;gw47b~OCz4ebN( z(iwSxcVCDNJh-?wwnLJP%!h}U6^gvVn@5DZcprw$5z;EO4;mjJb4}s{+_2Mq0f#Hv z2Rs`YheqxpG!|5ob_h_3%tvjHV2W@JZ$S{-vkl$&JZywSXKX4&XE<&8JpS^xXnQyl z`aF8SfC!21TX>7qIKL=fB7PUw*u=Mc@v^9KY&d?9`S2nKV6-#Xtk21$rNk$q48>Nn zrmcGG#GwhSy24hyVZF{Zd&N5wd_8*ldua)Nch8=^@M@f^m+I|>f_|Us>E*8-xy73( YAhD&U#iyk4(hU@i+A372-#pg#f8MppG5`Po literal 0 HcmV?d00001 diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/doc/OpenSM_UM_0_3.pdf b/branches/WOF2-2/ulp/opensm/user_3_0_0/doc/OpenSM_UM_0_3.pdf new file mode 100644 index 0000000000000000000000000000000000000000..99511713d56b7e92b2381f2868b675daa12d6645 GIT binary patch literal 223001 zcmb@u1z42b8ZHbgNTNT)O^NQg+Qq?D9` zz+zhI0|Et~p9h1T!{FiMJjaEH z3vy0>JYb&l^SIC3gNFz3urspp@baBs55{>;HXc6ib9(0GRzH@%h$IW+62Yit8zQM->J0}Mp?|B~w+~AxXd@$%a zKj7m#7t??g(6e%IadPpV)hQQ{BF?S{BxyvlNBsJoOSm{8yl3^y#mRFnX1F+^JZJp{ z7(16YxVRwa^vngM;&b2S;yvdZTo9n5oaG1MhMgVbJgP*e<=_MZhWpQVU7U<8ZQxEo zO~c{P0IC@XkdqsSL(b039t2nksCeo?p;EWEcL53MCsxItPRYS)E5Ml z&C3VlF*O34LU`atd{9mYAda((k(0|&G2_IcqmxpRJ}QSmWkW#!uDzNb4sZ~MgprGpjlDU* zK-I_`?hNn)eD8>#65ItqaxnrV07N|+QgL;$0V*~y3*i+WKP|n8u-_s|T`kwXyl*e~3blAfaS$3J}wBhX029HLhr6 z47UN0cz{fdK>DNH|3XKIrVj$-Jf3j#q#O7(@>_B_5YT*ZXj;11z(I^+Oo(+jqyd{D zQvA7v5n}xQrX<|i1;OChhJP>sERImz@k|a45D%~#(9rP0ARwS;fdZ}ubTLq%o8XYP zv~htu0l(WAxxgjiCP(5b!tKmmED(+Z#0NkEv9z-bpj%rUEZGoaLqkI|!>K!6O}M5{ z!5Ew%AEb*csxc3Ivma{tQTvwqBI9h1a!nEnv^MoTZ*2m7?sXOAOz{X0@LfZ1_~Q4? zKwOahr;8=7sH(or16<~Y$g>S z79Prw6qhKeC~Gjp(r&`V)W%{UFJs&i%`>hpd`$|=`fi)(AU{S$!wp5LELr$PNxSQ^ zeN!QqgU#1oRq1!PWiw7|<|SZ8@^gJjQqIem=`wrGcA3OCM%|&UosNCkO0Wkt`exFP zdvRCk@49^ZA-l`Q&#NVC7C2$@K18(JBF(xuDl}It-}YrpSddyMe7zXt-!$I5ltBH*aXDx@>{pjr5KJgEa>k?*EF-C*ktb6txTOeLkF|u|5=m z7*EyB@X?>f^m_Nj zc9MdtFcJ(%Cuah;DVKrKSW`-qo6k$Jq~Tf+fmFp!R-*4=_IDr;m-E1 zP9{JU134T>rHGi|kg&IN0j3>|oun`cCwm8R`#V5fBfiSZ#RYWE;G>3J92ol@P>8@* zf}2_z{W%x>d#<{@3lIpv0;eMSD8u|FEMe~oPz35W5UG|<&H!6P-*!Yy(dg*oudq42 z#2*m}>=S;)J0cxvD1m_V;$#2@b2@{RjO<*EY?yF35Wx*%l;L9Mh4#4852R)l8pa=rL`5uFD12~p;<{*0j)Y+C5WbbV2YymQ|Ge!L50^t1z7Q)U2 z=H`R)!v2PPR4b0k^O49WDgesspDOrmmLp{WTckho)2}a|OdZg*y6-g$F?~6cuWcCj80KHRg6z!j2+Al z0|DvD%+lP|2@!2T*t%FAaRV7JYAcEaVF>}w6aLiW3Cm+W9ydIvun}W_QwQ`E zwi=L2EL}Vhp`-zKah`WKM+&gF zu{7}ju>sNT0ylR8f*a6^(H}YQWTKRvInd9Y(G3@{_xrbQfK!=M4F964qbYx5$OBT8 zlLQ$#J6oFD*&=F=>Jibi_}tJ_A#_GVCoXdAP{#^8r6I(Wzu`kbl8A;D(O~|O@DZ68 z!UY5K{uiN7QpPdpi4Kmv80hhS>ExFeBerFKW|T9T7;&ocS9;t>_Hr@;nq@aQNZQ8U z{j6qS;J?P!FR%R_TgN1i6?IB8e^0Amc0dOpF%zKVAC)T?3-}+JI<8@IrhvsP%`D+g zXG0#?!Tsqlh#lx3J`6jy-zgq{PpSwWKw>qvf|~%1#&O31D8z|VMU%3ez-h!S?T*<0DhV$3Kyw3<69+liJDurmAly*CKb`lCw<3-_5R6Z0?O!Pu@Dq?2 z;2*XQHgKSG{H3?Q#0!*@=dX~z?8f(()NwTSH#Y$Tj;Uec>T;AyP3_%*W(iRQ&o~Mv zjO))V@>|AZz>~Cb>?nUpokwc;J3bhsf!NpoausKHINaeZIPZUx_Q;BecI+4UUxoiy z-sA!dtpWcfyN10j9Ox4NR{FVt!;3$C^4JOgG%4TTa~}dg5^iSXYU2X3cS2a!7HCH$ zjGW;>^7%_23On6ooesd0hVB&Z-xD7f5d6yac5Elue+T0}RgO-;j%|7zTBpGNmfg5O zDsG5|0DdN^b3?dJneF#p<7j=LojmO{h$FhA$o>_|z@MLF+oM;I@^>A#4lP2M$uRNXM_|9awvs(FEh65O$)eGR0F7^&by`2lN zi8FFC1t|eJ+Q<&r0|QA9h))x1kfbHBBeygLI>M`rT~EbTfRl4LIt=7qWdv{ zI{+$AWDFep0`MnP z{*z~bcn7v;r?dT8v!3Lc6WsG{3!wVH^_uFyX+I}BLX&@-GXdv4r)tY7wErA&oq+w- ziB4x%;27^X1#_tWK5Yl?9)R;WUTzRKaDv7I;R7LVND!xT+K9uf-vNU7aK0xwp7Gmj zR6)QE%W+H{FAJ=USQQG~iJYv8xZ3;Gf&S+l5OG)ko8DmN<{LxTU!|3neL)<5C%&-G6w5LFQ3()LLDe=F!W=OY15wDnJbQ>g*~IPt^( z0&qh52;hX!KLJi<22~K^Ny7h<;AF}Xz)4&5Pk>V?0RZ^lHb7kC{q~{XKKD-m#Dag= z`1eKDe^Jp1=_3hFRQgYVQ(>(NI(o{2=&1h-z=@DY04IU@Pk>XQ3;>*b;lBW!kUj!9 ziR6C*oa%E_fm^BnZR8UUM*t^n)IR~v#PRPg?Y~HHLK*=8J|XlkfTIb27#VSk{lDDw zg!B=>Nl^R~;7lYVuFn4lz;Dt=04G85Pk=L#{QI=z-zq{}UH^^)#5;6Uo0% zqy7uP3F#vVPJ-f}0B0ik_s;Ua0GyCM0yqhZe*&C|h!iiu16X8rK zBi`Ko&qz3-jX>Z&Ve~JAqX~b+GS^Yx^xqRI;?>1(J0qS7{nt=9ns5r?;o!*AM0 zGMog)KV>)*&0L6QL`R(d3&II)1j6s`>z@dx!`aE+1UQKSx;YNuWhL;40dXP8A!iGm zkw_f%Uedrd?a}iFX)c5femNC~G#K&Wm;Diq7l)3@(IM;6OgUS`RK&YPfcVj$O5Jgh z0XDP1(Hi2Rgp9_~QomGp^yd=xHug>$4n`)wCP+B*B9{LZf`|!-|9;;`AB`i706fj$ zkdu)3weJJwA3MwMR~o?3AA!$t{33z}4Ey_&2?WT0UP#>2=&~CW#joGFG1xEdRQ-HB zxftJ1l$<*FGI~sFr&FNVHN02GKX4lo^6gZj$g(@NZ#=)vR$RF|^ffbG%w*H|Z5$1L z?|#lA6pB)-iz-goOvciJ#+F6%=uPW>#!A{$Gee40TLkfluK2!T`UDHs(`Dn=zRe54 zvm%vby=gb%I0UqA6Gktu#E__N#Is8?`r0ODnSIZ2X`y8b*Xz+wx9b<%(f4BFg{}U2MD0GOIX0txt^1932 z=r>ngPEu#OCQ5eQnf!YDJ5nVNgR1v}@?cUl3C`EK0~A$n(+X{Wc9*G?!lxnx)VLMj zpjGvS%2|t;$}}f9hhnCp78EPpB8-0i+K*<{Dhy0vzNePT5j;j)wlf*DV0LlM^4dyI zK4!}FiA^+PU;3y219Os#SkYpQuuJjTlugy;wwbPIhaTnu|O9tBY`~%+1UiB(Wj!? z6-xBRFn>NwyM-QUSx=+b-NdIoombo@OYz8!r4Lji zTv|tQtb~+WrPa^fo8=pQg%z&tTgGIbDxS@`Zkcl9Jy|U5`ZJjO(6iVr*zL9tx!q6I zKK&dcdal-Og)F*2Un|DM(eVM#yhfNo!EfUNQm4z1fWa>A)fgPKfn3_58tHmHExV?% zFV_+nA(~-yOiRyW(EK?i=!;_(t|a8>Wk*|HMNVkkNP*>z8sB;BFO}KcEbdL!FYsWu zIJr?ZZ{p2BbZ>Q<*iUSGTamdNLRda`h>KtEzN~!5h7?we()4XsKe=ZQiF3Vyvf=w1 zukU#tOi)r6qlSj9tu0}z+_4VLKIm>bZlmaG-P;bAvE*-tj@{tI(r%x`Mf&2ReBQ-U zy;Q}bR{XX=UZ%q4!*+4@AWP-}X5n0XM*wSri~`cQ+=8$O}}5qV!# zWm1e>Jc3@r{tfBdOKhYs?~v5XaVC8yHrZmM(7|gwlhYGF$KGP@?r2O44`gc>COwQc z{bJ~p-C%eB?WXR93mF&ar;u3;@lt#R@Gp4dUuY471fzF>C_npLC?V<;l``g;qlW(u=jt_Z{%V{2w)AuE{uDyN6lit8Yl4=pST=CWu-L!k`hm6pXDa zh8xN98TE&RF(W}}ka{NTQzT|z%}8RfI9ngqQ}o54z)Z?MyZN0ywRsd5+!_=wR3$OI zjMa>I&Inf~(@S=7iMd)tRPhM}#Dq$>&;gsi>60^+NRBLDKU?gE0h`FK3 zt0fwqF{{e*ba{|^@%|#&qU|CfdHAd(b}szgVELDF>d{q;^npAJj(Lh2hMVFXSyva9 z=BeI28feTCG2$e(3$u`>Zf(-(7~p(K*?Kcvz;JkR0B3i zP)Jnj6`Q4=m72Xy{NPJ_REcSU_Atg0;}V*6+-vy5kp&x^+W7h)uL!SniJ2h0KM# zI^p``rP75$h1`Wpg)eo}OYfVumSMhp{L$qjMR~O)_D9cAvk$x(!QQWI z{<3W)X8iiy2Cs6j2m3zzPqy(Ws&F6US_L5oy`?w^O*G-sxxyQe+HOW+OBqcO9w9)% zKyjN7GsP*DKLr;y?wH5_FtsNIJw=88Z56C4r@FlAt84XwyyKPHxLP|mp{3nkrKz~p z%5K}S<%TA8&=m;gHkMs2_gMCr^_a|fu_wOJt81~>^o1HW1BCnqdxT^JIXs(hHQ%x- zF1!_AhdGfsp|`5GdR4rJQ(A{%j3wpU^j^-c%lEK7!EM)dw$1UWyTdybwc&qGMrsIeIosx^J`$s5qreh>BX2yCz#D<9n2n91C8E`a zHqGN0PcU>}MFe-rvc91Gw%^$W_@M5f#UQl*O@HWoYX6S0pfR)YcAH?t*2AHW`$T(+ z1oXP}eAj|r(Y3pFD7|u?asCwasZrTMUX|{vQi9wic^hTHG)Y-`xzR`$2`h$J1$PDW zD2b?ex^(5tC#Fv>J-HXXn3%636o>YN?uo5pZGE3>rrY!#e%bgud&S0R>dvQK-zDg| zxUW0YZgA*k6~q;keHi;X^Hu1BinFovu9MxDnmKZ3m07Nh&~I*YLOqXqR^O%@e6F?l zkhOt2jJoJ|{XtGkT}$eNvWK5Y?DYh15@`-S`6VqwyrGj7%!YZ$m%FIFPRIv<*`a)EoB`vd{9+n zGcI}CVX|`T)z;|Nd#I%C$k5vr`^CmuF56Gj$Tk^wr}mWElHcH<;o40qj@yh0^2O|` zAmt$IA0$*I(k4bG{!Fq+8cG&VE>59H2}#*WHBEh&CYn~1PMQ8NeK*50VT-u@H2CsR+=pT2qqefBJ$BLC6z3(sAjFBBLQ^c6}L zRu!=oWfl_`KP*8iaV=RaH7p%|q41)m3|3ZDPFJ2%L0A!5iCpPXx%SfHuclwHzu}$8 zyXFDOf%ZYU!JZ-Iq5fg5;gR@$hO8KhjYVVrP+Lv{w^}}yr8)O?#HX)lWTdG?V+qT<#JE7mnzCZl|`_Zv`V|Q-P z{U`d*gng#{ngfM{u|wO#!wZ*?b^Q^=4o!71q9^@z*?+o?J=%jF_vjqImOI&~{-;Sl+Uz1ab5q27c^=?hy)4|)+ye0~ z7ien5EnS>d;ZBIRA@+8NCuYE_M&Mn`@BQlUed>RDVQ%20_^*%hPwy~4-|$e4*&%!5 z!apE4nj=qpO>~IHBs`0fn@hQ{JrsWc^Kom4Qr~chMzl1SwAgY^niio+_Rt-lv7U-x zAJ+Mrs-6lEHY-*qHEVEF%gT$%iP}l8&3&(0v!B`fDr1>1MBEzo18+`vrSEu5%uS=F z?F?MLql~YkZ0Lb}t3>c825SwG4*AViHsbM}ec#4K(>5BuH2)iycBNdMjrZ3Kr{vde zO7s^TF5Wu`n(4bSD+DoVksXiBF6$Y6$`#WUq`#VcC*lhXD-HQZsr&tQNPJbAlwfK7Mrnd9*odMoLo>=e-|`-xjDnsD8@*`0_p}?5nVAbpK3- zZWpchh)X7sbX}D#y7!>ge(s9*E649J*2KM z-$7Q=ESUMCTkWk}K!=gs=KDd=4lhLGQgg}ut2X8SsAw>Y(#y}YnJ>0tAvJpi>A$0^ zK@0C%H2xak)nfH31vdeDp{g?!)PMv*!SV|tyZ4opd&+(A)7*fk+lu`J{%sy1M)$U) z7it>`LzWPMuj~|{fG#r~kq?5%j`&|0$3NI6R%CE8)-lqHCAvr^Cq1zqHa4MuwCyV< z!o_P;+Ej-eoRNE}qYeYZk9`PAhV{^eSfH>#hGML`kqNBKbvJV}H$5+Hx8cJ=|Dz-} z+$TLaH;vTvf2uQJWBN%9*?qXR@lK^Eph1fuK0}`WT~gZQWM11Pw?%RJCwc-lZsdyE zLD=rmkWS(KL)x6N=$JWduM19SB?dO^i<=+zr0D#$8MJViv6RgkXX{~7eKZTtxt&{D zaw+#e@y1VBl-6S6v62>>$fWaGMx+vw1%00GqD20{COt*!5iZOq`E8V<%kRs3D81%& zlnoa)+k_9wsg2*JCYg3Nwf+08Dr*E`3wbaCCbU&bq(1NAc;Y9smtUnhH^7=g!!L+_ z7!6$4V5oQzDw7aiP{i#My29@OrP1c%h8*r(zGBbL@uBoNnuSF zQK=KuGOTTy1tGVAzaz8mwDY9^T_W#t@tz+AiU+Z9cgGhw!tgm)$%zo(h>Lqn8LwPE z4LfAIOpUmYHpsY5fpS6~HZ_}$_-hULZD?!tbK&ZDW<(v3?f zP~<>hXq#oQkA$b686%R{DK{Yw`KM_UwkI4evc)*^3RI&)(hqx9sO18voo=&2 zE2cly6BE%&4bnAaU+j6a#KKAz91%Z9f@i=%^+Euo6n0Z_NlEajF4dDeu5NFNQWsf1 z2ptMOdmXdcxb5jCFGeEgr}fg8Y3rRsRDh;vQ^?zSI)ZSaE+yyIZ_Gs5A$PA9-S#eb zlV~g8wCvS}gVohOOHt#^65-|LY~3r7qrS1ok?Z1uM_PET>=V-mlDXF+M%%j782)U* z2ZXXQYztaE5nkn56}Gj^wX!>}6Zdc#bjPQ9{IAYDzkiKYw|X|P&J)7COW)`4sl&Zx zvO(C0=K>D3?d7aE<)}!S=>T=L+Q)HjZo1~ZareCHmgVK&&pul1v=c&0r+D$1JO^{c z-x8JIwiZ6t-Z_Vv0rwd z4pUc;A{t0`c@G3fJgK-7LgryVh6;jiuUKQle~WXD{Oc-84IEuepb}_bp>wy69oSck8U0@}K=I1Kf@LBbvDs zO0O4R8PGpzU7?i=&Gi@=N1_qA(zKfn5_eBv{vzwRF!iN3?Y#so!@-cYI+x%o6tx<) z9-_c()$!)`vhvTn8+RSG2IjuV*hS@J33Zvj_f;IE>AyK@FP(W`H4b}aaVO9 zusQGJ!2_!g-Qca88efTj)JZ*f@$q^hUws8ztKB2pIBOT{pL_Psqt??a}!#Ydbgd4>97`9g?Rt{spP9}=0%*q|ge^ z?FpvOZ3yO|@i^oNc~JgX4S6M`L2^j1pq$+Udg4tzEHqUmr5=Ba)T>stjwZ3PG3TLV zyrTfyk02>)XoXAYbXmFr0RdAhVT8lrrw#P${iJ@zrLb=X@a?S}!%gCW&>L6fGQL5q zhjZTbbkh|Y5QaY=OY2ckH1{JD)aODoaM77*kINc*9ZFT0$y*v`nn!QT@@Zrheb*;9 z@-z2=WjY5@urxlA7zT&ew82k%^fq_-lu2Z4$>E3ba9x2aq8hzH+aB-6y(f1+)?p7g zPmI)~Z|Ca`G0e$)!&)tr%_NQs)_(xTQrP)GXW6~9*#pf1&BE=zP%sfl;n#j##SUx% z64m6KwdV_H_^CaK_%5Y zq1wOo%SWqDLcA-XY<#vM3k5%E#-y%V_=v3<;B(bvj9pyz_>rZYSrL+ZZ*KpMJ8m$# zw83p{m64Pc(Gk2&v{z^bhdB z5hm4a&mqiY@b*gv@m)?=iJlOVOPo6NVlNlQC2pcNu9&SGVrei9F@xQmqrnLoN>i8A zaaup!Di$$wWO;k&YG{iV-NvIqmhU{z?3q`{xim<=3prP<^vOuh<7XLeU2AT z4W@HdU2S*rqM#*D6_=ZW!&{;8_aG(L;|21gRqj%z@l9n#$Vcr)Z)ERbz2Yd$y2ePH z|D>Hf(TSc)c)J!|VA5*!>wC@jVmzk%-2v^=apYox8^R*^8bSijKm4$?&G+y6nbb_vpJ%eSU00mfBN% z1Y%3iY7Q>XJ&ro4`^o+`B|9Y3jzs5$TSaWz(t82=0&ce*n{xN2132ZIsR{oksb}a9 z1FSxN9~ahAs?X1t-spa0*&=4kruF7a@=hZ|cduP4&W!XTwp12q!N|x^MJ1ei+a{$4 z6rWy77xSGE)k17i&1&wpoE3W`t*ynoFrgPvF3slyWQH%8m*`DBEeyD;>4K7D-taq= z@33}e-HBR9B6-ledwFZ*?fw4yPpjhH-^izv$Ab6<2f-jAYrS8plhVo8>?Em-6{T_T6bEm?-! zM)TLcfv>AA{oXgF5Q^bjjZE2&)3F>HMU!zI z#v2npBIFS?jKYC1>__%yy3>cHa6_Nxu=UXFo^*zC^fVKygGvtTt3fP2tAk>hk^5`? zckQW&obEVWRC<;?EcniC&>EocwmUtQX!+F98}^|kO4 z&57o^(FdR}w=Y%MMT2B{2qSj)A0zomlW_SELc`k_UU*N(2(?j4k6o(yu4DM{no3os z*n8-FXBQz6v3vGYjWP7H(Xd?eKq$N{m%or;ctnW382WB}wP^=rLD)#pxJh1-A&H@T z#i`7%C2)j7!$|GzTko!yZ^_9QRJmWTt#<`6Ex6PVU5!AyXCz`l%=mb-1h!ofnud9W zjeaC$rl=C=Q%Qq6;W`&cW zWq`zPZxU_J{VhnD3K_=%lQ!HH(>C=&Pb@Q|hme=SBF2L!NqU+o$~`OfHyioxznvZG z!I2JnzpySTn*2QCB+i;^nuI+tc~lPSqqEMNOH(+gBv+H{b*n4Gq#^Y;S>$7 zL;Sl7->5GoCt|bvsAA3ReoEP~$My=0XPoh#}tG;Y!8Y#m8<| z>X=LIpp9kE;BE+gp?$R$Lo&7nsjU^(kg7JjoUC2iV6A_DhBvZ>K=5tsKHh`k!>ey# zX?NGU^g~6uu8=;*x%F7|8U1tn$wUebeiN>b>(O2x?%pwI_=1a?6u{%jzzR)zxzbF= z`W>n2X^did$OlwO>&i|{TT4E z9{8+g8~M0#HPksapiZrRMOs;_6^noE+f#v+pSWScZ$XBUomm-pSgyQVIb9hQNsDCBDQ-P0V{as=LT_%+=Sq1O zep9P$imOi4a>*hQt8+g1Vdz4QHcTDJ{%E3X9P@f0F7%!cZ-k$16@IAgc$bh%PVzV! zl-t!e^5b-6{W{^Bb&W&ghF<^dg14{(Z`VB6P*JI{fT*yGqgDyvck<6d`7`{oOvK7_ zmp2_4w~=~uunRR@`Li#@Q_qgjCfC2{qE99SZfs@WiDLMEeOy1ecYm^e!hNz{ZntjL zuR?RdyDu?SXfkzwdBZF1?Z&=%9!9c&mys|Fkz(s|07)w? zA3H{(@8#X6%KdYjWMh@sW__s7QKmWP3_C4wmw&XHere@}`e~GwI5WDu7{;bQT#>?g zBGY+KY}ix(^+n8whUuG_wLsTzKd402^rNNUB(1F{oNah*ozPB2Qr0|S!pL;pKTl<8 zzap@@zlZb^s9g=&4+)jz#z^H#UrJaS`hx_6HKS?FM+~x32F+_p`NLk`X)pL9i!woU znK=Qr9$SO$=6f>q)VftoZqLcI9ylbR-%ffjci>%)m6?cLBlPCV2EFxsFJsx=Rh=PE zbUJB5tgD%wqtZHl-@AD#@gfvu;ICwi#Ry_e!?XP7Dg>+Me5BQ62|4Qd@N33+W-X~kSL6yN7)GZ~?N>0`SCR9s za?4doOqTEyNn1clkaitxZcCEJn8L$#XDaZu*S^=C?6!-`9j_uMoFBtkdKnh)yT~vPdpxi8D zZo^%?;lW{nzjkO89txR}3Y2&6%_DA(I^OTS59|9iW5P?t30CK^VJV#v>5qg{v!y{{S z%5GKsWu4&n)C${>7~1FZdP;EYYGd{rb=$F6izBRlT7f($zB8c=l@`y|$0an-vb_y4 zVu{pZJ}}``+{-0nb&<%nw@IQ!0k^0shPCMwS((he(;6mmPuu?_7M?|@kra(w*T#fq@(+g4wUi~^sp^?@l{_TCZ;4^#- zg=~r-XB&f9zV*f{f|Pk)q6(^sA<^;m_aw^j*mcy+t~K~@V+NQeFhPHGsohY}|DM*S z6!g59=%G3d(?tbmR1Aaa;;d*l&E?O#?`|=E-R!dB?43K~6rT8hwh~m+C6jTMGp?4^s#pvc3s`%Np0 z-UvAQdOJBEvIw9L+Qbl`^1iw0I1o5n9UXp<`z3F?K~*!;A&y!yZK_&QuUf9Tc9RSR z)ytIBNLSw2A@HJ%k(G>gVQJ&xdafjvlq@dV2g7fAUmvF*SmhM7ghi?GU`unvc0I2) zRx5+twlgc*a5kbA;cvgcJkgH#sA>_X!Pz7r2LlwBrCMCi_kD2V$@22$?3)sd6j%6_ zVmzV<^LgF8ia?T5BmP``R2d-)qD_xJVJPHVP8T006#Xn3?+@oCo5N3P@kokLi_Fn3 zw!M4z@bd?w{4VelGm}zHgEGhi8?~kV|>t(hkmNJH0r6(l0;*|s7{A~N#gaEdl8Ge&bzk^f2mGaak^WR`3p z0~W9Hg&zkU=_`(##zQ>U)QF7+)-i>BE?;?6esItf(?7E+LSi%n*~DX7%iw5Ju=aNG zLYw4+;Sf1S*yB)npK<3;s6W#-I%uYg^*8cOB1`&}vRm#N;G(diNS zDA@RM>CM&btuv&pc$G07=H>lw2Jq;v2?{l+O!y zcoY403ORXRdVV32b6_Py<#=`9>Fe#f8%y>YJ7fnJnM(_oNf)r#uxvy-&>o0=$OAvk zSJR7~csh!kZ^?4?s>#en&K$Ko+pzpATBxRUwA9d#aw*u=th50E0g<9rv_u3pbH*KR zU%#hp2;4~D<8y0CGr5>su>1u6SVS_!_2;hF#N4)S>%x3iE|31pbcI~W0x9rj%(Cpl zMUdG(d8382)lk`1v5oLjA$FX{&#V^UA9%vldr9y9b@^t^jOKV_t5ljk7w%NUNDbV&+S`FeKDzjuOpmzVGk{^!)FSmhhC@oMZ!(*72O{L?d_Eo)zC=L zI;>~^%a68WcX`$d{_1Pa&xtsO*#TEn6R=5;F6j!te1bWR^Fe*6I$u+TVU@CYJM7N zEpN(=LBC2f?@$7XHbof<9K{Pm@h`myh zRdZfDtL3HZ9;gxl!CCavfl42pYNj=Lsf1x`y-o3Lxap?XQ=a4vtb{&Zc^I-Ra5w#y zhJY9fO&M1^@?(vK{L#m=+=N$oD{MV$l{8aL2^cP6%!3$1YA|sZ&1(r|u=WLZZrvC5 zpIXu%^&8|Y;+H2VZ*q20FO4GMXzQuV7TDfqJ5b|!Av8jHz0Zi8AU@tZJChG<*>gJA zY+PK{fhIg#d0}wSCC+Q1cO=4^usq{yJO`bhR_gpj z?>}ChWqfdr$cQnl+m9u%wVCR$4wHGeTi}Cmf|}YBB_IFRX3~+xv8xkg%E1cSgZq{{ zaC?b)MRy%lOArQqH^1d-#BA>lg#e$yBxItG{Dti;)ho0~F5T_*AKs|1;s`op%yd*Q z584W3XFgk!DCiLyb>ZC}H&7AtXo5V$j1#|a0<%k@{<0z}<;CePw-w~^-j&kZ9N*A~ z@|KOdIGZPuSb4}@j2S+pBn^s2pU5=E%`dgmW+Jmz3!$B=mVpnVX-qb6g?oD%a~9vZ zGhC3BG@D@=YM?%(IH0)nLH5&~NtfZq!hQ6jH)%^nR+p%HYA@&A(W99HN4AWhi!9zQ zDbIUhR97X)iM(~4NV*NvNO>s6f~HvSJ!J3h?U0O(`d75YvTpKs_UhlH3%w7sn9Ijq z!}7o0Os6WBb@gW@YDwj#uI8wE?Ck&YZ~s#X}YY7RCY&- zm-Ul1Ecki5vJdFOBU22!x179(gWr<8ylZWeFwNOgFz^jcQ5o!qcmkmfZnF#KRwy{{ z+2v}?MtLpfKLv?!_%!Klj}!FN|AMWSDK2Yjm`u)@K(ipOy4JlGK~ViLKdh zeT?#$kCdNIlsgfbYX4PM=*1v3y-|~*d>>ovx=>?e0Y#vKB`T&gartSQH@w7uBAe9uZH?r*Q7#(M9s zl^Ng2ut#!?7i~4V6&4fFXIUxk6=7(O)@(>D*82k$1^&9^$|R?Nz1+}&_vVc|z;KMB(91BPtnAVh?8jN$mHmgd|&%^yG9ZRf~O+bv(y zp458b*17-Lv*@3%hh2oYj7bJFT+gvH=qYcY0k5{gd@y2gGmH@zf9*SaipS@jBv3;2=|+e0?T zAB{q9{qLz8%;L2h6=U>5t~n>33A_1or#B7<2s4Ot`mVc4wB@u0mfz zE2WirB3>|OO8H)nTEo>czaDM6(4BPi?(Ul{Rfe8>kzU%d)VXe>9-#5#s|3~w67{pS@Tz3 z@T0{My6&=jk)keWY6Jx)8$e6^)FQ7a7h-TnuDY@JYHwHJ&(GhLT3tqIu6OC~G><-- z#TkaEeC~B#Jy1xuRmiybq9_)e=Q#HA_1taYa00dW1YInov;yt; zWl6U!5WXV5Zc5uNm&y9z(!~qLnmWwWgF{PY7;g7){IcvA0|j06_oqHBVSDS`{7A&U z{@r27g`iNKMh^3$K5_i*#k)3QZ3~rmrsWQsKybZ#1R$DwnJ7w$WYnpADBML(0+h*v zSPB2gT_cXiw>Jm5$Ry%c{OtogCTwjz@Wg~gz8eN(}{vYUQ}hTw9K0=Qh6`$u4$YPGq` zq_6elz4DyNj;F)~;Stxxe4gdwczx=hx%b{-Vm%XCL@5ea^v?a1IbY!mQY!?jR6Cp1 z%Rxe^Rvj(mEQ9Nd=&V!O7%7U zWfe1L`#SSg8bwGn9<^}(vpf0HSM{@ch6fMtyFbdy)ahSWoNycUEjkR^a$2`t6m0!Y z#c4Yu-CLlmTTzm$mOmX|s+o8GdV{c3A=LD3+rJua$m-AsYO5gBW-Dr5b zahDoPvQ9!QNNQZQkLs$lee2{Jyk8AJ#8UU&(AB|pr^)2i%`Y4~VKOBbOBlh#(hORq zhFE)e2F3PRY+heKKje66NzaCl3RhFVc3Z#x%Y*Ht(U7QjM%r?)Z)zi3#wmuR_pHt5 zeFbl*eXuZEFA)iY2l;*MAjL)PXb61y(K6L6mydSf@B^9TJL(sXJi4(q`bym`c)YxI zRr|)at)Ca-khC$IC|Mt9NPeXVq`r{6`qsU=&i5OZcSml9ol}=)H^gNCjMR6?@G^ip znumD_W^U&Bl7@IWJyJeYn!m;vPsHilK3A0VYqf!zEdy^>(YCAoz8WRzD zt95H`z=arY6otj`BzV%QD`KNLYewIDZ>}kRF19=c&nhoLSz!+wZSFNk;hHi941C8r z3^^BtP|e9OP3)FA_-DjRcJIAf9tIVqxHv*=It3PqS8aD%np_D}iq#7|(I2|)OlWh; zfJ+Q+syw3~)9*3;{BolHg|VxWgu;B4H7P79S&S9~nNKPbvRz$RxCUGj5z0hd@_8Pe zA52AFY3XMX-0x*{nbLqdO|X!%v~R3icX8YGR@mY0*2-!D-xZ^1#ZV_=A>NgyWV>~t z8#6;&(E<}+bsM?`2wnw5nflgd8DHSb%}itrPthn@ZYlRWlm_EIe8X&^n=kF6=(|!^ z;oI?k=y366s?JOn1yKyj<6uTvxm(kC#JCWMikH1atA>cxpew&PHgHBF`jA11EL5v=~4kO9r5Bzl!p z+@eVra@#m{%+UuH#8}{&avC4=*Q$yiQw03Wuy)OfdcCN`_33ShsA7uJEE0Qmx|ha# zZfL2?GV3CBHF@9B{d|Qp2>6GY-KwT$8PZDk8no5j&5YkquwZ{1-+G6??n_X?uO(=VCvEdN$@Laqux}>lWhHbYkxntqv7_BC6)8qTDV~t zA&;2!04drn{u^SN2iLyYc~ome+xobfq{EJFn;qM>ZQHhO+qThB z#~rI<+wRztK7H;NzqxmM&dfjApV~WnJ@r`w1Rgn=%CO2gW;3w3V;(9e?oOV~Cq6&IhO?LjL*eD@07~}2T zCdL08yoyKX<~3tQ@d$62?y+Dp&Cb2Mb2SQ%)3IHgh4eEwQ7c#Yz5objn1egFXB zk=GgsHlo(bZE;XVG3xy>-~=+o-5qR4Ea>xhI%x=1Q~7Del8P%ZmrT3qL%&`#5C=9^ z6+W??XwaG7FUY3Asdg$L$(5DMt?h%f+qQB+= z=9?s6U#D(|O#@v)kYVY7OHCn){DbuEIG%6z8I+iIl$;D|Wf?Kg5fE7kLW(zwXd5&A zEqq*EK=?Ed8DD_;a-=B-xe8#Zuf9?aN>B>FC^*XR`2o7t)*x5|hi*#aZ zUHSL=O#@V*k*^Y~5EE>3QHo-8+sOhkw30Xb8G(p|xL4C-GPCf!%Ug)c^alkp_=W+G zG7!W770>)!x+4$Vl<{6~zDg7377Ah0{e*pBN)~E`YHYe>>js&S>L9nfS?QmX#fOlA zqT0(yjcEr?U}XvEUQWWyv(n~mz?G5j7WOG$0CpH}capNam{=wY$LHep+cQd{_d^U{ z%)-Xvd5rDWl_{&J5HI=VXXWp7jopbKzhKW>T<&vhAKRV_EPsTFMl)jKi0%)4*VE$> z_E%W2>}dC=MX~2t>6V)@bFz%r=*Tx;$gapf?jFdFEv#Q;wdGe!QIrBBH7lk?FHq*( z@;ZweJ!m5oA`NDWf&#)PGZa~FtJ>@oHRE_oBbiC*VVX^zx3yBZ+}V!n@SJ>HFRdi< zM}nrcl^5VA%Ja>YbSdg;v$J0!B)xxW(wQNrl?*J}<_rnYYwZIC+_G)fgxPNn%kRs~`CjQaI3vsY%k$eIayx&OY=|rx%aalCtub0kQAfHO!17A9=fa` zpCN7b_u4Z!3I@YNs$pcyY4*Oya)!YTbrMR=+sSfR7%?al6(ix`woYN{v=;9-v9u{h z1-a=<`sS+k)B1`jiIqf6B`PW(aXbuHfkdpGtsSz{LRk;W<$BF7%40vCwtjBbet`Wv zQGXce5ALkcqSvb~pIED)n*ij8#mbp`Eu0ZcfYve@q|J} z)jo@xuIs;}N5v#ZgqIDl>r122;>1~3J)yy|RfbWda7Bwau>N^SEZlI<4|luBkYjY! zSuS=Acl{L$M5%9nW@@b)AV734CK`(7$+)P+yS~;CEh}=$n7C)D1nLF@im=GRboMsm zIA>*kdM)GOVKKLmR+r%?nI1$57}QXiZb3P@Msad(XatTu z(&~-nXv$Ab9;_NlY?{ioEMg&X8MKT;1YN9U~fWhX*?`;IeIU!ro|$nq=~eJ z_yzJ0uTv691y_(ijg5G1@3WX9^<(te9Qi{D#_bB0ioub|O3 znj@)K+HBPB#Ve8;E9S)2hrPbhpWTR{jn0L9SdMyvW0x@Aq+y9(#}ui9q}J+5^RJB(0-nF)%Kgi2-5p^aO&a3Jyf z1hN!w<)i=XHROk5I87Y6Uyb63UkqDYx(@0h0E$R00o7K^s;@z8D?rzGiL8b1R-c4)4Vb5{~LV zILwAH>k%o2!zv|X1t~fzW7%E?s=+RDF~qj1_{f5V(?W%&<@W(unk7PKsLE ze&u}KrZT?6CwKC69(~o&A0NvZsvcP$J#Gy9D9yL^5?1M(dDzvB8!^n_X?`zOLXk28 z?h)~~M)CWm5=zYFO1RB&@$sUHYZyF=3@<4SB91Q5x+>l_{TCBtr zX_&$6pB>vE?b4|nV`NFk5(HQ{Ncq@e+*he+;&X3flon_!!2Ib-2c80nrn zDF=|)S)w)7GUQ*`*YY&7a)3kr8x-g#a%xy+`#_e|-9u-n6hW;I3>0VFZ%gsySh3b^k z_e<-DRb_m+l;n!#^F^HvqUWV{`wR~|x=j!U5muZx=i}8~N}Hi{^(rQ4cb2mrW`5sM zE+B6NQb;jSzlxv@dA~&s4V+d}98E?2eqaH)?fe-~t`~G^96dtWae8lE2}HB}h8uat zi|gTwE@uhvLAiy}f?iqc)G-X)xWLYChWP$0gs}h!)QPIb^~E37oged4Y4M@)CnCsM zAM4|2xa5G0;S*n&OJL@iFgTvDDi*{?PntS-)jk2Bp_aMoHj4&E>FI1ezVt)Q*^mBQ zP(VDE}8&EvSM&3F#|LoZ!Vh|at2aw|A$yu|}` z)Y|;i`+hU9O1qr0hOScUig>&)Wbx$Mj)p=l#J>sEs|2u z+4s%KLuJD6jqIWUtTUEkipIjO+kk)HbrQ<$piuM%4OR#dmZWrBd@V;h+InsJb^K!X z{4rOh(=>DX%LFEQ6L~2egSvodfr%nyUYeUan}ifunVQt)gs;}JC8wj~!`y;KBeQxH z#P|t%6gem7R*uq)F{z1z@Fz*mesCNf)ctr!_wVPCL^D%f;+oZ2Zp`f4BM>GQ0+dknM%pFM-xPfE{;N-Dsb#mv=_K_-;#iUR_D-O!Y;Jg{07VHq3(2zxpGA)SD>a5G6CYe{KSV)vJ?#%^L zl-0HMsBV}Cb5T5H2_RO7tDm7R%*oVL$~mSr1rIfbE1RKZBwRnZwsQzi`?KH$<^xe~ zMuwjA&F;>JQW}4bP@Jr?GEGzyr({9_GjOtHCuFFAAvf_i80nrWwb31#@!0Sx*;tz1 zk-uR_dW}#SnKk(`k^My$Su?9kt}4al%Y?bWj>AM9Tf_RXAY#}+Uw$ZK7@{lQEwzv; z_;e-=E;swbJW5c9h1_!abpv1hBbHeWKLWZRdGQi309CyBvp5jxoo+o? zA18fU-!gG%aY9T?!8U@OY-vTMBm=X6jaQAsdk1hUOkW`yqX!5 zq(KGSd%gMiQ!t2t@4;Fv6$L+=SL5(^$w|4jPZMn@5^_Pz?~rpQ2Z=sxY<3TeL%468 zKd(x5T1$$hvvRmy-0tkJfVv60Z11+4TK#KK!bcewC>@J#pUlh9Z}})17+n@uIL^Y? z2d>O?jGEe{^n9-N_GM&Z)K{@cO6LP_i$kY-)lu0}LSR9+9a+(h6zph)!m-Gk>FWZ+ zQ9Yhhus<$xjI!eyMy2di!Jr^!&ir7w?ioJnJ|uFo8CzjE>;VQeu4*}3#8NBiZ0b{9 zG4vxXpwaq9?^9=s(|$kcQ$d3|?xU7hX2v|?VF{ba-I;a;tRJhyd|x0TF}eRs#U!cob~k=Pz5#?tqErVUGSSX2tIKlmNoxG)Y0sF#1*Ou>=e`Sirc#sn3r zR?eD&Ec`k)QPEd$IhOJM-pkeD|&3 zOf2OVmV-59!K4H?@4*-TXa>WNPe!A?L};rrg@XbUcnX77RZ)6xcqkL-#WC*d`(Z-8B(Ua^&%W!)wLRY$kbJYLHwaRy#q+I(57acNPex6&J>sKv~{keg5M zOh4+v4kjG<>$7TuDdit*+r1WS@<*iapDQR~aBMKWSNq(A=BYoQN>=)HFvm zNGOmcC|LmGE3WkSa&bFKvr*FNr`V^V)M~8PU)rEhwk&-*5oy9~p7ZIbu(J?!aBcKl zK&6fgS-Hcp-asu_^(ow$DyvSdX^YNO3XtHzENM^8jd`9$p}_ksdf|PS|6RI4JH0r`&CtlC&k|{5>!M6w|sN zToq012mcH(sjPOM(B#X#hm(ByoqII=7JB@d(3!UH+&Pn;cIVuT)up59Y8CbbNs#K? zP>NEWt^H^5(n_FhcN)-dC*th!u5&-N>fw#&AA#4>SjWpE)<`ER45VFpc%JU@ja+Z~ zs6EnItSnS9)!U!?(i1h3eT0~;meqCUy7y4k#7e+AP8JslFGXp~zmwweL_Z3PgycZ= z=>CMcuT_Y?Y^n{zT{%^Fod4c+BHxz%$U9!+y*#%<%k08kn$3N@Fv9;-PeWO1Rwk5Iu@9 zqqqGGvYum_M10C3IV%?(c;Ru@+L-viohK~!y&t_W^I`uKQ4^xh(9q@bs-%-k(TN;MPwhL`}OjlJT;wNKXH{PSrol5^=`|hm`<8!gU-yN*%zI+ zEtGndw3O-WTY@bQbrXe!qu?-B^9d!@XLAQ`F(gX{BZYhQ^QL%}{ID_m@}NE?rOZ=B z)K(?|eq$|VzKpoUqNwf8?RsMrZ$L?>Tk;bb;q`qw#pB&X(k&t)27*iO1BU+wdEd|a z@oW`<4Bu`sfNt0x8Bs_-VGy7#J4g$LSmmhk(t6b-&_=PK1&SdLC)af?Dr!tIQRd8! zTyDpF27O%Hg?egnoV&D_oc44U8=FO(xy(3=?5;v0?g8M}-J5}Ew}=Z#4cVKg-W4A; z7aj`bxVRYfX>D-LgoGG8Oc-vv;GhL7s0sxOF7gGab$r@Dfgg;(q^}GCfC#UxdIYg3 zMJ#|VJZh?uOyrq#r0vNyWG81A*zVhh^kH@>O%}|Yscaly4udfHzN|mp-ejumqjmv9 z(B$V8V)@7pR;emoxmilg!tZ5VBvQTQzPvgmVY=BxX}O)yp(emtK7h$g&nNW%6i zaMa8Nyb%2JHeRk@wC!S_op&_aruw%3!4`q1IjZX-RBooeE?_q{Cy714;>$}r!T>KN zXK0E0W2$LFP!lf@z5Jatq|U|!(%NABkEp@P3If>1;9!<2 z*eb22y1Nj@*EX4Q-B8Anfx?p~ro1_P35gALZREOx?+s(V9?JI3NYe6l4L z?(=C=EE_7ak+G0P38lFe5fLyy!Hv@0XuQN%dnE1z!v_b2tjtujpv$BLlZr~zbuFUy zxEN;ghmXl(HJx&BFBOD!+b%aX_dzNx|Z6>0({+;srRZ4 z9@nqYIJIMQcgJrD=gRIj{_3#V0+5(cBFKvDxyjj`5YRUMCJfz{JR9{0D3FXVo85~Q zxF*CaT9^s!Xk6s?rR@7RnFSGSb1ux9C7;HnU~A%1P95CgOIG()vtdxR&H+IMoq)`E+`z_xwdCi|x4?4C%Vq zKUKhm%=9+cDjOghOK?ZLltYDRGsfPS?;8SKoh-)qurPz#Jf%4XM(T)3S&kb#t&syl z2*6aXJu%%EiJ*G2B%xMKa+O4VvG2>2D&aywV?bc3O3L)fmGVuhm7*QCpa(}BbMzCV zbLB)kA&&Cp%C+nHwsuJ8K#72q6$IHtO0lxTo`AbjzFnIhG!nJO@~$90?C_Grp2I|_ zmqDgb*I_NejT0gM=e4M>akIty_p}@4Ecao{$1`PUaXOh!EE;<_)-zJG-UZ zcLX!@^(g^=6IpW0C`>K1>5vy;Ci_d_XS6r0IRCr=CDc|(C90IN_gQUo`&RimiL!1O zq^4jQGGV0wf}+hy^-gUCO7W~y9EI>+prGpxbC!y7ALd&8ZBiyGqj2>BCyHD9reI1k zGQ;QkeA>zidnLerES);}-HJze%Ihwmo=H{8C@_n!F<2%Kj zsaays*JNrlnB2ugmEnjYh(HwwFr1m(~edk9wJvQ zXbx8Zr7{fH)viW%EuQjEeX;WS6RHsAuMh~2=@f-dlaLo^l3;*vs+L5j!ov?w5Znsy zWcXk04V}6k55Q>J3z%Ij-_i$zS50qS@nCW>fq_f67oA(7d!QM$<=V6I}Z6?LlX0Q*_`IR<92FPMX+Agx>k?<^^6VXf#XXW?sHJC6Ro zwI7qWY6Hjtn27wKA`m6;`YPg{ny$8Ek2uw5>7*=Jk{z|%qttw$oJ8*PzkKO+zv{44 zWs_l3y4p6Zw=a@S1|$3?!W!9EWHlMb4* z&Sl5N=rykAHOY6{K>c9Fhx;9(Lja~H6_AyaLScZ}P!m+mPTI^?Pb%ly2eNX14dALk zpeuBg(a7~=eG^$?>uOd0uLBPx##!>sM}L`XYgy_MFOCG zJvuMW<`X_%Bj)Y<_Ief$K|n)u(~dwLeT0DR(aayS{xpv9)HNX3BweDEb6k(iSCzek zi-Bk@px1=AvVm07P~*(B+EHE3URPS~-)_^m4qP~ST3=hktlB5In=JI78xVEY?DnS~ zRx4MS8#Ys~pR=Z8zaYn$1U8DAi;Wsrt=BOSq$w|?gLfWd=iT`LUs>VYI@{Yp%1on5 z-OC0UHp6s|gsJj34D*{`rg|MTBy6mD=pCG2ueju_G+S(Awv&8&!-APOE(9A-G^ zw4)18?XRw+e-;ikD>HA(OJbBNpR1QAj*IKvitNj3Z0}{k>S43EeDc(thi~IPY1V1r zsN(J-#Sp6JpXVc?FrO)>kf;*8Yw^34@>4RwNT~Fj+C>y z@=5C07Sbds0rVaPcI_J$P97#GD8*-i%Z)R3b9)_I&|_dg-$c>OJ`aCZ10gJ|1!>r^ z7#Hf=K&;ogH(fANQ`W-=o z<^+>t!;+dicQAir`>V8+uGPZgocfDr!&MK9(Zx_m&Zj<`^7_H86m!NKbnANMF4(6V zD(L2US=uOd(<>Mp?VnbcG?QE!oKW3C6ND>hqK`ASS(o(5bh6C#~MCY^|`c1>RuS>Hu z8oyR|FHG?nUN(xhEjiW;TUcoyrbW4Ho5V6fT#$gJvvkdUQ#{xd2&d86F4` zBsOPs(s=;rF}uQyi!+N=pskZljH5(&{Fn_EECaF)fg1pjKtq_!OsZsS+ap z=Uq`hf9{a6yoKkB{4i-|LaBhTlt^-5C)YbvqH+Y`1Vq`i3`V}@`(V;8w8)!Ir3!?i z;sUxi0~O6z|9tpR;VKCUL8xP~M)TDIoG^X)HP$-~?$?|i zw;hf~;B($iRRfEQHIea}m03<3ywSXFH=Gi19$uk>g<32Ea7kc!I781E<$^<@Gf>6P zUpt!$AVCEILGm>KC-W3NoG=_<7#^sG07Y>C1X!`t0j*+$H>!^O5@~Bcu6Be}s(?T$ zO=Xxj=H}=2_#xsi(K}>Vp7Fb!j%~TIb2Uu6yT&f)mBG+&zbEE)k@%}N6YAhoZJHL2 z)3#=aZ)!2!exbox08h{%!(?IB?;{EGBj($B#*!Yn9u(Qwk0l-Q>+q3HN^**=v0=ME zm(89U;UybMXr&F=inR@)kt`|U(*WS{s{urqTcc3gkTv7I4zQi|wceFP8jJ1!#6V%e z@!rUBpgsaSr8d>LK4iA@1-Y|{O3l)1t5iGHq#pr-qUSCv-Xh_t<8P*bGEkI#;H%^!gbF?&BfZV)pz1<>>`oWGrlj%P7 z#=xQga#LOuXBe^HAR>VvlrfI;MxpsG@b32Uz82)ENECDf-W=ryE^-HN*B$fL>trg5 z$Z=P!*&IQI((673MU!1A**mb-3rcn`v!PDjlML~m#X~(Y+)goEleT5uhKD)#8 z6WUyVl`o81r-ZmuIejhS=;(O=>NOS!ZY~=dw1+H?rcWm*s0IQCs*HKXo{-7AMjqvs z?z$S<35HVt2vW}%(3es(++Rg$L&O_?Y`du(N_-k40WPga1FE8+xT$tw@1KM9eoZ8L z=QcCjem6#?}9mY3U4tw5~$x?ePYTCH{5mp`LrEvUWFnE5lX zU$%CP>X_gKS_iD~I!kqYHOiaW?WundTu-gXqm`hv{eHIpfuvzTLD(%11zdXK&JKTC zlGMY;JSi%8HrCKZe605wBU5vB$#~SPEmTD*2pSKM6ax{veJK2#Pjh&i#)_I+wxU(y zQtFr!P!IjXW4>X5R?J`6E@K80@gnPyh>1G=Rm{wwH{mwFe%vM^_Cvp8kKO&|C(Wv$ zZtP^+29+TEm>&eWnhiPMCifR|`NdFi)6}wQJW)9dv~)gLJ|J?YA%;%S;!Xh*-l-rZ zFlV)v^yE=KMZ`W|YcruQRSOBP5KbWHvrkEqS;Kym2Uq=ues zXKw^eW=L-$GtYvO)CiF-6Q)&_rE0*y`nLQEvp79hq*7)IQvfClx(H>Dg3#5V0QPMA z^}U;e0dyJM`Hswv#qYL*hkx4l`XD>KbEJG$GDEXurp`4wTZC!is7X>J1hg4s2_jq1 zuG!afz#n)NOtuheY`SM4OuVO)6n6WQrSdIC62lE+r6V zbQVP&7Q7I2lx7=&K#>sy_cMs1^t)AWVVRvt=cpn(QBJ*sMxZjjj@xcGH@R2)=TA%UB2bi8V%Uk{n{agTH+X=uszP6 zC|O!|A)@IpyW$n+DY_$MERb|6M=uxSu8*Nh9rr73jt(SdAU`jQ8K;NB!72b#OTiOC z>&dHkp1dHHgw$ zlO7*WAboACLfvm1YRvZWINT)5el{~#7bYa{4nGL5!f_#C?dePW86N#DpE*6(SCqv4 zF}-r5m1I)e)}W{z*t>d(EDf~BUd%otXPIE3Z#QsP1?V_@CNVI^xF2vMNQ5f@)5tHr z4rXoFPfigCUQir#f_f-rDJl#O2HMG4s<}4IcLkeA3-nqhn+9GMHDpOA>)C8MRxS<+ zIWcw_z>JDIJ_;Sznv34DSb|u}pRC$^vKn`k zszXP%W+9=HSq8m+1(Jhy_uvUSr67-6SrUfACP_aB5&`4A6lQtvbOw33LYd*0Dl z#;}cmaPrhwsTNxcnw-tVbJj4x!U?<2F)3}HWYN>xbVA(qzI|t7{JqOezHdLHWgiNi zhJx&@)V;c~3FOro(Y^FEqzWb1uz4fMU2>eC^I_bZT$20Z8Oi$QY>VGiuH|9~#F6Vn z1+ay6M?qRmliRToZ61eJ6Cn5zSg~(;hg71QdOan(>~<`iDJ|FRVz-&s3I%DDx>9I# zVV#5)+3gmLVWHu>H}Dk?d|=RE*O#Di0|iWWj~j(7#6k9OWQtD7Vr=g7^4ri-uo!iY z_B{N2Nb$WsOM;IrTU3(KnzJCR7EGg_49KgYT!co)Zja(D6kG_As=u@hC7RwrfX;L{ zl26>yHXAI#H%WH<(`68+FAUY+e6u}fQUTz!fK;3;@7?U;v#;2_6v7ArE5nIZNxXAf z0==c-*G66%>O{V+6)!l2Tg|-VqJy!{{X?XMsX}Y>1ycU@OkbEmJL>W+`&vI zeL=z&56I9MAu36okmiB|7Ie!@_$pQ0d0(nzO1|6(Z8q)5E5|qW?UTH&!^6v$wK;U; zy`*51;ON92O9hV*MqhNpqx6qK0(B_o+-M{D%wzY2p5#=qW<+ zVDLn-frIJ$$j0$n2$Q?oQ8_E>Cu{FWMb0o;xlSe3xHEqH-@U!J~wM0r_sD ze8oS9p&%{*Ao&-p!+A+0Y?Fyd8)A&>^C#I7KtC~Jlmy3S9UU=jpv00~dO*6nex)QEI~;|4~%izfJRU;?5djIaC>cmz?a9AUbXR98?;d94H~qeiOMkF~xW5 zXw?T`s&^8t=&0-Fl;g*C650-TP*!=ukb~G@f;*3VkHfhA^8S@vI3cvc*Zw92Y|DT5 z<`83*g;kJ3r3?mVgy2YIZ{GzD8&fvu)>fIC)$qJyv8V#U0}TGMIJw4~b(C}8>8!gu z)pK0fZ#;i7xw%eUjVG+1(-ydxf2OSseo$tw*+t41_%xZM!wTa^o93;gqtY9u;EU{a zh+GB8{ry+&n$q(Oo6!%wfTbBSBBg1^CLukeK5B%Adi!_fYBxdV-Rkul!>T@odb-iY zz?E70NMm82HVf68VF$b+)(ZvT*>A0~p$GlDF0@6G+SoVnE7h5 zf-tb*p3o(YqfANcA%taTpV)iiZ1)>8T*@1Z>+;K8&U;lask77sR4seaC>0r09^S$8 zXQiJRhT1ZXP7)Su#OU(Z=VoHYyqA)bW`Y&6uE%B`!1zT3FY|*>*PgR?bkx>z;gcHX z$e{@c%FgMS4GjE|K0CD*+BAdMw45-g!n-R{v$D}bS(f>0m8d&3a}@KAqD>33fCh_` zmL%qI6k(v*3L>wClJ-O{7$Uqn#};;a^p0)g9M-uA!f>>htso*&TsR55ZhH#*p0fT9;f&zLbdZ zNrIW4q(vvoP_Hk?09iqM&EY779_ii4`DE~}u80zN2qQ%1Ap4Hu=9|28UzfeBXm-Mi z^faJ9Td9dSXdKw&b7<`&3mO*vs~){&mA_XFOoQ7=in!wGz7-xC&Ui&Y*Jqd%zMuYR z^o>(A2a2=}r&74=RFU`tPdpc*jPTN0va?};!2Sz1il&p24=Pg94_YW$%BPO-`4}|k zX(pZF9bI2qoeMf1`)tM8dk_w|uD3=Qg+KD$vYGDCWA80nTYmAkjsDDbCld_sy!^He zSCo~rSU4==|#Xo z+k0Uq9gvf5D399IfND}(xfDS@v5A6V*#^VZ6lX6Rym7R8N8u3jTkAQUT|Q6L;A+pjP_Xb@4{8!QVDQ#K?G$r8O~zh*#$7+UiS68Y?x5e$L>8{ZT#= z1R}WX$x>r@b{>_KiRp~tA&ruZq}OAQK(UK+6|~6kFdVkmV$e}X*V-%CFyKzHt!)DZ_^obHGUof;oC;YWwyEduQ-=a8~ z!gIY+gZnuwCGd~zw2>Mun1F1yY5j>TS)GQsBt%l=NRG_hdGckV>Y7_OX4xa>g&7hP z9SfYYv;vROQTEu+T|o;p$j>s2%K2oA$Z80Tr|Z(zFDwPzIC2TP0Ci429FA$lt~NJ1!WPD_-@@!+JkKB zHN2I>gDDDKz$9&eo=NBDD|_>0Fv32vmAx?Ug%K*Nup2uLfXdR2t(ZKRsO{M;jd!?4 zky4*fU@&RdOBj#pXNRAA7DmFwnZ(X7#rFk=)d?ooQ+*II8QhMM_!z0<`$}T&O>TS@ zAP)k7c_cY(M17#$J?4h|kF2-YkyoH0hP&XO7$(A*VsyKwUN|y;kP!vXaOWKq`R~um z*}0(#eOyd;VRy&)RBbb|zMTphO`URsmQD+gMWSS0S2#Eu*luC-Is7iq%5jbq$Ux!F zMMa$1+8d~zzgJ0mRG=3^Dx`i>P>ft^^Vp~Y=UE$3q3Wyi-Idh1z{6clN&T>4`sl(^ z3Fl`!#Zi#U{7+tlytIJMb$Ldv^404H!8<~(I_^z2KA`GZ@JayzkJ>bEZ-ev%U~vSV zFX2fTCLQk1vNc0ZdF#58Me>PGRZz@^s~# zbZZ@x-H>87d|eLVZJ?y`fe3R0K8LoKY*5B~GoD*pjmr=ns^C{0w=_jKybu(X;QA># zodu^#hIP2ssTS#}tnwAz8kjr1f9*B1X$w*si|BQ>niVn(gq~s26&S2S`3@OWwY)S& zeO~)6$V(z}j82ES4&y7oKhgd?mnZ2dze3CEqL_1;WS2@spSHJ0n63!dz#EAD`tdXbS3tGyd;73#Zb%|u=*O!r^9U&1 zdP6hLCv$4e*LpCNYkj)gfP#^6>0wG0Qf6jYgX{cw>F1;{Q)7gnBX4>eQ&$8B=btu9 z@A_Th>KWnrwBeilaKN{)p%yCEg78RzpJ`s;t6!o0yYetmL3)%dL@bIFCDhYJDVt%U z9O2u=B28VVe(NHhmg06iu8-1TBjZf#?Ixr%?b0C z5a+Zcg?AXzY&4vjWzV~9!L0G^fY?3h)PUXn>{bZk$OQ4Ye)OIr7&*rr{%UwF^}%+6jYAQj4Cj%Cr)1 zPiD63-_nGsr55VxG-Z&ojPXf#hQUO4gb0GhrU8wS0Eozj6_v)d?&j*Pg6HWg3pYhq zy@FLpUc1BnzT(IDwEG~Vb~1>_ZU&lf`&O|*tP>uBGY-R*ZPCY^d|>(-bm5#=cUbN{wI9}uNLMZn|@ z+&w|4dbX+;u4!w*jXmG%D8BhuB}aory&QVrA_BBw9)khk!a5_$%ahh`pH4GKB#@Gb zC<4(V6#@c4`dH2tnX0z;l3D!(3@i~~_OkZt+%Ihr9D5T=C?~UPayWQAPwoU;y$LpV zi!Yrk2jKO}j3Rwk?X1C`C&VHH-vP`#!BWuOTDu?-;0Xe!L?NM3(_Qk%82aEMy^gUh zNN2v3h%$3t8I%u@O*vu}^WoCPUaz@MY0KF>{%Yi=k?mqqvbVIeiB` zhI8N2iRv(ZNHn(+4T?c7=o3X^>qsTjY=8T_Pd^kunIa-vNneK+oT(qk8*jzy&;RoP zAczh;9PkmTAYLE7kChNx3KBV_xSzgh(YIM-gdPz22ci0nys0NS;NAv=wVF0Tek83g z#~e1wfmms=k04@?*u((;q0350wLx+NzH=ZXCafa`9<00{0~Pm_ItGe$u0s`X?=Z^p zeT`8MlyJBlCv&zNTN`Bg@Ld}8r$%);W4iDetZ2+2xBK@emz2<)sSFhOQW>7d=aYMY z9flL*f1?BW@JIe1em&U_EhQfG7g;^~UnUMV=6@MM<&7L{oa_yZ96n5SzipZSlCk6c z%i}6wZ)3}EYf^20zVX!K!IH2TXd`rp3JLgf`}Ocpq=533E~lCjx(>y5_gtd&12 zIRU!R)~+6$vk^=jnd9Ju9Tr_5kWLx6 zVRk!6iGecKciny=gMlQ|`Z>PcSf)a+wSL{km1tDcC}~3-N3eNzjHpe?0GdnjID--g zpwU7$e%DijOV-dIVc)1bV1b%!Ycp)*3&=lzPvu$_9& zt(w%j>?3n8=8JH=z5szCSn-1nQ+fc6Q(?DLo|br4%z?99w0ynX<|=Je- z8c{iysSnLt{OIijrR5LR09;hR=~4Ez?R{YEExH+-&h}6bgVFpYw!{EI-<6>GAIFR z?4Z4UxPnl4!+3Wm6N?Wy?&iGB`xq z@*n|2w}9T$-CNng(J$N39MQ=y6MK>7AeIx0w~gDENDlFn%kA)BU3<4| zY4a^PCd~!E*hnpMD>{{I zg>PMTlPF{lM8?1k(C#YZ7>~%VddQ}6^ad>Y?A(AOnoBN>^Aj)FR^@5fy`&IY)w7Ay zb}Ro#I088&slg(2r^jUGQJ8nNSh;ULahVc}3=w-ui{QXjM#n5!D(~}li%KXl0VHY1 z48ysm%24x@&^oZf4=$U}gE{4i@Q!5Mr?sp|jrKWPAM;Hw0XDUczxe>#cS5a?>W0!N zJAcN3eAEt$KZ!K+LTe9heu(Czd!l=Tv6Ft{m?Lomhv%b-AyUb7UOV4@k6mR28IIC= z7qqYD^^Eiwf3RZGZoa_%_VkH60DHE0K)310EnZu2vpvpb_7gr)2*2)iWQIgNwaV-) z0B5SsRq0cJB$YPIc9S_|TxKQewp}Yxdr@Oc=5@_yiFcF-$YHFWtP|bWtk6|I9!j!q z9RP1}dVsQpOBJw-&me5nOHx>Cwg={%4#}t<40CqUUn8`r1-r(F=h}a|OhxuA2&zG1 zzO@GWsF1C{sk8Pul(C+l4*YZuVfw;C(Ub4QbGn-Gp74&Jq~)DGikk;O_AOpZ;?z&2 zikdJ^e00_22iL#@+~CPio$D8Gh#Z1>#m{F+#DxgvEdyWx^$|{*>KEoL{a0NJJf8r% zzG@r%-%H^C&=>!!D*U+wGX6^k{ogh4Uk>U27e(;5;Q6=N`FE24?P;d_U28w;=C1<# zx0Raice$neU1aJ0R+`iOZiDW3BY&3)y5G(G?Y95hK>v~2f3^0vg8pykI{n|x(Eo0R z{&zDU*5<$d^>;IWOSKt(uMNZRW*C02&EMYWzueCs^6$Tu)eOIz`CAgr@Vl9h+WD)| z|1SA|NBRGy{qTP>|7o0bAN!V>-7Wv$3TDW zuKyFtNJIA#CLI&gKZ%ry?XRu-3;svwU!CFKQt6qQ+5QQYk?A+}gZ^jguRi^6sf_eY z%>RV?adiCZNz5PgKU4qLi1qL8`+E!1voib>>c?UK7xjbwXX^hNl>SdD8x!+C+OM<> zzo{SeKU4q5FcbR29QfCv`d6%M%nYpmAXX;UzkAaM{m<0@mCXMqm64H^?w?RUT-$$* z`akG@rvAIM^ea|I7FO1O6zhl7@Gt5I{m;~Ymze&hve5pMSQ-ERh4VrGGxgu4roX5k zIrtw@KPt&zv3}71O#P3!iH(K%A8p}}68RVPgZ@YAUv>1~W(hVHx_^@UnLZ?!e^Ec^ zf2RJ&+{DI8`%kEhY=8Hr5Bi^}|1meQvHqhv$H?-#H~pgjnfjk|6DvLaKj_1Z%)fin zFZ!RU|0y>yGBYy#lZ?p7_`5g#qW_utpK=o;0~_lL0}>COS6yzmrRRY|XDb{0sV@qW+qk|GU`4#7g(~o|WY{Yx)KK&r$y< zHZjq&G5nqHm67>3YhwIB|8vwoicP$rbwP4pjo^*7=$1N%R$=>z@GpY;!86FnpA z-}z6+!1kLp{eu4IsDBun=$ZcBv$FhVO~0W3IqDzACZ-Sa_3!L3^KaI~@PYp4sDBun zK2ZNo#li4V%>QD;3?Jx!iu&=ne_vgFc+OwXU_QPLe1;F6;#b%Y_&p^Ppf3?=Je~|`2U%G|6MGj{SW$`jfw5A(C-bZnx4xd@Lv0>WBIey3JvAY z`LyDa8iO|YhXDy-7$7PHMB#zj?@@1CKgOy+fCTOG^n64-FOSB)GNy3j!Rd6w;p=f> zfw*9Q+@buk5ixo9%Jzx1fjAN^Kow0HAR*k9O-?$zr~Ib~(B53P-=)#UVl)ycoj3L> z=DGA}GdCeK^@K|ln4Q&3_(`|j_{4T|z=EOke7{&W^EbB;)As&i+7@LoH;~P4lvQsR zJr4NTo^Dq|PH6laf!-$cz+RVjlT^4b6Sc%qIB7ao10Fcdqu?QNr$R?v<_CiJS%~^H`;(7%bwlnp)J@NtI^Mdj7G`0wNni=z%I^-r z%seF5$rVnSHmf9o8;<`x3;UuiEXYA-g~EJ(rS^OZ&6%MJxEM1g9Z z?VMt0S8pw_EPK-w1J2gfp~|(`UacpQ!q#$}eM&mdBjm_ejBP41W!*&KOjMIVylt}m$8L0c2{i%$nv%& zm#6wE%hVws=Y)u21HHsiRLGVz_{Pi9%Of2k8mA*GqJIo1{h+$gdnuEfp*NSYF+U^C z#e1I)gMrZmDmf4cL?>7nZ9v!l8hS{QyOH`udJmg8G!FlcGQ>>sZLlDx_8UM-nn57D zG?oW_I$nav`4~Inl_+sUwCp5i2nK)5^3Jzk$63T|^de(XR&r9n z>EO+8vfm82RRf#^moS8{PM3(Y1Nj^~h+|@w0*Npuj(#VKCafLxB46SVxmTJIKFJDw*j^fk|B)cEZL?V`a3fPdzhm{@u{9YRcWLLVnHgkv<8Ot>QMTjAV$m=;I(FWNU#F z<795(HljU;(zI$w%kiy--gR4zDKXhGN=Oz_eMNthVUFrtE&W$5DojwV1_k~>y(<#$ zUAT|w(mY_+)o$x*DCzPR7*|f3Li?{j)M}^sHo(~oA}vg00Lfu`v79yxV52;!vg+t} z-1YJG3g=TmyeGcdxjNh9Kd=aupNw@&yP%e}?X5@@)gNCY%B6ey)3CkV(I8`GP^*Y= zN?1y~Cm!r!-jry`saG%`w6LmRe07~X#Y79c{gNqPO<$OpEVn*RVr>}M{}d(O0e&kR zb1|I5vg3**oW4)|qFr@$NP4|P=^rctd#`(Nfl7zuo`n+LRVwbYVl>8}@^RrKXgmr1 zHMr%^IxTykx1N{oo2OzXM64a5yOO=m#BU%o{S*TksxjoGd%MBIS=*zwL3R}5N_!&r zmck_48Obril8i-U`f?+&uYhaYOb;x@xICHi%xdw$U;8-Y3M$@^O`j26n`&*Af(eD{+JiFA)Bch2QwjSb{SHjV%M$A91 z{J?SXnLvciw#9*+-$La!jjRtVYfWeOCh7;T4UTekxro9bLzMAOH;=bIeaT6iW zL2E-*h_iA3?4aFjL6rDX(fC?m1c6GL{wNW~JSDs*m~`~@ox&~V9&s$nQpZz!te${d zp}*0l@I|Ev{1S_sYjp1zCG%y0W4QhaVgw_yCQ2_}6>f>>bzM^v4dqGb%sHBLXWI;H z4~A67t6ppFtIXJJycYw{n|rWEPmn806GvO+)4lIN{f^GWgOp)3f|EA&0Qow)EPJbN zP#MRI2iJoS0OxY`#D8u0F#StnujKx5aQBDW;m<@5OuzMCU}*odA9Ek74?txBh~Pz$#wac7+Z)`1}clYXpoj zuhYwV9+oT?7j-Qh7ieKzp#?$?c--4toE?J2kWNq1gZye&@Fz;6M-89cy3%(V|IK2W zc+iw7H!?hn#w>yxMHCpRSNTeB8;H9E204#8OePXhGSk}%A7*R5>X6`!Hwz63GiG$F z)V{5T4O|X6riX^YAQ+D+ac?%hINQU-1 z75YpB0u2#4LNG?fBArf07ctKmWWS1o5!x@4{l;g`F<74a?!^`L1^dR_2fYX~6vEEq z4nFfnK3(68r*A)J9eE`S6z^KVppPc!)WQF_SsPal`k)0ElJ$Dn_2OPrger>8(!BJC z31eh_WXSWG7?8S5%G9mIxey~dw6Y+peD@+H`aDJIHneXndbE=jJ@Ij}_Isq0k2{{L5!QGUH!geko-BrHS}U9{t-Jf7_@2O#vv)M8i(Q@-fIv zM4*iBkN-9;9_p<`d7;{#*bbt^9S$wL9OAl(EX--`akN0eto)sy7zDW zieHz)$o#=%{^wE{XvA$Co%BCMOit#uHZ-;-G_rQaHj2_Ta{7jrAEE0nFYuRU%13kI zqoemBY-0HfHPycDuktF||Kkq+YGnW1!T*Z@`FqI~tq9YH{OUK8qZMKPXrcaQ%Ky_r z^jClQ$KwAZh%z!TvHX=Nny9*BvnqnhO8`WN)pT27lN-2R|Hm;-vGtAAbTj zCJD9!p99g#bItn(t<0KR+>W;XXTH9(vZ}K(4(GOIYn={eiSjk?ga`LLpojdJ*%GFC zZ?oC67I$ZEqB87I%#vIy)@tun3ujgn+>-2oB%%=hQbD5^KZ((@s z%~fd6wfS%CEgH{X4Luh|UuPfpifXvQlVTujH$6V7oVJ>+{&eNF_FlZ?tZKfBKE0() z=X(Xw^(pCI5aA}nDbc)LIrl4L(U`MHu;7(eN_-G6icV*Pd?8CPt`FlHPE z%`;zuZ|-sST^Tf{cG6?Tpkm}5dSIg2#ui%{pF0cV-X4138`}gpz{^zzX28-I3tL;m z+khC)0yq4*qh3~|dwv)!W56qwI8|GXgt%KQUp49x4aNdJmG6n3Xu(IJT8%pEqt+F9FO$v zdD2DNHN@%@E?VIcgsO;EqcMLeeN494tl#OqHqjt|bk;|z&hQLkfS5pBG3P0y4T5<% z+3L#u$!?=fXOC1y%%jr->k?GQ?1c#2u)#SJXkM1Mv~}?ab<&ov1Pv%J{S#d!J+=u_ za5VK4Kn-3`UR(JozAFT}lgN1x9<+G-)=cC~KWaplD=)-ft?8_7*p52f6D0do@f|7=HKJUmtW6OzcZkcfnF5KK=TIM} z64ieb;j^~@AH(nGFh|UdHHTv1z))_QX2*A;FYKA zB@PIU$pjb`AS=CO%hNt9PWjJ`s8Q!O2qE+y1aBn1NqO$7xt?w)B>UnMEfv_lW-@{n zDDS9_g$@8ZR*VBz&%*NB*TPkG^Be{AX=F^+eroO(n#9(h~zkpkc~7)j+|N>^TjchkIEWOvlA)0*sX?C{*!Itnqq-VCbuz zp1;@FLM>4hpqxh?Q%uT9D0^qdHID@y9V$vcun_N{6tsT$Xn3u8If}?2FzwOdK^xMg z0Kp(9FzFZGWo*8Rnx&(T%8orYlFtH5k+-urvJll72^(6hFi-iuT17n! zuA!uMizVTX!b0GI*qpE&&%4;L5& z#wtMM0$ z6bnjGSW~*~B+0O&6hKElAu7o7gFHd= z^%^%#=@b*vZTr=t#DzsET9?Lh4*-k})gDlVy(-59-<5;kv)MN_b+k(q4WZtepg$i> zsX{n;B1NKjm`QFND$Di! zk%<_AgBTk33~%ePn1BeHu+G$WsEiT9=8GLVjs-4WYRUYt^R2SFrOv>!I!JBvbkbJq zZr86>R5Nz6?A}W6TaA9HnKMOt z?-Aq2^)Ym8;-rtONw$w1 z)Ny(epta1)!x5wqH^tm~lw~2R#6iqUY-oRuNiQeT9*)ai?Uv=pl=vqHJi~qW7kO|s zO)JciSE3})64kHi=+I}GyLEbuDKYx=2zxv}4oYMn_$iWx-VZR{3~H*anIJ3Bh3aMs zl*sz$W{-)!JASbstb>MoGKaxc;6CnV~Q+bny z0nvPI))jxU)FWRAd-m%yZ=!5!z-pxqK!|wFBJJzbs+gpWI~%~AVFgTy<`ck zkrQ}Zkqz}-ha22Yn0|7_v=u|~Qs{16BBH7AfiynUq-c;!L=8XsM8j0`Duz1&Jd_py zTvkzPQf>hjAlchRD_idY&{r_#W?GD&eE!;zc;o8KDZzPIi@>$lwE_IoLbFvHuq_>l zF;)HMfN243j<#rEUuO$q@SyO9w{TSnwce!X_}$&$T+;B~8*~#{$0Wz7!hq8o^s(9Z zVCsVNfY+#1x?_rUV3)Y9XS4AlUWW)v{Nho2Ba+?evTlDEIrvA$^u))itt@C4a?Nu( z<5qBcRjhP9RVDAJ=;OEe6zdI(lrDzRW8gn&oCv$HLlDk!#oR-!dqaE0fkse2V|B9mroBavjKWJonQJJV*@uUaablN0Yf?BCF$S^M zPZ*_`RkAlSfgCDHckqni)7wnrW2v~;*^dad!e`QSFicC82fLa3xC@ign^<%igIkM* zxABq-^>p`dlSCOs&kBe2lu4a21-N=C)CF>V$p%iO3dh``30wBuG}N(>LzhBe_{wkL zM*~VNx^=uz0Bzb5lUHHup<0~2vzO4^y}GgEo8$RO94`}Cs(e8e`cf?%?BFQG-Qt_- zm8OfNpuYY(`hm6uFWn;%gAg5C%G>bfQBY`o>_)-3i}f_v$j|N-xLU<0ss}qD_oD?S z3UXEm)0tV~omnJG;kq&!l#P6vX1`8_AE+3m%V)gB`yWSsBhc57g3aKae|oe08b!jJ zjK01|xjqBQNU#lGazy;4%B8b53QRsU+Y)CPY3y2CkeIG}8506p)d zi+qk)O@~Khgx-zHu_ZJML@M$ank797HGm^HIm%DGvQE)MJ+V|#C}!5$P&Dbb3FKT^ zf(^|;qIaM-*Z%_eQP-|Sh(Vi4Okmbu10q~CiE!-rM*n)n>Wu$;Sf@M^?>Vez?&%NE zOwf5~jVp(s0`{(*aX+l{y7Er(R=)*=KnpR@J~|i4+({TP;kHf>VJoV`xW(nro#Nss`7ullKh=);GdNw zJJVk&B&`&NW%}sgJDw@`4zL+6-R_eF;$lbqo`TtO;3edjaR~skCl(#LrNU;119E zyy!bjd)cp!2&ruTK#m#22oYe)n-^YaeyP2+qoQRrRmlv$W4b9Rs;>cqCm~o9I3>Un zS`~U&EIc-gr!I9idP!4YdqoL61#N_Vgbe)Ub>$ksJ!Bw&BxDDwrB@H>h36PRDg6Gs z;*JUWAVa_s5e0JwL@cc-;#KVqGKVngvaWcO5@-p%X3P5M_93uC0=PKrxL_v&rr_ir zwv)>I#Lzs$Pe&tN(=Ke;ZFAKTri6OHA7uuW%W#ZxlTWn$X_`oMnHG zR>MzCgrB9&=NdB`?P$&@@KJvinGv~}R*G6%rb)?$KiKh7kT+ZuBo4;=f39|AxGrjq!uK`f#HU@xzBw z`_K8SUmxV3&ii}RzaxJBK>g6@eTW}EQ2&ash53)f9*loSuKEiq8v{PW2MzX@Bw-)4 z+3#c*{~u6c|I?DV>JW7SMp4l5@x zrgeeEhK!GuD+tdM!F`W>**ZldlW?&p69JiAJJ?@{8ob?Fn-DQ?T&KAz8BvDzxsgX# zHsX+o)WAbM=gD%I%Q#?CDK64%f1dbY$IKB#?X7$}a;v!%k4Lv0a|E=7NaV7kn>2&m z6F*ICGDOtzy?R47MvrvEZq|i|Z=Bcoo+e~4q)*OoPIs4aE?7SdKBe?`EmRB+CLPp1 zJscCLbagLeQ$#n&qZJz7R`9$dl#dHg7NZ75hietOC#D?L3{A61NUAqQP?dfhF$%@> z;QQVFD1}-cOKY&jtEFledq^5$lp$PlZ@^fkXUgKTrSsY}ISm|^QV-x+@y0^RMlc3c zxaAFrAeS9c9QA7%RpPt$y6pj1M7$P8rZ5MoynLLB#T#Bg;Ag<*Zt9+TYt44xvnr

jtcLU)E zdpO{%=O>gvV$$J}#R9f(oQPLRK5)>XI`_8+_(v*A3D@{y!;`)lya4H1-X6}uR{zkM z#F3-@Zb)azyc&z)gpJ&-ho(6;Ijo=LszzLxO-izb-Ty>WWakY#?|C7CpyqsxI#iDS zu(eWx(5yc|>LiNlw2{tWr^ir&Xr&#Z!|LZ*ambg9^#;gC*Aw!YiFlI5(*!4Ifo1!v z%g!p|Z8&?(iy>CCv-Ehx)a^?TN6C8-$Bzv`7tLgs8j0%xVBpv%>IybmCQ!yZsCo37 zaz4KNl^{j~8EPH|o@DuWmBTUd!<~XJKr-|^#hjDE2hEUNpY){Cir+wNXykdHlUzhs z=<`q7R7q@px@pcibmn>)nz!vbT zjS}oCb?>32kyzlv{@2cdWhpX0^uSMZ`D-Nz#>y8_6hu@e2NMnCo>lpCGIKAr@*Q@7 zfxZ|497E#L$C=!VG9W~$`-7d%QH1%5Qb*|4KktMX$TV3!@u1|NXiybBQzUGjYQSN^ z6Vi^T%y9Zq&t~uytTz_7n2j&OSE8G+o^xbU`2p*)!{8JFvAqlT3qVRijWH5g^vR%_ zq-YQVwCIQ==E?vABFr7}1IskkzuBTPDg|L7ILgatluUZXAf=?~*+`d@K}y(DWn%VzJjbm!FOyv_Sc?Ji?8f zbt{VN_i!e%Ms^nxrf)LM`#KSGyk-VI9eX}`W50In4^=tI4 z@NrvIsuZ^iRaas$<+1!#b)WrIuVmcd(&cUiw%|#eFOn9iZ_~z;GJiajNt(52FYifV z5oXVSzZTGR%SN%fAdHsUm9#}83H?FY5N$PLx-IYXy#`+fnQMIGz%>tn4s5LbD;PeC zzFAu9u+|!p+%rIraON>=hvCo>qgSqR3H8CtfT;A(xVeq7HTMl#&8`NO9=V}Wq?nef z^T1tEm)?TZeG=0SvGjs8O}F^(oO*GYEu?32Yb8iY?s4N%l2t{-o!K#-RQWl)=K_Hf z9U4A?3wpROXaYM=H$v2h=$5*ljy!+&ima}XiwgK(D^L%&aDE2 zKj&J%2G^d_FKhTC0u^K^K{ zYIs`KK5-$*7dlULq9$@-@8w7+WCn$Oyc7R+Ygt9!R-a)LV-CtEwuwZqt!Ouyaxo6t zBoQfB@fph_T#p_iz&nPjaUqCUC~p%9>RheYyrB`?EA|E?jnN)_c<-z#97;n1Uam@}uBVDiiEFI48qp217Y{RB-i#HsZW?yC8CJRgP z8fZYIpQ5Y*_n5h3m|QS2`F<8vgOS+)l%Z_`VG{^^LjbqIBHH@=vjpi-k10UFu90K{ zI4f$^mJF#AByF(sM)JW|E#g2Fi#GE%Ft826D8-M4u}>R!7ZEQ>!uK9n#zBcDF%FC> z2*|Pb@up`9HUvZiHr|LiCOKc0@aa%kEF?>xBkEca(a1sIT3U+vZX3)`RaTeNqx+S) zI4g3ywqXZa)1gOE_e>w-nV~bJH@?Vi8xBhY8l?Lsm2Q&$%7DGuING;@9Do?$8S4*9;p+O)5?6r*oVZX|pYy!5`8>#g?Fo)i)L6R4>j@p{@qu@Ql0K}~BYGM>jy2zfUxK=C z6r(Sb2j6X;$5@H(HI$I_{LEJ{?GSMKx%3W83|Trvc$knmVXb8h(uz>TAEYeCd(G&m z*tr)^fH?s1a2Z?ey~El?^ut4%3kYf z7d{=Ok3MF?o;@E`ubZ`nUk8u@1g_Y?mHe2}h++@`^HD-FVO(TWlf2>sP!v;;HpD5z zaX3=wBbhYqQ0H-AaXbAtI^YFCNGX08RCrO5xI5~JjW9^CMh?7JhCE%F>j}F#XoT~m zh^R0!zaK=iuvlt59=vr8TEP7HDg{d`d^)c=DFS7L=fmF&jd#X)Ccbtmm{hNqZ7kOG3eud!E%hAG8SSD_R))=T zr;HlSc-&{jA?31B3L?p}efs0$R}$QDt6Bh|`;cBwz=?-B{I zS2&MMfzg?_6CO_aWndwW=o-)>>NLi}G{2GO8}Xn&tPnDn`N5EeuIBDSpJT?>HDIrq z$j|0V%G)Z3DaKd>{lJ{Xab82XN#pK zx2^W`LlzB8F88vexD6yu5S=x^h=4cO;0&rom|*Y7RU8KbF-OTWmTd@^p^dz@KhWSZ+HfGi!ST+sp;);$_EFl7{K zzkd~Wm*;YL+A~JNf}7rS-cym)6kYswo{*BncD#BRxC!gp%%D+G8H_5~DRd41{5bjT z=T^6T$CRxh3nr&o>x!dIxjd?+rL{8DfM1JRAr<9&hNR7@fgp0d&ThK8k3C^0(LJHQ z$S1ft2yJyV0QTF+z*pM$d*IZaknj4=u98Xj5pE@0bhZ*Iv0-ugE~BjHO(CMUg~@;v zX{?=FfQTa0Ws|GI4frOJv2UU+y(h-)I<<4nRSS@)QFjHqc79=K%UOUWAQoz}sEtNi zC`4KPOGntj(U{>Gm7kCzzIa#BLnSJf2Gg?nuw{Kozm`3~doCPvcQRZKpg8_Gs;S`t*1tV5z^c^e_UwaOK!WIHZNwLh^NK%Xf`hU#d>Kknxvk8# z-7L=WolYx+rCv{;*yLr)tUrR2DzwAgH>>Y6=v@(@$99&cur$wo9B}LN!HI_YeqFsS zvgFkZ4-MD;#*XBX~A@5T5VbiJ+al%8W;vw^;Yd*MthoW%*?&1EGWF z-G+N^V}XNGH*}xZ1gKkjmWNeq*^ek@Z*P>Yd${l~!AGUmB@aNzF4mXp*bUa|o5k<0seU8TyFjI#775450kxJA}s z7VNJQR7zeNK_v`#ACQv-?KJFmH||A67t$Xl1I}TV4fcj9q9Bp?`J9#Bv_t#K87;u| zP7%=+nvWw|tdz_%B(dHFrhIb#%IM~F@L{if=xb&{8DVkw)oT`&4;HCk5b=Pi)MXSl zK7~;h+ePjVaYL`l;iHjDq_Wb_LmsW`K86HM7xuLm!qO3jha&j;{cLKUl^C zggl(X0kmfr-3zvo&1*`D~bX2fs8 z;r|Yc`YY-``ONS`tw{ysNxN8mnJN+IGEDsBDgA@qv3Vu*2=$2OOHZG|e;+XRsLVrUl1v;>VD)I4tI zF)kO^ba&B}cn3sMT*sD3sO!V;_P4KFw3I4$HOR)JAzi)m=bOi*C_x-5q=keZT;2Dbo0?ifQri@{hl0xQC4iTbcvUkM^1SBbV8 z0{eHjR_3IM>acem^80%A@Cj~aDPQJf;W@`^C8z0VBD7k6Zny}Tnx`63%$t`mP9yFW zDP4D=D?l1cfpM*zqE7f4N=7l%#Fx+IXXtKfAQ#24P^41#stQ4x{kRBndabtDP2rfe zLvjPPPu;h7C{L`KC|9qi*E_G=i~OPe=8I6;_9=jQWQ~^EdGb6YjYo{pk{mzNNIdtX%&X>%5WBex;;THA&#Pom=|W+qVcd z;pu>RPKkVdWh=@orulV@p$yNckr%pi0AS$`>f5r-(*dQ36?WQm&FGHwW_#FY*P-+j z*_!5y*`0K{5Y1jcWl7#3N7xd&I~}vSZ9ilFTPOp& z4O$}NG%D)M7l83yXIGlaYo&YQ2$7PgFju!t;o7a}m@Vc|n&^3W5(ggmb6Xpw@Tys8 zXnx=oC}?+xQhHx+07vfOmi&Iz#^Rr4Z%ZzjCv0H4&LfOHl zrxt&{;>$u~-@vuFS6d#Bz%hjGvE^E9m%8Hf?QJMK zsU$;`66=m@@`}L=*ExJcHD5kUBE^q_s(?aykoN}$)Pq&XKwd!rh#)Om=WGf8POg1< zi07sAyvG8XnR1O4HX$PdG~&suOsgp}`rT~lAr*eE;H3Ig>>v>ox1@>C97_8JDNNv@ zCjxmgn0#60Hdr4ps8DRiU7>)6JdbSm`W^%b9Q@ldp82eT-bDnB>(BZz5W*o5u6*8$ zCy`7R>kj=TZoc4&px*So{*zVpYcMXs-a*_w*CX<`r5muWo2Dp#knizPjcMT$B!okt zp#uK*kk0)oZX^I3hxAIU7ZQ1N=8IU zNEV5fTexn{FZMY6p%|g@=@{m0S&TIRg*fUHx-WZiZ6t1g2L&RCR+?406 zz+G9{N+wuLKJx$s;^m?eQLkhTjcdv`Ll+zJ%lE z5~0ef&?)A;ehp-ha4-FNyqbk!&uqqox5%tHpR(NG{bYp9y>6^kJ{;@yLPH;d@_Vn^^lF^9zqNan zdAu5BgBpxfErpMss=H*%7o1Vm<*KIhhUq>OQ;vAcR=3J z)T~?2GQ?!8ASNL;5yC~61+h zkfh)Hmt2s$-%%i>PeeTFpDe&qqm!Y?XlDBxlix9rQl19~K^jxhIX9TG4M;@aAz;P5 zVZiXelhbvsXgIr{5=YMguMEeY&e}CJD{lwK!NEx!kv~Kc6Yc`c#J_MTNG>eNq%T!q zsWqAiIN^g{hzaw;Kt*NbqQVWR_#qOUJ+(yOP1docDf?Lse8#V(tIqMozg*N#DKD3L zau6xesPbs$B-EnG90LiQs^-I%?=zEw$xV;TCxdw!AV|fQ(M!qs(icukN2(1I1AkaY zSNA?&ImTC>lVVRoMqhvK?@j>XKgu8#yX`Yy{G+fH`P-6Q%19WXrMQ`gJ>c**ZB0TN zS`V=B;mQ@Oe+sU*CFvP*+`iBC6tV}fu-c`2!b}NNI59L2d9xSy&(1)8+<~*2O)>#T zOQTcRHWP7KfV?BwDrX~m7F(R`+al4`?m=b3W-}W>YGgLIS0_$yXXlwrOb-jKkT6f_ zu;OWyrBc{)C1IREn!(;v`B6)O);Ov$XQeS+cAriqDYI&qS0Ttjrxj6x5^2U8QZ4RT zBrNK%8k|J>O_fDO0sIqCC5XA zjk~si`hMgwvUT6{RrR|>^b6Po*XsC=4FN7dfizvYWo4McPGoc-OY8(aDm2#1bzxmL zvZ5T4eY4?l1mZ+4<5EXoK1pTBM;)*&d?g#cF|A(S$}pZbII67tMB*HaDb^3U<5PBi zfJCm#*%BS=(9h>B&nRC~DHU_W0QK&(c0W|}l#-re?-fyw_>y&-H)_b>ObvR({Rui; zKq?TAjilJ}c%QG?p)BbWEh?^o-2BbyHC?QtO~A7{gy%)An2x;JTkUK>uwley{^Lwh z<=05c6@?zA)Z^k#a_FoG%~<@4x~ZRT1E^w+7f3pj0kaRv%vR#E?_+}rS}9m zNTpVLk(}wG>Yy+^1-<=iTB|WJeM!?V33+k4d2xx#g{`2ZRhXNKT!NF*aZ_uABL z5Pf_X>(v+ZV$_i6`}QZtzDf{E_B)8o@+gfU$OHv%B3&(iHoeJKg^}lnxTZ_G$Rnm= z{Cd~*_{F$@`U-a{4nOzo>sy)UdKKrkC9|YQNvm+w0PzenCTG&~z%z9b37VFdQ-2s7 z%B?BCFD+Tb8?c*hA<@1tFF+I6AcBEB(g>Kj#b@vNz{_~L1*@I_8|M;CMxJgQJoSzP zHUFPH53U?xjm#Lw2oSD3ZDjZQ1)`HqB_KnzAl;KqFi+REfCSDv?e-a2+lE(sVp+X8 z$nQ$0TUf9=$7QloR7ob5Y%bF>L>&@HiFOA_e+UGUb}F9F6Xti@dh|nn(qELMc(fO zQh!}c^Km-O|E4%&`As16e;Q%?hvMwF5B|4`ynhk?{J&7-{Z8BSA4MJ$+sDw>y=$n0ke!gcrRp-kkx0e z#uz*6qP)eY{Ia`g(<*NaMarHPnD5PVF%jn~1cNJ_N!w?qvJsOnV!B=FbfE^04Dx0+ z`8rbG%+8j@?a|#wK2-qx$~VcF|N1*el65i`>xRx zEcxV5;wD>UFnN*cpsm#7FSHpTDY5DYDCbQ!nC<+wDF|i#s)1Lfg~01=Duzui{J1noxht$G6k6o4(u`t}w3w4;di-*xLhD z?on#fK;O0hLQRkjYtS_z;()oC97f(?g&wx4jUFHy7pCDOxTvmRZXWR6lYst(V5mJ% z`O9ku%KGT{Pd7|m1whF^_}pnSY{++z=p;gQw`mC_?N=YdRHcjhIOP!&*VAT6A+_)+ zPmcJrC3n~rQ0oZJ$UX~3$PvLT0_bny4xlY@u&|!esYokEwN){%sUTj=w^z^Om4P+k z8zVS|BaDhm@WklLNJMn%SRphgU`Uz{C;)zz+~OlhS#KcML6bFG?z%=|SoE9Cy{Xj9 zhR*hIwSpco*AN!FTwHk^jdbw2fSOo^nyXzK65WnKA}eZ-TDmMli6*4wP^Zh6N9P`y zOH-OWMsZsJMvB9D<8S(LaLZfod#;{`g?H7?kd5-R2cuiL4D-&T+#xoNv#Z4(Ar#|0 zF&Z@qU02SU;q8c$s0#HNxZYvw{P#De_VAv0S8K#E0Ly5UV7pSLveCb4^XtEyR z^E%V*fK&S#0kFhGWDGObL5UNu0`HEvsO!mfNEGSqr`oF*jNs8DHS7Gx!bA1U*dye}7wtE=u**9IVDh=} zj?)U)AdN{ArDrl-PJtEgjoc8S7KOq!2kX}tPRZcB^W70Z)up_MZoOHER&)zrSGV5p zQr!KK-(Wx2=I?7es7Br=U-B5V>+T7;2B1?jIeX?qj1b3n*{t&!f9u*brrl{P4m_d#Mc#3(Mhu_a_%W^Wc>@lpdRQ@RwnZ*gsxp`(UBx;9_Q{W zzJtv{XF)o-qmUh>EGRz`Qk0O^AOL$s?g?^5qSHg9Gy?asX%MW2NH?GE$LVraABf9d zEH)!KskI!5^jJb9ip z_SY^B8&MtJ(XA&K8lb{9xbNHb^TLeCru?_@S@%k`_ihz-s-!BW?yDVjHqlp~1wL;X zcVPKuQoTF@XUDPkqxvDsP#bf$z>pnB3fWGM z`;lRvf32TJT;>?V7T~01R||HTi`BA*q`xhCaukQh*wIib%8MpZB3zx$jCbA-_mr=t z!E5U3zQ?=$4MXo!IQbKjT#;O#l=$WOYofw3v{n{b zy#7upy#Rc#32DS0zEh7N`I&iW8h~1^JO38BvZroMGDxExu>CXtW6V1ccZm=#h>fpA zt^4D_;>hj|$4_6w-FIH0Et75(2|9sc#4$CkdpD4#$#M|PPYcVN(Qd*@VG)z@DO)s? zg5!@M!)d>F8|>J!qZ{?CIa91T7p*n!#^KM$@#Sl9+=FDcp`XM(RbpGLE}W$;Igy$a zAAhoo#0^y?=qp+$yKGtr;1)nw-v`50P84UDDk8qw$KUP5Z=LRcIm%rkVS3_SS1pAD z0c7NSJxZ@aBVp_rtF+*5HYhKizceu$~)QpB6 z9SZgHBaxc~J+^tj9T-zU87~T>{ZX_S%D9j^H73q7Y%J0z71B@U3|V5O&8fnGoPx`5 zIM6dp8Nl|#%mD-^Sb05ZGUuZ8xM@3#j#>ao(Wg+fUa4$y>We*3(q#-7*$vLMx>SyC zF)ypv`b5f#j3|w|x4vBgu2oE&z}Dyc9}7}dU>ah1gjU4bCtuVOrV>0BmkP=i*Lw~I zlRfqF9ZSL)#7W>J&CpWqX(r@zw-mP<7<7F?LnqaYSJgIy?pYmJ=~&C&@Z+`234`tC zvm9-;t1n9BYo_pmth|CI^?6XFGhrL%NwM|7dx(qiAq#GALZL*1?TH;5v*Tanz56Gx zye9J}t}8rDG|~eMIX$<k1Vd5C$3~m;hh} zqa)gL=4MN9PnFZEv)@QkLlJ8bb&td>SV<4#QD#W$eP{Ms{_>=ro8f3#J4WfF`=m zhB$JLuCpdKBlyO7?M`$x9%>Di$+$7iZZS_IqS1FrcI{KoWfbk>X!6@25m9Oa`f&%( z+f~A=M-SL1ndm9!-K)E?NG(|E9CL8y6BX4=mo>%4$|CrK9`i|npBrM$!Q*bkpy0o<8Hptj*iAnycpgGGYTbOsJ`668c(I;q9Z4>t)rIr*vBeJWigkk{2h62QT% zF4>IdJzzn&?zxO6#2Aa;&q8}lM0F%09DPKFi8DjLUa@6C&vAc}tW&m%I@CuyBXpj? z{FqpE;+0))3jh8x8uapM2Xu>lW{|&1&Y1|=PcHYx^0bV|hB9gc>xCO+2PCnqfZh7z7{HIk8R>0ewVKrYb{sf{pk!V$%8{?#FSm`5R*qZ3hifg7smuJUw)c!Z< zsIw89n63tf9rODOg+orC4wpsKGpj9bmU65{9d1^@$IdopZD*#Ny8nAxL>xmgrD>2C z#-)aHY8Gf=ULTQ6PclwU6HS0AzAgQL3f?HFA_sC&Qjiu`xYnEXMCA1F<|Z>1G99U* zOQ(QjUeiN;VBZ0dSj7@wh!5n4e%sEi)Ap@{&Nc!8iBQN84vz|@2-Jw*mihd5n0S_P z>`dqA^`e`(>7E(yC{DyU5gv!>o-d$HC9? zDM|MtT6lduzMzR3>h9&!Y9Y-ERJD#LbW19XPajPzngDdWbtlJNXOBgxEp_8}IQWD; zK@fbt+vyNQ;SY$}wWcBHYo zZ4(PDmxXf4(twq)wae<^1+zZKGhT)05bn+ZVxnwEUeFu%#B!uY?CC%i2>dIKM_fVC zqqQc?N3{e^^DFLZXg&kJYul@-!{ze73AE6f?80eYaFgF_E(7~p+HiCsAAs1BwQvFZ zf5gdrViOFk?RKGdA8sm_dE+k23LD0uk5UYy{?>6>Uo*Qz62Q9WDc5?mvy>-`Ri2d7 zZPu%0)P)7TB%3$6vgygq$=}<55XgPQe6VDsQUr7;+{j_5#w{$>5h7rvk`mA0Ke5n3 zL_b!-m8{^z9EPZ*GL(kP%hCfXMv_0YbxBbLQwh3>4I*esDCt4WSwuFaC6A@shhQ zTqL%~o2pzKm&E?E%&6B;b1*iVzG@}ik^$_RpQR027~ylQA8dfY)|~hMKzsamg;W3K zfXTnYcmEtP`3Ktfp9M_*72o@BX^;O7UHhM)J^mB*_HWuFBlF+7`2T|TXssq~x5CW zZk;r~?+*+-CZm+m@f*gcf9PWI05!2Ed#u|ck90Evtc<6niK^t&`1Cp6bCprDs&WCP zQE#9zc#HE^J^d*Hf5LMC7e*aw1dz5haffYgM#WqNY?*7R7^%_)(uOIz* z2QV`L>iuPFkj=3ssKj+hJqDe4S|=}Ld)Of@1yA}A$P&&6$rQ_77$pv2v70|pzFm1X+N+f)H+e>r3DC|s7#hpAu zV|ob{a_ZXJS|gxO38$jy0bf;@nJyUq_F>%*x-i+{X)>ZCo zVI=~)uJOIcxl5q0Vyjwpo>ee_5>xEI!1RmaHPJD46<$$3(mCvdi3{yyi*V2t;F8HDlE5AYJS2ql4 zB8D!|EqTv?6k|rPV1jo^z^!c;R%1tk2YHB(1J@0$oW-!q1u5U@n*GIr{dxkj$Og&x`iU4P3;j- zy3Ns;B{d?Z^96Gtx+cICmEC=$X;083W@oJ1VN?4R#X318F4)pJFI-O+< z_qY3p1MB)rQOPuq`V^Ib~std)RBErIkA3`$ndga(Mi&6m zfZUPMB^PTon8f+b!Ht=Yu)}Z>`e4PzegF(i300jnm{~vqpKRamu zdJF$M2kn19^?y=g@_+v*{~s!vjrH%A+JE7oRjE(L9FCxFUs792f)TSt+L@kWj{3tk zflE+RZ$h)FCYUQE5hyL@c!%_Iobp8!EU|S-%n4NDwcb2#f%Ds{$?uYmWK7$tintgU ze%=?z$fR#l$WEQKdA_rtmEgXyu^Dk!<$S*xPWx&PE8>v5?>tnDO`q62E9(nsiAn17 z-5?r%Kp(`VwV{j7!I z8>KQibXe_3yS`;=gXdt2{bJjf2#572?eo@I= zbFeg!oQFk5{g z0UofDW@)3GKGB*7nixFgsYjjl!a>fh zKxq6HZJX3z;EG(>gI z^GO4nzT!$SS}cRpOoNB=1fX}eRdFZ}3#>1q2874NGz${_MF1ypI#zUbiSo7#>m@uR z&~XMew7Vx9=2y*_MV>1N@C3on+(=O-qS{x8r4DJGTtp_pSTe%)BO zBBWO&$r35exxK>oC~bUE_|cJ40%^WfustUZ9Y12q7|FT;*_0N_)F3UyKS%7M1MrD z)^y8FTfu*WYKsXT7%}5&yD_To^i>d<{}IC9E+r_o7=TMe^`JRPIAA8}ZI|KJ$6B}7 ziRX|@x7SfxN~--zCk{tLNfopeM zW`rLKP#qY1`l;z2ETtN_mm8yJ-Ed**C3P+M0!UiU6#J$T`3r7vJXunJjWndiv~x!g zrywa*J`lr)kNG%3JG)IF4?*)PWL{PQCUAyil(x!sBPY>Tj^u~>fxwN-*q=$4xNZ+< z$>Nws+?wK{IOsAz$%=2Mh((tJ=9wiX0)Y5Tt^BR=%UVY&vn5V|2GiGxUI>09^)#E{ znJ1aDqlx*fATd%I=!8TZN@O}*jk`4646UqR9x1!YYu<7%T85%4-j}Y^&AEFZkCH&n z1rkU7_hDF1<(Rl!290hn;rD#|2~x;0g@$&D^+eai3~}L!dlsXvVW}Q}1UtacG0hF= zKW^y;na3op1h0QG7DSsR&b2Njn_!3_c)DQ#s8-ouE zsGpjNy^xy@TW1~>$<%vtqkjLW?yzgk#{BLm?_4ZF^zB}~r{Nb-ty9<;c%pjsORz8f zb}gTeL27#XtPujnh_cOC3Xl`I;hl|Q+MC{7eW9R+4k^jLrY?d8m>nQw!mb6GBRP)> z$RT?(V(Yz?T+lBYQw0Q8)tb%hHu<>`$F>YNe zWltM{QWoM>w@kwON^zXJ;*tXRlT_4vM3d~e_{WpAJ(6Zka;d%~u&yKL7~PZARD7(~ z+!XX^_iVHJfD8$zhRDOqK`S3$Bq2?bG(ib$rt6`;;zbau`5bI*qa5tO*zPVc_0TcI z`=VPL00u{rdQPEC!(U8ljzemilkr+D=6O6c)LQg|GXC`^)wRKTFf=p) zr~jzua3-=cu}Uj%{E@4kZK5RKP)q2g_T7Bc^Slw-1XaU&L}h}>bm~uEknPhAjRrf{Atg9|uu1?D z9xS(SM`CUY7N_80p*L_wBTr`-fD;mGlr{Xs;8Pds0va(Lbdqrh(}3sQ5K>IF>zV;M z5VuE@8Qy9nGHvwTQY+C(r8S-lfvey6ag0u+Gc6FkR8ndM`Wj5bvn zseNFwbO@kMFGN&MvDkoyi7x%S5m#k`snf)B)G=0!@tN}$iPSkiX)1)}>7@*mNDYx9 z{J9Y8E+SLaQaX=&_HNvw)&;&Xs1?|9Y4XBA!# zB?wwKF@wCpu!r3bo z2T##;70?-JR3j$1ShAewq9<0rxJ#Qs*tNoY7R?~vZ=a3?x&GQkH&_i)mLL<(9>aK{U zu=#V+EECw}*7_r-LE5<9)Cy+fO$W678KvOBJf8J7Ds4t>j>39As9z<3QuxElgoRBy>ew++6;Cmdll|4{*k( zTel0Bf2^DhupO&-FI7qjk;YoCU3nrwS8)ZU%92WsfAUGgsB?wKO{C)-!nK&|%Z{FX zkYJ=MPEnbFhuMmqWK#4JPlp1Xs`ftnDFai02l*>KApW4(IX}i3)d)=XKW>M??^KJ> zXF3&%QPTX-ZY&bxl|s2tSMIYt#@4>z4_)N)?GO^*JZtLp(fq(%d?lwMPq3YU?r^Rb zrz&o7QiHbCerc*W^}eUc@Z4$z5<%R%%Jj)KH@60+$WX2@!_8j~j3lenB@nK?2k6S` z%Phs@anGLJDn-i-OC-kmI|$@5K`t!NaO%Zu?8->0g!MZYn;?CPbc5m7@10Q%V0Y@p z4vpP-IX)Cat4Vu$t;F(s1FgrQc@Ip+yK?)hbAr z(@&zj4AQ^wRu7#I=e&hN1HTv?LA1-?Fb6M?nYSTL1MV}xD|1irYSWV0}WMk;N3O1sWGEs%#|uL zN#Nu(aHz~;sp+)FV#oFCD10+i zB!ql=#HIrLVhgR|ng@*`^y@4SE|1t(bHi%y5x6I5_+u{w6TqBBM)^wA*Y@Sp*#%lP ztrK{vcNFB41|oXxi3u$sxsjlDeP^lhlqgAbdco9zqxuoL?gwH-R0jdAu?n}VS9?r2 z=O@|{;19j=5t?~4ZZJ?NEZla?#Ifvp9*VJ=ecv5eo zICX4M1zcV@R~U9n6}zlbx`6p8hOKr301Xre5s}1UMs_px zE*Sfp)0W))G3*;$IFM@n;U};!s30+ZwwD8!iO_qC8>&n{(a#W`gXjCaK(>{bmW1+^ z7G#>oI=re0>b!Z- zW6x-F47LPsrMwfi_ddOHC|Fr+D23RKG=1w>U$nf`A(%{I0+R;Rd*X7@x>)*L52^sK z>u=hV4*^#^l~~vf#NX5f1?@rfVt;U)KPC${KZv=uw{PC{4^2fGxoMgjL1GY(=sS1$ zZM82B{~Ur9^EKIDsnC2te0u{Wyn^T37V9~(DBAn-j*nE=)Sae{-G8%uk_jt*BMi5t zl<7VRMp@W8o)ag0X+AStnn_#V+6bzor6V?nHNj7!OWS2}VnpB`?fzO(4E|tclqIMz zSSxmq9^422Ce0~jqUF`W^!-vaTI3x~q|-9zC=bykQV7nu@OQy=o@ee5WXopMQ=GYj zG?XGH++F-Y_BzcvU9Zks7OYcs;f{L0Rqvc4wCAFB6}y1dIVpozY21$DPpfhHWBKeB zA_+%*7piDnyoO?1nFIoLojtRejkkR1#JjI0mr!t9^dNU-qX6&O^|x1_>HBoR+7X~w z=7sOfcu*__8&|XcXC1i>b|wUn6!ui!tUG}%SRCe_q7arCEO0tPh%!ZJKw08Nl>$<$ zZO{mp4pNd*pos8l0v$4~A;JZ7X2H*sjKM6MV%0 zST|nYiKaPX++)qcW^-qrm1-}>!}Wt&AO$ZlyUQY^+l8L#kOM2ALe-SKgh$O%uJu|? zdzFeeYe~D9r4ICLzNr$AET)D0ue>A#&4>15n~t5b3a2Cm{2^#HvVdxDPVF@BNVtj& zk)x_jVTx2P;2ki_69R5+-Isn&s(o?m4c9qm?XCeYA7O!T>Q#Qt)vc<&+;E;Wg;Qr1 z2Ou;=xjvYXb8j%N*+=7v;w{b5*aDMk+?6m@?q?U!HDDHA{piyy$SHCvgY_!mDi|nl z!_S06M9$iHs3do1Hb*eGZb+x>j`(mf_}go>nX4hP(|A+}S+S9x-@#6Nr!UaPuETmY z@qve1qv6G)6O@=lV#jxTSW`(^+S_NjBNl0j$DH-KV?4jLZ})<7=i@b`hSI@Pjm5;N z@`S;hDM-7Wiw~g2a2W7?d3p(Yk&%@w3~a{4c!gWD zUsOoP=qdOk0`*p$%>SV(QmICko{^LMebI&bC)NB-$}UcR?u2p_&)#o|8OLOyY_1IG zbdMf2FsiTzjf9~_(NM;)4KZIl3c?7vRj>J+tR@virPvvV6CFo4nvp|F`O#-XpT|g( zbH`pFc4&(&8EFt!8K7diTPg4yQ3yx+D<9h>l;+yGsAu)r#I)AhBKNO&sfLudR{1cmQCggElh>{N~)&G4-x2*Nm;nlY4Jo@ zDgqfuG;csqqCxjOzig64>4D(q{PqD9A?DWEz0tSD-kLj zU#oDT#aGFi@`tK@{G>@6pdq+?;4Ix_8yT{N(Gq(oH269JaC|{ZOHMEIZhc(jLYGJ# zyx!>N!yT;QA(pa0r7q-xfGoP89Ll0CAH)0zI5=W$DUW_64m*Z>zf=q5QP)r7up=<2O^LcbSUJ zSgq$<(TndzP&||%uYW}IKx9Hu2srBR@_%GljVI4AnF!c*4YH`4OFPMG=dcJUH@FM8 zLc&kxd|nxv3d{hqip~N0D1e09t@&iK)C6k6_YYi0;CwBoC&7tE^<+ckQMoaf(lOt&YWmc)l3#fZ%;+FjC!UB9WrLIGbnD7v50`9*;>T%QHtFi?GeimshkGV;Jc>{cE(zD3rpG>Wo0;R3aGB+V{sz2xN(JJsS0^sBeYw_?(Vm2 zkbN=Du$n$0w~5wa4^rTDIV>8gd>uEo1CZ+rwr6xh9muL*h5$D~^CdTzBe}{xGUpv7 z76iSjgL&r8XJa0RmI3I2vnQ84l|pOKNR(O_g`GJ9goVrJ#Y|Kg{3K`v@9$FdNh^r% z?}Rz0ur4^RW18l7s4B3?14xX>lk_9jCVJS7K$p?C;y+{A?p)<`S1Bzw)zaf?>mC~U z@#Oe|uzl*mkZeY&6{#&im+~>?c;0n$(Rn6#qJmdBb}XbpkW=D#x~}TLMZ0vRdfC%n zE!XhL7Xj?R!-+iV;j5fAfp}ayputJ9%a1C`$%|y9y%XgLf%a})v|H$ym5m^HU}3%%H5t|KdX&j&VK4YUG9Cy z33vD;!{l4>(c|AybG}s+%c9>)oQv?5Q~8OSbG z(;#+IgCX{K@B6BjXcF2W8c|j_OKkY76M=%{Bi$w|KT90KHn^r}P1y^c3{H4#K96(l zX)|g`<%E=v(j9yIpF`vl8RU}ZCCii>P)%DDPJiFG+}RR9?u~d=Wq|qkJqi`VNia2c z{f(U=nJA`-Y*g&Ygsoa{u?9xfv|smB7VDX}wME?Y2WgldSQUO+Qny&s4td#dlJ0i4 z{Ph4UFd=44FQll+t2+#Z(-~6<6P))xyERwrO-2TUi#RW9QpP269=N|wz$MN1eVnhl z1;$Mjj1eGKtS*M1QrPinGTB8jih~yn5=u>>m~%P^O%r4F!JPX{^}9m;VPr(GpgWjQsUd)mYKfV>F0fxZTCLLs!P9D;)qt*ON)+_N<>!*yolLR`~uz_p_v zFf2fB?HsYES!I7tkopWnP|qm`h!(^garJwK<(*jWB0(gmxPU+83YOS+qHWixcFo6g zxShK^q}X(aH9b_bbMRm3PhycSQ|XC_>?d6pk4v$<@4Q`zE=Zd5W>D4XZ!}wnhcwpY zj9!!U8;kO9#iqv{My@{E4DIA!V%{M_*k}U)q&*sCG)9K6ylnx`J?)H;LtjMmEWw7T zxG$?~m!=U)-_8cBck@P412UwxMT`rwY>IRH>-jB%O}6#Pkmy@OdzHT=f7?pv8Xao} zC9y*=VDo7`mV-TtEk|K_SD8qY-nQ3iE9#Amutv+L548+UOyws4xb;g91RIwM4OsFn zv@9_!&2J=sk1V?c!^+26k5RUnW@!#)n~xPKL;s#SLciUX+=`5ErlCITmZc;YXPhR~ z1$9_S*qq58kwCTp=3d>NZqMeWhcgxJnpbWfkdsS`4DYct%9xRLY~y z(hYZj3S6Q9oa|Ky9;v4$Kt}bJ2JS;8q>sTcXU_n;L@HMRoCa|TSSKvQ)1c@8-^pP^ z{8-|61>jw44^a6r5LPG!bAZ04JVlbPdUGG;C*DMX{{d}qfi)+SxibT5G6ZT0+C3Fs ztwgS8x4T-7@W44b3(g0=OE-YLsYG3$2%pI#Fs;t@*wOI=SMx&yM4;MRox4Cv%KtVz5`>wMWNPfoBmUzG_(DO7v&``~q~2en z(~js2>tSXjB%g~{oBN$STYm>0UBaS&iH;w^n_oFoUL{FUVLS4h98;O?F!&;Oj9!n+6l$ zsi@wss}S|~g4~Y->mn;&c5p*AfnZ?xV+MsUA=zd$eYTSY)?Y28{fy7DzOGSR;QIq}tAyj4nhLjhloz;mbc6>t zsOi+hYkl?BTH%68_#9ha?u%QUM)EWF)GfoBgZb>W%$?>^Qe=|lnr{TZTC=?l{Ndw+ z_rT^}&i7o^V&aT!tPzHy+!9PWlm8BQ_vK=tAHoe+%Xd|%e68tP8zgH6pa3|tM$O7; z zKsd3UR}H8$UPPsd11Y-k!DAI<_Z#v}5@UU6#(A+rC_*Qf@46#Cs`yUK zJ=JQQYPf{gmM!Z}rDv-y_$=qB=!|c&;eZSSy!0=QU-*b*;IQ6&&zPyo5so|u?2E>!#xiz0Tsct;b;JXU4eISy&pL)c*;Fgmu znk=~7p;o%>w{bBpNfMLEL8rg!$4GI~ypav_h)sTd(&zep?<4-P{VfEJ5JrL?p6+A- z!N7vVG1eF>>P$_iE435qSqxKuBjPo~2F~SHL>te~UC4UfQWX~Dr%{XXfxo-la7C6N z^70*_DHK$!2zao6=RSXP6Bcu}nS;?;h<*r*BtaA<0Orh_v77d`H*N;labQbQ!9-16 zN%eR%4#(e;a|Kdl(=u*4d=ONM-}P`2BTi-%zpJ2D-D00}s(pcTpi0mOCclsgZ)$WR z6v05VieU@UmLAh z<%7d=7LF+bp{YkhGBi^!bOld+%F*-gKE1s(n_asV1OFPSD0oO-x3!m&ODN>CaphRz z@R!n*aSaS)sYSXMFkAm1;*7Y8I0z771L!w#dq2ucp9sB64`Vx4JEkr*Rke(j?qr?G zWH#2-sR#^|PlIgsY<`NI6=~ql5F7M5+h>2^VRZ47ybxqr7#0>*#?Qp-fKkK@0)5&6 zH;H?Tee)WZf!1ceF587_HAKcwc(EjN@_-N{&s5cXcL{Tiu#$u4LX@crM%9ZBn)bT( zvGFhx&@XW+ruKCHyB+2S8J>nDq@n#fFRppyB5$rFK&4=u`?diDAIUPnWqME>4T6?o zybu`xsa>hJIW)--P%Hk$mNGogXzy8A9F6-K8R`xRW%6eOL)q=WM3))nV||P#gqv=T zdgrtjjj6wxu39YU#t6$;%f_KCKvsGDsbYKWDm?X;>mhKokO@ZQ%+F20$_Gij#$(^$gJy0B28sH$CJ7Eik`#f04ZQO73TKo5XSLoQ$9DA5}0Gicw(2kaw_Z1 z_+#|dbo3TFg|KNrB={2}j%AVZijuv!2V_`qE`sVg*$`Z9-r z=fY^0i_5Xzu>fX-D@cB&)Hw%o?m*-Kl*@@32PXXyz6G8UkAX<~A#+%cWWO0|h^Pv` z3XLtUKv9PMFn`BS9`paTSn%DW1ASvp=fXj5Z7G_Ef)wHpe~Y;#bo)_}aL0LoTLg2e zy`XGkDQxG`wZKD9@5w4IU~AHWCVd>5D#34%M#7`1kK7IuH>Y z<(XS{541))5E2z%f>4QBPq=i$S4f*_-K74~gImV=6Bc+l`2D zXr17go1$;&LBlhInGhG=j=7HHpC55EuxtyB#`xe7+Ix2QWEM&;+;2rfQz|#4dk?v; zTj{;Xw$E$*yKs3V3lsK{q1W|RBYRPh6RdRH;ZO@~O!+j@irkZUDy8!_CA(6^komS; z>h1J7(l-3IlQGTGfSM|kVc7s3YU>inM?WOP=QZom)=8EaA12k0s~z@Si!>zz!iDRAgs~$TNgh7|=f3&St8C>)9qGr)bVD>1b!gXlE2c{z^YlE`5$sNM;0> zK(_~=h=+($Lsl9FiH_S&_=tdE{~amtsg^>euw}xmULZG-_!iC<+uh5ut_O}HF7{-F zsC&{^5dMmwSJEX~-(c0A1Lt(bnW62&IT7NW*SVNuQufj|1~xK4-)FVs$%tjBSBE8T z4~xUV$Ow24p)FZ2kKygH5Az1%Oo@IF59tSk42Oi{EvJo@L~<@mnBg5~Zf)qwWGs4P zE=1H6|5Byp;u{p+t=l&0ezf0z#KM?O_D6e)bt}lGogCW04(X79SQC!Xg#dN$w5Nr3 z%tW&Ls~dh{%-8ae#C#S@>tSpXkXHA$Y<*zq!yheLx zZoNi;Ol;bd73UsGVtKX-fKX~x1H1GJNEs96FuOxqVn&F`!&)suF~}&OF>yw-9YhKy zG?EY8_oMl8n%u0paNZ~bU_hvKTe99YuI+7UiZaJgGi5jQx7;4N4$OtL_o>Jzs%RZj zo5jEy&^dipzCN0%2x-+8Kq4D`}Zf`@HyzU01{|Mx&_eRU{6TYJK<2{)ElI{{mucT%MI6rzLxx7kMzeskwWAQCyD-{mAQPjpTFbr@7DI!_p- z3glD#HG@wf{E)F-d%&7U)US8>;D{QC@$=#LB~S5tzB4@|Yz|AKkIPd$qI zdx`h&Eeg=m4i6O5S7J)WvL55&<8cnv2xat1ZV9fiuxBXsSwvX!f|nd`p6@em1$`G7 z)(?^g*zei(o9U05ga${6%qyX;g96qQ^YPBWK*M^UYps^G#@W=H05}WBql*f<5H@RS4mpEvj4~^%q4VGlmmd z49A+a44vIQYWe`bno#gQBd z@FLhHW-KUvy!&AMyo{ImjB-V-uk@H{TH-+1< zjx^0oC}H_b`~ZKr-y`~Ae#fB|*Fij<6JY^Mi{z808loTedi!Te5Vci|+x6P*>=g?h znF)yb`-qiL@8axyK7r04JYf0}4SDy!8nEBhkj?l_47o32BjpovXCz(h(Ja9WW6<>N`cdJs2qL?1eKf#289Lmh?%0A2m&2Y~C?+58Vg@qcO-`@ayy|CN9I zCv=kiA28*AB8vYlE&CTF<-aA0|2xd{e}X9fPps#^iQ+7O*~$NkC|>n1`+FmZJ&)>B zh+(ocV0N#j(uxyw)z#+b+9ddO1QJ4kfFS^>8`=-}37>o3UjPtQ1vpAI)tZJSUL9WV z_b#*WnakUmeZLyltC8sCqhk5LC4du0R-l0!IcsiopTjA=O5RK8H;q;T1>E8%s(rs=dq^`9c6)@(uS1Gp_!Gb*J^kA0+isA!291pT7fXbk zd|04hfBZoqjez_FVx93>W+?)maFXW9D>8l5tnzCVeC%Fpjn|kBdwmFG?8a|P)U`L6QdK9SfDI@Pm$@GP z{ll7UBwZ@ww-w<{orC|Fc4Qo`eaU;Q6GUB2Oz)hdACl=2j{JanyCXv6g)4@q(n!Y2 z@V}@#ryyOzHB0ZZZQHhO+qP}nwr$(qW!tvxs$EsHPoJ5N?wOA0o{pG{iTLyC{~|LZ zFEVniZ$0b9!$~eBJjdn0OU#FVz;v@AB6d6sm1XFNeOjBF%t2fQ1H(1&nj@$+- zyIg-83P6{-zo{TMLScUAx`ReMMs4X?g5VUY_2x9hqurWvo?0U)E&R z;F*|2gqFu3V#TRWN3|rji*CbE4+lcNObc>cD7J)PCNAyBzJ^754bppWFTK|lQnehSnaB?G z7f5+bcH_z(+p|1$io!+61c_TFXl%l)@7WO$Z$u8}Ou0+Z@h19MfU<^lh~WfC)I{xT zqsRVq6R;bt?2PLp(;Z79?+Q~K)QqH$?OLOuGaJK&VV}NntK|%9`^x*uQc&mbr5=tb zU6aqvt%G?ZGgv>C9haxLb=v0Z^s3O%l8zH%sSeX3#)vv#+4OzZNRw5TZi*i+0v#Q}#>}=29upYj$$h}` z)gP5sPbK*V0?`x>m5&Y}#$j2v6K+w*AiqzX&10ofLZc!G)xdc{F4GIXEf>tfcP={u zQWsxhf{w>bMu2ZBbX3ByN_vye>Lxo4Bu%u)q&x;; ze!>(Jji(?FIm+?vB|%z2T+8Fl*{^5=!4fd1^P>SbS{ZKpg-lhU8i+h`ZHYV-^l%Mw z7*$aY*E1DysqqM4*c-Zs=P_%~QcV9r!k)BroN=K$879kRVi|Q*oSG@U9p4|Ol-g+X z043TQ$|@u#SiEhKtpf&I0nXRLM}Mu~UxWNA2Uh1{iUAeKE@L9s>0p^iM5hwsE)*PZ ztqU=dh4W7b-lV8CbFGxIFQ6*U@x9tj@)deq5CGlLh7@v40r2KH={~}FOBQB{DkCDT znU$}iXuyltO=(~6JPQf_VC9bGGe>5YE9R`5mSQP@SHkxB<+iVmWP?bKC)w#ul$Sa> zhH1sJEgLc6AV(o7M6C`?CB5dtG3=NvOr(`gqe<%X_U@tZOP8&Ufmr;tNivV z$zVJ5WCYAdcfr%qIS=bHjP9>m9S|hDC1z^^Piy!~!lFW_#`5eK#T5YDF6V)z=IX2j zC?QXhU!6u|+OxsE!im)6GjZTB1d+Gghg-U`)g`MTsUz2EJ+Y#qIVM8S!Z1Y;II%s= zF7w0cSnPt8lR@i*7LJvnj`?X&562l6rM6)g+Q~s3f{6+SDHfenf}6^6Duakt9LtOz za}61~fCkKulQzjpz`VDR#6A*ggX&D#$3V1#ha#?bkwxu6F6JP#ELWpWI-V!{gfn2p z#@vFHiT13!`-WHT*B#Ro-FHsRj-7l#!UqHTnmgL{)0hJvPitHfsd^Qx)# z5lT3WceW%M<8(%K%Aidi&#CZ~I9e*Ks_BeqJ?C(OT^|gy$ZUv>CqXf z3ig#Nf`0SD02+VJ&og2m>qLDBjb}&GP?v)qa67VNblc;h_@Wfhz74!1Z3Q<&fFPg4 zzN5?YD&&;)jXo5BL~C)yYqhyvQZ;z7ep{fXL71_t5mp+0xO7UsA^}X;~9r7_)u1aOF;^GxY$O4 z>We}p2QVR@tc@eCfxfzQHK5H^1j$bge!(>KfWOF4@CbRD>K+gTuYHk?#dP8$q1X^@C?`#p+FHc3|P2Y z8<0(w&c|8Rpx&A>?io!G?P=9m6Uw~ybxlVq5f&8K@lNMf=EAXiWjOx$wQkd!SZ9}h za4Tno7VLolX#>~i}hgH#^`vmp2vhc%x7AU94sxM@Y9EQ zDAOkrUeBlE-5iGq|1v&?5yf7e_dCdxaNx}{CW1WB2=cJ-IQjiW-c4chq3d=xwG2M) zna&7wrabqP_zmMJ+mUB}1{YkFP;*)bXT1^jJ45R%R52FPl0oi^;LwXSuH0U?U^B2P z-eR-z-EqqlqD$g zJ6WL3pVV!LKjT_svVC5qnQquY;*j7*;QAWgDHU~sVE_@a&5lRJRk3Q*V3ZfF2Ql_b?;1bkaqbjTuIybQujm7M-sIn zl$n`i&$ZWS*O*OOzfT^(Ft80;;l@sOt31Gz^8aYdaNV<8P+Vp6Y({cYCmOl!`(O?` zT_4XZg&B!;(5Im-9TSPYXQBy#qojop^)d!$gZGpZD&@Mkr+01JIAqK$3FN5HURE>M@92 z#;X?1&NoEe5STYn?6sBwhF(Qu6|^30C?fvEZsT=(6F=`0ztBRfFHFS`VkE}JRkmG;_VYyR5SC(4aKo}Q^%NOVJ^D!Z^!m@Q5-hk5RbV^p}{Tq}* zhqviiLeWO;hVK=8h)IeGL?4n%qQPMtCYksX$PMW0Xs_tklA!fK%D5^ogYMP#$Z}eg zHBEwL3q+jaL1%UDP9Eb1ZlAyE`kg-+v2^v+Vvy^0*E!o`@sXk0tn7pLJE(>F^zhGn z3iS*U=kn1{ePx|}Fa5|nHBJ)!F=yeTsOfFpikhD{PC<1ad=xOVf&f}PxcLE?iZ{tS zamXz>twEMiB0#G+nRrH$Uh{Y-aB8`Z2&|WGI*Ymzvie6V2i;{H=Vg&z+5(+350x<4 z0;0OflyZ6&L&!-awa@3x+S-r|?JbsI!2DSmA4nnE zGJZfKxsx*-`?YFgE&85zgGJZdaYbhrGvEL?1-Q{kQd^$+8Ub=wP<@D(VGTMv;rf;M z>IrybFd&=o!HmzR(M!pC8(TkUFMG8v8}%m<`X;I6)|JOaIky888*vjz(tw^I^13dT zQD++)85Ls7hI6+%3OwxIBz4?F@bV*ExnQ41K2nabXqFerfkb{z+rWeW_w&tavIagjW%sL)P=-rV|Tp0&Oe<89cCN&aS0FmkC?}d zSsnDrDTj}LpthxQkpMMpH9e-lu3CXkb=s<3l&uRYZ(Q;qE#Q+txb2L45ws|POFKCg zMhXTF#dKItn|qH1A97KqK<;_7-~8Qf& z%s7Drhw9O$dCEZs8n$Kq@(f2nT$^gsJyUAWmW$(DI3<-~_^CFU$;rm9M0zc2g8Pm3+h(0^)Z{ztHb}+rW!2Das$8K1UIIlBWUKS&#aa02pJI>iEM33`9u@alHsB9F(=^EB+0ki54Gx&0m zE$V>?Ay|v;FF_8?uRu|tWnA`{_YYKB%yh*+#uvsm!%dM_;ldX7u;R{a7# zDGOK1R{#k{^X~AZ?+O)rt%-MobTD297D+_-#}8AYYFjWjZp>5o+y%9aJQ@%OL@*4^ zT}bgk6Jph{J)+}qjK70^#B@1F7QoOs&jmhm(?o3uMr6F#+G8{F2MeQyWnb_7i&o<; z!=1%NIER``JQZGLPi~QkYvR}GnuKuJJau4yi92Hu5FQB5@DIC`?Xd z9c5j46b`P4%$L-&KA>L>M63$`ftT}dnwtLWUJm;|4Vi!A<*@&2kH~-K<@|Huf5*%D zm#hB2Yz?6kWx;3opJo#;FFp*Nh`Y0xlCy!c2|hPBKAo5n13m*i(?1iM|MI_(owc2# zlD&b^KNko&vHoMhKhvN8Sn!X-#Mby9_xvvp=znVvVP<3bFZnv&YFc)Otf;=Pb$diD z<;;X4+o)?Gr50uBgiTu3+;Rd0?5s9cqN&}9IZ%;bDA#a1PDKaCwBYbjNBbS#rxSQ- zQEa!>jFufb$Pzl`$lqs!99hLFluk*;sx)v>Y-&mcD@Y2(mYT0oY<*kkEm^1*iKP~` zsa7AA{_BGWs(#sp?MpU&QHDyyC8`Q1iP~^tyNl!dVdS-lMa%wDZ|q~Yyo@9ZbssU9 zM-Rvu%ncvEq|%T-kTu?JOw-1$zuUlv$xgO>N3tqVb5AApu*{C6gPosdZO51yoBp~hPgSt# zcgX#tpVZjAZdGc%k;%aY_R)Ky9e?G+=R62IPECF)`5akESh>Pfw6Kvzxo|%8=EG7w zV6rkGW{Lg`KRHxPxmNlk?2yY|KWhAeD_9$h4mB0yk{oos~ zl~xpS_(QUi#kNFKBrTn%$CcNrZhzKAlu>n0`4fs=_Se`W!wCDvu&p!HZz{|dM$^vq zw?sI(+sv}0v=dA@41f`aDASC!U@K(I7U3?a^$^e_Q5Pa}T6+3fR&#*GKzVvXOFa>= zcf+r2-TTk|4fT1j=dMFJx!v&!V`0B(O^>ZrF)s8dj%Sh2Cm-0PDw=*R3rN}ljpGU2 zk8Z_Mq%CXmhWbJsFmB(>5V2J>v6J3`g!USCsoO;lw5- z2I7C<8*@PO(0R+Ir&KFP6FQj!5UPDOYYMdtGz#|&`;%doTEGb&g)!Yur6bB;)3-W4 zM=-t%q$btOuG>T`&-;}Nhm}DoFdSZ024HA>g+mSnkg)0K;ApymCp(R&3QT3i0J2s<$Xx#-Zm6eldyp;tf5G4Pa*g zS2yJ!^JEzh-D@Lx40E8ldj~zq3w7&yY(|sM6=ElrDaq>p;7|CiO+qU&uv(!#>p+o? zLlop<(DE&P#Uve>>`8)J5Q?VLb^I-EzGRSPF-8w|Ej#SR-;FVM+4+9Eo;Q$ckF+c# zqOt{Zsj`awDi=+RyukVSfiEvHVEcz1mS|JYY8=s?E(M_nkJJ9qe)fK7BKoi+Oe+z< zy(1xdz{<;43xz<5)tiE!4AX~Y54;oJZnWT%IQgw6tW#kxU&uUYHBvkyaW9a!$x76r z+^q0k;&;ROY#0}wtdOG}2RnfsafDLRW)v+(qy9BkB!>9-XPGHtE*v#V9RO7xlQU@ay1Ic-UNHU#;mKWIu>}u* zLY0B8wdVtBIxJBRarpYhP8+tdq^5qltE?>E~ zU&N8~rupVwvfDlSZzx|LsskN>qHlA{H0>6?W$PV?#fa?Mhfa~uwCd%9uzAq&&f71+ zztSP&QqzAxcu{fUy`!lGvnyYSqUeBw08Az_R08 zX$sKsdX@USMXKp*h}aD#bPO7E-@y`sY_(mJL!W$1g*9d*N6HNDVCoJS@R5PRpynE+gR{J~i zMnUU^KAM{i9j@d1SGmSl7U#nIn2EKzmnl{{QeUpPD>{Ozz4~{IjjPj5)GUPvWbR&p zwbIxeQTdYD&ZX>iCKHq{yEOii*f&Q@;|O~21E8KV`hz_BMF%}QB{V35QvvmoGOG5O zx;iR0T8Kt`CJW_R2eJ}xk}mp5F=if)o;mAWt~iH?GV#sZS%lNYNlmAqw}twUgEOLQ zp9p#fp&xOH9ATOa{9f@;L-A1*braK`!JPkl#N-#{Z~LAoN=AwzVXkZw47GuNa<-5edOp>j6d>_w_%e+j>%(-c1CQu4@DBl4 z$$}EKP?;KwQ^>tec29dM2}RaZ9ktNw$7)SoTzq=P(lv=me6m1a(bIUcWs~-Bd=ya6 z{Vfo$H9ghEbcf7`^S+wn_omLK4)vbckW|{uNcs73AFz3;aL6~hpM(K7-jpg!-l2w3 zBjxrdz`iWXd~+cJ5GPRr2Ay&3BbXojKS9-u%~J!Clm|q8a~XXArq)Ljg7h#5py}D$ zn|;YZJo%=it5aoS+(^zEfN~w0Hd?UNG-sW(?y$RRlE?%$p%2VF zvAfEhCt=$(23!{lw(FIkZrD;xI$3C7Dx||P6Toxc7r>o;cDVGd6zt=+z->OMOW4^y znV{?6h~!!O7zM7q0$W^``KrJ5w&CTpKBr7q=L>0u)WAT_8$43b%B)$J@hr;#gV>9% zmA>;!v-Hr;mD7c~ABWC_NKvA$oiFLFQ)QI!B8aH;mx?3PoeLHr(VRXmG!?24)IkKj zk(qYY{Sy66zPZ}P7d^mj{<|%6S18j48LzcP13dG1SvH`DfZ3vpW=-6EDk-6LoB_0%wV7AqtTJ3QH>DbcSZgT9l?zg+-FMTm{^ zGOjPK-ucaoa3*A6LilX!HlE^)4_tCUw_QKCIAOGpAB^OjzmCUGgyqxYUQ~;)!KGI? z-Tm{09TU}bQP*Tt4+IE4W%bk|yGrP&ZKiv9B%2Q&itBVf4KcU+zQ6I%;66$!o9Jw0 z`jXAxb zcDR9ZFof$Q^8Rk}%31I^^D|7vA6hb8%zh$bo%JsKrkX8d_EPbIa0%O}4BcSN?^5gU zSj?L)-M&~vsw^hNKZY&-t!n$Moat-!`qDVLiLJ+G@NfY6G>R1R{@-* zl_T81Taj9d-v_aop;#;$>EJ0At95>koa?DEW+A+j!?VamMw_I4ijJrquyfP-o_BS$6g6?9{ zBSwPra-5BLlM~^=yIKYk_T%N?61>O}3k+1I=GtCOEM6eFR#oOX*EQSiCrfGp-#H6e z?KDrb*W>LN04qUGy#Q7LVVy7UJ_iYT0aP-ZFf&{)l5EjIQ}0Iqvj%J-uPn2O^5$f2?4^k~zJ-&{BM>seUVf;vr4gewlGjy9{N*X?ppHdj{e(wC&OT=C!#UxGGu z?Y&gcM)OS8vHY&qDSLf%z`WpN?)}kL>lwRMIy@tCHG; z?u~Iea1S8Df~fUfBFvO@=j4724=E4jNq{Cs|`F?)d z9CBmiQ1)u;#-43j+qke!RKEtB`aYD7wM%WZRshat5Iq4*S#89Zk4sV}2lbEcfDaI`{ku!r! zx@x{Ro;JWEF<%t}N|@!viH$m%+^P>LfqqVt*83An%#{v0NZ5f* zngC5Sb(vVgD)78ys7)}SZ9gZV$-ymh4gI`B%t5mcJw$&qnc}{cfNdEzi*@o9HA>2P}81ATq>GNO(w8Eq8ZYG>Y^Cg67P4icT{wPv!$RN z%N&RF)nGIC>-}IZ8Ttxo61P!5TC|&J=!R*f9;>vMaF1GdlyFnoQOZqdO)x<>VNEny z@qX?8YN&5`_&+^F_J0u2|LV*A$5s0OCnU}O542kGugNB4_dlD5+5Z)r{?9zbf1d5X z$lfn$bga z+qOXxK{#z+2{oXxwGQV+i7-;RbMeQdo+3W+#5G)5pHa^Y{Ts&e{>+BOsYR_X;#Jcd zI&eKooQH(+eT>zNF(t86p}sbi)p^mW@+h>Nsa;>4@7BhwJu&5&+w6Zt_Wn(3gspQ? zB#$Fe4bN^?_Neko9AmM}CQ3*8y-cJR$1lrHPZFp7sB&1p228B}UN6biQg8V*De~3% z!~E$x;Mv^^>#5!6%e8nw_VyujHl*$VFB-*muwAEFZ6>;8n3_fWO86W>H}pj<<&ubM zus+48M#v)P#QcT}cgakP#cAVE2>+9yB`9roKKf+k9PX!rd+^j_njyPi}knoL(BH`VY1uPB%SpwA!u zz0?vj8Q`~6kePpC)UaDM2s@TJ=XkTku(x0^osE%ufatzWmso>*i9~cYIkUc|?KX!J ztIcrsBJvZ@>6OHb&fjUCpm7@Vw9~`u6@jwLC`=PIJSqw0JfF92N*qk?QtD$h%2+Sn zQ$|Nh?yQ%1>24J1%yLL%c>FLb#JZe}_vdgFkGWmU0Q1BYWX#G$w%U})z$&8tbBbC8g*}V933f3nK(&SzRj#OMK zhF{l}0wwSyWQXBBqjr?&R;xdHb*jTILR^tYW*8Tm6B7>NcLcF6z?Fw$!Qi*jS>9$T>rAn&80wd_CPX{IL-}#K~t$$}_9_gAg zV%@GgPMy0we2T%F6Bti^+8|Nu{7Df?#Dn2z09q51g4QssKd$)=rop(ua0{o>(o>-o z9yhvng)4|=?8SJdB|v8v+wyWyGEWwAr}E;C=JjD=vAOrCMk87mZxv!VOtS(wg1JZ* zpPDYM%Q{WQ3sj1%&Dzcb?ZVz>@W4ndB6dkr7utCk$KR7qjVZ~%BZC@g>dByn?7?g* zy}IKVX#LV9nSBIBJizcxkm={y8r?IPM;e7E<3OOXwS=tQNWq#eNFj8tB>C6tqutY) z!kfyq2QdtjHBYCk{wCru5t8MIjoBYVkA#9AX2@7DqJva$fRMI#0Ab=CE{Ljn zu^K}h0>J_)0!S3rrup<+_NFNeLuZX?v&{Ud1BICu&u849uihHPc?QnczBfx?rn9QakzHa^O69{yE^`^Q1FQM6dUGTa(2%@l`Ir zNy$9zm$Q!8V6X|RP>uJ=@Fx5)kl^Zo?x7$7iqANMD_}0zUf4lO_Q$)#4+9cM^MznBNH%6>#8x*2b1XMZKwQ$li#^A4RGkg|nfW}!}hYI&8$ z>=833=b%x?>7wuxuqh77o7p)WYizJ5$l;eD-yPxy08$NGP?`HXirvqtl#S5xkhFj= z&Koiz&az8lZt)O@tyL38s|HxrkI(AEdzR2ZEMmU#Nb=MGU%i5RqCZU@%Eg^vnVr1KcGzG!=Hk-un94a@xPW zbNhbRqaH)C0Fty}cf}2QvdYroCclMsy*rj7r zgPR!SEurHRFng?yjr0RRS}0rQONht-Y`p9h=$*23P z=Sni7LlB_cM=`x&=YWN=-o+7tj7g6nFY>C=neVQJz%G2YCkYl7Zi^_xFH$jY-XT!&-3-k#}_bP{+gv~2*;K5OrQ z2+R;kIJZryE(M5K*MacF-EEX>n!nChH~HRPF~kF0H9tiH2KnOz2dkPdB?dR+ES^p- z%kwD*o|mgp;$5hK*rm|exPaNaiRBgBVE7e2+lcX9;?%D*ocBl?>NTgo9ztD#k4I0A zdKZ-{Lu8)XJeLb51rCLB{JMtC6I(__40ZJc6!Xrs04~M`z}6=07l1YU1y-L+MasTY zcKWLFyA(0x$oFOx8_32{lg}s6Kg1U+@)*(FfbXgVNr-J6pPi z`c+BXeSzv(sn_^Gvm0E`$K2G*Iz+ZsRb}g3MG_@=4(rJ;ARPO*_O+|L@lTK2I$$pI zxAlZHP3vNV_;jNmhQrH2`M43Xpfe9aK|C=MK_tj5Fq4K?a3qjdrJl3fB(0%<_x_J~Cc!Xq&Rh}cDT9mCjp#ta;T z&V7~O&z#n(bFlgs$5&RK-*c+?UjCn>F6@i1F5<1MxcOo!#bTjm=&=TmYxf>>*`0$t z0#^$O+kTLBso1~<_?@rFv{Hqlyd=lJa`|6@fhZ#a=UIj2ZoSO`stg9nXiQ3TUNM4< z)VBRV&4Xi0>-**a?mr^}t##-l>Mg~Z+;w!%!_lIv8;g=EkjbYTD7sh+XUkiaE)O*O z8j_@jO>ewOlq)f3UejjN+`Gve;&Vy?XU9PVb$B1jI9RW;Q_jGqx7nVYhVSs|4a!Rq zU?0#-fQ*TX!ThbexAdYxgAZ2x^KZuYwwd~O5=NwDBfwTBj~Js&u#zC zLKHhnl@zifc6 zQ`ejKOQ;83f`}Io_Oanw+Kz@MX@CGT9UILxE#!^729d6ofUhypT+C2Lt5cJQ_g?b9kjx@o7aU0{X8pmY_!t3hFx z%<{s-N1J|Tm}nJj*j;1lDJ4C|4c%tQ#nB-Fy@L5OW+<)nGi&{w-uM;k-`F;T2b&Sf zZf;cMsU4pT;WJqGS4rWVx=WdKF>htmq&N+!=(1&E#@xw7Nr96kkAyby?KE){r4t6= zz$0TkNIeqYnw=%7gm$n7O7J_$pHme2wC)7W} z7Y>LUgtN(hvUsxT%n*ml8cD&VBpL=MkS=d=JA%8v!0n^I)mdP20m9HgU;8CXP5YWq zJBM1xr3nw0p7as6t$VTzVz#zicbBQjq1kH*`PS$st^dgX^^ncRX99ZRNXndFDz7td zK-)CrXG|^zYO`IJQJ^NOc~lcr!A5Q+G=nCqgVM(6FLEb|iRIQye?S(Ao%Q1)o@wN1 zff54<$5xd`jgKdlMh|QdL@f%W(~l}}mZL|_!!?e?;DNmOPnOP0DL`7ur#viS%|aOL z@!oaK1q(m}A2k^AK&94eyMbM}{1ou^X+iHs&f;2b%evb{?7r z;UyXB=~3AL$TKcVH$XW6=vnUM@BAO1vJ%ua0LCArUmo_CqK!tKoRGSMFSC8R|f0^J6=`U*2 zV9Aq45jgxQm0WHb+HSR_YC*Z5?9{p2bX6HB2ix@LP?A@$Q{mWMX_GdKPd5Rbg5TY6 zUeXfGS1dP&jFdC#FW9a01Xq-{!Agb%?Ar7c(3%U^rW0h*x>u*+^0Y|ThCz=v&+UYQ zMwfpSlu}|VI%-r|cFUw%%_>#=GmeN8TA@VqzK2t_#2gu&;c2Cx6{CG)6X`UI8A;D< zxeg2~?6P-`t=!<>y0L(4k6d0XgAzRTCWnl5`if{BoK`QI;sUB1VIyz;cgyfZ7OjwWN3-h z5B;%7AIKI%1Aho)a>%U#{MZO5(4^^DP@i~(_yyL5^$W~SWNG@PmHwyo)z?0}?DX}9 z%3)XNKJI-aHXpXvK;EM74BoOW|B#`;cB+|avu@H1%thBg-(Q{xz3nfY^c?$<7l5_L zE=oQG*bXYdSL*yd@_tA>hCXng1Sdbfn8avtlxT`9DXVCIpxc#rg&&?(IMO5=6wSJu z4@*4n3v{!=AezlEb5aWji2%{SboW4Fgtzb;R{|E**p^d4bXm5$t!u;a+C6@u0*JeG z9of-&WTg|$ACK6QCLj_Y$;aioQ@XO}2NGT5pYdSKvq%KXR2V@?3-VYFJmdDsqcL0N zpDFJyM=^a{s{vIFJcW2a1hCzjIXK7qIPprRA&D?}y)zdj&hwCZ9_5bGfGkCH1m z-33w?XToU`|KcV}U{T94S&0Cx&+joDW0tEBvkM$Jqh5khe&&zDV)Y z(#zM9U)P!}5upc)#N}Rd4DjZ^!6{7=&e$2)4m{B$hV5=_Oq@h-CW?vi=2R#(TXc?l zbCwpl%lEP}yjT@DUBFB~BH5>&Pv!dODr21{?#~U9yWyYQXz#L>x7-g?ZUTn!wc3$k zT%WxArBwk$fG6pAB6h#QrW5IbbCAfx8tbBH93uUAy>3iw!usp1Qeu5z)xC}D_KHg} zz{cRz&=9;tVDi5`5;M+uTu>`M<*i$z62S+T%P{S(d2;n0f2OETw=&T_E~3fG-)Y)2 zBRVqDp{n9#pz;T=c@rj1|D=rh57JtA%NxNWxDBU!sGoX{yJ>*KKb=60)9BhMelAnF z1iI`NxHWY2z~P=UpQG19*vp+XPs6fIKj+Jq-j-e@Kk}Kt;RHZWLKDbiuTJn5`guPvgO-a}O&O&P&p7@QMC={4-bNN7XMRdNt1rNq zF1Fi~6hZf0{K}*$`Q!k11KWHN%EF=_ibZc;d0T0D7{m=*gdWG+t%C4&(yrv&bW7?u z5f++=&0VQ`-+n0KqPD^HusOT{-GrxGH;^n7!S%Vz{y+`{yU4i@m&^fskL%%Y~T4v#-u|XTD=B z3lA)afUG4}#DCLh3!U7}9eu)?*>>grIwLG4`MsGYL)3$JB1>~DOPWxLZ+8)KG(NiLJKh;$sWl*BF1ST0|O z^Glt^BL0mLT=K?vtby{Ifcy|A*YJf3Rj=fLQ&r~-V#93P)mzlUYJay{ErW zUv#D5zW5fu{mVE4t1RG3U5}i^hQqSE4{RZaqc_ zUVJQu^geO+_6=MZSdOI2FKsLSpg7Gngj`61eR-|JT24~Rpn3*r`jl5B7}VJmlyQux zI0K_DSJycu6&yOcM-;;Qc8W0P3@}Sdz~#!Vio{AhZafZqgV~6>{q4P@D{Ea})(uQ@ zqc>S9X7W6d(?`?VqkxDEcY;yx^a>59pF_$uBw(C*6-2*46M7dVNvY(&&QWftF=j7u zQzRBI21z$|TGhUI^T11ca%7oRPkVrxC%%Dot9l!8JYib7&WaITey?i5Dk|Y4K&hasv*&mXXI1dPrkqXddF?FD$ha-SZsGP){L3KGXT&cjv;s& zau>mcx%2ppkCX<-h2$1M(Kk)GdlFog7ZK)^tB$#g|Fl;rsb9+~X}`cO3);a?QEZkI zyuk@)o+(U+5+i!vS^mVEy3f21z8aezP@+F3vd8~YmHjJbj8Rq1izz&#@{G+Xd%2mR z9B~>4Db7-YChvlL7F!O@O_7e`A%7xy(>ns9kMLzwxSg!m2-;$asVOCvr<4s<=|yn9 ztsNR?PVep;6V774;vd3(rT;uVSfHRCEY7oLSSmP#+h`^*C>>6@&bRp>ND6|{ptAak&ni!=U zbqH@5Mv0oAjmQ^!czk`GOnv8M5}){u>?I4hD(D{(6R#_EtCAoMS(uRy#1KxqG)N`?Omq5aRC|G(Lv z#5%)V+1U-yE8kzZX8fd-Uf;p=`+YXd&UdF; z_Xm-phILZ~6S)F%KaRIi+#~|_K->nlYSnI3S%oMk)UvvB`Lb`PEfwyKLI7>J@9{@H*zq;qgVUO8yH}FHZ&iOq_=Tr_##hlS27fvP!gu5y!ZK(IWoj zqFz!OJzYEXnlb{4ds;da6fd5g*>)Y#CHNA)4X&&u8^|MhkP+^8w%s8k#on3e^W(|y zyod-ucIrLAHM_Ygg1;M-C+AbU-l6j5up-&O3JGQtU$t~>&Y8dtm4rFKoFuverjRXv z;uLxfhcH3ft@$zm>Kc!O3hG=@3{GF-o{e{9!r~X2>_4>fjRPaho*p8t!1wTi67yc>%Nh;TG>nm-haOGT6CX1IEuJjtC5Kl22tQ zvl@Fx#~ALfdtTk(Cv5Y*N@=>3kBtrbUDfZM-w(AHG7?KDD@~D25u$8@NUE4Z%;nTL z@I(BmmYnISHMi}4fngKbgNr=TO+>c@R3l#pe_35rlIh98yMSqlh`8NUx&J6JCSY?7 zLr(lSVQGo`o~i=&l!c(sa`l^J46()3ll*SXDtP|LYEFrzXoJZ?2#c$ePOIju4wP|J zwXkR`5iemON1~Rl8j$JCD0^ZhL-vDx@WpvR(0u_g6@|$ra5P5)E^5B_c#F;69v?U+Q4b6YQH0~t+2(S<*2<)q`ET$o%Bbu5r0Q)Fy_#d z9cH+?X4g?lxS#uUf*(-J;vWugQ0Hci*Q~~Y*vauq$xWZ z{E3wF>UFP=Y->Z`!j3et)0ynQj)f&y?rc)!aDsV<)a!@Q%-?tc!c#;Hz+rOmlOxVkAUY#mF3!xP zb5Uxtx%#E)9^e_2Dij&Arm@dz)e;Lmb#v9Yqu1$uuFh!bWqhi96=!;W6x&0Utg>F= zwb3SA73-~Ub(MmgoI7h)N2oFQM?=mZCt~LLx7P``lpT-##u*tm|3%VuI}(3XNN;-@ zE4fA>89KW&p$lx|SiDFflsSMv%sBO+X$kJGa*0xPc$9a6IxiI}gnNaYg*i90xhz0Q z+`hal;$$$8-27zP{Gfp%tSTX@P>^(^HwI&E^Ey$;P<88;LBo}K_nu+?ev&~b(Mb;) zrul08#9WF=pOY0^J!8FhTufLgp00wH!SbUkl`@UfS)RT1FtZPnEM)Np$H*ddXTo}q z^`r>`!qg%7JXxWD!vnOSAOOK_-&^|k@qWQ^=1hC3k|%(E^khy?AZ5En_)$@w0w?MY zkXq{gukrA2vqg<_NeDNR^!_b|bD()0#b1?Z?qHci#YiEA`Z>6VZW_22tI zr~iYxcMKBsOSe4Jwr$(CZQHhe(zfl)leTT0v~AnYJag(+*MF*~YvNYlp6Q7G{zmK_ z@0Tam+P}4)jVacv!|f^l8WP|g*4T=3{3`>-CI zx*CyXQG^9V`o0&DMRHyE)8r3Pdq|i76Nn$5zghKM_V!D4cV|H@I16jMLDbeiU}91- zMMs(`b`T64IAS%6hetpan$>!D^2@Pch7WLYYc#WB@(ia`MApCWU=?dxO}KO(Q#EEP z!~*FK39%8lpGLZ^8IKSxs)>O z`aXj6v`>!2y(~QaVFv8vOU$urNXu#XxarRSY>CSVBw;exGmO6zkmkAf=6VT4_Jh(t?#$(A8pib8Du>WM$(hK-vm?S{HbGNYwbmKl%;w({+ zki`~2sFtRIavs2tD3r!cjQ#mB$Ck6u7NK?$CgnOeSN~Z$Ht?G_cywDG%-$JGlJT#61hA z5`Z3uMk zZL( z7a{jeFS*A@vjKR-Tu_m5?xkmQeuGL`6WPV9SJ-HWAzGy$hHkVTmz&Mn`s-VK3Th$D zrYqw3d)WM9nvx52LS$ib0OWt*%|6&Y)84+EL(X)R8=?SDU<$wyLYo!fPpF#OSxrtN zt#1sjL!82T8~!x5ZZRM_P<_P|6L0mGkv^8JpUr?Y=OW!{^_geWwe2nIWjcqNapj3A zCu&zk?exr_XY2wZVm7v z0IdA}IS9!RsA!ov^&0I{EYGYlLjlWuwr9uj9z5UCxjZTtN1K^{jC+&zc#oBV6X)&& zem3op!>gWTgxf^dl123;_3%Bgl_#nW40q%_`M99BY<8o=W{d?4-`Kl!bc<#k7 z1n&wQGm#=f2?4_*2#uod3eEP<^zXZ+jqR*AeVw=Y_B+YOoJd=}?pY-|8Q6>GaTZH2 zHMzHDNO(je5n*(sX$m9l6t0*oue%N;uuy7u6%>Fod4HC1tGd>Asz)WsyP3cC_7!T6|mIxrnqPUS> zB6w7G&uS|g6#Tigb~?3!H%jHXOwB9xhfh4%aDC>S^FtpK`(pgl%c7iW9_EJ*x>C$t zQH=>|pMYd1cu$t^K;LZ!gTjwPXyk<}gS&j#0T9gzU$DO3B%k^fBoo}q;UqTb!RmTJ zdi9&EWLKU>`O*f}oHviM?bZa9iIY7qA;w%n0YOR0)-rFyn1pJ8w?(X!FH;Lksb9{_ z2kj>C9J2WkZ=!RUr#R&Sw(ps`3goyxG2`?H{ zuyDVG5h;Rk)CUD0pDVfEP;6W7gBM3tHu6u!#f=lWoCNYhJMvv1j@93>r1-4C9~EP+ zHA($kTwV4`B*?Lul5tHaj6<`{#w@Xzrs5MzrI?dJ=N!6nemBfiqkIo=D{IlD92jO8m;IqLi+w)x9nhEZc#F8 z+E=Drx_;@f^nl}YaiM~HrD9wV=dwvtn~oo|8yO}oqR$41!rq@em=TcO?<#PBubb7k zk($P*3mT5fHmkg@M-2`TH+fVVm`=xnZtGcfnE~BkB9R9Yo`g4E1nP6B7>%5;|M9JF z>{B_y$2Q-E1$kLYF)PThFZo#vo{{*TFIVCM%oPAs!2uX@Pa(&vI`!tC-`rvv*00eq zFZ-C^$la(PYso(@mbl)cbZ<=c*=)i`0fZuDnI#?wGhra6b3+{b}&T!eKBN}2F@b>N9&Mwtzh()(3i zPu{|+$+i$^#3ReLjOm6~w<_E}UKIaQz-9>imX=2#WUDjr3OccCh}i%UEr^+3&WB_1 zy~%XwII|n!G|L^Af5i zMSWOm9UsTQOnAXuML%D$gK5C@UB=>;S|&T^#}_%bBez|^`lCd zn}A;0&r?~Mn^3COj|h*J1^PsI!yK;j-ikTUfcKke^k-mGbJ!*d{{+z^YP`}TMHaC7lSQ9IGI%*Wo(M@2r*b!xMxit$h zDe1TQs+-HExG6ilOptZxo(C_+`*E+*z9$wyWg9)c7CL98d`pLNwH6=pIKQ7{{IsEM z!_B&Zx0?!&05P4-RYaegE5xs0e@HF{Z~e$Z3^PYbc~irvat(8wP#J2Mwla%;$P$&7 z{P z%aZb`rl`4e0===lH^+kvE5`ugn4 zOj7plTm8cFD7pOr^vrvvxZgCn7h+8q4|5MxNMK%4(iMMu|JmT{Apful=^Ep&v{cYk z)iy$EnUO!yI)6FloIzf8npO;?p4cTlf0%hv*m2xWQR_)}Z=EX$e7LRIkk}-vrbWVG zqW-b1m)+cs_Sj7UJm`=n3vKw;Ffp7WY*05H0@lq1dh!G^GZ8#PpiITRR*52VcvdBo ztC*RSX8OdL_Zt>qH1><{f3&GM|JIE0KaJ6I{)4Rl3!~@!3#|XoY^uKjDF3xu)&Ds4 zue<)AW>fuB2H+n&2oonK$G>A!CI6}7*bqbWTdBnW@x!1a3LX3vPm>5>J5Q%Y09!Z5 z*B(l!OdO#X!6GsdtN5yJ^W!#mBfjZ!NEaL7#OZjl-S1>lK58vX-^g^)h_}(u^3Ucm z7KsIpXs8r(G8v=h)tPOd)2a%t!f+LJ)<*Wh@_37*Ft9t5Ts3>+BOTta@RP6|Vds z2-PRA^mV9zwS9gF6#cvv75Tj1d(kZR3z}<=6hf}#HYIwJ%+VLIVr8ySYupTWEKtHO zEnlB$U`f2QOC6>9gVcl6{t{smkmq4Qx-!#L3T+SZ3^3b(f2azcqHoMYBY$p|3|}Op zQEIXiITrq9sSFZj?GRpgGQz{Oa>i8s%My+YV{uV2MO^<+{OAD zzjE^c*U`f&4#?4=}eb9QaJaJ>$jI830ES&3W`SY|aEeb3=XLv-b4(`!D6rGxg9Asj|~Ym|wR zlIG&E)*v^8^3)i~7n(3lI6i;?qgIW)_$W(X$qYZu&_vpFpsMbUz>LX6cz}i<@NbPA z4=Oiq(u~?DXk9A(x`sgYad&!F4MMPh)9$1`=px>jNn<<%ugvj~Ar`q9@DB1dY@E?lqRDzwp++^E9u4n_+tBc0HxKnV`ouF(B=C*5Lk^B z^}%;3IjGn#&wq3D5w&qHy;NMa65y_mot8roph6i6hCfG2)G}&8vFuu_zMLP=&fn8Y z8M$^lQD~N{&bVl=yXKPHKLd_{>=M}0odpg`eYLK)ebb9}OfmxQzEjZV9#a@#TY}7M z$2)`=>RNE@%y;d*VeP}$RI&5$&Tj{xZ|Pgb6(JQZ65QKacA9GKtp;QRtPYgnV&?B0 zre25k8X)vG5ehX`GZd9?uE?QZ0Nj~Q(cE~R1WRwZTS(q+G~9^3zehgD%B&(IlbaA` z&?`AhL_q|ujs`uAM3MOViLPij)L8Wa501-$fz0?iU10r?Neu4xly({bp1raAl|l z>rlja=!=*?Hc~!_J?5|tB)QMIKnhS_Z8~{1I~UVn8M;JNz*L`Knyj8~>RvGk>F0Jq z-5}nf(OX=>8vy#Dk3)gTs&hwUt@@CY_nejM_tfA54+Q#jPFGB3T4`k&)GP!5gX&@* z0j^wFB~(W|r+2wu=Ez)?_ODkJqr^jyI{Q+}u9C(M59J4TA|IDB@Prc^<#jn)u~MM~esO?|B{H*zt))(@j6l?dZ?Wm%ha2uvdJD8Xl9%r}${uR-rw z2$4#_P7#$4q22@2N0|f*tCJaBRYK|WqUVb=6f^?sx4=Ugp<7!0o}voWDF);c%!g3v zs!khXgN{LC5F2qkP<_1Af%gg>&=f&*544^bEeyh5d9`zm$b5+i?l2xH*gO=COY{;J z0oC?9AT4#E;C|kmyj9%+&6JLk&oo(@bic1U|eM_VXEl3!q6n3xJ0c zWp^7CDa*a&8NwmaAl+T0AkLy|kR83Qwi0S6Uocvp`4faUGF*lrMUbpaaH59`>EnUk z?3kz@@f2o0U{K)_mTLFioX?B4F41THkheeioO|6v)MORF`ayyUH18lm$qJ+(WzwhB zzuIYtE7g@P=RH_t+^o`Bt;9fq^OV3_Ns9a>Q+aRly-qD-arj*2tUEh2+W||bM}QqC zcxi7H=Rj*CS44_wek{`rwmJ{Upb@yg$sM1Y3cZj<7lGl|hnY4yp4*In3@B$yY~e7z!+7sS3P5B!k2Wbok3XPU!XwB;^z4rB zGT6nHqPnB(8&bKmpb2_QN$i0#O=KHY75BwcP(Hek4w^(42@*&I4zrr+BZ)x*t&d8| zl3DIc!Yx=s2tXT(;JJh^V=SU&oe=i>vMJSzAWf+JULE^XR-Uf)cnF};eWmaO!zh&< zu)wE}+4Pxiw4$665_Pxbm7)PguiN)Zm9$&Qc}#{t4xl zD1+jmVk(I-vl7qUU1Nb{oTTe9p5wR}-S9$uA&o0H%|*!dX4xZ)_y~%mUb3)(_I7{; zF~jsuND+BZP>^^TNe8i6lObeby)nK~w$}J><~WBBY`~m%k7*JgkR&O5+f_*Yf=4OD0`0vRI?6 z+WFIjk}#%Z$yW(3qqvUamLk8!OgxdcxYd3mtM?ako-Y2o+e6JW>TQD>A)oiy&VZLs z%nR+2C)!dzKq)Q0RF*+fT0Tn4P`MxajH%YYwE8+{$^fX!1$u=-25dvagBSMwosJFr0@2`@#< zS|FdMg_6v5DXxK-lj=j zmsH(dIyqOVQ@v9~&5h^jkZel0rpCwKSua?FCg7XD-L9MXq`N^H*Zr=&YB;e)02{d7 z*6)`{gEIcPTcFKs_RCID02XNgVv*{s_QrRuIZMVt3gF}VvuCEfX^BxZm31?<3IG11 zu0aZl#_R5t^76a%l1D^bXG2irF>2*Oo*4<^XEc%v0Ogpx(=)J|HY(h& z9sy*9!GWt?cJyCH0`Mx;Wi+sIhBuJppsJv79RB=ESmC^<=5z)x3i40jfF?!khPC#? zXVGSs9Pq=I*(Y{)D?s4-#qkLb8~Psgxd4FiPf7a`#Ba)>doMCfGTt}6!%^aHk5|V) zUa$0lDP?$6$e^gm1mbqxn{JqdYNN(|qnFQT=F#?bm<=UvB0B=&y?2RKm4x%0snF8|2ImDg@BRq?@+`4pCM(= ze~JqHLtQa4{wYQLHz0suwGFF7F$CWg^+#bmEx_iF3Oms3uqQKM=^u-+`@&F%^Gl{OGs=XmVr79iZD5%_B`=pVB zS2+u&%utgnORNiSMdkjE(;UbKpf?EBciW&{2RKL(!fd;%`o`!6XxNj3B2O_Lo+GU) z&Ru|ZPu@24F>=+TEbtI7518#@`0*~40kFqLmjW7;XBKvkUYRiWM0jK?0-r=aP~EJ%GSf*RCk31A z_B>E0QeRgrXWD#Q$%~THh$Xl~Ci`I9S*AAxp+k#zDDx@kHz=GYqP+b_#8;q_iDH8g zw`f%{vu5w;-mMK5`jV~iKJbg=lh#G#lAS-sVIO8YZLK@&YEuU z79Mi|SsBWnICTcN{7peh+@j}tR%`zoKHxLXy=lniKmimR|2f5X=?2%!h(XJj=bV=Z~zht)aH-LOpo9c6wv znQoE@(Wa>arsai29;7s^O3^@b@I?8se6xhiy!v0s6tKmb)0hp{OM?!Fg!2fm%$oN; zJB+f&h+(S)E`#`PQ+_-mdyp`D0I_a^(2&y`WoV*ARvB(nQ^LK5_msF3N%~C5vlNe~ zgyo6~!#JoadCy*FUY#f_DPtZ^O(PNHR6apT5;N-jTKN z31;+xQ18iRPQ%l#Vo8Og$)I?cGFgrm>rc6u-5@b>vM=ckb49ejHkv}5){BXn#WFY* z-w2X#p*$+D@l_ftI1VFhn z^(tc*Hhf!kEI)c~ok6x7*ezUc{Pfz8`QqOSRKO*cXzaqN-It-B&*t9h>doa3{l*5s zSYd$s7gOP%VnY8DQ{k^AM)v=$#)9)NaO^*u3V#o7{gxcXB8V$r>ST&^ZM&9a+f#SU+C0F zuYU*a=_%u2Qp-t+Sn__ld(o&y7i+dsOdm_7nkr&Z{SZwZx! z0%Dct1WD=KvtTcnE=svMO7f1WRO3$qEX<(q zoHI+i^O@Y>p)KmDM~Q4|YG=-z)Q*LO_J%hE06zw!yye>5MjI=&Z6%X*Zf?~1fWp&TbzfG?2TqyEIvvcWf2?*=uSa_*<}8>6Ge z6LD|<=fp=j68{k@N5BJRYypJ;q}RAv#)}eU%Go)c|7XyjBvA+n2RNh}XH}p2sQ+`i zaW&hMl-oMN3UCC0=p!1j z#GECtPHl&gFI-w2x6m5Rm}9_8m$eaPCj_8hL0XM0E^%gx`r&+aL%Hp!Nph9BYg>;K zwdtaliUxb-Cxh5(G7UKt_i8@#GCJL5zpyWbokUN40k7*FwWclkf_hT2Ir{2h>~I2| zp}&NvmtZvHGp;Sy9tK#Isq?hI6%Byeg5q-L{K6@vG1^tf%(z*(5d#6GA73dU20$j` zBu0Sg*T1mFaYb$}VVSP)0@}+0HQ}{ex|;wau|5h;4Z*$9W8EK?ME!-!NrS)qVkK9a z_1;yJk1Gv7(|)uA{;$$<)*llyiCwg> zL8AoFlDT;MNm|bP#{jS&9R<9Rdi50`b>KuSn6_Qnvf_(4mTV^Sl;h6k88cgo@GVLU zrfFz3^gI{na($4mHw1EDAxf+*8scWH{3Ze#B1rVK)fuY{RR@MVqi@o>3*5}>rXvy= zUxZV)`xtSee)3=W-1Xh?sFhd0YYB;Sr}1dTgusbCd2d5Y_jgWbZd)}P5o(ctid@D; zCj1z~&3hyclq>u(z)8O%9ZFHAD`W(Nj(-Y3X;IJGu&l z88bhB;A}&}pC*_PPYoMj_{C#@PC+2h#hCkAv_=_dTBUKyGBx|~9r`E1@~5-Ay4<@& z&!*PxQ*m(Zq@aCJO;74<(ilg^ToXyZDT$}sVuJx#cq0VS!+k5cfOnn8n>V>fF9BW& zd9p4>Gsaf|zpfvH!AXc-d&)&sm<{W(I4CvhEjFVadlqr`41FSrxubXBjXRW@NLYB1 zJA{2Wd7#SjJQof(md->LLIISJJa_GxZpRq4E3#}xEQif6_gj-+X?2z#yq zZyQX8^jK}0<#i(L;we(BFfUVy$HD)VJTn+2e{0F zMx1sxD?FWc!JA9;N!QDjH;HUtxpC+h(o8;>xgX&!Jn(L%>ViXamH1QbD7abgXd$5c zGLgPR!|nMCpx3IW@n;CwcR_hv&-av=j`zWh4?X*g)6=h)OD-KR?V2EhqKp_jGCrg# zIz8U4*dIi$qLrB?P_3uwB^*!PZNX^-W)pA2MkSU3?of4*_z4X3uw8*rn5IH7)MMRV zR@fm^cSdn@E=7Ldw+=JG_yumSuT6uMdkWsr$pmV@Pm(|~*`Zzdey0L{?U8cp9bT!shcvI*v6r#S<`S zcqGa@qp+T6YW2Tbzb##)af3slX~_#WJ+dE%c{Ru}u^29wlS%Pz^Do4_KbO}Lbr|&6 z8y$ z-7rfG?8Ocv<8_Q5xQ)V1bn3as%X*IuEQaS3127_Dg?Whj^qigB9{xpse9iWWH)xri z1o#+xKGsR}8=i}tTuZ*l0Zl`LvztcaOjluQu)ngC0DGR~>qpx!73M{+Do_Pn0z#_n zglNJsFz8r2=`4tH(gSNjiD=fjXORsd(VSE1Qw3U7SdnPo_(HN;J7lJ2W-#*Q88!z` z>9?eN11QStWri?V8OzOgkw$$|T%1IOJrEgVoyY@@#efg5TN##?J^$dsP`y2mQc(?YD=ejSZ<(HJ#fQpFUea)BT&wNneH*zSm{9 zU1>u=%eOHDWG2EIaM@ZIDe${Aq&G`f@XRKJ&z>ch*~3OCd9)7gme_JIn)U!W0^;mE zFT`eRdu-SJz&O8j3EChves}l@n`W=T$i-i#?Y%m=Tf1$qTx`7uh#FLLlYOdWXF`>r z01EKE*=hyTPPxscGPrI3Dlu$9YRe&>Nmf34Y^)j zKR;?(NNa|x4kDkA%~aA?0kb{$Pw|5n`p4uD8|=ABizMHZt7}7zdB~*`u?3inoYib( z0*1F?_}fR84(<9O?X6ZGGwRr8fjNJf{IKW7x>}^LXghaxWkZSw_B_{$_Bz)}?zhOZ zVZ~UPz65Z?aoyv+?-Flj7T3ExrgB>t4q20m*D;yWA%4h1AVU|ju#o>LC>}E0>ViAI z1M^`C!?{CE|H{*|EMVf40#Zh6oy1q02mgayv|i+Ylz)s2e~b70<+T0l8pD5}6-uVg z_O4FGrp|x%ef+igM{U<3Ce?e;1Gc6$SYBbN{;T|B?j!-(w8^{kQzL8~>B; zWBqrW!7BANyA27nKhEGHi5~?VLFk8(3y@5rC2@=g7Y4O_ECB-&ZKH4!mZFmp$a}=w ze!DiR zf7-v-R}DTB1Q{NCVdjk(W)IE}A3j||%y2;IXiV+_tl|?^;Pr=wpY^$${qU#uaTCSp z6wED|_>_wy|0Ho66an?Se1{x&TA)xL{C!IL2)PTia{ACva|hSP^Wq3!Rc!T~+6+)< zIOS|S6SwG62cfTLunBE_xLx{HY9@Ex*+VzZYM_M`JSw!-L@FIiH2b3AB;>BoZo5_E zs0}b7TF$keGFMY!B4~*aty;Vkd*{uNY>Y2o4q!xm?<2N7#5ggI#CEZR;f|Qj60@nW z6Nn{uOvXimtpABse`$%)?!dZ50(A_Q&tfWhg782H1tq9=CG!OV)b1vvt8sdZ$M53Y z4f0?Jjt78J(U5du)B_htOJI8j+=vuh0{F4{Ak>ky>u=ie+5Qf2&w~I9wkO)ly&%%N zccV-`Iur~jl1Rrj#xpjm5CjE~s8^xiGbZEtV#UEAZWraHU(s>yM)8D7c|jSE`{8JS z0I95vSfvDqtFPWl!nABktQ_(Vv>#j7bhK96&_BM~&27G8G|a z-xvGU!k9&GS$Leki3Tfs;-y=GjO^SR575wQqvo;^P)x<_OHln&%oa{aN?M5%&K9-f z5}s0l>b4Hl5PagvZl+gz@>_(Rhp96!;kVN(D_xP3bG{ac>)MkLeUpPIS`7^@88MdR zc)BuEp!N3cDGHU06@5}OG}cgWU_tfJTz)#GTGQd zR$M>Y%a&~Gt0QMz%iCoAT_Mt9YAKpJq+ojpfeF>wvnn*HB|dR@dn{YIzqM{Emu7Q= zk%564j%mbIpU#t4OinQ4`1a?yzx|?iqB4+0bO;^o?zU+L22c*}SV1>G}dzniDAS?AwuyL^i@U+flvsjUAz=kR@*v08!UO%ELU6E|Ei|43YMuX z)s=Jx#?(>XH!i8=5YdKHRKCcc-`g|13ZKG*>&FI9atSca1ED!>;DnDAkfya5ZQc3s zsA*#mj24bhvY{D*h}BAwrgDqt&BsDf^B>EubQ?@CQ7f!wuZhyOmM!2S4s*|-UU7-T zp?y>06qcN|JHr7Pj`6vC1JTv9J->G`ai3ke_io$yIE6_J?ux+z=`q|Ltx-xVGIS>v z&Bm$UrD`N73<@-;*dLf5n?(I+ddcU))ZxKrmD#9I0wwP_{hoSy>*5om|nQVoRs-t(R$xJ z*m2~1Ykbgq*gfFTQNxO3=-|~aiUJoBOrIc^=K%QSYV0urY!HXh2meq)bOFc_+JoS) z^3q(Ganw8&sYDC90Q4RznA0iOd_Kt+s(;%QoPP?Mpm}&gZuZ9E-pj3VKh}vro*wR= zn78}h>j>#FF0YJ=6HmKI{i}uLm>+KTAW;&_#O$NYU!>PeUUt3Giw$TAHA9yJ{= z5ogYYfHi8Pu%aE>c^I&Q_AN(SO1E0fF3y`Q>5J08=sgF(i*_NzHjc7I2Bu5HStm#< zODvanf`9hiqqQU@OYCbtNhbUR{wpiQZVfPE!sRENjNHg*rJ3atfTY_@eJ{t*p!lj4 z|KyGHgR63NEo@hwZ2@{3>%OT+$Jpe=tM9J92~Xm{<+!3tSO#stcae}x2D}eM8<1L6 zxzDSY=H+3~Sg5DI&(Bx+@gEtlGl>G@J$^zaiUVe)h{f|+j-~--c5OY>x7XP$oMWVB z!B!D&R%>idsR+`pjiVFR(jWZ>4<0xj#?BHo6!MZFP|BU%#rDRjx3}0(mQ7;_4^sn~ zYncx|X0nAZJP5*S(7Cjp`jvds&6rP znIdC#%;n5jK8K^fxcPpkic7F(*qDj1ITAa{vb?f(%LX_?=SM@_fb!>qQP1rr2?KJH z1A;3x$zSG?a`BIy;KvhDq@5o|gX8bq-DvyC2HR*^=^>Y|ilq))V5XCFnNbgg>!Zsb zL&en#I`QP=gpKCE(;e2MUe7Lo$}EHwU|!{MlWCJM04?8G_Sepe8}D6@J|OPS6=_WRu~LyomnIPJ2O5-u8vcU<|mRHejAu0A$4iw!|aH z>Ae!;QYm3Iq;-|0>N$+`E=TCyrjUJKLFuVrgK(()&O%9a9li?qTfQmGln737Q9ktK zwd`t$&+IZzh11{qCuX`5u{p`L+*LBUZ6z+3r-017I0?eTSolr|pS$cN8X;-@6wNM~ zY7mb}N$$7OB|nuXl9VLm6R9eD1qVkjiIJHncS~yax@i8CaNNaS_!>O9M!u&pQc7om zxXy1o9So$9>TJEz!LZ`{C~5!9~?7L`SQbWMFjaT`YJ}=nft@yk9p#ZSr+! z2mY@F-;2c}fpM@>FO^bcEgS*O23Q6^x5{Dh;}06Tl+Avp0NZE8miVM_HnuR!`lr?2 zI7>ah=k;d1!wZKIP}(+u8ph`-#SK8W^wJeBz+Q!1K_ zq2P@zJyGU{M4g0X5aq+-FoPLYPZN`#K3L0S#@ruY#u!2T{;bsju#iD03{1p)GRH_t z95uMTe^?t2v}XkA%s41G?Qu<Qiya!f>`{&Gf0`PhbK!aC3bzogD9ye)`8NZA!{!5LN&iK`#F z`N};A8X?P=kqAqgB#t8Kn2S)KNF&IUf;=EZ8zBW%B-Dvq`1t#xOUn&8G+?(|AF&*r zt{O?3RMtM_6fr{B4u=SY&Q}3FM9D8NXHAwNMyq_&$eh`2xs%zLg%y}RV*Y3JN1PL2 zi8@7(!*tC^6q~nFAxU$M@?#ebo%|Iqie94jnQwkFq0~4k9r0v z-Z$B>B`3xH-F7|8CYg=hR;Bt)TrjTp{JiI3J-6J86BnaayAI#+`fbH~va~!X0B54N zP2jT``UMYdPd@*_dP8C)-Cn}gonx?Rl4r5CYsD2eshJ5t8g>52C|J*qKmc^mj1h}J z1M96rP@tIo?<2Jh{ME47y-e5`EB;(q}QlKB&q6rEWsaJNGBuM@e79&^5vU z8d#0@XdQ=Usn*4LrBJdrTYE}2LFG1_4`+<@2{@<|6BF_ z#fSW7s_*X)g#R_w_uru_|4XWm`40~Acl}8(_PZe6Q?+hNN*F2FIdu_WGZ@7P=i;GtfC0W>LU%{NU~4 zk$mUW8BX`cVSQ#eaOH^U9nDsDYnPVRzMNlv9iQZsy&fl3yq-fO{_W(DIZg6p9rxcai;YfdwcZ21bdg6yX*k)cLfoKno&y8v>Dq zcM}-u>0uq!eUsWJ*v~>xjJ#QFq?+X4@(^HcN*cbXH90`7KXk9c6Rp;;jZc|5GGEtc zee7{xZt@6>YCZ?u%`XP8$Q)UfIK&byzGONNG{Aq&!m%b`s?bU8MN%18j6fAFrc0xG zx+8sjAuOLVA@B9U51m7&W=N)v<@mX`)}!zF2F`kljFmtzsRZ93vVQouMT|pwLG2LA?wf` zm!2@QqTG5mG;lRo1w7!RGYiLxZ70q|@F%X^HfB{}Py<)KS5n^(qqcVtjn7R3X$Gr# zflX95a<^fQbb}t{_ak^%qJfPG!s0Sp+2KwSwim}|GmnL6umnl&p9o*#Fl9z8sxT;# zN#eFgWf|XFUI?ON-*cO0AlSR~$xaG|*7)hmc${HCTKuG8C`-Q=fw^ooCgfXEEqHHD zVP?RmX_Eb&Vv%Ch=cw4<-H9=6a6PqeJ_Q`1uf)p&RrMCp1al`c9bdAujXH+LW4-0S zXbado?Gw*S2(o3Z^Mmsd71x|%M=Uug#go|Nmtnf8pMjR?Qahyceon5t%X~W^sn-%% z@^~K!{6zhstS0w;?KyMQ`rz;Q$(HrZRq2OSfPwi}#TE{3D72)4w?z}X=n0IjmD5ZF z;&>^Pf)uvhL2q_4KR1_2JyZC#a|8>RG0#`t}9UXh4hFLuZA>; z%34`7rqkvJHozyKV_=at7R6ogh3K_A+H4|X=~1r|)rD=IFt(wRZ3ml!Oi)sb+RPYjMW9J@($9#Fi8H`^;fBhpATn0;tJ<(0sK zH=KNkq=)$_AOxG}Al^8|Y0iP)5DOk|{Yxiv470Z&p5j$8Y^Q$V2p7~qg$%d-w5R7o z;$pc|44<7qrB@UHoz{z}rZJL^H~Kv!7=fAf(&vYcJ6i}uxJN>cnCYVs3@>e(Xkv&D zz2``y!g;KHcig=NKd^Fs7L=XZ=*4Q-%g6gXf%2#gjUBN?3q&s)bV2jEqkxz7)`xHb z@MNGec#?Z37N4^xys%*u?B4OF5{&zA;#zh?@YnE6OZ!kTB;Wf*EfW?Ku9XF`{y*?52gNO@>?lfV6H{YWqL()OYm-yaw z#8**k^%u4&0jp6L@e@oej`@D3{Br{>dNd?GHIktoG^EtWtz9cf(RpvfbG0#jGN$Nv zL``=544LH#7~&(t#I7Q0na!|s9O$cmc({)h^Ag{i^9{-Kn`=7dNt?-?QE0b|EJZm^ z2e_W?m3x^S&t+5%Wx-)jMEoSa2iK~iz$lmUKBtXo zAqZfWA&$~&HQOI@`Be|9!LM_HJVlW&HaP+Fq&*(vBRqwdxl))#XDrTzQ#iKp$){O9 zag#;)RHBel6xEN-{f(nQ!yH z_aImOxb$viK5mApwY8H>Sx4bI@AwzLVh;;GeL9EvRtptGM{})08wsX8r1Bq6rF)jD z?h)!~dO8S<>Aue4>`556+YSwKJ|B}b^v{xk&Aj&A6E%C?La-_g$=gTAR_K0~&UjvQWpkod=9;q>#O2kkHmUOzD%HnmCIlOS$uA34U8GkA z$3q2Po!pTqr*Pa8lcuFcnea!7MYrefaH2@r8!E6#Z1ZU4gwKkOwKY4aTMTLnpqU)y7}05{a%9f|Yb#qi1m=g6;=_M`Ib; z=l1Q;{p)u0o6eB`!TP5%e3gpZ_RR&{94XLmTj=p7JGQ4GDCO z6N>4&ImBciis4~3mI*k+=_K-t?m#!M1@R!KQ%!`Mefe>Mp<)o8WU2z^VPL-}8%*_1 zQO>7XsutI!#buV7_mMQ^L0DX+(D%|O7(w`%e!0@N*^wl?=SH0cnSZPfvnt9KGc|;D zt#2R{=Aw^BCeZQn*;KqGkYp4%=(lg>xk@Vuxuctb-eqcss_K@m>vTC?(f}@cyEUN^ zI)__*PsL!h&Aem(&fbmWW?7kalY#R_H@ugKq8Xo;2Ukj2aDYJBwuS!_sysUIh zBoZumblSq3o1x#JxU+5&p)Dkj*q~V0QGvm(3+sJiW|mL`-QkE?Qqnt>M)LHPk-moG zA$8bdk@ous_glu}N6cri6|bPV#H43WUm13x0+U+16x5tw&^GE_ z-Y<`GC&QRg;BlzNw1O5a-Z9=EBn6{1qxpqJVcA=x5(-$*eu|D%_48dOi$?46tAyq( zPZ*>SsU__4@frk}6s-a<=p&B6JY6%n@5$349SCa=2;QXtbdqk9FKbl|7HApt${>kS zd4aXtQzIN!^8vkJQvuN3tK47)sb7<0SxVPCIBc3D8nPiRqll&W-qFLX=V9A==kf}% z2Dam&N6z`LwE>mtUCk62%9wMQv}USl$sT#T>F0Us`W-yx5>UwF_dNv2Sir$r)mLiG z{-MrNh<-^y&t$&~8Gzv8OlvzLF{?y*v|k1qhyE|>-aH=5u5BAukujO2WQxqgIhtoO z4;ey2nMr2K&_I-VjtVLBtU@S4B!$ROq>zNn5=zv2obLCz@3Zqbj??u#-}Cln||}dX;$yY&NE|Ph#5=EV?(uqHQpa`Nj=C)_0j9M zRL4yFfhqppaYJWg$&F4YnTAOow!LO{PF8MfpRdJK?5l}8Qrw+$`SH@TSfQ_0A58%~+>!h_k*fX4?ZlI^ppj;ipC>Z}ZXMlqV5?v=KCnq@x7W=1^9SaZ zYX(w_`A-C0lWDZ>l-x>{kVRZRbE58LmT2U-$khqguM(D2w5OL(F%Q3g9g-8Ka<%rJ zq|LV(vpmIWC7!r@qgM{q?V~Jxn4jc)hSsF1(y3%HXLLpDBl?nl?Y`XU!So zuj?$|>U1<8CmW!%Infl}`Zysi*hN%O>&Q%|<*BKD@f-WXl*9K=rmWagzDHb0sDAD7 zgw8hp?Nzgi_CGdNO4=^sEOYE68GB=vzBHGvrK@*nOkAYt{xw#vGV}5$kB;x&BU+~( zQ!TdvZ=kLlJDGR-3!jyl@SV=>a9>_R9ul`=_3qvOHf`C~GvsK;{cm$VM_^l%dV%bK%XOjO8h<3J^S<1WvLf#oh{(I!5ln`oVt>$(&ljI@$*-a zrv&LROmcj7VTFPuH*7}855EriwXjD)I_j4h>Ze;#CR@El_$Xfo@|BX6ke*9%eXF`A zS8$5DyZRJM+fhlXCw(uSjusv;NtN)YQ9f}-;^}_h8w<-}*)x_=mru)LhNc^5MS15q zuHGVXv!U>P+!}F^s!aa9F8O`d#8V4PYqAEm(Y^I!XLGxH+S2dkTU#~Iu6X>BJw5WK zp)KsB;Sa$hRMzuf&i}eRxY{{3SV*cKR%ydwd4n;tT=CJj*Rvm$H)a;H)-o_*Bab;dydPv*J9>oAE~>fr_tcItD|L#{xWx;T;AG6G5`DfQ5JU2%en{hT;nc#z3-pX z9?0X_&&V84DOA4Lnv-tomH2l2fr5d&qGqn*;-#M+Bv(eadZ3gSyo)0L9p&X;RnvIa za1avzuEE|xc|rZ_1<(JP^72=C`2X*e7rcV;|2lg|W3d0|&4Vg4%lP3oX55O$dhmGYKG)i4Y6!7R$umP^kJK^J@iuNL6fWF>(08% zQ|y;&GUR_X-)a7M#&4Cj}S)lTv2#SQC~T+7x!SJ0aBE8WfU*{465HYkdRe)v_9_4$Hf zv0UGiJjI&9>K6}}M@28+-trR+tgkhbU$EJfqwX>=zbJ8r&SJ$myQd!MF%s^Giq<{n z7{D}fOY0$*<;^V-y=Pn&(~oZDc`5hHy?i+)Z$-;kbMD8Zyo;JIeyv!4t#xM|6btp_ zu5d|b;riJ9)NQZZz90D6GT-+7NhyBH?+srv9?apsAGpV=(opPWS63O?XtD5_ z6w9D89%J(5QC4H=*y$S&+RJ!jT35v4BfEJRD}O5oq&4LRFtmOXhR9?Sm71-O@mZd?-P`7MXk#S1HJ6lSi9@F_^Um%Hi|G?dG zTl(uuiRC}I)ppBtlP4j6A3qCSMWG zV%KVXCY&A^jQsfagV|P*buuGW?CeC(GwG_H_X*6N%!0_qx2?bnrUs|3%#tZR<-fxs z>-{1wC5mG9t!(>a{&@b4NnWSbW0y*r+XIAuO=^v<7qYVrDakgRYH1^Dbuc+I*1uAj zD43@m__#;ePwpX|spe(1`%md<9fOL5lMQR$Dj0Q+Cu9}1m(k6VKMkx$R=<^1K{X29 zQ1!ZJdA?aNF(>FIvv%sS(p>?~Ki#azCf&LG1<6^?8$N5OKvO1#soJ^cOyRQ{KqvA-}M`lnsHpC@ODOY%GBr-StOL0*GnJ-P*8?!d6 z{qaGj4%pSVH7DXqp1S_*)#MgcD=*Kw=}Gd~C~Dkt@psCZw@ z`PUp9E(ZK~TYrqfa*?m9W8!<RN$o%D43u?w1#F1{RxZ-Zk!$zj&4E*a&-P`>(@88G(VWYok2 zPPU!H<{D!Q`e28Bm%d$a!v^kWa8)-ZZ?W%Z}~lV%5n(zSfqm&IwGIiAcf zhkB`+kAWZ#cW>ZXec1)YegxT?@`@DIykM(De-@e;BO1&BooO5iF$11^b<)O=C zKdno9lZ>z1e;jajE?Z++qcYT9GcsPG+!y=xgzg{1GL75o*@Bxr)Q?AxDQ2M~)sr#z zI6kp=JXZfa9$Pe~dL&HrQ|LvFBBc=Dx9@9)6nW->Po|X*${CVTvK}9wVls>w%#_7$n zx|Cx1n>K0$J!bRMv`@>YH=h`LFbgsncUPX1GDN+ei5y$2E&0T0&-l1jnyP3f^Yih^ zzTo9wwU%jRSBl*!Pmo7R{Ak+G_+c$m#C2hIxPa388oFRWprN|=@IJQJ3qPpBJ~0K9 zBwoKz%fx-8G!gS=(b8O{DpI*8ecU-g_)uw9GQSAs&UBfFg7;JV zi34g&$swL&ROUhbn%_d6sF|`xc~Fo%592C4OJ6#yq(30i?>cEz#Y-A^gggD1N-1Uf zTUBQDW@G#Hfv2C1pX$=}KCm-BF8rJN`_y_W&%>qm6hGq|&%QI>F}~cj%Ds}XXGNn* zYPoo#W?y1laMR3INfN)+SQ~|Kp`W~L`q3VfsfesCa}~A+VuCeCb^Oe+vLPs!lsd=q zvwWs*bj>b0cl5di024qT_SlE?wiVje=iw6x%h`s17cdma@hN9}lcNWc2!+ zrGH3uek8g7yVOeHbY+1DqQgSnhQCbO^ur^&1*5P1c@(AVOo0#f z{y@inX>vI?F{LS{E2pNsmdk$|u_A-D5me10_xpNkvm+{>qB>R7$*g~lYPqB~?>!eg z1CNxQaGVS2R=c?S=%;rdxu0J6PHBuGZ|h z_ryCzwvDC-9Fx-H`LfnWtY_`wyAAJUyqYu@Y#6@u>Dz4DWVy{i{ro4ng=1tFNqt36 zhUgVimyYGS^BwV>)Qi0SmLbo-STp?Xv~snK7vdR>eqT!{KULD^wV{<7bA9(o*&vp! z-;*zYJ)GJjwbbBT?K-l!TKIv)**kMn$%NnblIutb`9{I{(uHr`y}1R)Be{>fX5v5mz5LVy{MK`9}|DBciQ*JF4^nRMXe#CYvy9e9nlWPESa=vhodbXQfRZ z4(nl$Sor$ATM4d}DIiO;V|SD@Re#VQBr`&Jb|p9avEAZe>3N4=p8jlp59Lvp#69R< zJS-SQ9idXlUKsJ8Kk?f1!_|7}hYScOlxf3HtuNa83F-~T&x29)6>>MSDqE$s@3$FC zQD0Fe?_&8TqY#r~T@kM*Z87MdJ`=V2$GPGmM?oUj=IaV)N{(?WzHf(vq;t=RbDQ6E zIQEM)Dns`=B0*}9HfJ+->$&BNcZX#qQ1x><;|eni#T&(P4;5arKArg%V*L#L?mEe@ z!sJuO2M%&PVfSWx;2Cg#5X*CiByN5r-slLse5CBG78!^6Liv7c**UbBeBz}oiRv!B zzDwh@qUrC#hCMDE$Tb?RQbp`{VP^{vkXPtC)7x&Mq8-t0+Z(x`>7>{1uPyiPN3dR) zwA9QnIvzYVce&NtKYDuW;_*@JM*ho;*9?y86ZEd-SxToWzSG}Cm0E_>>71`@eqbQ7 zSK*<01XFscQyHJAPrNqOnT4-oG8?ylO1n*9DP1QG@12i)?0i%2R>x6nhn(%u(TztZ zDH?q@wNJgeYhSf`GU?S+|AS`FZ%=v$PMW!{9SA;tHkEwE!DINUOG^B*>5InNpJUJK zPUgf$TbevGk3QM&W)cwpKsRHfVpO22(S-Fkho{dkGS5F(WJcz?-bOv4Zc}dH(AgBA zl{Ae#T*;AHb+w1#on2S`pm>c_uNno7hokoQg5MT-rb#t(srI`i6U!D0M`T`|xK{Or zugmAw0Uha_{a;L4iqCoRIOM3++VXdP7-n!6GU@SRvvEGWCsZJ+6$ z4f$8|28Vx=1g!-f&Ufsi46-ngo;#)}eBpg{*Qb~! z?@yhLaNOH-GSou%!AV|C(MfK<9I^g@fr}4xXOt?RZED|4QmuNcT#>I_G2zbaUE}(a z!N-nX zck^}h6mzQChQ>v`-t8H`6M=wT0c|n-9fd`Y^qz0-kCH3te0cw zs*A0}=VIk@R}JekURYOa^Vyl5Dj;_~D=MJXsMu7fU1xNbHrr^c;&C(LbRGM9>xz`Z zYZeVcCFz?P2khR|+hztX9(_f#Hskl9^5XncPq%uHpSQ#JE0~Qa*9<;pQ*cN`{q4; z)c2{}9C#Mv_~fAOBbC$l$CY|+lKH>Nx;V}|YB){BQT)B##FlC3#AnqT)n*}C9`{tL zH+X|+j^t+On{p?bUtSnm)gY_U{=Um!g0q@N#*c;S)&sU1LtimT`KjxF_Ohj+rk!Ny z=Dyq+eDpBx)gh5f6`93;M_w4dx*&P=hEHRWmulU-mrU^*%{rX}@VQvi?tx}8y4(3` zPke-b+D#!zl2NCa9HyjZ*rjW{0#R!vVxsPc!+Ps`27GQA(C}K4Fx44Ff03?pJj$3V zjWWzj^!a2a70&zPs&h;7@=FY#Rf%Vq(4PfU{-+f;9I2=J<8GdM{p)Q8d0!INddAuL z3?NZW`g63F#(dUeqinN#B(D5IOLUHW@5?mTFY?yYjMw$!s7KeLj<8Ryzv9@H|7DN`Hs0MvNiUmE?Ojo0Po?vuxp1Xg;Aq|>z6C9dgWa_$cR7znE;bhmweqQl*@`{N zvY>zX!roDPLCx)DO&^N=Q+$YWd)^*Wvxit3!=#rsAIw%>4tY#=eLEsXDi>PHbv;n} z7gD=A713oGT`B(Sq}It7z8|Y57bin+^{y(02A8(Rj-$!Q8f}s;uA~G@{Fpy6OgyOcL7FXim~)zzz0X&Sr;_nG4dx^IePpFFN z9T@CoNN3Pe6dEuxA8Kf%K$UlHE=t1;OoDK=v=QTEfDu16maWa@qPPIX)f?PpsZurmrj{^@jK?vmq!v%ACB8gl!x zQyb@R8{JyDs61j{YWb!_gfb;Hng7YzJgL*;%*SM{bZ>0Vu*nY~-+D3Bcy)j5v0CZR zI3>YP#dhB2$8g!g%;fFt)baFLRbjH}kGZ=`9E)m%4>)A@`%$l8fmfc(j;DuYPX(8$Xn!grZ&h-)lWdX#lzQ6Y-@V`+KL;ADP}kaojM-FpE2CUJ@rtXe&I;U#%Z~NY-ms zQa3Z<#W~a})eu%9SvPWw_R`r9_neBp^<>5T((zfJ;^mcou4+tk&Ur>}&Om)xPCXB9k<^wX$F>{y3|k}>_72LST*@=LV!9&J z1cQs#E+bAJIOMrI;*FEva5fE{^~u~_y7%%u%&D!o#Sj*@4N>a}2OK5C*gTmgP1mjT za(Y$9T%)d{)Iasw<-5I)kq+9w!Qt~-YptvJ?31&+K6f+3`{_-&it`!4wOPGMG$%Hx`NMBc5`@b zToG72reQPvb>F+Ti=1Z=nF619wZ3pYZrA?a)&7(9p!S0aZIL3n{kf_y>*R*z-`}Y3 zFfWWM?K|shoiBMjBhk`Y`#dBI4{rh4YGKONZhCrNz-auuOnW4IpE+j$EkTc?**Tu$L_52?W2|Gk~btY>{e>Wsq^po z2sW_YCyU;bzKF3qSI z%kOJPJ@7Vs728v^y7%7d9%Fyq0M5uWcipH=cahOr(b9AXltg;_J=+(bUtfE5wV)iMFFi3uu(!cDr^|70L9@A!S zKf~)!dhc)Bn=!S^Y}ePOw};=oLJRFac0*^KDn@AtQFGBqp8sal06$X={(=1wnj(?J(_~hZjqh5-*1j`@igjrFvc)Kz+I{+x$IQ#!>p6WjUybcvAH9FP z3AO0ZAB#$7Z#WdV@p(Yhk&Wh$)0g27_srikA3dF`XgIFvZ#|~J8Z*}$>kyv9`T3%C zANnfqv)>eo60IWSOrIl|Gaqco_y=!6?*IOFV{Kz?v4XO6qmpP z`QALGeZS^WdxyNvHTy-)g@k?b-?PW7T){M*ibm_f)QzfTddEY%-b^}MM4mx?v!GWx z^jV}77<9pdn4Bh~)AJPV-@QLBcji78`|hBcH4vIy_Jq{Q7Wg*gD&M@8_*==%ar)>{ z7sskeozCv5M%CDqxO!Pb>W@mzhO6l^Jcb%nMIm>7yc50#e4j&k#k)MmWTS`Gin3%O zsz?}7%#kaGwH+~vth#f3^;=TKyXxAj&&$~YQ3sa!cwX?2Ie%ZiBWw1|!A%yL4t!nJk?8{VRS+%7T9}y#EzbklZ)hf}CaKAI!wnOutxqlgic73~ za=^H2ChG_7a@A9T04?>VKc_pH?20akFyB6XO6ZOb-xnjTIumcf8zv|^1_S+Cmx;g? zVMXctb;B;yy+7(A!eZAeC~8VKj`yGORsYaB8TcZOU1+8&V$$8Yn5WKJe5ZWp zUpIsQXZg-wmFoYG4v zKxP-Kc|3)Qbl2pe2F*p?wmW^N_q$r2JIkZ9Pix_h!WTvRb@C}wX1>dFbCY!F9+sE3 z56o9*OqW*!m%lX}KUucODkhW>wfutf)^UsCoYunCGt1w)#`+z{2F&-R`!9cM(JuLT zKO#p8JNWdIcv|sl-}u?PDw*m>4LLcB{h1%P@2&ZSjO|sr$fi=3BUiZLX`yDZlqJ#f zeay@uJx#PFuene@Rqsc~M#1wZ)q~59U*^pleg@E&WG$`gJx|2WXni&RSX|NA>iVRo z_(Zg>#x3Kw>SAWs)m=ZgPhJ`n>CL@6(CO&=X%FQK|ASbObI$C2-#?+(X6YoQuLUqo zJxssm5|TGCzPj-$s|Z8SLhaVHB^rQntVw*aJNeqI2Ss?QA+L*ll$>$j;q zq)cp;oz-ziYQNuE*=mRo8&6$NOU%B^kQQn^r1{JKjWY9HPIjVkz2=tHa+a-TZuv{L zu`R>?qXRM`zPVSURIipe9IZPcWHub(c=pU&~#s!h`s;c7*a?fHU;!hC_4ed^fx|az7^vP^L*|=P2-0B7@oAp0OUg?|PsiaIwhto5`o-5$2<} z{nDksGm#qY3m5EV*+7zVz89?1SS2yIb+;g9KzY4AC(ttTzR-YF^fk&MK57kbLymsC zyaiQcMRFuZYqL-jM@_L?jhvxd-Rm5l?lTe@-D&>Gk>NE7v_cU^V}7jcOFBwc$4&I^ zzvv;QSGniD#8#lDkCyJtSLrb}G=id+wq_C|UwJO*yVEIr4E4 z|Ei|=m{xv`2yc)5tZU=_WHOIuz5?RQMJ+Z%XJ;EV<2vUA(*8)YXB^1zQx((qba_0Q zU!k2vdS$mRiRKJTWayPvrojiZSuWq6x(f{)moXei#|m+FJQiG(_~lcR`K2MBRizP; z_*nLNSFX>9KJ!oGck!y4vUFAGC5!NQgD(Q>qbolu)ym)d%FWeGrStB&S3~lrQ?Rh$ zv0+X6WW>4DrHrQf#~=NP<*)A(IF)k81+l&h5_z+lyv>ByLG`H#j3-l^l%n7Tb4%qyF>+{b=EyBc(J$JXAw_vx2PE&fLc8s-*_a>^=G- zE?jA5|HVQ|mI3dvK#f-%C1ngDsazynKk4*N7)RKeED5Ul(&x7n_>WzZn* zAG~I$*z-_)ME=CQ!0}6*j#3=WYM+8^6CaMgt>1flGJr4JRP$mJ*B)u?)3%vKoics~ znXFFJlH&Dn<}#oAMT2*`dxei!1(n~mEV`?Gtd$u%IKcY6M*PKNJ9W_~VM5EALfxXW z)W@*_$FkJh6IN_qIt)w=C*1tT_+pFEg2czm3jIpiCR}iZS@roJ0UK4+qr`U(OM9j^ zm1CE0xltaaXnSSG{wi%ic(prc$!~xS;CVzf*IB7QfE4KPo0yjF5Z2r!aA9-+S4#Cz~m6onoy% zS=7@zYTa@+3bgsTR3m5oCS9mtow0e6jGkQ2Y(~IV)p_Vhik0hNhdsZd1`C;0yG|)9 z`^!>AldZr3|0|D`CL3p;|8CqH#>wF0C*XMAfT=un-F4+qh>b55HQoCG+DmkUhnl5N z-};r9)NCDWTy*<-84YLmqiUXr;LriF3#reN$-8bLCy(n(exWw(v=XFqu&tNizi;oO z&;L|q_kplz8ZBKi26^Qpn2B3XyBJ9(itHV$O}^yP7#6R;IALGjayL&rJu~%vhs0ew zTG|{rt@2-g&R(Cr6<^?H){&q|mq({%_50XnR##CHBHbu`kI1uMRS$RnMjyY-o3#^I^58pj% z>m;hu`?z}S*%W0~gwObQjMC+?&EM@}=LRYm!jvxzJh_-Mp?;lYDe#4NO8>XS=aih< z3hIRwi&+J`x}LuN>^NtwCgv)j@i`fvX?hC7b!OwhN$ALPcGyQ%-hc=PR*1p zW-q_L`C9h(m|Qh;`VUh?BeF;|m*lO;3RiKV?90dVT7M_0Jz%lzT^?WhmCDI4Ln7N|KWL+MA+7&2Uz8 zEMB)KL)zx*d85DuKJKr|+UF)o6HONOQeo=T6_JNRjwS7OWILfN+HBF1^0FaSt?yvK zbHv8*b#Y0L=7N4k2A1{B+K0`f24$y<`|5U87Q~$noEMQUV82xKaq#f0Xv(vVv5tLP zjYeXDiDPfgNw!o1X7pdlKMRpX){q>-jEzxTx^S2Kv56JK)XM9;qYm~y_$?Kk<*ADgz4{5r1>5hGJ(OONbb zb0c_vaKGz3Q=F0e$o1$@tbEW=T@QmjiZ7DGDCvChrg#!(#-)$@=u$-aSvyD~j^(`B z+Gwbl`-J>$aqS)D`{AV#Oh5zehA!Dg&c%FRW*Z@Tl_?ns)YqGh`~9OQZinQmQF0E> zi(>qLA5*+I7R5_C*d@;UqW$J-M#a^`d+w8FUMUuNGvvhc=E~`eucAvzn}R*@JeiC3 zylg0tRAwbkxE%-I!VsI*@2_8QBzr4ldaQl-bq8wFl&VG0&O_&Oync!&#KXz zQnGB31@C9IyR_YFg}Ei8TzRh)HQqc+{^wE2^|;a7C+%l8FHGK!_^|s;*O_%r_km*` zrYoO6;+A%#q}aV| z`bWa*&z`pBHrwH+p^+mG*+!kd4p-;WS!cLJy_wUzD1ChT@x=*8&iUex6hoE2b++Pc z#om4PRe!$XdtYwyp7N)$&g6p+PIlFgqLdESNEJV@`t$Y*+L=S0lMSxOzd)a;q#GzT24@06UpB$9W0EndS!V0z!f z82bHt#Dsv%H2&lTU4%K~vROhHExk#Sq5TCbv!X}?hZ^Q^uCU~;VyV0He$_P8E9*B8 zGCQ^Jp}g(CO7~Sl1~Z(R%ep^eWbM(=Yjnl?!@KTYAzRYZyh?uUQUPUAy5-Bdz^8ZP z=v&*~sTcVv2lNl$IA@S5oF&!xfv=XsVqPnpp?;y(lu0u^-5~h%SA|oYewRlV7X22u z(#y=*ecRKx@-HZ+Jvi$=GaJxX6q<4Ot;lA^A@q-Sc`HaL0#jaRN%g1hrv#b5 zvel~3Q!)}us7iT~qHu=nk^t3+0Ak@{&7-)QhN&+JmMg6ZbQ0(|>#`gTrZc-7>O8A! zec3%J%qMa&!mA!kyb8zU$r9P=4E9iT)^!BDdU0%^Q8npS-LfiXRrILe5fs&r5r_TL z@fv{_ zw2xgldClb{A7QQ7=B#VZk>yvKWci#a=3g;Hjn<^tcMOUymqwZev(tUT(ar^GPH6+PdO>>=`F)Vl2)|@x3Uc7&iG)_*YC^u)xHk) z6}wf1z0c&M5S7_SuOdq$m+8|IuAOs7_jgw5?{)3ZonnfAL~k}-m5W76rG_j7nBS6U zm|f#2`cAgql0wI`s$LZqX6P~=xG@)pnYoyMcO%p?(C|FtBMa5Sw86Eeh(`ix^&+E7`=2{|-^#Bst7!Ch-&7U& znz66dz~PYT`+dq?Z(l#X&nT#B!fa!VI>7OTX74&>0^8QB=6AUtfAppPu5y!`@9^pf zQR37DG+Bk3h{oXFobrppzo%HOe(@ed|&GfbXtDfg=?@H1&Ef4mh~Yxqm(+Gzx}a&Ep&i=M32UG=L%^S;mhHSVPL zolMm0WlP9yI;3FaG@=r2OFD>Ny?^B@C&P~s9!KVw9ML1gyY|YYgibw*%}q9-HHjtv z_=wTsG~*fHxxEg%zDyK0MO%uhtz}hC z?@_d{ceK@A{gccgspy~6s)7n6%g5~al6g%@Znbh&s(u%JD=j1XDCI*7w~TKwpNS`( zow}8IG2<;inftfjnOZeAU1xoj+HucUR6H&9`Z9BXGQBn{wO5%p)0WCces~Y<%~+>` zi8Y&wCS#%RCZ0__;!)G~zn;8KTeCdZ#+cqq`c3zco=|4#Gbp?wKm$9qLarjAu@LSSVd_H$HLT&F7n6zwrc} zl@@>aGn+OQg|awy%!xIv@_G6bW8=oUjHh*{Y|OV7Nz#9Nb3uu%cuzn4cMg~T{fU+T z94`O+0>};JtL@;?(>|GJ#=|5$AO-xpZ%?yCHkz>2_P|Jgw^?wt)R-KF&kt{&Fn z!rF0eBdT5n`(!48+qvyB7qvo_&ib4qe^_;Yj{VP5AH#2nbJ^yn^}Me61fw$86wehrb6D%}ltX63Jy&4NsjI?B8;hxXyeO1>I z*vO+*P&0O7$qBD24LmCAO=vgYoVXN{LY-iLnqsmfEw#Qr@T+-!k?E(i_e?DUP`6wP zhEH2e2-EG6<3gQ(crKmP@}AJh$tz+G-0O%@AR%|-YPK+Y`Iu{f#zHrGOoF=Mx*Uq# zzvqx4LfW`;JcG&Xo6V*l*+fK!QysanlG(0eY~j!zXSci4i|d+_-hJn7rEbU8doHq5 z+`PazB@-n+74u~H(jf25d7%E?yF-R-F4Z^W>=5cpEk=9fDEUFhACHDO+C)X@Ne`GL z$|@wZ&arqMP~Vkwq&i%*C+NUi!!)K4%ZLvGjGZaAc^r0A#Ye&ts+=)DHouGIROlU2 z^y|XD8RyJFdm5)1AFXwzi4gl%l9AG+WM}6pANmr5 z8dr%`Xp^_nje0mKkaoZ!Z9LyNMn{RxuKren42@R+1EXijRNv=GPfk{?w#m2yPqS9| z&)H+%E&-RJcP}0gkG)VtzVuK-qxW3!S|-WW59Y^`zBu?eA0M^Y+sta;q19=2k-aTB zNI_%4T<}8UcrYzPZ{bklnPV#5(!2}5_Cz}vuh9QY4rZ%hW!Fi{@)wkit&e>|p7iX5 zT~xruKph0XNK;Kr&Gj1>Zo3?j?eqv3)PKei@y8^s!;?nwddu;p7iXyx=v4&CcIT0J zAP%eOJ_yfb7Au>AGY_f8@kN#K0-4r=0PzSIkLy=RZD}xwF6O+#luz zyX-GIh*qrF8gC%o<}aTiH-^V5YoYx0+M&(n^iL)qJ+HdM;}tkGkAC#S_nbnzdf%t! zkdP}n6Sc=4`tOeuNe=X-ao@+n+=c1#`V`8zp0F_VAVm-PLw5qzay>>NOD=)mSn!*j z;7OHLrw2R+(dYZ`iID7jw?1()oKf-O&DXOXE8WJ|TP&!Rb-{2tF+W(KJ$j7HvQT2b&_w#b5`fQiuBcP$|1^A;U0VD=GAri1RA$EcZ@o<)EPHopx=*Af9B4|F z6)-R@ysSwhdFzyZ2qrD$VkC!A!myHX{E*EhFFg-Gnr zy`wItb@~z)MXKg2$-MW*u~M|?Tc#Tar&{m2AiKM-hq}5}>>B0T*PxkEf9~fp1DWo$ zoI;dji~pS)80YwwJ1@r%UXzcae9djy+BNQ`>O&KYrdb+okHcKm_d~d7^-Hct%4+Gk z$t#pPA2j+LJw0Wx%a@kJ%`fkC;5EuXR;TknRO$j<7^yyY>QY-Z&GE|7l)TL{=;H5@ z5IW5kSMf`4Z`Y%s4^)Tm9!utCaWwaFe^p1u!jYpC+)k>u^}QiDr0LzDl?3`j>-|Jt z)L6AybMzz69}>cvIco6&Y&lSq>{nA#{ zzUIU&*BduMpQQFEK1t{1olCh}k|dQrQO;1=1K#z;|H>YY0T}^Mpk?f5>l@(dz$K15 zz(wFHw%qMJ>|NZQxWvs|+?CyZT>kwR`@~hw_&99i#7$hzIrxaGc(~aU)M!Bz!ToPo z((*my=3@7^EhNN?)BoRWX*#(1JNUZTogpxUJIEzC>Hc3bv>ieNTQ?UkKL-M%e;u!@ zaanRn0~rXea8BIZ;v|>5pPL)r|9~tFzf=zS*J1a67mRnlyiXhiMoLO>VX*(QO=$M7 zEER;5!g3*jta96RLgZfwBM2#p;KBg)29QX+WDUYw0Eq@Z+XspKYgFKD{_DX0pTzes zn*X<;+n1>SO(p^;;4M}HI<~04NC?JBVxS`n)CJ&?7mPz=AcF(EDhCe(x?d6v9n|gG zO}OSEas4O>Z4X2pyv`s(92AH+csRhEBrp`9Iv)k1&EGhz6ihgYkp|a&z@>0Vd&C%n z!vP=gg2JKyn&iOUhmnNtKlBcC!2ngbkoI<>izEz=7+-+)q0!L&fCf!AI3oO`Ne*Bx z0Y(2g6vP@lC_)mTH^5`a@PKH84@6?PB!RkWNFaze1VAkCSA10Q33|7J0l!`zvNdaA<%~5c32Q=vJcfL<5sLByI=3ps|qS9VtOl3J5r4`*z?95_oKeulQ{nZbEQu5Cf5F{{E2z>o-U_tW? zJ{B1GFo_cq-~|z*+cO4qLqWvBHwZ5&B7wa>5rgol6A}rc4!%YB+zAP6ZwW2peE27- z6cX5r{g1I=Z5WMbmq?$0#o@nzaM>&pEDq!2w$oYYWf%$8hw+g_Vha|C@qrj%76&9< zsDT2kCqx2^3l6kMgak{(_!a>m77M)ufHh)5Aiyw4SBdfmXAwGiLvBBf@b_f!Hvurv zSu}2PAs!qIU=_+$uue?SMhq}!Ac5eyhrm@}W`hKRC!W87XlOwb3GB#-w-F7z1p#Ss zC+5J2)5z^m5bF*!3;_T!e+O5A$1EUS-HACUU;_#XBs%Q?osWW636Wr#n1BE%V5mb` z1k1#PK$wgSEE5v|;ZgyxOiT!bKAgZU*~Gg82^XB5n1ckSY{=l?C{2tx2NW7NJ9Z~Ny4l=5Lz*wK_V*; zFv}CMxIIK5`x4kV5#n&P_(x#{6tDj|7Q~_LQ;Yv=7uY_cptt0>%$A5zVnERBgKrT~ zY9ygmG30h-!e4a%hd>Cy7%#R&Xb1d=NE>1GJ0yf&jAxKo#sg@HL@W~F9fV+vZxYxq zK_81Dfumg_7IDFWK8L}Hv&4Z|=#w8LgkX&4Dqs=jkP0bDlsPyc%(fnwv5C71r$0al z#(%qthDiq@1Y-gq^bsy@qe}?Z1UQ(gArx3dCIDig({mJ9MJ5D7XP_vsj7$iG-b&(*1PMkm0T2Vd%|c1+ z#2XBB>WTs@$%Gc6&>f==93G%(g7MluSlB@_I@LxwW_*nR~4E6UDO*l>Rp8~<;!Lj21dW)Mopl5RwSXIWi z2moO+4-{BdCIG^mTcLmw2EwlV+g03WTA;cTEG!dRgkA=4r}R5mgbNOsJb$~2hAuip zfwg46j)X!1VRf@D4^($cz2+n zMH&=XS0=Ow%rB5_1nsW~fJh)yfCTQu9GsX93EYV}FsBkIu%b-pDj*$0Sp+M}gh1%Z zI$ZG!@$NtX!UCklo#q?_^a%ihDU0(&A3cfzIbqU_p6%$Ni7ya}sQF&<%DaWur6l7aOXvXx-&{0)RDAVq;SWdc{RFo^(IQzit$^dzt=C1~TeKJbqM zyM46tmjr>2C9+5Yvpf-_#DF0B;9DfJNN%f^u&xqWB*C&WfkiB^{z7p8SRRP95wM5> zb|8>I5P1kJ!X<-XS(y+BeJ+hV<|ghc8oGc51(uZwETW++HBew#nE(i*xud|cG9eI{ zh@hgnEshZ*0B+uf1cH(sLW?j<7Fbrs2Onsiky?aH0HD!E@+pUB% zNt8a@NI09Ilm}!JCX)mgA>$*rBMay4PW(Xt`+um&ZW|yLSp-a;4FsJC@o@2hHA$2| z+ekQ@MESFggh{o*x-wy8VZGgH0n_Q-y{$|1a!3+3M?$+1GifVXOigrvyFta zNt8d^NSHhXtS#evi{mU@fWYE1J`xuoXdN5{7MBTuF!?rET*e1(w-U}I(ZpvP31^ci zf3}g(Rl+E+zKrkfc4Xna12ihbWtTf}B+>Q^lO*B|)#z$_) z2hQeB{J}u0+i0-XjBgSMEC%>9M10U-tr;JPYbC779r*)mlPG_-Z2~(2NNNniHs9mpTM@0D1&gJ1@tc{XTgFqerRz(Kyrlyf|DS;@wMGbIFm&AvyFtaiL>x` z#ztrpTHQc{1!w$b;%uUU^DM}A?#LiC^dSK5*4z%>qM>hPqrsXp$Xg)0hxB%52Ep|T zQ3h>u52jbZvNOK7I3!$zz`8RC2@@f(@C-u2Lt{42z=&5$bIt zq0=WcSb+vb2s&j$1Ao1fP3WUxG+2WM*@V8gg$9ezASCon6*PnjO|TdtfdT@kUV+e{ z@sK#a!*K{ggeFA7a0n>IAdD@J8~_cNGEbFkzA4l?%@#5|G|tkvq*gxcXJdRubjTwzDwEZCML;fNVPphumr2K|~_ z1lo2M&L&X;;hcpbJGjOfwV4k17jItzy+Ist7v3x_01Ai!A|-3VOfOvnN_Akpau=PDc!%pM#o{!xk#E_L3% zaq*wD2??E3;vU>0oJR1B0^z~k%!gPrF%bIm-#`R(K_&)V>P+A&ba;SIU+&;37JBQ1 zfl#0EJjD$WSR|M`ct~7V!Xm+w4;~T-D;9d+jse#?<40%PSvVw7`fNK3hs3$|_fkvX zEcAvS10g=+0k@rnLxLwCJmj{sa7ggvgNMXL7FsF5y-7!;mD|q3A;FUmp2=-z;gCcL z1UQRoU^b<@brU+#5oI#BuXHhvoHe;X#5V5g+oF}&xFpx*o2Ut@sK!Y zVaN`lJmUekBMXNlN}%n?!Xb$g2%cYkwgiEi!3aXD1mU!LZ5|WAVg=v$ig9sPC(nv!Xb$g2Lt*ZW;?fP`KrFNxi~;M<1QxNt z#uI7>2G*YmfzWm77_k0K2n0^mAT5IULkNUfros9%0TAY_1OwKe34y?$AzcNrhY$#T zKMAvahvlzagb)b*P!8_?A#nnrq2C(E0B65D0HNO?#68lm0}y7O1Zcbi5J=3Sq6*fY z34#N+=4~I!5{oJd`W8P1T>VUF5xSHe_rV0>ZN%M0g>2(a%t1n5qQQWRp9x%ro3FsS zGa(RWJZ?(^#G;CO#Sf~DVAYw>BFs7f%(}#*ih$wj_Pe0SN@JSAS1dFl#dIgEGXU3UfSjqm5(Wv@nDLzjmR9I=4hvS8@o_kda6mA1aIO9)c>oq%-MqcP|7UT9QHrtP;$}i1 z%%lvKmtPlsn+`+|y1!e+QVIKR&f*)%p1VX>| zjRniggh1$`GAvkLCImvi1BUy&1o7Y?pzGpsN!JcQ=*MHQU~!qiRRr`73k!a!`TtaQ zuD^L5#~J?~fd2!5qLBH)B;V^fN3c``anl;L6T^1VpcfRB_}V5SO9Dm5cK-VQX7*fm z=GjB4L6As~cHX_s&dxqNJ0}aStVn+EiKeza^P^JBxkg-!mdX*x@OX{;-al`HC_@yxZPZ3OKA z+M~uZC&4whUPp9+N^N8s(ME`KbLt4J>s_OW8H5S!Q!hQeEcU%{9qK?T>eJP4ZC^L94f<{Yg{20 zlwnSSMwPYJmom&*aK&&b!<+?IC>v#%v)~G4;|Iw=hG)U{o$*mA<}A3PIm$05!IiIZ z*!Qs?SAc!{>EcoOQ%m_91MoCVu&50A<( zC&69&uJEY*au!6lntgoA=IpqlYYIMPb1WTKQ}8Lx*|i^_9+h9teQX~pI^~zMVEgTS zr~GmjY@gOU<(IP{KiwFdPWj~|XnD_@f{$)kY&w?QzbPmlPp+{|EOg2*XTkQ~(J8;2 z1>4t}o$||Buzls%DZiWr+h;@jn)~Bc&c2`68dXxPJTADwMl=P**-1^^w3k(<{Bjm- zFRM=Z+_(cc0 z6;r1KbE&CKI@cV&Vud4ew`A`S+MQUby&d12WQ_td~`}MryBR|FR^r7 z&OcFO`_$4Y!<=huXIktuV@4Ki-}-e*FmK%B`Y3(nB$WCYgdZ`JN-~S&ik;M)8Ci18 zP%6tTk}H;yv3sJQD_=Ud@1Q*;+0L2JY4ozR7Ot>m*Og}$$@Ux2PSa+HWII!A2e0;2 zKihn9r$n>V+0IAODbt)KSH3&ZDb*~J?f1tWjPMivJhZBOw+p%_? zX3-GIb~=~9f#6s9J5HabGLRH$Sjg8mRi~7EV+_PrDNlGLgOtNZEHT+SD%tx zacVV~Sz5bdsWqBeBv&l8lFcHyVyTsF7ReP$t#q?Uu2^d2n?-WPQY+z{CAScSt@%{O zStM61wNlO^xnil6a~8=JORc1{NUm6FWt~NG#ZoKnERrjhT6t%YT(Q(jJZH%br={k6 zKDn1|RxGtr&r;`#rB?1)Bv&l86BL1b7ReP$t?aW%u2^cNpG9)TQu_h*@z$0_&gIp;bp(yyg}%0p+#mE6O<644^r4#w)0i5AKB zglD{D<*W9+Qq#H4m9W=d$!U>nb40yT(<0d>iF)Ox zMRLW0DLE~YD;7-IX_0IPl=ezbi)1_gqgQ@fB-?gy)x7y*?#fcD@84m z?I*vza?~Q(j(6&nq~5p*{+JEFSC%>muW$Ih($pf^=Baz-sk7wDhTkhuoh8>cd}XS$ zq@`7E85E_eMRH}^R<2qk+qY!BlGRyqC4X_RY_&+Xub+FRt3`6fRZzZKB-<>cG9*y<>GXg>z+ zTWocbTyc(DY;`4R(Fm5{sig`ny1EkG!kw&&KB+~AHm}gP`0A=sZ|{m|i?FUly}fIq z4YsioWk1`u*~Y%bSXYwP-c`}Y)mbHK?Ohd>XrXL7_ibjYZ*kUDrQY5(Q7f0u>XoRs zcTKe6UfTufM>!iU;<^%k#Mx*O*HLoiwNBq6u9IY&0PJawj8Y|O18ff@S_`hlTvwtt zz^kGSU8+QBl)XS}R@zXdO48fACMuz48$TD1v+C_#6K&{HRjajk#j|gb*OjEVcTKcm zl`2th@0zHUOS)f)(%zL%@b)eGx{|c^u8KacO4i<0Q9bd~vyWVG4Gy~&rn4&_mgpNC zc9v}45A+QVJ4qhfEPvnNu(RaKdTVglS#rg@*XZd@mTWV$eS^c!k}G>ugTqdeD|g*} zgTu~}?HjSa!C_~~HgDcHIP5IBGPVs4J4>$UP=muxl54wSgTT&`D>PSwz|N9w8oF-~ z*tMj8m}yN^tx+w?0$sUQ9U2UFmTWsZLxaK2l5Hg#8Vq(V>EA4B=TI9O6t;-AIhCQo zVb`KIMs22RXmHqBvdwf2tlYdy)RN`vOigEdXpq<<+P=;m8Z34#YCUbUoA!|(fbCET}xU|S1VQjNJQ6aeOi+? zE6YuTti#^q4Q_`q3=J;3Zm^9~+YAm3E;~!MJ;9;DW!IA4+?7fjWVVQ|)%vt1wL>6= z2Af@1YGc&io`wdST}ygT*D7sjl0hGHei|B#wqLP)oUoqUYGJx->1!JYi=jbkC&`t= z*U%ufYe^fZHPHsEU5nD(l?44mgVN5D?fBUN6%(spO^!FWodj=aaN2dHF1l8$p4)0s z>uH7 zrL|=`cGug1VV*|AW{4!syNff+&{-r$tf$yi=LnhPG-d_b+nmj#QLrQZ^hh>q#t6|T z4^dm7j+Xhky@G5~{6t=1CRsOQ&j)0H>SpjELnhr1$37`mCzwf2qfwwegXZVi>G%1P zA(QS0)e5p^jPJZA9o|!cpDn9m{JtL=7wEw6k56uxlv1Z@m7nvfVhoTU;3~*|zn&*P zl{i>4Vh2q5JQ`?`JTe30>xZdICSdEQpK3IY9oVE*rDaE^a}1f9B)bhztp|KR(R9O4 z7)za%7ga8I<7wBIisz<|Acd46_!duyE95U=GHt5@cnG?5s; z{UugzFf|O;Zz-~MA9SvcRFABs$v*5Z38AAatU|wGuwoO2Vr>2HpaKtOFpYkzF@&A& zudw45tgL<}rTpS{e|@oaM`S6uWvy&SbGwu~f=x;^${wz1&1_vKkk-uBuVAcOut`HE zjB=y-n_F|((!^;`7+XljPOw-r-U2^3t&j49$HUQDGbz{zvTEpJ7#m(%gGFH;7=sn< zpIgH#5x_}R$`5v(VX-TnX`bH;E@MbQ8?Etc#tPg}i(hh8*cN^CE3+E2sV_4+w}$Wu zz&H;5&VFz*=%t0+a)V6^d1w14=Ea6)GNq0|S1^Q2=P1Uxp1w`L<~j^*ORb}=rYR2Y zY`ff!#%{rw&)L{bv$BowHFL%b7E<^|AeNCnPa{|gvK+yt5gaizjy=^|J-3E# z08ZmN7DQ=wvxOWnY@bmbRhRcf0$iN!W*b=w+Tz)brf3{5K5a}Tv%M(g4x7V;rTwuV zoLa+2TL5Pj_JRZ33u6;nIPkR?u+W-ek6JS}ldc!x!=|IzVWzNih6TL=>%ry)H40-8 zcjJDNt*RBB?<^{-I!dyymCo<+SdPi8E@gJ}o-kr;VY_)#C>W_@!6rK~Vl?;6lCf9Q zF_1uyg0cUkC}WgUIhMn2G>g&Hu?ePdf6bQ9*wj;RSWow+y`=mgD;+GXSc-6d z+Rq-~Sdg0c!NO6_S{*DLBWhdVK3FpY_ZR!w zgKcPGSj>j8ruJbq8^|;V+iIA#Fpd|NfvGQpJc?zp)vt-&hpMysA}t1Zbj+iE}8&$g8Su!e0dWp@57 zs%n~v^Pv$vxQvGf%^-^~=kSPRR2 z$0c(VW=#AMV%0)apOH`Vi|+4&|3Q~geM@Z^e$WtOc;zCt8F0!yvooV;I1no$@R$ueFAVVDnGorJN9!?sHIIIo=TXBTz+K{L$rQDVYa zvGZwQ!psJjSzgBGNNd7gYqikqu+@S=y6l4^4AwI?`#XZJIwnJJfB*nfsD<8Y5gxUEI!OdjTz|@pa)KukI%=T%{ zFg8b4^C7L3&YGRr-G02kgornq?t|=I;|G+_~eBGfgN5!L0GV8&Bwv|s^%mra; zn3ZTU!S)w@R5o5ZuttsWo#(OAVxb1#t%l52}Y}< zc_aW6Z|E2|EkODlS1cHV9XB#CW@=oV)7Wrri||Yux$%LEx0=J$!$>m$(b9uiYob-( zaN4GpFjE_zU0)od3E=e4FpMT(ZjJd|$GBZWnKQ8A2+sxz72Ty)%WWRxox2D}Pb)=PZ?A<-vk8zzqpw(*+U*cb6F`IZP^Hj>siD zNsZB(@su`?jqP|PrAS?{2MgX4mC(X?O2dZP*u-NR;D&;!dr%%-Jf2XFR*%QIr8QW^ zZamIq+iF9*YFqia<7``d1_bHlqNyCkyi7^AQS}vPkIRv;==L~!B}GP6&Q9Sa`$Y}z zC>ZB_Z+Z~@cF0>se)KYzzTzo%aX+OXHOKuFjFFF<_GXXjpLOG|J?{8`jC`QE&<(Di zy0o(Q1Farc_R^Yx=}1eP)KXx<`tyU<>NLGr!m}=|!~+{y7dK-vO4Gu)7lYBl(Gt$B zIbcV-v|&CcIChUvP;JLz%JO0&hgxuBi5{o z9^i(YNnlZLFoR&R5^M~u2~5p?Ln>OEJy`Jp> z|04|w3+$N8UXPJKCaXt`Fv?b@eCaEetK=V8M&2CUk{_VLI0%%N|24+_NO{y>gFOY~ zoD(_*7Q07K*hP6LU-@PO+-i9PU;Q99rMzyhu^m{{USh9kO{BEAfId(#&N;zSU{QMq z)<{3HT=Uov-UOJs!r`a9>aJSDS}O0gYm8m6JjJd-x)P}`?!)Oyq`ts#gvT@U(i#qi z<;`>bgLGw%FDTyQfHf=clo!$0a*1c--;8 zIAKKAf}3}+QI{sY;mVv^BGnGYG)J<93l>hWkqHE2h2x*ph6#|fe%!RcI1@)^90SM? zCQI*Dv3xdLIRP7qRojZ>cCxJp;xbyc)ytGmWX}o%#z`}74`7fdaVy}$gcVypA-xDY zc@m8^d@h_wG}a6WyxDkLFpWHvA`2{zJQyY*o}9oi0dXo}%+Sj69)4~OAjT&iU7^gV zB%ZLqFahJ{zO)7&h<&D>N^VwYP2BOpFg|g|2ea11{S~#$d-&2bfh-Y|1<~+#~|VL4@%Hi{oYI-aei>2;#!F z_VL)k?=jf%)B&x^c*Ro(bueDzVPa_wma9C#S`^U^OXZnUjUgP_at`aZCr8&BkQs=c zH9avbc-DLP#0&OiSJNYe8fdO8yNR|ar?zPg)iAhCkBwqvABhT znQ&NBxUpQAjn2R{Hh^3b#$6DM7RFr=j7s7z2!!`!nyHf^hE&Z=$2p6+Jb z$`wk>Z}l>kWxiSuVAkBQXMkCA)0jY!o$(J*n6tiR{tG|I#so#0Fe*tb9!C;tiJLYU zgAzAwPAOCp_hK*``M8qQBnW6%u;DXS!o7nT_;+7Aj+OAN#T}+%2Ko?1T}wOF(Lg+a;J) zlE#az<1pHuWo)nu^f3-1ci}iD3A0M#)E~@#uv@2s)RL^(0sFyL7|UTl7$3)$)?h!_ zR8m2@5(!D@M5`oCirEhaG74iqEd5N-5$p$pn=mRFx7wvO*bhcL6{IUMoD9yAO5$xB z7+OpeXcWeNFf$3WN>W!Wc3|9Um)2lE2=0u+SO)thc<3Ih{t%fA7*x~ZNM!(0OQbTO zRjDL08DLbhglN0p257aUuCVG4kr}6)RT3w~LiK4)?21L=qbH#&_Il?KnG85yDp^9b zOKZ$39>(o5`>m#S>$cU->?7X_m)MLGfI?Vl&);s8~jmv(JXX>un=X75DgXM6bl@ASV|E<7|*^3oOnC zd9>KvxZuJO&WeM?oZszaCeay zPClvxeHDE!zO%!XOI)2?Jagp|7bkbjcFz}AA~#X65vet{t@f!kwypLldW9P%yy!@2 zad&J-v2fnuO4!bJVN$r5r8OlF;_MxB(MA+pJP>fvMzmbCtz5Jbc9v`_H*FTW9tYca zdYGAdR=Bak^^7JHzKT=$F4{~YfVi@ZTL&0dPq7?#1CW`c%Q0y&mjf0j5cE}1uKZ>WP`amgk6o`xUh^lB4o(Hvt_x#0T6@}i`v^D zVq6l4HWF%*K}@WDmE1kcc@3jyo2i!zNKF$}v4GSxa}_g+f!|E7%L4Lhd-7ct&}tfI zZ2_@uo5_1wP^&6;3j4d6{Fk{Tn!cGGm<6S($un6%IyKQM3rI~9uQG!cn6;Ulm<6?} z#<^cWt0{L1zmL`716@rYOM}oAN3%m~W~^a!=UPy)PrklPG(r8ZmPR4YE9+)6Q8Y_Q zT03zx3usd?ku(cRYbTaw23aSTeJ0jqPxNP=W+`e_<$=My*i1~#QqpQllWh-GX;kVI zA+0<-pEQ_rf<2YuMu0bX6P5MFjM|;4rO7RgU0^Fb{qBTX*zj)JbmpJ1*k7KGjs5+S zH{+8V^d)5Dv;%wz$vElimw0`XA^&QBIb5A^iz5RjJy}kVBUr(=pezNO^8L;0zux?CvgVHm?DAVYE8R`MwYl6~ z{`&`hbQ1dWho8Rv@$%;F?InNu?)2e-H)_*S+{Jle)^&^c_VSCjA0BSryt#R}d-wM8 z-S^WEeLdFBBcC#ME)6TwZzgFvvbp@X({Go5c=z`8>HWh8ulKvt{ZAig^t2pYj)~k| zPjY7S{`|Mo{on3Rzc35qoPT|3BRlq#zc6n+ODuKsSB&O#qUCS)AY(Lv{0;7EIr7>xctS=7^D92H}?0XY1|)h zF+4TfZf|GufuiiQlZx^;J8jI>bByA6H3^#KA2sglOX%kD{Af)+5Iymm+_-Kl$2{avTmfLn>!g{_&pFE??dJm3AF3Sp{{b1mF0^E?s^1+xye` z)mNv7o7#Jv_p3hGo zUf~T)`dwaC1f;aEWXq`-*<3KE9MR^;myYGL~Qp<2zsn~y) z8`b#{$(Ns5K_82vCcl64Q2y}d&bspa&CS~%UOfBt)7#VcH$T65c=j?5*k@O!!*A|h zmOr@kRrQnp&(&al{P4d2`TmXT|LyCm)0@*zr?(Fu7~;*Wkhibr5q_lX?d#{S&1#q$ z6wLs6FcZ|Adv7mG^5wF$$*l6?**(kkcl>Ew`BSzP_mgL{Sd7TmI2s=a_Mhzk=o*!+ zzu5e7D;O>RXwOIQesr?O&1dp?F~?Vbc=z+$2aFJZ{QBme@i-sG!ojXN_Eek71~!b& z`!M?JOD(uu@kecMef&p9*Ld`BM@Mz^H^;4cztBvWKYdG>voi^E zwjp6;9Lx3c0*Wz@<#+%k?c;EdlBIHD=h*GQN%%@HHuQO1;rHt7e+ z6{H_9-_j4_0Hhy~|5}IhPN^+U!X(Ue%%Dn#xI>jXxMP$$xR{fEaC0U7;6g_0@L=~; zuRldemV9TFw2iceY9Ixileu zHuViYFxyzl5ty9HkrB`i_Mu*0A!M7l;c-E>CA?_%sQf6)`=q2V_VPLVB~UWX;YV4v z%cRc`cAi!_Y+Ez@~5ou;*O@kT#7wh10mj0eotErqPD@vGW$jVr@ zf3~EveKySQw3DpA?M#^X=*aq`>{QO5o@LB}BopSb!x__Yfm_e^lngo+SQlmShom2@ zX;}+wG}+dX5=m?cnAlSgUB3{Sq8qS{GQVt6+7C~)kow_aC>gWsiG-;EWxokoPY;&LdDw5lJZvvxcJxk| zzuL=~9m5mmX&Vye&rCBWbBR@JjNc%(lay-~dlY|<9X;zVkB?-pAoY|*fh1XH@)PFS z7c-X6280->jR2E%iHk040ZjCd5H`CvPW5`ANycRFA^Dqy4yAJb;3;ALDk5V#=R81> zvEnVH)PWNs^Fan+=?6)-MX$)it95v`vDiM|RA?O@IGxIQz+=KZNlwPZu95soYzdh7 zW}G->?*Y@fB!#TBnS7%S%-FElKIn~XcS%TQ(den1=N-<8hdc`xIYVCK0XMuckt^AN%Gd!BD3VIJU7rLejLUp*e3SX$3QuMI2}`Qiqs=pxxd-~jV;Sk2 zM+YWZPY#qYPh5~OqqY;K=UM`S?K(Y{gUS%Sf)W(HA~;&~iZi?PgRESlSGfE#ADr!F zOgV2!KX^JK^TAnCG0!`Y`sO$N3G=K~8EcG-2co5N{?apJnfoGa>pJswh6!)MyCpe0 zgX!K#V4;jDOHjs?7-$(&(qhS&l4D244<1Q$gM3w@8yssD^Jv#NE)Y|qFYrjBF9bzv z-x@vx32~%vL?KJx2uPK_QLXfi%pB4W=qu5Ch%@O20gloS)J6J1IHJrE59_rbp2R1P zAAGU)!-GUqIk`))%vkD6@mO2?(XhLyxb%ZJ$|B1VyMgJr@OoB%uc5oVVU=;=b*aoR z!6=IP)1NplT=&SFbBvNX9~!zlG<27b0mz(VPPK0h-G!6ReZ#7W?y}{H?%Fn(`$3uw z(OodnUEa)z-360z;T@ff3k;*|0bs&&kwHw(0brTCCKOfeE|~1o_LN`y>o4cS{PHX> z-_LL{A@^m5$(fGWTsaeiiBHYzJ>d#?yeDT3F!ArXu@T+^O#C(8n27HPCVni;wfIQ9 z`;)Z_CO$Rpkl1!GS*w<$Ag?XEy2~~ZOwNP$mOtAAFya5~m3>}=V8Tamt08AoTsXTU zk9vSxr@!Zq6;nCSfSWK+otZJ=jMy2)SLRWo`0Zd~Ct*B>K~td%j~`Xk#W-Z-i~AV^(*uVD|kbI{*YKMeO-^?+33T8F>iO8xb8dkIsHj1?n% z9hj~`Ben9F@^J#`2PBG&JyCmNhoE2d_mtnYYwW!5^8i!VAn8`}p2C|kzo(o6Z^?DP81SZ2^Z?3D#uO?;#(<`X9+0rdr8#dyYat&-DA`{o&3ldLC3OPFU*%9#4{+;>ZV*#@P*BwiAI zAtjQGA8v{Mo`19{wngKS@J=Oe#4vl%n`9*(j&h!rK9%$2tqJp&m>HA%Ei;`u2A)VP z$@(LOfU&EJFApZ%EBOw@j{p;$B(zNQ08DH)sS?DO$J~ofg2`US=*hVoO!R`7Fwp}`bCkyvOwM#{M>&3oXAyi3FX;hvqWBT)3gSnAS=4WwBOVK7y@I6{J%B-x zGaZ*AbPm=9a^#Bu=Z80Zeu}xsA2T*<4K9dwxe0eaj2jmw}Js_WG zw#B#tvR{J9e#yRtxc7#GhP8rLd89Xc)=cf-w{j!WZQhBvO`!nsWP!MRN4mkUhM zQ_f{FznsftemR#(KS+%x^UH;btT!^5$$VhOWqxt>v>%=ZI*uu1uJ%LyFiX!R{jhgx z*`7j(Nk5ESl5+m$HMWJVN7@3ZAY;m5Tz{`&cgYQ;ZNbBrws=DO)E3VZldy)}#c7ps zCO?hn3ofhS1+@=q}Ttzo+qzFEL#J7`az*85eavE<-RGM&ZL~`!X2=?#pCt5mztkgZna>x5j-L@%QSNH15k7W%Wx)mn?eK zxGy6jRs9lD49og$+?SEsNOh9?GU*%BChM2`G8rqbl*A5kUnc$FzD)F)N8B>bywlcx z_=n%3UU9`Dx;uFOq*PAh@LGu#$Hq1hzb3eeuo*KoI^^eF3v0-3h zPszn3_7qHXm-I}s=YfemwY+EA4^C3jH~%O}7z3lFv>zHDMrJ2D|ANW62P$un##iT9%)!@`VPi~tqz1xBHmOYPcLC1xyBCj`| z*@!Oy)hD_OCb~=J2-)+%RCoCS{{2s zfAc!$Nr;?HVQ7Uv1(W-DtZsg*#VZlL>*eK$@B)Oj2rmGpI?4Crr60WKlzwo86&>e| zr;I&RxabD&KD7?L+rf>HeFjX<;)Lf2Cj&JsoD7(7GQ5a1ZTa%J(c<3o8K}YydTs$ln>)Yi0~kIP2yjHNsI$u{1UF- z!l1Mt{-M2Sb2tuaKm1z^shlTb&zRbr#<>i4Quip%WinQnKN%~|Wzr9>4P-tzmq|ak zaMU{FEhtvfKS>+=#z$4M55l()T&}HFVE8@xfcSHdm#&vlYS7#DE(->iQ{A?d?%RjoxIx7{SBvI>+tW&#ChY5 zo$TGXbuu63B;_@Yb0Kw*no)cevMWj*Y${rZr_+z^!?0-`dgs6g9Ocddi>SVZDT4IF zzwegn^<<41)3wDBLe>`Bo7SOskbL@4_fV2~%KEjmmATDiQj|J4cFX$Z0kGHz+(fOz z6Bft*vL$OB`ksVnZ{0)r#*fw^@4LzWro1iJjk<^O3|#x6F-pAr*FBUonCKt$r1Xt% zjmY?sLRa*jGnljmb1(hn3?^%VFbbJV&S2UW|A2O!4`LRzeV)%Xl~YcJ8%VXCgC`?P zvi=#5fZ6lzJbqxZeo<%fOTdJC;HjnT6=1SALQ#khOqj3OD=;}@bL}j5B9`(ukFzD? z&11?Elr;k;YldA*{7x`gGtesHcY=uyancYS;;LNyPB85+cVp5I!g8~oVoJpCgyNAk zV>xGKtcak@Hrv9f^ZMY%Q0JE>=e5AAF|p5>HJxA1TUxKi&fuA8e|bxm_YY=G?!dvs zMi71=HUdocUzmEa5n!_avI2E}2`iOx;aOm|5zuSmZ-9xvf#no`gOCZ;XW|oeTr>{> zU#yd}JzI+S@(!VJwn4QKJjd30 zm5((VQ`_R7p^LV2*BDc1WoaJ|XT`?ygh()46=@$$k@Z0;fh@~wVp)T{d=)*gtt{7J zAsx96ouK1?6c3#uD-qd`^mCwon3wL`G0-J(HYM3aC@`8-5*Xj_N?Gl zce*+3Uhlix*Vm_)pFypi_9St9{r&B$U3WUZI(~mV5q^P}{c3x7ee?2v$ZJLd$D8{H SPvJ$6&;Icr|M|~ 0, more checks are added: Within each group of LIDs assigned to +same target port, + a. use only ports which have same MinHop + b. first prefer the ones that go to different systemImageGuid (then +the previous LID of the same LMC group) + c. if none - prefer those which go through another NodeGuid + d. fall back to the number of paths method (if all go to same node). + + +Effect of Topology Changes + +OpenSM will preserve existing routing in any case where there is no change in +the fabric switches unless the -r (--reassign_lids) option is specified. + +-r +--reassign_lids + This option causes OpenSM to reassign LIDs to all + end nodes. Specifying -r on a running subnet + may disrupt subnet traffic. + Without -r, OpenSM attempts to preserve existing + LID assignments resolving multiple use of same LID. + +If a link is added or removed, OpenSM does not recalculate +the routes that do not have to change. A route has to change +if the port is no longer UP or no longer the MinHop. When routing changes +are performed, the same algorithm for balancing the routes is invoked. + +In the case of using the file based routing, any topology changes are +currently ignored The 'file' routing engine just loads the LFTs from the file +specified, with no reaction to real topology. Obviously, this will not be able +to recheck LIDs (by GUID) for disconnected nodes, and LFTs for non-existent +switches will be skipped. Multicast is not affected by 'file' routing engine +(this uses min hop tables). + + +Min Hop Algorithm +----------------- + +The Min Hop algorithm is invoked when neither UPDN or the file method are +specified. + +The Min Hop algorithm is divided into two stages: computation of +min-hop tables on every switch and LFT output port assignment. Link +subscription is also equalized with the ability to override based on +port GUID. The latter is supplied by: + +-i +-ignore-guids + This option provides the means to define a set of ports + (by guids) that will be ignored by the link load + equalization algorithm. + +LMC awareness routes based on (remote) system or switch basis. + + +UPDN Routing Algorithm +---------------------- + +Purpose of UPDN Algorithm + +The UPDN algorithm is designed to prevent deadlocks from occurring in loops +of the subnet. A loop-deadlock is a situation in which it is no longer +possible to send data between any two hosts connected through the loop. As +such, the UPDN routing algorithm should be used if the subnet is not a pure +Fat Tree, and one of its loops may experience a deadlock (due, for example, +to high pressure). + +The UPDN algorithm is based on the following main stages: + +1. Auto-detect root nodes - based on the CA hop length from any switch in +the subnet, a statistical histogram is built for each switch (hop num vs +number of occurrences). If the histogram reflects a specific column (higher +than others) for a certain node, then it is marked as a root node. Since +the algorithm is statistical, it may not find any root nodes. The list of +the root nodes found by this auto-detect stage is used by the ranking +process stage. + + Note 1: The user can override the node list manually. + Note 2: If this stage cannot find any root nodes, and the user did not + specify a guid list file, OpenSM defaults back to the Min Hop + routing algorithm. + +2. Ranking process - All root switch nodes (found in stage 1) are assigned +a rank of 0. Using the BFS algorithm, the rest of the switch nodes in the +subnet are ranked incrementally. This ranking aids in the process of enforcing +rules that ensure loop-free paths. + +3. Min Hop Table setting - after ranking is done, a BFS algorithm is run from +each (CA or switch) node in the subnet. During the BFS process, the FDB table +of each switch node traversed by BFS is updated, in reference to the starting +node, based on the ranking rules and guid values. + +At the end of the process, the updated FDB tables ensure loop-free paths +through the subnet. + + +UPDN Algorithm Usage + +Activation through OpenSM + +Use '-R updn' option (instead of old '-u') to activate the UPDN algorithm. +Use `-a ' for adding an UPDN guid file that contains the +root nodes for ranking. +If the `-a' option is not used, OpenSM uses its auto-detect root nodes +algorithm. + +Notes on the guid list file: +1. A valid guid file specifies one guid in each line. Lines with an invalid +format will be discarded. +2. The user should specify the root switch guids. However, it is also +possible to specify CA guids; OpenSM will use the guid of the switch (if +it exists) that connects the CA to the subnet as a root node. + + +To learn more about deadlock-free routing, see the article +"Deadlock Free Message Routing in Multiprocessor Interconnection Networks" +by William J Dally and Charles L Seitz (1985). + + +Fat-tree Routing Algorithm +-------------------------- + +Purpose: + +The fat-tree algorithm optimizes routing for "shift" communication pattern. +It should be chosen if a subnet is a symmetrical fat-tree of various types. +It supports not just K-ary-N-Trees, by handling for non-constant K, +cases where not all leafs (CAs) are present, any CBB ratio. +As in UPDN, fat-tree also prevents credit-loop-deadlocks. +Fat-tree algorithm supports topologies that comply with the following rules: + - Tree rank should be between two and eight (inclusively) + - Switches of the same rank should have the same number + of UP-going port groups*, unless they are root switches, + in which case the shouldn't have UP-going ports at all. + - Switches of the same rank should have the same number + of DOWN-going port groups, unless they are leaf switches. + - Switches of the same rank should have the same number + of ports in each UP-going port group. + - Switches of the same rank should have the same number + of ports in each DOWN-going port group. +*ports that are connected to the same remote switch are referenced as +'port group'. + +Note that although fat-tree algorithm supports trees with non-integer CBB +ratio, the routing will not be as balanced as in case of integer CBB ratio. +In addition to this, although the algorithm allows leaf switches to have any +number of CAs, the closer the tree is to be fully populated, the more effective +the "shift" communication pattern will be. + +The algorithm also dumps CA ordering file (osm-ftree-ca-order.dump) in the +same directory where the OpenSM log resides. This ordering file provides the +CA order that may be used to create efficient communication pattern, that +will match the routing tables. + + +Usage: + +Activation through OpenSM + +Use '-R ftree' option to activate the fat-tree algorithm. + +Note: LMC > 0 is not supported by fat-tree routing. If this is +specified, the default routing algorithm is invoked instead. + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/doc/modular-routing.txt b/branches/WOF2-2/ulp/opensm/user_3_0_0/doc/modular-routing.txt new file mode 100644 index 00000000..0a593467 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/doc/modular-routing.txt @@ -0,0 +1,78 @@ +Modular Routine Engine + +Modular routing engine structure has been added to allow +for ease of "plugging" new routing modules. + +Currently, only unicast callbacks are supported. Multicast +can be added later. + +One of existing routing modules is up-down "updn", which may +be activated with '-R updn' option (instead of old '-u'). + +General usage is: +$ opensm -R 'module-name' + +There is also a trivial routing module which is able +to load LFT tables from a dump file. + +Main features: + +- this will load switch LFTs and/or LID matrices (min hops tables) +- this will load switch LFTs according to the path entries introduced in + the dump file +- no additional checks will be performed (such as "is port connected", etc.) +- in case when fabric LIDs were changed this will try to reconstruct LFTs + correctly if endport GUIDs are represented in the dump file (in order + to disable this GUIDs may be removed from the dump file or zeroed) + +The dump file format is compatible with output of 'ibroute' util and for +whole fabric may be generated with script like this: + + for sw_lid in `ibswitches | awk '{print $NF}'` ; do + ibroute $sw_lid + done > /path/to/dump_file + +, or using DR paths: + + for sw_dr in `ibnetdiscover -v \ + | sed -ne '/^DR path .* switch /s/^DR path \[\(.*\)\].*$/\1/p' \ + | sed -e 's/\]\[/,/g' \ + | sort -u` ; do + ibroute -D ${sw_dr} + done > /path/to/dump_file + +This script is dump_lfts.sh + +In order to activate new module use: + + opensm -R file -U /path/to/dump_file + +If the dump_file is not found or is in error, the default routing +algorithm is utilized. + +The ability to dump switch lid matrices (aka min hops tables) to file and +later to load these is also supported. + +The usage is similar to unicast forwarding tables loading from dump +file (introduced by 'file' routing engine), but new lid matrix file +name should be specified by -M or --lid_matrix_file option. For example: + +  opensm -R file -M ./opensm-lid-matrix.dump + +The dump file is named 'opensm-lid-matrix.dump' and will be generated in +standard opensm dump directory (/var/log by default) when +OSM_LOG_ROUTING logging flag is set. + +When routing engine 'file' is activated, but dump file is not specified +or not cannot be open default lid matrix algorithm will be used. + +There is also a switch forwarding tables dumper which generates +a file compatible with dump_lfts.sh output. This file can be used +as input for forwarding tables loading by 'file' routing engine. +Both or one of options -U and -M can be specified together with '-R file'. + +NOTE: ibroute has been updated (for switch management ports) to support this. +Also, lmc was added to switch management ports. ibroute needs to be r7855 or +later from the trunk. + + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/doc/opensm_release_notes_openib-2.0.5.txt b/branches/WOF2-2/ulp/opensm/user_3_0_0/doc/opensm_release_notes_openib-2.0.5.txt new file mode 100644 index 00000000..a6555733 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/doc/opensm_release_notes_openib-2.0.5.txt @@ -0,0 +1,487 @@ + OpenSM Release Notes 2.0.5 + ============================ + +Version: OpenFabrics Enterprise Distribution (OFED) 1.1 +Repo: https://openib.org/svn/gen2/branches/1.1/src/userspace/management/osm +Version: 9535 (openib-2.0.5) +Date: October 2006 + +1 Overview +---------- +This document describes the contents of the OpenSM OFED 1.1 release. +OpenSM is an InfiniBand compliant Subnet Manager and Administration, +and runs on top of OpenIB. The OpenSM version for this release +is openib-2.0.5 + +This document includes the following sections: +1 This Overview section (describing new features and software + dependencies) +2 Known Issues And Limitations +3 Unsupported IB compliance statements +4 Major Bug Fixes +5 Main Verification Flows +6 Qualified software stacks and devices + +1.1 Major New Features + +* Partition manager: + The partition manager provides a means to setup multiple partitions + by providing a partition policy file. For details please read the + doc/partition-config.txt or the opensm man page. + +* Basic QoS Manager: + Provides a uniform configuration of the entire fabric with values defined + in the OpenSM options file. The options support different settings for + CAs, Switches, and Routers. Note that this is disabled by default and + using -Q enables QoS fabric setup. + +* Loading pre-routes from a file: + A new routing module enables loading pre-routes from a file. + To use this option you should use the command line options: + "-R file --U " or + "--routing_engine file --ucast_file " + For more information refer to the file doc/modular-routing.txt + or the opensm man page. + +* SA MultiPathRecord support: + The SA can now handle requests for multiple PathRecords in one query. + This includes methods SA GetMulti/GetMultiResp and dual sided RMPP. + +* PPC64 is now QAed and supported + +* Support LMC > 0 for Switch Enhanced Port 0: + Allows enhanced switch port 0 (ESP0) to have a non zero + LMC. Use the configured subnet wide LMC for this. Modifications were + necessary to the LID assignment and routing to support this. + Also, added an option to the configuration to use LMC configured for + subnet for enhanced switch port 0 or set it to 0 even if a non zero + LMC is configured for the subnet. The default is currently the + latter option. The new configuration option is: lmc_esp0 + +1.2 Minor New Features: + +* IPoIB broadcast group configuration: + It is now possible to control the IPoIB broadcast group parameters + (MTU, rate, SL) through the partitions configuration file. + +* Limiting OpenSM log file size: + By providing the command line option: "-L " or + "--log_limit " the user can limit the generated log + file size. When specified, the log file will be truncated upon reaching + this limit. + +* Favor 1K MTU for Tavor (MT23108) HCA + In cases where a PathRecord or MultiPathRecord is queried and the + requestor does not specify the MTU or does specify it in a way + that allows for MTU to be 1K and one of the path ends in a Tavor, + limit the MTU to 1K max. + +* Man pages: + Added opensm.8 and osmtest.8 + +* Leaf VL stall count control: + A new parameter (leaf_vl_stall_count) for controlling the number of + sequential packets dropped on a switch port driving a HCA/TCA/Router + that cause the port to enter the VLStalled state was added to the + options file. + +* SM Polling/Handover defaults changed + The default SMInfo polling retries was decreased from 18 to 4 + which reduces the default handover time from 3 min to 40 seconds. + +1.3 Library API Changes + +* cl_mem* APIs deprecated in complib: + These functions are now considered as deprecated and should be + replaced by direct calls to malloc, free, memset, etc. + +* osm_log_init_v2 API added in libopensm: + Supports providing the new option for log file truncation. + +1.4 Software Dependencies + +OpenSM depends on the installation of either OFED 1.1, OFED 1.0, +OpenIB gen2 (e.g. IBG2 distribution), OpenIB gen1 (e.g. IBGD +distribution), or Mellanox VAPI stacks. The qualified driver versions +are provided in Table 2, "Qualified IB Stacks". + +1.5 Supported Devices Firmware + +The main task of OpenSM is to initialize InfiniBand devices. The +qualified devices and their corresponding firmware versions +are listed in Table 3. + +2 Known Issues And Limitations +------------------------------ + +* No Service / Key associations: + There is no way to manage Service access by Keys. + +* No SM to SM SMDB synchronization: + Puts the burden of re-registering services, multicast groups, and + inform-info on the client application (or IB access layer core). + +* No "port down" event handling: + Changing the switch port through which OpenSM connects to the IB + fabric may cause incorrect operation. Please restart OpenSM whenever + such a connectivity change is made. + +* Changing connections during SM operation: + Under some conditions the SM can get confused by a change in + cabling (moving a cable from one switch port to the other) and + momentarily see this as having the same GUID appear connected + to two different IB ports. Under some conditions, when the SM fails to + get the corresponding change event it might mistakenly report this case + as a "duplicated GUID" case and abort. It is advisable to double-check + the syslog after each such change in connectivity and restart + OpenSM if it has exited. + +3 Unsupported IB Compliance Statements +-------------------------------------- +The following section lists all the IB compliance statements which +OpenSM does not support. Please refer to the IB specification for detailed +information regarding each compliance statement. + +* C14-22 (Authentication): + M_Key M_KeyProtectBits and M_KeyLeasePeriod shall be set in one + SubnSet method. As a work-around, an OpenSM option is provided for + defining the protect bits. + +* C14-67 (Authentication): + On SubnGet(SMInfo) and SubnSet(SMInfo) - if M_Key is not zero then + the SM shall generate a SubnGetResp if the M_Key matches, or + silently drop the packet if M_Key does not match. + +* C15-0.1.23.4 (Authentication): + InformInfoRecords shall always be provided with the QPN set to 0, + except for the case of a trusted request, in which case the actual + subscriber QPN shall be returned. + +* o13-17.1.2 (Event-FWD): + If no permission to forward, the subscription should be removed and + no further forwarding should occur. + +* C14-24.1.1.5 and C14-62.1.1.22 (Initialization): + GUIDInfo - SM should enable assigning Port GUIDInfo. + +* C14-44 (Initialization): + If the SM discovers that it is missing an M_Key to update CA/RT/SW, + it should notify the higher level. + +* C14-62.1.1.12 (Initialization): + PortInfo:M_Key - Set the M_Key to a node based random value. + +* C14-62.1.1.13 (Initialization): + PortInfo:P_KeyProtectBits - set according to an optional policy. + +* C14-62.1.1.24 (Initialization): + SwitchInfo:DefaultPort - should be configured for random FDB. + +* C14-62.1.1.32 (Initialization): + RandomForwardingTable should be configured. + +* o15-0.1.12 (Multicast): + If the JoinState is SendOnlyNonMember = 1 (only), then the endport + should join as sender only. + +* o15-0.1.8 (Multicast): + If a request for creating an MCG with fields that cannot be met, + return ERR_REQ_INVALID (currently ignores SL and FlowLabelTClass). + +* C15-0.1.8.6 (SA-Query): + Respond to SubnAdmGetTraceTable - this is an optional attribute. + +* C15-0.1.13 Services: + Reject ServiceRecord create, modify or delete if the given + ServiceP_Key does not match the one included in the ServiceGID port + and the port that sent the request. + +* C15-0.1.14 (Services): + Provide means to associate service name and ServiceKeys. + +4 Major Bug Fixes +----------------- + +The following is a list of bugs that were fixed. Note that other less critical +or visible bugs were also fixed. + +* "Broken" fabric (duplicated port GUIDs) handling improved + Replace assert with a real check to handle invalid physical port + in osm_node_info_rcv.c which could occur on a broken fabric + +* SA client synchronous request failed but status returned was IB_SUCCESS + even if there was no response. + There was a missing setting of the status in the synchronous case. + +* Memory leak fixes: + 1. In libvendor/osm_vendor_ibumad.c:osm_vendor_get_all_port_attr + 2. In libvendor/osm_vendor_ibumad_sa.c:__osmv_sa_mad_rcv_cb + 3. On receiving SMInfo SA request from a node that does not share a + partition, the response mad was allocated but never free'd + as it was never sent. + +* Set(InformInfo) OpenSM Deadlock: + When receiving a request with unknown LID + +* PathRecord to inconsistent multicast destination: + Fix the return error when multicast destination is not consistently + indicated. + +* Remove double calculation of reversible path + In osm_sa_path_record.c:__osm_pr_rcv_get_lid_pair_path a PathRecord + query used to double check if the path is reversible + +* Some PathRecord log messages use "net order": + Fix GUID net to host conversion in some osm_log messages + +* DR/LID routed SMPs direction bit handling: + osm_resp.c:osm_resp_make_resp_smp, set direction bit only if direct + routed class. This bug caused two issues: + 1. Get/Set responses always had direction bit set. + 2. Trap represses never had direction bit set. + The direction bit needs setting in direct routed responses and it + doesn't exist in LID routed responses. + osm_sm_mad_ctrl.c: did not detect the "direction bit" correctly. + +* OpenSM crash due to transaction lookup (interop with Cisco stack) + When a wire TID that maps to internal TID of zero (after applying + mask) was received the lookup of the transaction was successful. + The stale transaction pointed to "free'd" memory. + +* Better handling for Path/MultiPath requests for raw traffic + +* Wrong ProducerType provided in Notice Reports: + When formating an SM generated report, the ProducerType was using + CL_NTOH32 which can not be used to format a 24bit network order number. + +* OpenSM break on PPC64 + complib: Fixed memory corruption in cl_pool.c:cl_qcpool_init. This + affected big endian 64-bit architectures only. + +* Illegal Set(InformInfo) was wrongly successful in updating the SMDB + osm_sa_informinfo.c: In osm_infr_rcv_process_set_method, if sending + error, don't call osm_infr_rcv_process_set_method + +* RMPP queries of InformInfoRecord fail + ib_types.h: Pad ib_inform_info_record_t to be modulo 8 in size so + that attribute offset is calculated properly + +* Returning "invalid request" rather than "unsupported method/attribute" + In these cases, a noncompliant response was being provided. + +* Noncompliant response for SubnAdmGet(PortInfoRecord) with no match + osm_pir_rcv_process, now returns "SA no records error" for SubnAdmGet + with 0 records found + +* Noncompliant non base LID returned by some queries: + The following attributes used to return the request LID rather than + its base LID in responses: PKeyTableRecord, GUIDInfoRecord, + SLtoVLMappingTableRecord, VLArbitrationTableRecord, LinkRecord + +* Noncompliant SubnAdmGet and SubnAdmGetTable: + Mixing of error codes in case of no records or multiple records + fixed for the attributes: + LinearForwardingTableRecord, GUIDInfoRecord, + VLArbitrationTableRecord, LinkRecord, PathRecord + +* segfault in InformInfo flows + Under stress concurrent Set/Delete/Get flows. Fixed by adding + missing lock. + +* SA queries containing LID out if range did not return ERR_REQ_INVALID + +5 Main Verification Flows +------------------------- + +OpenSM verification is run using the following activities: +* osmtest - a stand-alone program +* ibmgtsim (IB management simulator) based - a set of flows that + simulate clusters, inject errors and verify OpenSM capability to + respond and bring up the network correctly. +* small cluster regression testing - where the SM is used on back to + back or single switch configurations. The regression includes + multiple OpenSM dedicated tests. +* cluster testing - when we run OpenSM to setup a large cluster, perform + hand-off, reboots and reconnects, verify routing correctness and SA + responsiveness at the ULP level (IPoIB and SDP). + +5.1 osmtest + +osmtest is an automated verification tool used for OpenSM +testing. Its verification flows are described by list below. + +* Inventory File: Obtain and verify all port info, node info, link and path + records parameters. + +* Service Record: + - Register new service + - Register another service (with a lease period) + - Register another service (with service p_key set to zero) + - Get all services by name + - Delete the first service + - Delete the third service + - Added bad flows of get/delete non valid service + - Add / Get same service with different data + - Add / Get / Delete by different component mask values (services + by Name & Key / Name & Data / Name & Id / Id only ) + +* Multicast Member Record: + - Query of existing Groups (IPoIB) + - BAD Join with insufficient comp mask (o15.0.1.3) + - Create given MGID=0 (o15.0.1.4) + - Create given MGID=0xFF12A01C,FE800000,00000000,12345678 (o15.0.1.4) + - Create BAD MGID=0xFA. (o15.0.1.6) + - Create BAD MGID=0xFF12A01B w/ link-local not set (o15.0.1.6) + - New MGID with invalid join state (o15.0.1.9) + - Retry of existing MGID - See JoinState update (o15.0.1.11) + - BAD RATE when connecting to existing MGID (o15.0.1.13) + - Partial JoinState delete request - removing FullMember (o15.0.1.14) + - Full Delete of a group (o15.0.1.14) + - Verify Delete by trying to Join deleted group (o15.0.1.14) + - BAD Delete of IPoIB membership (no prev join) (o15.0.1.15) + +* GUIDInfo Record: + - All GUIDInfoRecords in subnet are obtained + +* MultiPathRecord: + - Perform some compliant and noncompliant MultiPathRecord requests + - Validation is via status in responses and IB analyzer + +* PKeyTableRecord: + - Perform some compliant and noncompliant PKeyTableRecord queries + - Validation is via status in responses and IB analyzer + +* LinearForwardingTableRecord: + - Perform some compliant and noncompliant LinearForwardingTableRecord queries + - Validation is via status in responses and IB analyzer + +* Event Forwarding: Register for trap forwarding using reports + - Send a trap and wait for report + - Unregister non-existing + +* Trap 64/65 Flow: Register to Trap 64-65, create traps (by + disconnecting/connecting ports) and wait for report, then unregister. + +* Stress Test: send PortInfoRecord queries, both single and RMPP and + check for the rate of responses as well as their validity. + + +5.2 IB Management Simulator OpenSM Test Flows: + +The simulator provides ability to simulate the SM handling of virtual +topologies that are not limited to actual lab equipment availability. +OpenSM was simulated to bring up clusters of up to 10,000 nodes. Daily +regressions use smaller (16 and 128 nodes clusters). + +The following test flows are run on the IB management simulator: + +* Stability: + Up to 12 links from the fabric are randomly selected to drop packets + at drop rates up to 90%. The SM is required to succeed in bringing the + fabric up. The resulting routing is verified to be correct as well. + +* LID Manager: + Using LMC = 2 the fabric is initialized with LIDs. Faults such as + zero LID, Duplicated LID, non-aligned (to LMC) LIDs are + randomly assigned to various nodes and other errors are randomly + output to the guid2lid cache file. The SM sweep is run 5 times and + after each iteration a complete verification is made to ensure that all + LIDs that could possibly be maintained are kept, as well as that all nodes + were assigned a legal LID range. + +* Multicast Routing: + Nodes randomly join the 0xc000 group and eventually the + resulting routing is verified for completeness and adherence to + Up/Down routing rules. + +* osmtest: + The complete osmtest flow as described in the previous table is run on + the simulated fabrics. + +* Stress Test: + This flow merges fabric, LID and stability issues with continuous + PathRecord, ServiceRecord and Multicast Join/Leave activity to + stress the SM/SA during continuous sweeps. InformInfo Set/Delete/Get + were added to the test such both existing and non existing nodes + perform them in random order. + +5.3 OpenSM Regression + +Using a back-to-back or single switch connection, the following set of +tests is run nightly on the stacks described in table 2. The included +tests are: + +* Stress Testing: Flood the SA with queries from multiple channel + adapters to check the robustness of the entire stack up to the SA. + +* Dynamic Changes: Dynamic Topology changes, through randomly + dropping SMP packets, used to test OpenSM adaptation to an unstable + network & verify DB correctness. + +* Trap Injection: This flow injects traps to the SM and verifies that it + handles them gracefully. + +* SA Query Test: This test exhaustively checks the SA responses to all + possible single component mask. To do that the test examines the + entire set of records the SA can provide, classifies them by their + field values and then selects every field (using component mask and a + value) and verifies that the response matches the expected set of records. + A random selection using multiple component mask bits is also performed. + +5.4 Cluster testing: + +Cluster testing is usually run before a distribution release. It +involves real hardware setups of 16 to 32 nodes (or more if a beta site +is available). Each test is validated by running all-to-all ping through the IB +interface. The test procedure includes: + +* Cluster bringup + +* Hand-off between 2 or 3 SM's while performing: + - Node reboots + - Switch power cycles (disconnecting the SM's) + +* Unresponsive port detection and recovery + +* osmtest from multiple nodes + +* Trap injection and recovery + + +6 Qualification +---------------- + +Table 2 - Qualified IB Stacks +============================= + +Stack | Version +-----------------------------------------|-------------------------- +OFED | 1.1 +OFED | 1.0 +OpenIB Gen2 (IBG2 distribution) | 1.0 +OpenIB Gen1 (IBGD distribution) | 1.8.0 +VAPI (Mellanox InfiniBand HCA Driver) | 3.2 and later + +Table 3 - Qualified Devices and Corresponding Firmware +====================================================== + +Mellanox +Device | FW versions +--------|----------------------------------------------------------- +MT43132 | InfiniScale - fw-43132 5.2.0 (and later) +MT47396 | InfiniScale III - fw-47396 0.5.0 (and later) +MT23108 | InfiniHost - fw-23108 3.3.2 (and later) +MT25204 | InfiniHost III Lx - fw-25204 1.0.1i (and later) +MT25208 | InfiniHost III Ex (InfiniHost Mode) - fw-25208 4.6.2 (and later) +MT25208 | InfiniHost III Ex (MemFree Mode) - fw-25218 5.0.1 (and later) + +QLogic/PathScale +Device | Note +--------|----------------------------------------------------------- +iPath | QHT6040 (PathScale InfiniPath HT-460) +iPath | QHT6140 (PathScale InfiniPath HT-465) +iPath | QLE6140 (PathScale InfiniPath PE-880) + +Note: OpenSM does not run on an IBM Galaxy (eHCA) as it does not expose +QP0 and QP1. However, it does support it as a device on the subnet. + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/doc/qos-config.txt b/branches/WOF2-2/ulp/opensm/user_3_0_0/doc/qos-config.txt new file mode 100644 index 00000000..c90e6f7b --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/doc/qos-config.txt @@ -0,0 +1,45 @@ +Trivial low level QoS configuration proposition +=============================================== + +Basically there is a set of QoS related low-level configuration parameters. +All these parameter names are prefixed by "qos_" string. Here is a full +list of these parameters: + + qos_max_vls - The maximum number of VLs that will be on the subnet + qos_high_limit - The limit of High Priority component of VL Arbitration + table (IBA 7.6.9) + qos_vlarb_low - High priority VL Arbitration table (IBA 7.6.9) template + qos_vlarb_high - Low priority VL Arbitration table (IBA 7.6.9) template + Both VL arbitration templates are pairs of VL and weight + qos_sl2vl - SL2VL Mapping table (IBA 7.6.6) template. It is a list + of VLs corresponding to SLs 0-15 (Note the VL15 used + here means drop this SL) + +Typical default values (hard-coded in OpenSM initialization) are: + + qos_max_vls=15 + qos_high_limit=0 + qos_vlarb_low=0:0,1:4,2:4,3:4,4:4,5:4,6:4,7:4,8:4,9:4,10:4,11:4,12:4,13:4,14:4 + qos_vlarb_high=0:4,1:0,2:0,3:0,4:0,5:0,6:0,7:0,8:0,9:0,10:0,11:0,12:0,13:0,14:0 + qos_sl2vl=0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,7 + +The syntax is compatible with rest of OpenSM configuration options and +values may be stored in OpenSM config file (cached options file). + +In addition to the above, we may define separate QoS configuration +parameters sets for various target types. As targets, we currently support +CAs, routers, switch external ports, and switch's enhanced port 0. The +names of such specialized parameters are prefixed by "qos__" +string. Here is a full list of the currently supported sets: + + qos_ca_ - QoS configuration parameters set for CAs. + qos_rtr_ - parameters set for routers. + qos_sw0_ - parameters set for switches' port 0. + qos_swe_ - parameters set for switches' external ports. + +Examples: + + qos_sw0_max_vls=2 + qos_ca_sl2vl=0,1,2,3,5,5,5,12,12,0, + qos_swe_high_limit=0 + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/ibtrapgen/Makefile b/branches/WOF2-2/ulp/opensm/user_3_0_0/ibtrapgen/Makefile new file mode 100644 index 00000000..9c985f57 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/ibtrapgen/Makefile @@ -0,0 +1,7 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the driver components of the Windows NT DDK +# + +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/ibtrapgen/SOURCES b/branches/WOF2-2/ulp/opensm/user_3_0_0/ibtrapgen/SOURCES new file mode 100644 index 00000000..c58e0c79 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/ibtrapgen/SOURCES @@ -0,0 +1,64 @@ +!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_MSVCRT=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 +!else + $(LIBPATH)\*\ibald.lib \ + $(LIBPATH)\*\complibd.lib \ + $(TARGETPATH)\*\osmv_ibald.lib \ + $(TARGETPATH)\*\opensm_ibald.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/branches/WOF2-2/ulp/opensm/user_3_0_0/ibtrapgen/ibtrapgen.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/ibtrapgen/ibtrapgen.c new file mode 100644 index 00000000..bd378821 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/ibtrapgen/ibtrapgen.c @@ -0,0 +1,442 @@ +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + This software program is available to you under a choice of one of two + licenses. You may choose to be licensed under either the GNU General Public + License (GPL) Version 2, June 1991, available at + http://www.fsf.org/copyleft/gpl.html, or the Intel BSD + Patent License, + the text of which follows: + + "Recipient" has requested a license and Intel Corporation ("Intel") + is willing to grant a license for the software entitled + InfiniBand(tm) System Software (the "Software") being provided by + Intel Corporation. + + The following definitions apply to this License: + + "Licensed Patents" means patent claims licensable by Intel Corporation which + are necessarily infringed by the use or sale of the Software alone or when + combined with the operating system referred to below. + + "Recipient" means the party to whom Intel delivers this Software. + "Licensee" means Recipient and those third parties that receive a license to + any operating system available under the GNU Public License version 2.0 or + later. + + Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + + The license is provided to Recipient and Recipient's Licensees under the + following terms. + + Redistribution and use in source and binary forms of the Software, with or + without modification, are permitted provided that the following + conditions are met: + Redistributions of source code of the Software may retain the above copyright + notice, this list of conditions and the following disclaimer. + + Redistributions in binary form of the Software may reproduce the above + copyright notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + Neither the name of Intel Corporation nor the names of its contributors shall + be used to endorse or promote products derived from this Software without + specific prior written permission. + + Intel hereby grants Recipient and Licensees a non-exclusive, worldwide, + royalty-free patent license under Licensed Patents to make, use, sell, offer + to sell, import and otherwise transfer the Software, if any, in source code + and object code form. This license shall include changes to the Software that + are error corrections or other minor changes to the Software that do not add + functionality or features when the Software is incorporated in any version of + a operating system that has been distributed under the GNU General Public + License 2.0 or later. This patent license shall apply to the combination of + the Software and any operating system licensed under the GNU Public License + version 2.0 or later if, at the time Intel provides the Software to + Recipient, such addition of the Software to the then publicly + available versions of such operating system available under the GNU + Public License version 2.0 or later (whether in gold, beta or alpha + form) causes such combination to be covered by the Licensed + Patents. The patent license shall not apply to any other + combinations which include the Software. No hardware per se is + licensed hereunder. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + --------------------------------------------------------------------------*/ + +/* + * Abstract: + * Implementation of ibtrapgen_t. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.2 $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include "ibtrapgen.h" + +#define GUID_ARRAY_SIZE 64 + +/********************************************************************** + **********************************************************************/ +/* + This function initializes the main object, the log and the Osm Vendor +*/ +ib_api_status_t +ibtrapgen_init( IN ibtrapgen_t * const p_ibtrapgen, + IN ibtrapgen_opt_t * const p_opt, + IN const osm_log_level_t log_flags + ) +{ + ib_api_status_t status; + + /* just making sure - cleanup the static global obj */ + cl_memclr( p_ibtrapgen, sizeof( *p_ibtrapgen ) ); + + /* construct and init the log */ + p_ibtrapgen->p_log = (osm_log_t *)cl_malloc(sizeof(osm_log_t)); + osm_log_construct( p_ibtrapgen->p_log ); + status = osm_log_init( p_ibtrapgen->p_log, p_opt->force_log_flush, + 0x0001, p_opt->log_file,FALSE ); + if( status != IB_SUCCESS ) + return ( status ); + + osm_log_set_level( p_ibtrapgen->p_log, log_flags ); + + /* finaly can declare we are here ... */ + osm_log( p_ibtrapgen->p_log, OSM_LOG_FUNCS, + "ibtrapgen_init: [\n" ); + + /* assign all the opts */ + p_ibtrapgen->p_opt = p_opt; + + /* initialize the osm vendor service object */ + p_ibtrapgen->p_vendor = osm_vendor_new( p_ibtrapgen->p_log, + p_opt->transaction_timeout ); + + if( p_ibtrapgen->p_vendor == NULL ) + { + status = IB_INSUFFICIENT_RESOURCES; + osm_log( p_ibtrapgen->p_log, OSM_LOG_ERROR, + "ibtrapgen_init: ERR 0001: " + "Unable to allocate vendor object" ); + goto Exit; + } + + /* all mads (actually wrappers) are taken and returned to a pool */ + osm_mad_pool_construct( &p_ibtrapgen->mad_pool ); + status = osm_mad_pool_init( + &p_ibtrapgen->mad_pool, p_ibtrapgen->p_log ); + if( status != IB_SUCCESS ) + goto Exit; + + Exit: + osm_log( p_ibtrapgen->p_log, OSM_LOG_FUNCS, + "ibtrapgen_init: ]\n" ); + return ( status ); +} + +/****f* opensm: SM/__ibtrapgen_rcv_callback + * NAME + * __osm_sm_mad_ctrl_rcv_callback + * + * DESCRIPTION + * This is the callback from the transport layer for received MADs. + * + * SYNOPSIS + */ +void +__ibtrapgen_rcv_callback( + IN osm_madw_t *p_madw, + IN void *bind_context, + IN osm_madw_t *p_req_madw ) +{ + ibtrapgen_t* p_ibtrapgen = (ibtrapgen_t*)bind_context; + + OSM_LOG_ENTER( p_ibtrapgen->p_log, __ibtrapgen_rcv_callback ); + + CL_ASSERT( p_madw ); + + osm_log( p_ibtrapgen->p_log, OSM_LOG_VERBOSE, + "__ibtrapgen_rcv_callback: Got callback\n", + cl_ntoh64(p_madw->p_mad->trans_id) ); + + OSM_LOG_EXIT( p_ibtrapgen->p_log ); +} + +/****f* opensm: SM/__ibtrapgen_send_err_cb + * NAME + * __ibtrapgen_send_err_cb + * + * DESCRIPTION + * This is the callback from the transport layer for received MADs. + * + * SYNOPSIS + */ +void +__ibtrapgen_send_err_cb( + IN void *bind_context, + IN osm_madw_t *p_madw ) +{ + ibtrapgen_t* p_ibtrapgen = (ibtrapgen_t*)bind_context; + + OSM_LOG_ENTER( p_ibtrapgen->p_log, __ibtrapgen_send_err_callback ); + + osm_log( p_ibtrapgen->p_log, OSM_LOG_ERROR, + "__ibtrapgen_send_err_cb: ERR 0011: " + "MAD completed in error (%s).\n", + ib_get_err_str( p_madw->status ) ); + + CL_ASSERT( p_madw ); + + osm_log( p_ibtrapgen->p_log, OSM_LOG_ERROR, + "__ibtrapgen_send_err_cb: ERR 0012: " + "We shouldn't be here!! TID:0x%016" PRIx64 ".\n", + cl_ntoh64(p_madw->p_mad->trans_id) ); + OSM_LOG_EXIT( p_ibtrapgen->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +ibtrapgen_bind( IN ibtrapgen_t * p_ibtrapgen ) +{ + ib_api_status_t status; + uint32_t num_ports = GUID_ARRAY_SIZE; + ib_port_attr_t attr_array[GUID_ARRAY_SIZE]; + osm_bind_info_t bind_info; + uint8_t i; + + OSM_LOG_ENTER( p_ibtrapgen->p_log, ibtrapgen_bind ); + + /* + * Call the transport layer for a list of local port + * GUID values. + */ + status = osm_vendor_get_all_port_attr( p_ibtrapgen->p_vendor, + attr_array, &num_ports ); + if ( status != IB_SUCCESS ) + { + osm_log( p_ibtrapgen->p_log, OSM_LOG_ERROR, + "ibtrapgen_bind: ERR 0002: " + "Failure getting local port attributes (%s)\n", + ib_get_err_str( status ) ); + goto Exit; + } + + /* make sure the requested port exists */ + if ( p_ibtrapgen->p_opt->port_num > num_ports ) + { + osm_log( p_ibtrapgen->p_log, OSM_LOG_ERROR, + "ibtrapgen_bind: ERR 0003: " + "Given port number out of range %u > %u\n", + p_ibtrapgen->p_opt->port_num , num_ports ); + status = IB_NOT_FOUND; + goto Exit; + } + + for ( i = 0 ; i < num_ports ; i++ ) + { + osm_log(p_ibtrapgen->p_log, OSM_LOG_INFO, + "ibtrapgen_bind: Found port number:%u " + " with GUID:0x%016" PRIx64 "\n", + i, cl_ntoh64(attr_array[i].port_guid) ); + } + /* check if the port is active */ +/* if (attr_array[p_ibtrapgen->p_opt->port_num - 1].link_state < 4) */ +/* { */ +/* osm_log( p_ibtrapgen->p_log, OSM_LOG_ERROR, */ +/* "ibtrapgen_bind: ERR 0004: " */ +/* "Given port number link state is not active: %s.\n", */ +/* ib_get_port_state_str( */ +/* attr_array[p_ibtrapgen->p_opt->port_num - 1].link_state ) */ +/* ); */ +/* status = IB_NOT_FOUND; */ +/* goto Exit; */ +/* } */ + + p_ibtrapgen->port_guid = attr_array[p_ibtrapgen->p_opt->port_num - 1].port_guid; + /* save sm_lid as we need it when sending the Trap (dest lid)*/ + p_ibtrapgen->p_opt->sm_lid = attr_array[p_ibtrapgen->p_opt->port_num - 1].sm_lid; + + osm_log(p_ibtrapgen->p_log, OSM_LOG_DEBUG, + "ibtrapgen_bind: Port Num:%u " + "GUID:0x%016"PRIx64"\n", + p_ibtrapgen->p_opt->port_num, + p_ibtrapgen->port_guid ); + + /* ok finaly bind the sa interface to this port */ + /* TODO - BIND LIKE THE osm_sm_mad_ctrl does */ + bind_info.class_version = 1; + bind_info.is_report_processor = TRUE; + bind_info.is_responder = TRUE; + bind_info.is_trap_processor = TRUE; + bind_info.mad_class = IB_MCLASS_SUBN_LID; + bind_info.port_guid = p_ibtrapgen->port_guid; + bind_info.recv_q_size = OSM_SM_DEFAULT_QP0_RCV_SIZE; + bind_info.send_q_size = OSM_SM_DEFAULT_QP0_SEND_SIZE; + + osm_log(p_ibtrapgen->p_log, OSM_LOG_DEBUG, + "ibtrapgen_bind: Trying to bind to GUID:0x%016"PRIx64"\n", + bind_info.port_guid ); + + p_ibtrapgen->h_bind = osm_vendor_bind( p_ibtrapgen->p_vendor, + &bind_info, + &p_ibtrapgen->mad_pool, + __ibtrapgen_rcv_callback, + __ibtrapgen_send_err_cb, + p_ibtrapgen ); + + if( p_ibtrapgen->h_bind == OSM_BIND_INVALID_HANDLE ) + { + osm_log( p_ibtrapgen->p_log, OSM_LOG_ERROR, + "ibtrapgen_bind: ERR 0005: " + "Unable to bind to SA\n" ); + status = IB_ERROR; + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_ibtrapgen->p_log ); + return ( status ); +} + +/********************************************************************** + **********************************************************************/ +void +ibtrapgen_destroy( IN ibtrapgen_t * p_ibtrapgen ) +{ + if( p_ibtrapgen->p_vendor ) + { + osm_vendor_delete( &p_ibtrapgen->p_vendor ); + } + + osm_log_destroy( p_ibtrapgen->p_log ); + cl_free( p_ibtrapgen->p_log ); +} + +/********************************************************************** + **********************************************************************/ + +ib_api_status_t +ibtrapgen_run( IN ibtrapgen_t * const p_ibtrapgen ) +{ + osm_madw_t* p_report_madw; + ib_mad_notice_attr_t* p_report_ntc; + ib_mad_t* p_mad; + ib_smp_t* p_smp_mad; + osm_mad_addr_t mad_addr; + static atomic32_t trap_fwd_trans_id = 0x02DAB000; + ib_api_status_t status; + osm_log_t *p_log = p_ibtrapgen->p_log; + uint16_t i; + + OSM_LOG_ENTER( p_log, ibtrapgen_run ); + + osm_log( p_log, OSM_LOG_INFO, + "ibtrapgen_run: " + "Sending trap:%u from LID:0x%X %u times\n", + p_ibtrapgen->p_opt->trap_num, + p_ibtrapgen->p_opt->lid, + p_ibtrapgen->p_opt->number ); + + printf("-V- SM lid is : 0x%04X\n",cl_ntoh16(p_ibtrapgen->p_opt->sm_lid)); + mad_addr.dest_lid = (p_ibtrapgen->p_opt->sm_lid); + /* ??? - what is path_bits? What should be the value here?? */ + mad_addr.path_bits = 0; + /* ??? - what is static_rate? What should be the value here?? */ + mad_addr.static_rate = 0; + + mad_addr.addr_type.smi.source_lid = cl_hton16(p_ibtrapgen->p_opt->lid); + mad_addr.addr_type.smi.port_num = p_ibtrapgen->p_opt->src_port; + + for (i = 1 ; i <= p_ibtrapgen->p_opt->number ; i++ ) + { + p_report_madw = osm_mad_pool_get( &p_ibtrapgen->mad_pool, + p_ibtrapgen->h_bind, + MAD_BLOCK_SIZE, + &mad_addr ); + + if( !p_report_madw ) + { + osm_log(p_log, OSM_LOG_ERROR, + "ibtrapgen_run: ERR 00020: " + "osm_mad_pool_get failed.\n" ); + status = IB_ERROR; + goto Exit; + } + + p_report_madw->resp_expected = FALSE; + + /* advance trap trans id (cant simply ++ on some systems inside ntoh) */ + p_mad = osm_madw_get_mad_ptr( p_report_madw ); + ib_mad_init_new(p_mad, + IB_MCLASS_SUBN_LID, + 1, + IB_MAD_METHOD_TRAP, + cl_hton64( (uint64_t)cl_atomic_inc( &trap_fwd_trans_id ) ), + IB_MAD_ATTR_NOTICE, + 0); + + p_smp_mad = osm_madw_get_smp_ptr( p_report_madw ); + + /* The payload is analyzed as mad notice attribute */ + p_report_ntc = (ib_mad_notice_attr_t*)(ib_smp_get_payload_ptr(p_smp_mad)); + + cl_memclr( p_report_ntc, sizeof(*p_report_ntc) ); + p_report_ntc->generic_type = 0x83; /* is generic subn mgt type */ + ib_notice_set_prod_type(p_report_ntc, 2); /* A switch generator */ + p_report_ntc->g_or_v.generic.trap_num = cl_hton16(p_ibtrapgen->p_opt->trap_num); + p_report_ntc->issuer_lid = cl_hton16(p_ibtrapgen->p_opt->lid); + if (p_ibtrapgen->p_opt->trap_num == 128) + { + p_report_ntc->data_details.ntc_128.sw_lid = cl_hton16(p_ibtrapgen->p_opt->lid); + } + else + { + p_report_ntc->data_details.ntc_129_131.lid = + cl_hton16(p_ibtrapgen->p_opt->lid); + p_report_ntc->data_details.ntc_129_131.port_num = + p_ibtrapgen->p_opt->src_port; + } + + status = osm_vendor_send(p_report_madw->h_bind, p_report_madw, FALSE ); + if (status != IB_SUCCESS) + { + osm_log(p_log, OSM_LOG_ERROR, + "ibtrapgen_run: ERR 0021: " + "osm_vendor_send. status = %s\n", + ib_get_err_str(status)); + goto Exit; + } + osm_log(p_log, OSM_LOG_INFO, + "ibtrapgen_run: " + "Sent trap number:%u out of:%u\n", + i, + p_ibtrapgen->p_opt->number ); + /* sleep according to rate time. The usleep is in usec - need to revert + the milisecs to usecs. */ + usleep(p_ibtrapgen->p_opt->rate*1000); + } + + Exit: + // sleep(3); + OSM_LOG_EXIT( p_log ); + return(status); +} diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/ibtrapgen/ibtrapgen.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/ibtrapgen/ibtrapgen.h new file mode 100644 index 00000000..6fe54862 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/ibtrapgen/ibtrapgen.h @@ -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 +#include +#include +#include +#include +#include + +/****h* Trap_Generator_App/Ibtrapgen + * NAME + * Ibtrapgen + * + * DESCRIPTION + * The Ibtrapgen object create/join and leave multicast group. + * + * AUTHOR + * Yael Kalka, Mellanox. + * + *********/ + +/****s* Trap_Generator_App/ibtrapgen_opt_t + * NAME + * ibtrapgen_opt_t + * + * DESCRIPTION + * Ibtrapgen options structure. This structure contains the various + * specific configuration parameters for ibtrapgen. + * + * SYNOPSYS + */ +typedef struct _ibtrapgen_opt +{ + uint8_t trap_num; + uint16_t number; + uint16_t rate; + uint16_t lid; + uint16_t sm_lid; + uint8_t src_port; + uint8_t port_num; + uint32_t transaction_timeout; + boolean_t force_log_flush; + char *log_file; +} ibtrapgen_opt_t; +/* + * FIELDS + * + * trap_num + * Trap number to generate. + * + * number + * Number of times trap should be generated. + * + * rate + * Rate of trap generation (in miliseconds) + * + * lid + * Lid from which the trap should be generated. + * + * src_port + * Source port from which the trap should be generated. + * + * port_num + * Port num used for communicating with the SA. + * + * SEE ALSO + *********/ + +/****s* Trap Generator App/ibtrapgen_t + * NAME + * ibtrapgen_t + * + * DESCRIPTION + * Ibtrapgen structure. + * + * This object should be treated as opaque and should + * be manipulated only through the provided functions. + * + * SYNOPSYS + */ +typedef struct _ibtrapgen +{ + osm_log_t *p_log; + struct _osm_vendor *p_vendor; + osm_bind_handle_t h_bind; + osm_mad_pool_t mad_pool; + + ibtrapgen_opt_t *p_opt; + ib_net64_t port_guid; +} ibtrapgen_t; +/* + * FIELDS + * p_log + * Log facility used by all Ibtrapgen components. + * + * p_vendor + * Pointer to the vendor transport layer. + * + * h_bind + * The bind handle obtained by osm_vendor_sa_api/osmv_bind_sa + * + * mad_pool + * The mad pool provided for teh vendor layer to allocate mad wrappers in + * + * p_opt + * ibtrapgen options structure + * + * guid + * guid for the port over which ibtrapgen is running. + * + * SEE ALSO + *********/ + +/****f* Trap_Generator_App/ibtrapgen_destroy + * NAME + * ibtrapgen_destroy + * + * DESCRIPTION + * The ibtrapgen_destroy function destroys an ibtrapgen object, releasing + * all resources. + * + * SYNOPSIS + */ +void ibtrapgen_destroy( IN ibtrapgen_t * p_ibtrapgen ); + +/* + * PARAMETERS + * p_ibtrapgen + * [in] Pointer to a Trap_Generator_App object to destroy. + * + * RETURN VALUE + * This function does not return a value. + * + * NOTES + * Performs any necessary cleanup of the specified Trap_Generator_App object. + * Further operations should not be attempted on the destroyed object. + * This function should only be called after a call to ibtrapgen_init. + * + * SEE ALSO + * ibtrapgen_init + *********/ + +/****f* Trap_Generator_App/ibtrapgen_init + * NAME + * ibtrapgen_init + * + * DESCRIPTION + * The ibtrapgen_init function initializes a Trap_Generator_App object for use. + * + * SYNOPSIS + */ +ib_api_status_t ibtrapgen_init( IN ibtrapgen_t * const p_ibtrapgen, + IN ibtrapgen_opt_t * const p_opt, + IN const osm_log_level_t log_flags + ); + +/* + * PARAMETERS + * p_ibtrapgen + * [in] Pointer to an ibtrapgen_t object to initialize. + * + * p_opt + * [in] Pointer to the options structure. + * + * log_flags + * [in] Log level flags to set. + * + * RETURN VALUES + * IB_SUCCESS if the Trap_Generator_App object was initialized successfully. + * + * NOTES + * Allows calling other Trap_Generator_App methods. + * + * SEE ALSO + * ibtrapgen object, ibtrapgen_construct, ibtrapgen_destroy + *********/ + + +/****f* Trap_Generator_App/ibtrapgen_bind + * NAME + * ibtrapgen_bind + * + * DESCRIPTION + * Binds ibtrapgen to a local port. + * + * SYNOPSIS + */ +ib_api_status_t ibtrapgen_bind( IN ibtrapgen_t * p_ibtrapgen ); +/* + * PARAMETERS + * p_ibtrapgen + * [in] Pointer to an ibtrapgen_t object. + * + * RETURN VALUES + * IB_SUCCESS if OK + * + * NOTES + * + * SEE ALSO + *********/ + +/****f* Trap_Generator_App/ibtrapgen_run + * NAME + * ibtrapgen_run + * + * DESCRIPTION + * Runs the ibtrapgen flow: Creation of traps. + * + * SYNOPSIS + */ +ib_api_status_t ibtrapgen_run( IN ibtrapgen_t * const p_ibtrapgen ); + +/* + * PARAMETERS + * p_ibtrapgen + * [in] Pointer to an ibtrapgen_t object. + * + * RETURN VALUES + * IB_SUCCESS on success + * + * NOTES + * + * SEE ALSO + *********/ + +#endif /* */ diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/ibtrapgen/main.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/ibtrapgen/main.c new file mode 100644 index 00000000..f7f1de7d --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/ibtrapgen/main.c @@ -0,0 +1,465 @@ +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + This software program is available to you under a choice of one of two + licenses. You may choose to be licensed under either the GNU General Public + License (GPL) Version 2, June 1991, available at + http://www.fsf.org/copyleft/gpl.html, or the Intel BSD + Patent License, + the text of which follows: + + "Recipient" has requested a license and Intel Corporation ("Intel") + is willing to grant a license for the software entitled + InfiniBand(tm) System Software (the "Software") being provided by + Intel Corporation. + + The following definitions apply to this License: + + "Licensed Patents" means patent claims licensable by Intel Corporation which + are necessarily infringed by the use or sale of the Software alone or when + combined with the operating system referred to below. + + "Recipient" means the party to whom Intel delivers this Software. + "Licensee" means Recipient and those third parties that receive a license to + any operating system available under the GNU Public License version 2.0 or + later. + + Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + + The license is provided to Recipient and Recipient's Licensees under the + following terms. + + Redistribution and use in source and binary forms of the Software, with or + without modification, are permitted provided that the following + conditions are met: + Redistributions of source code of the Software may retain the above copyright + notice, this list of conditions and the following disclaimer. + + Redistributions in binary form of the Software may reproduce the above + copyright notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + Neither the name of Intel Corporation nor the names of its contributors shall + be used to endorse or promote products derived from this Software without + specific prior written permission. + + Intel hereby grants Recipient and Licensees a non-exclusive, worldwide, + royalty-free patent license under Licensed Patents to make, use, sell, offer + to sell, import and otherwise transfer the Software, if any, in source code + and object code form. This license shall include changes to the Software that + are error corrections or other minor changes to the Software that do not add + functionality or features when the Software is incorporated in any version of + a operating system that has been distributed under the GNU General Public + License 2.0 or later. This patent license shall apply to the combination of + the Software and any operating system licensed under the GNU Public License + version 2.0 or later if, at the time Intel provides the Software to + Recipient, such addition of the Software to the then publicly + available versions of such operating system available under the GNU + Public License version 2.0 or later (whether in gold, beta or alpha + form) causes such combination to be covered by the Licensed + Patents. The patent license shall not apply to any other + combinations which include the Software. No hardware per se is + licensed hereunder. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + --------------------------------------------------------------------------*/ + + +/* + * Abstract: + * Command line interface for ibtrapgen. + * Parse and fill in the options and call the actual code. + * Implemented in ibtrapgen: + * Initialize the ibmgrp object (and log) + * Bind ibmgrp to the requested IB port. + * Run the actual command + * + * Environment: + * Linux User Mode + * + * $Revision: 1.1 $ + */ + +#include +#include +#ifndef __WIN__ +#include +#endif +#include +#include +#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 -n|--number \n" + " -r|--rate -l|--lid \n" + " -s|--src_port -p|--port_num \n" ); + printf( "\nOptions:\n" ); + printf( "-t \n" + "--trap_num \n" + " This option specifies the number of the trap to generate.\n" + " Valid values are 128-131.\n" ); + printf( "-n \n" + "--number \n" + " This option specifies the number of times to generate this trap.\n" + " If not specified - default to 1.\n" ); + printf( "-r \n" + "--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 \n" + "--lid \n" + " This option specifies the lid address from where the trap should\n" + " be generated.\n" ); + printf( "-s \n" + "--src_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 \n" + "--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 \n" + " This option sets the log verbosity level.\n" + " A flags field must follow the -vf option.\n" + " A bit set/clear in the flags enables/disables a\n" + " specific log level as follows:\n" + " BIT LOG LEVEL ENABLED\n" + " ---- -----------------\n" + " 0x01 - ERROR (error messages)\n" + " 0x02 - INFO (basic messages, low volume)\n" + " 0x04 - VERBOSE (interesting stuff, moderate volume)\n" + " 0x08 - DEBUG (diagnostic, high volume)\n" + " 0x10 - FUNCS (function entry/exit, very high volume)\n" + " 0x20 - FRAMES (dumps all SMP and GMP frames)\n" + " 0x40 - currently unused.\n" + " 0x80 - currently unused.\n" + " Without -x, ibtrapgen defaults to ERROR + INFO (0x3).\n" + " Specifying -x 0 disables all messages.\n" + " Specifying -x 0xFF enables all messages (see -V).\n\n" ); +} + +/********************************************************************** + **********************************************************************/ +/* + Converts a GID string of the format 0xPPPPPPPPPPPPPPPP:GGGGGGGGGGGGGGGG + to a gid type +*/ +int +str2gid( + IN char *str, + OUT ib_gid_t *p_gid + ); + +int +str2gid( + IN char *str, + OUT ib_gid_t *p_gid + ) +{ + ib_gid_t temp; + char buf[38]; + char *p_prefix, *p_guid; + + CL_ASSERT(p_gid); + + strcpy(buf, str); + p_prefix = buf; + /*p_guid = index(buf, ':');*/ + p_guid = strchr( buf, ':' ); + + if (! p_guid) + { + printf("Wrong format for gid %s\n", buf); + return 1; + } + + *p_guid = '\0'; + p_guid++; + + errno = 0; + temp.unicast.prefix = cl_hton64(strtoull(p_prefix, NULL, 0)); + if (errno) { + printf("Wrong format for gid prefix:%s (got %u)\n", + p_prefix, errno); + return 1; + } + + temp.unicast.interface_id = cl_hton64(strtoull(p_guid, NULL, 16)); + if (errno) { + printf("Wrong format for gid guid:%s\n", p_guid); + return 1; + } + + *p_gid = temp; + return 0; +} +void OsmReportState(IN const char *p_str) +{ +} +/********************************************************************** + **********************************************************************/ +int OSM_CDECL +main( int argc, + char *argv[] ) +{ + static ibtrapgen_t ibtrapgen; + ibtrapgen_opt_t opt = { 0 }; + ib_api_status_t status; + uint32_t log_flags = OSM_LOG_ERROR | OSM_LOG_INFO; + uint32_t next_option; + const char *const short_option = "t:n:r:s:l:p:o:vVh"; + + /* + * In the array below, the 2nd parameter specified the number + * of arguments as follows: + * 0: no arguments + * 1: argument + * 2: optional + */ + const struct option long_option[] = { + {"trap_num", 1, NULL, 't'}, + {"number", 1, NULL, 'n'}, + {"rate", 1, NULL, 'r'}, + {"lid", 1, NULL, 'l'}, + {"src_port", 1, NULL, 's'}, + {"port_num", 1, NULL, 'p'}, + {"help", 0, NULL, 'h'}, + {"verbose", 0, NULL, 'v'}, + {"out_log_file", 1, NULL, 'o'}, + {"vf", 1, NULL, 'x'}, + {"V", 0, NULL, 'V'}, + + {NULL, 0, NULL, 0} /* Required at end of array */ + }; + + + opt.trap_num = 0; + opt.number = 1; /* This is the default value */ + opt.rate = 0; + opt.lid = 0; + opt.src_port = 0; + opt.port_num = 0; + opt.log_file = NULL; + opt.force_log_flush = FALSE; + opt.transaction_timeout = DEFAULT_TRANS_TIMEOUT_MILLISEC; + + do + { + next_option = getopt_long_only( argc, argv, short_option, + long_option, NULL ); + + switch ( next_option ) + { + case 't': + /* + * Define the trap number + */ + opt.trap_num = (uint8_t)atoi( optarg ); + if ((opt.trap_num < 128) || (opt.trap_num > 131)) + { + printf( "-E- Given trap number is illegal! \n" + " Supportes generation of traps 128-131.\n" ); + exit(1); + } + printf( "-I- Trap Number = %u\n", opt.trap_num ); + break; + + case 'n': + /* + * Define the number of occurences + */ + opt.number = (uint16_t)atoi( optarg ); + + printf( "-I- Number Trap Occurences = %u\n", opt.number ); + break; + + case 'r': + /* + * Define the rate of the trap + */ + opt.rate = (uint16_t)atoi( optarg ); + + printf( "-I- Trap Rate = %u miliseconds\n", opt.rate ); + break; + + + case 'l': + /* + * Define the source lid of the trap + */ + opt.lid = (uint16_t)strtoul( optarg , NULL , 16); + + printf( "-I- Trap Lid = 0x%04X\n", opt.lid ); + break; + + case 's': + /* + * Define the source port number of the trap + */ + opt.src_port = (uint8_t)atoi( optarg ); + + printf( "-I- Trap Port Number = %u\n", opt.src_port ); + break; + + case 'p': + /* + * Specifies port guid with which to bind. + */ + opt.port_num = (uint8_t)atoi( optarg ); + printf( "-I- Port Num:%u\n", opt.port_num ); + break; + + case 'o': + opt.log_file = optarg; + printf("-I- Log File:%s\n", opt.log_file ); + break; + + case 'v': + /* + * Increases log verbosity. + */ + log_flags = ( log_flags << 1 ) | 1; + printf( "-I- Verbose option -v (log flags = 0x%X)\n", log_flags ); + break; + + case 'V': + /* + * Specifies maximum log verbosity. + */ + log_flags = 0xFFFFFFFF; + opt.force_log_flush = TRUE; + printf( "-I- Enabling maximum log verbosity\n" ); + break; + + case 'h': + show_usage( ); + return 0; + + case 'x': + log_flags = strtol( optarg, NULL, 0 ); + printf( "-I- Verbose option -vf (log flags = 0x%X)\n", + log_flags ); + break; + + case -1: + /* printf( "Done with args\n" ); */ + break; + + default: /* something wrong */ + abort( ); + } + + } + while( next_option != -1 ); + + /* Check for mandatory options */ + if (opt.trap_num == 0) + { + printf( "-E- Missing trap number.\n" ); + exit(1); + } + if (opt.lid == 0) + { + printf( "-E- Missing lid.\n" ); + exit(1); + } + if (opt.src_port == 0 && opt.trap_num >= 129 && opt.trap_num <= 131) + { + /* for trap 129-131 should be given source port number */ + printf( "-E- source port number.\n" ); + exit(1); + } + if (opt.port_num == 0) + { + printf( "-E- Missing port number.\n" ); + exit(1); + } + if (opt.rate == 0 && opt.number > 1) + { + /* for number of traps greater than 1 need to give the rate for the + trap generation. */ + printf( "-E- Missing rate.\n" ); + exit(1); + } + + + /* init the main object and sub objects (log and osm vendor) */ + status = ibtrapgen_init( &ibtrapgen, &opt, ( osm_log_level_t ) log_flags ); + if( status != IB_SUCCESS ) + { + printf("-E- fail to init ibtrapgen.\n"); + goto Exit; + } + + /* bind to a specific port */ + status = ibtrapgen_bind( &ibtrapgen ); + if (status != IB_SUCCESS) exit(status); + + /* actual work */ + status = ibtrapgen_run( &ibtrapgen ); + if (status != IB_SUCCESS) + { + printf("IBTRAPGEN: FAIL\n"); + } + else + { + printf("IBTRAPGEN: PASS\n"); + } + + //ibtrapgen_destroy( &ibtrapgen ); + + Exit: + exit ( status ); +} diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/complib/cl_byteswap.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/complib/cl_byteswap.h new file mode 100644 index 00000000..60a741d0 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/complib/cl_byteswap.h @@ -0,0 +1,547 @@ +/* + * Copyright (c) 2004,2005 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: cl_byteswap.h 474 2006-08-31 08:57:19Z sleybo $ + */ + + + +/* + * Abstract: + * provides byteswapping utilities. Basic fuctions are obtained from platform + * specific implementations from ibyteswap_osd.h. + * + * Environment: + * All + */ + + +#ifndef _CL_BYTESWAP_H_ +#define _CL_BYTESWAP_H_ + + +#include +#include + + +/****h* Component Library/Byte Swapping +* NAME +* Byte Swapping +* +* DESCRIPTION +* The byte swapping functions and macros allow swapping bytes from network +* byte order to host byte order. +* +* All data transmitted between systems should be in network byte order. +* In order to utilize such data, it must be converted to host byte order +* before use. +* +* SEE ALSO +* Functions: +* cl_ntoh16, cl_hton16, cl_ntoh32, cl_hton32, cl_ntoh64, cl_hton64, +* cl_ntoh +* +* Macros: +* CL_NTOH16, CL_HTON16, CL_NTOH32, CL_HTON32, CL_NTOH64, CL_HTON64 +*********/ + + +/* + * The ibyteswap_osd.h provides the following macros. + * __LITTLE_ENDIAN + * __BIG_ENDIAN + * __BYTE_ORDER + * + * If the platform provides byte swapping functions, ibyteswap_osd.h also + * provides the following macros. + * ntoh16, hton16 + * ntoh32, hton32 + * ntoh64, hton64 + */ + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/****d* Component Library: Byte Swapping/CL_NTOH16 +* NAME +* CL_NTOH16 +* +* DESCRIPTION +* The CL_NTOH16 macro converts a 16-bit value from network byte order to +* host byte order. The CL_NTOH16 macro will cause constant values to be +* swapped by the pre-processor. For variables, CL_NTOH16 is less efficient +* than the cl_ntoh16 function. +* +* SYNOPSIS +* CL_NTOH16( val ); +* +* PARAMETERS +* val +* [in] 16-bit value to swap from network byte order to host byte order. +* +* RESULT +* Value of val converted to host byte order. +* +* NOTES +* This macro is analogous to CL_HTON16. +* +* SEE ALSO +* Byte Swapping, CL_HTON16, CL_NTOH32, CL_NTOH64, +* cl_ntoh16, cl_ntoh32, cl_ntoh64, cl_ntoh +*********/ +/****d* Component Library: Byte Swapping/CL_HTON16 +* NAME +* CL_HTON16 +* +* DESCRIPTION +* The CL_HTON16 macro converts a 16-bit value from host byte order to +* network byte order. The CL_HTON16 macro will cause constant values to be +* swapped by the pre-processor. For variables, CL_HTON16 is less efficient +* than the cl_hton16 function. +* +* SYNOPSIS +* CL_HTON16( val ); +* +* PARAMETERS +* val +* [in] 16-bit value to swap from host byte order to network byte order. +* +* RESULT +* Value of val converted to network byte order. +* +* NOTES +* This macro is analogous to CL_NTOH16. +* +* SEE ALSO +* Byte Swapping, CL_NTOH16, CL_HTON32, CL_HTON64, +* cl_hton16, cl_hton32, cl_hton64, cl_ntoh +*********/ +#if CPU_LE + #define CL_NTOH16( x ) (uint16_t)( \ + (((uint16_t)(x) & 0x00FF) << 8) | \ + (((uint16_t)(x) & 0xFF00) >> 8) ) +#else + #define CL_NTOH16( x ) (x) +#endif +#define CL_HTON16 CL_NTOH16 + + +/****f* Component Library: Byte Swapping/cl_ntoh16 +* NAME +* cl_ntoh16 +* +* DESCRIPTION +* The cl_ntoh16 function converts a 16-bit value from network byte order to +* host byte order. +* +* SYNOPSIS +* uint16_t +* cl_ntoh16( +* IN const uint16_t val ); +* +* PARAMETERS +* val +* [in] Value to swap from network byte order to host byte order. +* +* RETURN VALUE +* Value of val converted to host byte order. +* +* NOTES +* This function is analogous to cl_hton16. +* +* SEE ALSO +* Byte Swapping, cl_hton16, cl_ntoh32, cl_ntoh64, cl_ntoh +*********/ +/****f* Component Library: Byte Swapping/cl_hton16 +* NAME +* cl_hton16 +* +* DESCRIPTION +* The cl_hton16 function converts a 16-bit value from host byte order to +* network byte order. +* +* SYNOPSIS +* uint16_t +* cl_hton16( +* IN const uint16_t val ); +* +* PARAMETERS +* val +* [in] Value to swap from host byte order to network byte order . +* +* RETURN VALUE +* Value of val converted to network byte order. +* +* NOTES +* This function is analogous to cl_ntoh16. +* +* SEE ALSO +* Byte Swapping, cl_ntoh16, cl_hton32, cl_hton64, cl_ntoh +*********/ +#undef cl_ntoh16 +#undef cl_hton16 +#ifndef cl_ntoh16 + #define cl_ntoh16 CL_NTOH16 + #define cl_hton16 CL_HTON16 +#endif + + +/****d* Component Library: Byte Swapping/CL_NTOH32 +* NAME +* CL_NTOH32 +* +* DESCRIPTION +* The CL_NTOH32 macro converts a 32-bit value from network byte order to +* host byte order. The CL_NTOH32 macro will cause constant values to be +* swapped by the pre-processor. For variables, CL_NTOH32 is less efficient +* than the cl_ntoh32 function. +* +* SYNOPSIS +* CL_NTOH32( val ); +* +* PARAMETERS +* val +* [in] 32-bit value to swap from network byte order to host byte order. +* +* RESULT +* Value of val converted to host byte order. +* +* NOTES +* This macro is analogous to CL_HTON32. +* +* SEE ALSO +* Byte Swapping, CL_HTON32, CL_NTOH16, CL_NTOH64, +* cl_ntoh16, cl_ntoh32, cl_ntoh64, cl_ntoh +*********/ +/****d* Component Library: Byte Swapping/CL_HTON32 +* NAME +* CL_HTON32 +* +* DESCRIPTION +* The CL_HTON32 macro converts a 32-bit value from host byte order to +* network byte order. The CL_HTON32 macro will cause constant values to be +* swapped by the pre-processor. For variables, CL_HTON32 is less efficient +* than the cl_hton32 function. +* +* SYNOPSIS +* CL_HTON32( val ); +* +* PARAMETERS +* val +* [in] 32-bit value to swap from host byte order to network byte order. +* +* RESULT +* Value of val converted to network byte order. +* +* NOTES +* This macro is analogous to CL_NTOH32. +* +* SEE ALSO +* Byte Swapping, CL_NTOH32, CL_HTON16, CL_HTON64, +* cl_hton16, cl_hton32, cl_hton64, cl_ntoh +*********/ +#if CPU_LE + #define CL_NTOH32( x ) (uint32_t)( \ + (((uint32_t)(x) & 0x000000FF) << 24) | \ + (((uint32_t)(x) & 0x0000FF00) << 8) | \ + (((uint32_t)(x) & 0x00FF0000) >> 8) | \ + (((uint32_t)(x) & 0xFF000000) >> 24) ) +#else + #define CL_NTOH32( x ) (x) +#endif +#define CL_HTON32 CL_NTOH32 + + +/****f* Component Library: Byte Swapping/cl_ntoh32 +* NAME +* cl_ntoh32 +* +* DESCRIPTION +* The cl_ntoh32 function converts a 32-bit value from network byte order to +* host byte order. +* +* SYNOPSIS +* uint32_t +* cl_ntoh32( +* IN const uint32_t val ); +* +* PARAMETERS +* val +* [in] Value to swap from network byte order to host byte order. +* +* RETURN VALUE +* Value of val converted in host byte order. +* +* NOTES +* This function is analogous to cl_hton32. +* +* SEE ALSO +* Byte Swapping, cl_hton32, cl_ntoh16, cl_ntoh64, cl_ntoh +*********/ +/****f* Component Library: Byte Swapping/cl_hton32 +* NAME +* cl_hton32 +* +* DESCRIPTION +* The cl_hton32 function converts a 32-bit value from host byte order to +* network byte order. +* +* SYNOPSIS +* uint32_t +* cl_hton32( +* IN const uint32_t val ); +* +* PARAMETERS +* val +* [in] Value to swap from host byte order to network byte order . +* +* RETURN VALUE +* Value of val converted to network byte order. +* +* NOTES +* This function is analogous to cl_ntoh32. +* +* SEE ALSO +* Byte Swapping, cl_ntoh32, cl_hton16, cl_hton64, cl_ntoh +*********/ +#undef cl_ntoh32 +#undef cl_hton32 +#ifndef cl_ntoh32 + #define cl_ntoh32 CL_NTOH32 + #define cl_hton32 CL_HTON32 +#endif + + +/****d* Component Library: Byte Swapping/CL_NTOH64 +* NAME +* CL_NTOH64 +* +* DESCRIPTION +* The CL_NTOH64 macro converts a 64-bit value from network byte order to +* host byte order. The CL_NTOH64 macro will cause constant values to be +* swapped by the pre-processor. For variables, CL_NTOH64 is less efficient +* than the cl_ntoh64 function. +* +* SYNOPSIS +* CL_NTOH64( val ); +* +* PARAMETERS +* val +* [in] 64-bit value to swap from network byte order to host byte order. +* +* RESULT +* Value of val converted to host byte order. +* +* NOTES +* This macro is analogous to CL_HTON64. +* +* SEE ALSO +* Byte Swapping, CL_HTON64, CL_NTOH16, CL_NTOH32, +* cl_ntoh16, cl_ntoh32, cl_ntoh64, cl_ntoh +*********/ +/****d* Component Library: Byte Swapping/CL_HTON64 +* NAME +* CL_HTON64 +* +* DESCRIPTION +* The CL_HTON64 macro converts a 64-bit value from host byte order to +* network byte order. The CL_HTON64 macro will cause constant values to be +* swapped by the pre-processor. For variables, CL_HTON64 is less efficient +* than the cl_hton64 function. +* +* SYNOPSIS +* CL_HTON64( val ); +* +* PARAMETERS +* val +* [in] 64-bit value to swap from host byte order to network byte order. +* +* RESULT +* Value of val converted to network byte order. +* +* NOTES +* This macro is analogous to CL_NTOH64. +* +* SEE ALSO +* Byte Swapping, CL_NTOH64, CL_HTON16, CL_HTON32, +* cl_hton16, cl_hton32, cl_hton64, cl_ntoh +*********/ +#if CPU_LE + #define CL_NTOH64( x ) (uint64_t)( \ + (((uint64_t)(x) & CL_CONST64(0x00000000000000FF)) << 56) | \ + (((uint64_t)(x) & CL_CONST64(0x000000000000FF00)) << 40) | \ + (((uint64_t)(x) & CL_CONST64(0x0000000000FF0000)) << 24) | \ + (((uint64_t)(x) & CL_CONST64(0x00000000FF000000)) << 8 ) | \ + (((uint64_t)(x) & CL_CONST64(0x000000FF00000000)) >> 8 ) | \ + (((uint64_t)(x) & CL_CONST64(0x0000FF0000000000)) >> 24) | \ + (((uint64_t)(x) & CL_CONST64(0x00FF000000000000)) >> 40) | \ + (((uint64_t)(x) & CL_CONST64(0xFF00000000000000)) >> 56) ) +#else + #define CL_NTOH64( x ) (x) +#endif +#define CL_HTON64 CL_NTOH64 + + +/****f* Component Library: Byte Swapping/cl_ntoh64 +* NAME +* cl_ntoh64 +* +* DESCRIPTION +* The cl_ntoh64 function converts a 64-bit value from network byte order to +* host byte order. +* +* SYNOPSIS +* uint64_t +* cl_ntoh64( +* IN const uint64_t val ); +* +* PARAMETERS +* val +* [in] Value to swap from network byte order to host byte order. +* +* RETURN VALUE +* Value of val converted in host byte order. +* +* NOTES +* This function is analogous to cl_hton64. +* +* SEE ALSO +* Byte Swapping, cl_hton64, cl_ntoh16, cl_ntoh32, cl_ntoh +*********/ +/****f* Component Library: Byte Swapping/cl_hton64 +* NAME +* cl_hton64 +* +* DESCRIPTION +* The cl_hton64 function converts a 64-bit value from host byte order to +* network byte order. +* +* SYNOPSIS +* uint64_t +* cl_hton64( +* IN const uint64_t val ); +* +* PARAMETERS +* val +* [in] Value to swap from host byte order to network byte order . +* +* RETURN VALUE +* Value of val converted to network byte order. +* +* NOTES +* This function is analogous to cl_ntoh64. +* +* SEE ALSO +* Byte Swapping, cl_ntoh64, cl_hton16, cl_hton32, cl_ntoh +*********/ +#undef cl_ntoh64 +#undef cl_hton64 +#ifndef cl_ntoh64 + #define cl_ntoh64 CL_NTOH64 + #define cl_hton64 CL_HTON64 +#endif + + +/****f* Component Library: Byte Swapping/cl_ntoh +* NAME +* cl_ntoh +* +* DESCRIPTION +* The cl_ntoh function converts a value from network byte order to +* host byte order. +* +* SYNOPSIS +*/ +CL_INLINE void CL_API +cl_ntoh( + OUT char* const p_dest, + IN const char* const p_src, + IN const uint8_t size ) +{ +#if CPU_LE + uint8_t i; + char temp; + + if( p_src == p_dest ) + { + /* Swap in place if source and destination are the same. */ + for( i = 0; i < size / 2; i++ ) + { + temp = p_dest[i]; + p_dest[i] = p_src[size - 1 - i]; + p_dest[size - 1 - i] = temp; + } + } + else + { + for( i = 0; i < size; i++ ) + p_dest[i] = p_src[size - 1 - i]; + } +#else + /* + * If the source and destination are not the same, copy the source to + * the destination. + */ + if( p_src != p_dest ) + cl_memcpy( p_dest, p_src, size ); +#endif +} +/* +* PARAMETERS +* p_dest +* [in] Pointer to a byte array to contain the converted value of p_src. +* +* p_src +* [in] Pointer to a byte array to be converted from network byte +* ordering. +* +* size +* [in] Number of bytes to swap.p_dest +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* cl_ntoh can perform in place swapping if both p_src and p_dest point to +* the same buffer. +* +* SEE ALSO +* Byte Swapping, cl_ntoh16, cl_ntoh32, cl_ntoh64 +*********/ + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* _CL_BYTESWAP_H_ */ diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/complib/cl_dispatcher.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/complib/cl_dispatcher.h new file mode 100644 index 00000000..123bd093 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/complib/cl_dispatcher.h @@ -0,0 +1,660 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ + + +/* + * Abstract: + * Declaration of dispatcher abstraction. + * + * Environment: + * All + * + * $Revision: 1.4 $ + */ + +#ifndef _CL_DISPATCHER_H_ +#define _CL_DISPATCHER_H_ + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* Component Library/Dispatcher +* NAME +* Dispatcher +* +* DESCRIPTION +* The Dispatcher provides a facility for message routing to +* asynchronous worker threads. +* +* The Dispatcher functions operate on a cl_dispatcher_t structure +* which should be treated as opaque and should be manipulated +* only through the provided functions. +* +* SEE ALSO +* Structures: +* cl_dispatcher_t +* +* Initialization/Destruction: +* cl_disp_construct, cl_disp_init, cl_disp_shutdown, cl_disp_destroy +* +* Manipulation: +* cl_disp_post, cl_disp_reset, cl_disp_wait_on +*********/ + +/****s* Component Library: Dispatcher/cl_disp_msgid_t +* NAME +* cl_disp_msgid_t +* +* DESCRIPTION +* Defines the type of dispatcher messages. +* +* SYNOPSIS +*/ +typedef uint32_t cl_disp_msgid_t; +/**********/ + +/****s* Component Library: Dispatcher/CL_DISP_MSGID_NONE +* NAME +* CL_DISP_MSGID_NONE +* +* DESCRIPTION +* Defines a message value that means "no message". +* This value is used during registration by Dispatcher clients +* that do not wish to receive messages. +* +* No Dispatcher message is allowed to have this value. +* +* SYNOPSIS +*/ +#define CL_DISP_MSGID_NONE 0xFFFFFFFF +/**********/ + +/****s* Component Library: Dispatcher/CL_DISP_INVALID_HANDLE +* NAME +* CL_DISP_INVALID_HANDLE +* +* DESCRIPTION +* Defines the value of an invalid Dispatcher registration handle. +* +* SYNOPSIS +*/ +#define CL_DISP_INVALID_HANDLE ((cl_disp_reg_handle_t)0) +/*********/ + +/****f* Component Library: Dispatcher/cl_pfn_msgrcv_cb_t +* NAME +* cl_pfn_msgrcv_cb_t +* +* DESCRIPTION +* This typedef defines the prototype for client functions invoked +* by the Dispatcher. The Dispatcher calls the corresponding +* client function when delivering a message to the client. +* +* The client function must be reentrant if the user creates a +* Dispatcher with more than one worker thread. +* +* SYNOPSIS +*/ +typedef void +(*cl_pfn_msgrcv_cb_t)( + IN void* context, + IN void* p_data ); +/* +* PARAMETERS +* context +* [in] Client specific context specified in a call to +* cl_disp_register +* +* p_data +* [in] Pointer to the client specific data payload +* of this message. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* This typedef provides a function prototype reference for +* the function provided by Dispatcher clients as a parameter +* to the cl_disp_register function. +* +* SEE ALSO +* Dispatcher, cl_disp_register +*********/ + +/****f* Component Library: Dispatcher/cl_pfn_msgdone_cb_t +* NAME +* cl_pfn_msgdone_cb_t +* +* DESCRIPTION +* This typedef defines the prototype for client functions invoked +* by the Dispatcher. The Dispatcher calls the corresponding +* client function after completing delivery of a message. +* +* The client function must be reentrant if the user creates a +* Dispatcher with more than one worker thread. +* +* SYNOPSIS +*/ +typedef void +(*cl_pfn_msgdone_cb_t)( + IN void* context, + IN void* p_data ); +/* +* PARAMETERS +* context +* [in] Client specific context specified in a call to +* cl_disp_post +* +* p_data +* [in] Pointer to the client specific data payload +* of this message. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* This typedef provides a function prototype reference for +* the function provided by Dispatcher clients as a parameter +* to the cl_disp_post function. +* +* SEE ALSO +* Dispatcher, cl_disp_post +*********/ + +/****s* Component Library: Dispatcher/cl_dispatcher_t +* NAME +* cl_dispatcher_t +* +* DESCRIPTION +* Dispatcher structure. +* +* The Dispatcher is thread safe. +* +* The cl_dispatcher_t structure should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _cl_dispatcher +{ + cl_spinlock_t lock; + cl_ptr_vector_t reg_vec; + cl_qlist_t reg_list; + cl_thread_pool_t worker_threads; + cl_qlist_t msg_fifo; + cl_qpool_t msg_pool; + uint64_t last_msg_queue_time_us; +} cl_dispatcher_t; +/* +* FIELDS +* reg_vec +* Vector of registration info objects. Indexed by message msg_id. +* +* lock +* Spinlock to guard internal structures. +* +* msg_fifo +* FIFO of messages being processed by the Dispatcher. New +* messages are posted to the tail of the FIFO. Worker threads +* pull messages from the front. +* +* worker_threads +* Thread pool of worker threads to dispose of posted messages. +* +* msg_pool +* Pool of message objects to be processed through the FIFO. +* +* reg_count +* Count of the number of registrants. +* +* state +* Indicates the state of the object. +* +* last_msg_queue_time_us +* The time that the last message spent in the Q in usec +* +* SEE ALSO +* Dispatcher +*********/ + +/****s* Component Library: Dispatcher/cl_disp_reg_info_t +* NAME +* cl_disp_reg_info_t +* +* DESCRIPTION +* Defines the dispatcher registration object structure. +* +* The cl_disp_reg_info_t structure is for internal use by the +* Dispatcher only. +* +* SYNOPSIS +*/ +typedef struct _cl_disp_reg_info +{ + cl_list_item_t list_item; + cl_pfn_msgrcv_cb_t pfn_rcv_callback; + const void *context; + atomic32_t ref_cnt; + cl_disp_msgid_t msg_id; + cl_dispatcher_t *p_disp; + +} cl_disp_reg_info_t; +/* +* FIELDS +* pfn_rcv_callback +* Client's message receive callback. +* +* context +* Client's context for message receive callback. +* +* rcv_thread_count +* Number of threads currently in the receive callback. +* +* msg_done_thread_count +* Number of threads currently in the message done callback. +* +* state +* State of this registration object. +* DISP_REGSTATE_INIT: initialized and inactive +* DISP_REGSTATE_ACTIVE: in active use +* DISP_REGSTATE_UNREGPEND: unregistration is pending +* +* msg_id +* Dispatcher message msg_id value for this registration object. +* +* p_disp +* Pointer to parent Dispatcher. +* +* SEE ALSO +*********/ + +/****s* Component Library: Dispatcher/cl_disp_msg_t +* NAME +* cl_disp_msg_t +* +* DESCRIPTION +* Defines the dispatcher message structure. +* +* The cl_disp_msg_t structure is for internal use by the +* Dispatcher only. +* +* SYNOPSIS +*/ +typedef struct _cl_disp_msg +{ + cl_pool_item_t item; + const void *p_data; + cl_disp_reg_info_t *p_src_reg; + cl_disp_reg_info_t *p_dest_reg; + cl_pfn_msgdone_cb_t pfn_xmt_callback; + uint64_t in_time; + const void *context; +} cl_disp_msg_t; +/* +* FIELDS +* item +* List & Pool linkage. Must be first element in the structure!! +* +* msg_id +* The message's numberic ID value. +* +* p_data +* Pointer to the data payload for this message. The payload +* is opaque to the Dispatcher. +* +* p_reg_info +* Pointer to the registration info of the sender. +* +* pfn_xmt_callback +* Client's message done callback. +* +* in_time +* The absolute time the message was inserted into the queue +* +* context +* Client's message done callback context. +* +* SEE ALSO +*********/ + +/****s* Component Library: Dispatcher/cl_disp_reg_info_t +* NAME +* cl_disp_reg_info_t +* +* DESCRIPTION +* Defines the Dispatcher registration handle. This handle +* should be treated as opaque by the client. +* +* SYNOPSIS +*/ +typedef const struct _cl_disp_reg_info *cl_disp_reg_handle_t; +/**********/ + +/****f* Component Library: Dispatcher/cl_disp_construct +* NAME +* cl_disp_construct +* +* DESCRIPTION +* This function constructs a Dispatcher object. +* +* SYNOPSIS +*/ +void +cl_disp_construct( + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_disp +* [in] Pointer to a Dispatcher. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling cl_disp_init and cl_disp_destroy. +* +* SEE ALSO +* Dispatcher, cl_disp_init, cl_disp_destroy +*********/ + +/****f* Component Library: Dispatcher/cl_disp_init +* NAME +* cl_disp_init +* +* DESCRIPTION +* This function initializes a Dispatcher object. +* +* SYNOPSIS +*/ +cl_status_t +cl_disp_init( + IN cl_dispatcher_t* const p_disp, + IN const uint32_t thread_count, + IN const char* const name ); +/* +* PARAMETERS +* p_disp +* [in] Pointer to a Dispatcher. +* +* thread_count +* [in] The number of worker threads to create in this Dispatcher. +* A value of 0 causes the Dispatcher to create one worker thread +* per CPU in the system. When the Dispatcher is created with +* only one thread, the Dispatcher guarantees to deliver posted +* messages in order. When the Dispatcher is created with more +* than one thread, messages may be delivered out of order. +* +* name +* [in] Name to associate with the threads. The name may be up to 16 +* characters, including a terminating null character. All threads +* created in the Dispatcher have the same name. +* +* RETURN VALUE +* CL_SUCCESS if the operation is successful. +* +* SEE ALSO +* Dispatcher, cl_disp_destoy, cl_disp_register, cl_disp_unregister, +* cl_disp_post +*********/ + +/****f* Component Library: Dispatcher/cl_disp_shutdown +* NAME +* cl_disp_shutdown +* +* DESCRIPTION +* This function shutdown a Dispatcher object. So it unreg all messages and +* clears the fifo and waits for the threads to exit +* +* SYNOPSIS +*/ +void +cl_disp_shutdown( + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_disp +* [in] Pointer to a Dispatcher. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* This function does not returns until all worker threads +* have exited client callback functions and been successfully +* shutdowned. +* +* SEE ALSO +* Dispatcher, cl_disp_construct, cl_disp_init +*********/ + +/****f* Component Library: Dispatcher/cl_disp_destroy +* NAME +* cl_disp_destroy +* +* DESCRIPTION +* This function destroys a Dispatcher object. +* +* SYNOPSIS +*/ +void +cl_disp_destroy( + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_disp +* [in] Pointer to a Dispatcher. +* +* RETURN VALUE +* This function does not return a value. +* +* SEE ALSO +* Dispatcher, cl_disp_construct, cl_disp_init +*********/ + +/****f* Component Library: Dispatcher/cl_disp_register +* NAME +* cl_disp_register +* +* DESCRIPTION +* This function registers a client with a Dispatcher object. +* +* SYNOPSIS +*/ +cl_disp_reg_handle_t +cl_disp_register( + IN cl_dispatcher_t* const p_disp, + IN const cl_disp_msgid_t msg_id, + IN cl_pfn_msgrcv_cb_t pfn_callback OPTIONAL, + IN const void* const context ); +/* +* PARAMETERS +* p_disp +* [in] Pointer to a Dispatcher. +* +* msg_id +* [in] Numberic message ID for which the client is registering. +* If the client does not wish to receive any messages, +* (a send-only client) then the caller should set this value +* to CL_DISP_MSGID_NONE. For efficiency, numeric message msg_id +* values should start with 0 and should be contiguous, or nearly so. +* +* pfn_callback +* [in] Message receive callback. The Dispatcher calls this +* function after receiving a posted message with the +* appropriate message msg_id value. Send-only clients may specify +* NULL for this value. +* +* context +* [in] Client context value passed to the cl_pfn_msgrcv_cb_t +* function. +* +* RETURN VALUE +* On success a Dispatcher registration handle. +* CL_CL_DISP_INVALID_HANDLE otherwise. +* +* SEE ALSO +* Dispatcher, cl_disp_unregister, cl_disp_post +*********/ + +/****f* Component Library: Dispatcher/cl_disp_unregister +* NAME +* cl_disp_unregister +* +* DESCRIPTION +* This function unregisters a client from a Dispatcher. +* +* SYNOPSIS +*/ +void +cl_disp_unregister( + IN const cl_disp_reg_handle_t handle ); +/* +* PARAMETERS +* handle +* [in] cl_disp_reg_handle_t value return by cl_disp_register. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* This function will not return until worker threads have exited +* the callback functions for this client. Do not invoke this +* function from a callback. +* +* SEE ALSO +* Dispatcher, cl_disp_register +*********/ + +/****f* Component Library: Dispatcher/cl_disp_post +* NAME +* cl_disp_post +* +* DESCRIPTION +* This function posts a message to a Dispatcher object. +* +* SYNOPSIS +*/ +cl_status_t +cl_disp_post( + IN const cl_disp_reg_handle_t handle, + IN const cl_disp_msgid_t msg_id, + IN const void* const p_data, + IN cl_pfn_msgdone_cb_t pfn_callback OPTIONAL, + IN const void* const context ); +/* +* PARAMETERS +* handle +* [in] cl_disp_reg_handle_t value return by cl_disp_register. +* +* msg_id +* [in] Numeric message msg_id value associated with this message. +* +* p_data +* [in] Data payload for this message. +* +* pfn_callback +* [in] Pointer to a cl_pfn_msgdone_cb_t function. +* The Dispatcher calls this function after the message has been +* processed by the recipient. +* The caller may pass NULL for this value, which indicates no +* message done callback is necessary. +* +* context +* [in] Client context value passed to the cl_pfn_msgdone_cb_t +* function. +* +* RETURN VALUE +* CL_SUCCESS if the message was successfully queued in the Dispatcher. +* +* NOTES +* The caller must not modify the memory pointed to by p_data until +* the Dispatcher call the pfn_callback function. +* +* SEE ALSO +* Dispatcher +*********/ + +/****f* Component Library: Dispatcher/cl_disp_get_queue_status +* NAME +* cl_disp_get_queue_status +* +* DESCRIPTION +* This function posts a message to a Dispatcher object. +* +* SYNOPSIS +*/ +void +cl_disp_get_queue_status( + IN const cl_disp_reg_handle_t handle, + OUT uint32_t *p_num_queued_msgs, + OUT uint64_t *p_last_msg_queue_time_ms); +/* +* PARAMETERS +* handle +* [in] cl_disp_reg_handle_t value return by cl_disp_register. +* +* p_last_msg_queue_time_ms +* [out] pointer to a variable to hold the time the last popped up message +* spent in the queue +* +* p_num_queued_msgs +* [out] number of messages in the queue +* +* RETURN VALUE +* Thr time the last popped up message stayed in the queue, in msec +* +* NOTES +* Extarnel Locking is not required. +* +* SEE ALSO +* Dispatcher +*********/ + +END_C_DECLS + +#endif /* !defined(_CL_DISPATCHER_H_) */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/complib/cl_event_wheel.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/complib/cl_event_wheel.h new file mode 100644 index 00000000..129eadd6 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/complib/cl_event_wheel.h @@ -0,0 +1,493 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ + + +/* + * Abstract: + * Declaration of event wheel abstraction. + * + * Environment: + * All + * + * $Revision: 1.4 $ + */ + +#ifndef _CL_EVENT_WHEEL_H_ +#define _CL_EVENT_WHEEL_H_ + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* Component Library/Event_Wheel +* NAME +* Event_Wheel +* +* DESCRIPTION +* The Event_Wheel provides a facility for registering delayed events +* and getting called once they timeout. +* +* The Event_Wheel functions operate on a cl_event_wheel_t structure +* which should be treated as opaque and should be manipulated +* only through the provided functions. +* +* SEE ALSO +* Structures: +* cl_event_wheel_t +* +* Initialization/Destruction: +* cl_event_wheel_construct, cl_event_wheel_init, cl_event_wheel_destroy +* +* Manipulation: +* cl_event_wheel_reg, cl_event_wheel_unreg +* +*********/ + +/****f* Component Library: Event_Wheel/cl_pfn_event_aged_cb_t +* NAME +* cl_pfn_event_aged_cb_t +* +* DESCRIPTION +* This typedef defines the prototype for client functions invoked +* by the Event_Wheel. The Event_Wheel calls the corresponding +* client function when the specific item has aged. +* +* SYNOPSIS +*/ +typedef uint64_t +(*cl_pfn_event_aged_cb_t)( + IN uint64_t key, + IN uint32_t num_regs, + IN void* context); +/* +* PARAMETERS +* key +* [in] The key used for registering the item in the call to +* cl_event_wheel_reg +* +* num_regs +* [in] The number of times this event was registered (pushed in time). +* +* context +* [in] Client specific context specified in a call to +* cl_event_wheel_reg +* +* RETURN VALUE +* This function returns the abosolute time the event should fire in [usec]. +* If lower then current time means the event should be unregistered +* immediatly. +* +* NOTES +* This typedef provides a function prototype reference for +* the function provided by Event_Wheel clients as a parameter +* to the cl_event_wheel_reg function. +* +* SEE ALSO +* Event_Wheel, cl_event_wheel_reg +*********/ + +/****s* Component Library: Event_Wheel/cl_event_wheel_t +* NAME +* cl_event_wheel_t +* +* DESCRIPTION +* Event_Wheel structure. +* +* The Event_Wheel is thread safe. +* +* The cl_event_wheel_t structure should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _cl_event_wheel +{ + cl_spinlock_t lock; + cl_spinlock_t *p_external_lock; + + cl_qmap_t events_map; + boolean_t closing; + cl_qlist_t events_wheel; + cl_timer_t timer; + osm_log_t *p_log; +} cl_event_wheel_t; +/* +* FIELDS +* lock +* Spinlock to guard internal structures. +* +* p_external_lock +* Reference to external spinlock to guard internal structures +* if the event wheel is part of a larger object protected by its own lock +* +* events_map +* A Map holding all registered event items by their key. +* +* closing +* A flag indicating the event wheel is closing. This means that +* callbacks that are called when closing == TRUE should just be ignored. +* +* events_wheel +* A list of the events sorted by expiration time. +* +* timer +* The timer scheduling event time propagation. +* +* p_log +* Pointer to opensm log object. +* +* SEE ALSO +* Event_Wheel +*********/ + +/****s* Component Library: Event_Wheel/cl_event_wheel_reg_info_t +* NAME +* cl_event_wheel_reg_info_t +* +* DESCRIPTION +* Defines the event_wheel registration object structure. +* +* The cl_event_wheel_reg_info_t structure is for internal use by the +* Event_Wheel only. +* +* SYNOPSIS +*/ +typedef struct _cl_event_wheel_reg_info +{ + cl_map_item_t map_item; + cl_list_item_t list_item; + uint64_t key; + cl_pfn_event_aged_cb_t pfn_aged_callback; + uint64_t aging_time; + uint32_t num_regs; + void *context; + cl_event_wheel_t *p_event_wheel; +} cl_event_wheel_reg_info_t; +/* +* FIELDS +* map_item +* The map item of this event +* +* list_item +* The sorted by aging time list item +* +* key +* The key by which one can find the event +* +* pfn_aged_callback +* The clients Event-Aged callback +* +* aging_time +* The delta time [msec] for which the event should age. +* +* num_regs +* The number of times the same event (key) was registered +* +* context +* Client's context for event-aged callback. +* +* p_event_wheel +* Pointer to this event wheel object +* +* SEE ALSO +*********/ + +/****f* Component Library: Event_Wheel/cl_event_wheel_construct +* NAME +* cl_event_wheel_construct +* +* DESCRIPTION +* This function constructs a Event_Wheel object. +* +* SYNOPSIS +*/ +void +cl_event_wheel_construct( + IN cl_event_wheel_t* const p_event_wheel ); +/* +* PARAMETERS +* p_event_wheel +* [in] Pointer to a Event_Wheel. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling cl_event_wheel_init and cl_event_wheel_destroy. +* +* SEE ALSO +* Event_Wheel, cl_event_wheel_init, cl_event_wheel_destroy +*********/ + +/****f* Component Library: Event_Wheel/cl_event_wheel_init +* NAME +* cl_event_wheel_init +* +* DESCRIPTION +* This function initializes a Event_Wheel object. +* +* SYNOPSIS +*/ +cl_status_t +cl_event_wheel_init( + IN cl_event_wheel_t* const p_event_wheel, + IN osm_log_t *p_log); + +/* +* PARAMETERS +* p_event_wheel +* [in] Pointer to a Event_Wheel. +* +* p_log +* [in] Pointer to opensm log object to be used for logging +* +* RETURN VALUE +* CL_SUCCESS if the operation is successful. +* +* SEE ALSO +* Event_Wheel, cl_event_wheel_destoy, cl_event_wheel_reg, cl_event_wheel_unreg +* +*********/ + +/****f* Component Library: Event_Wheel/cl_event_wheel_init +* NAME +* cl_event_wheel_init +* +* DESCRIPTION +* This function initializes a Event_Wheel object. +* +* SYNOPSIS +*/ +cl_status_t +cl_event_wheel_init_ex( + IN cl_event_wheel_t* const p_event_wheel, + IN osm_log_t *p_log, + IN cl_spinlock_t *p_external_lock); + +/* +* PARAMETERS +* p_event_wheel +* [in] Pointer to a Event_Wheel. +* +* p_log +* [in] Pointer to opensm log object to be used for logging +* +* p_external_lock +* [in] Reference to external spinlock to guard internal structures +* if the event wheel is part of a larger object protected by its own lock +* +* RETURN VALUE +* CL_SUCCESS if the operation is successful. +* +* SEE ALSO +* Event_Wheel, cl_event_wheel_destoy, cl_event_wheel_reg, cl_event_wheel_unreg +* +*********/ + +/****f* Component Library: Event_Wheel/cl_event_wheel_destroy +* NAME +* cl_event_wheel_destroy +* +* DESCRIPTION +* This function destroys a Event_Wheel object. +* +* SYNOPSIS +*/ +void +cl_event_wheel_destroy( + IN cl_event_wheel_t* const p_event_wheel ); +/* +* PARAMETERS +* p_event_wheel +* [in] Pointer to a Event_Wheel. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* This function does not returns until all client callback functions +* been successfully finished. +* +* SEE ALSO +* Event_Wheel, cl_event_wheel_construct, cl_event_wheel_init +*********/ + +/****f* Component Library: Event_Wheel/cl_event_wheel_dump +* NAME +* cl_event_wheel_dump +* +* DESCRIPTION +* This function dumps the details of an Event_Whell object. +* +* SYNOPSIS +*/ +void +cl_event_wheel_dump( + IN cl_event_wheel_t* const p_event_wheel ); +/* +* PARAMETERS +* p_event_wheel +* [in] Pointer to a Event_Wheel. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Note that this function should be called inside a lock of the event wheel! +* It doesn't aquire the lock by itself. +* +* SEE ALSO +* Event_Wheel, cl_event_wheel_construct, cl_event_wheel_init +*********/ + +/****f* Component Library: Event_Wheel/cl_event_wheel_reg +* NAME +* cl_event_wheel_reg +* +* DESCRIPTION +* This function registers a client with a Event_Wheel object. +* +* SYNOPSIS +*/ +cl_status_t +cl_event_wheel_reg( + IN cl_event_wheel_t* const p_event_wheel, + IN const uint64_t key, + IN const uint64_t aging_time_usec, + IN cl_pfn_event_aged_cb_t pfn_callback, + IN void* const context ); +/* +* PARAMETERS +* p_event_wheel +* [in] Pointer to a Event_Wheel. +* +* key +* [in] The specifc Key by which events are registered. +* +* aging_time_usec +* [in] The absolute time this event should age in usec +* +* pfn_callback +* [in] Event Aging callback. The Event_Wheel calls this +* function after the time the event has registed for has come. +* +* context +* [in] Client context value passed to the cl_pfn_event_aged_cb_t +* function. +* +* RETURN VALUE +* On success a Event_Wheel CL_SUCCESS or CL_ERROR otherwise. +* +* SEE ALSO +* Event_Wheel, cl_event_wheel_unreg +*********/ + +/****f* Component Library: Event_Wheel/cl_event_wheel_unreg +* NAME +* cl_event_wheel_unreg +* +* DESCRIPTION +* This function unregisters a client event from a Event_Wheel. +* +* SYNOPSIS +*/ +void +cl_event_wheel_unreg( + IN cl_event_wheel_t* const p_event_wheel, + IN uint64_t key ); +/* +* PARAMETERS +* p_event_wheel +* [in] Pointer to a Event_Wheel. +* +* key +* [in] The key used for registering the event +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* After the event has aged it is automatically removed from +* the event wheel. So it should only be invoked when the need arises +* to remove existing events before they age. +* +* SEE ALSO +* Event_Wheel, cl_event_wheel_reg +*********/ + +/****f* Component Library: Event_Wheel/cl_event_wheel_num_regs +* NAME +* cl_event_wheel_num_regs +* +* DESCRIPTION +* This function returns the number of times an event was registered. +* +* SYNOPSIS +*/ +uint32_t +cl_event_wheel_num_regs( + IN cl_event_wheel_t* const p_event_wheel, + IN uint64_t key ); +/* +* PARAMETERS +* p_event_wheel +* [in] Pointer to a Event_Wheel. +* +* key +* [in] The key used for registering the event +* +* RETURN VALUE +* The number of times the event was registered. +* 0 if never registered or eventually aged. +* +* SEE ALSO +* Event_Wheel, cl_event_wheel_reg, cl_event_wheel_unreg +*********/ + +END_C_DECLS + +#endif /* !defined(_CL_EVENT_WHEEL_H_) */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/complib/cl_signal_osd.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/complib/cl_signal_osd.h new file mode 100644 index 00000000..01c1f90c --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/complib/cl_signal_osd.h @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2005 Mellanox Technologies. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: cl_signal_osd.h 474 2006-08-31 08:57:19Z sleybo $ + */ + +/* + * Abstract: + * Declaration of Signal Handler Registration + * + * Environment: + * All + * + * $Revision: 1.3 $ + */ + + +#ifndef _CL_SIG_HDL_H_ +#define _CL_SIG_HDL_H_ + +#include + +/****h* Component Library/Signal Handler +* NAME +* Signal Handler Registration +* +* DESCRIPTION +* The Signal Handler Registration allows to register a callback on the case of incoming signal +* +* SEE ALSO +*********/ +/* TODO : Required when calling signal function in windows*/ +typedef void (__cdecl *cl_sig_hdl)( + IN int sig); +/* Prototypes */ + +/****f* Component Library: Signal Handler/cl_reg_sig_hdl +* NAME +* cl_reg_sig_hdl +* +* DESCRIPTION +* Register the handler for the given signal +* +* SYNOPSIS +*/ + +static inline void +cl_reg_sig_hdl(int sig, cl_sig_hdl pfn_sig_hdl); + + + +/****f* Component Library: Signal Handler/cl_mask_sigint +* NAME +* cl_sig_mask_sigint +* +* DESCRIPTION +* Mask the kill signal +* +* SYNOPSIS +*/ + +static inline void +cl_sig_mask_sigint(void); + + + + +/****f* Component Library: Signal Handler/cl_reg_sig_hdl +* NAME +* cl_reg_sig_hdl +* +* DESCRIPTION +* Register the handler for the given signal +* +* SYNOPSIS +*/ +static inline void +cl_reg_sig_hdl(int sig, cl_sig_hdl pfn_sig_hdl) { + signal(sig,pfn_sig_hdl); + } +/* +*********/ + +/****f* Component Library: Signal Handler/cl_mask_sigint +* NAME +* cl_sig_mask_sigint +* +* DESCRIPTION +* Mask the kill signal +* +* SYNOPSIS +*/ +static inline void +cl_sig_mask_sigint(void) +{ + +} +/* +*********/ + +#endif /* _CL_SIG_HDL_H_ */ diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/iba/ib_types.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/iba/ib_types.h new file mode 100644 index 00000000..2111366d --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/iba/ib_types.h @@ -0,0 +1,10684 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * Portions Copyright (c) 2008 Microsoft Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: ib_types.h 1925 2009-02-04 15:11:30Z tzachid $ + */ + + + +#if !defined(__IB_TYPES_H__) +#define __IB_TYPES_H__ + +#include +#include +#include + +#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 OSM_EXPORT __declspec(dllexport) + #else + #define OSM_EXPORT __declspec(dllimport) + #endif + #define OSM_API __stdcall + #define OSM_CDECL __cdecl +#else + #define OSM_EXPORT extern + #define OSM_API + #define OSM_CDECL + #define __ptr64 +#endif + + +#define IB_CONCAT(str1, str2) str1##str2 + +#define TO_LONG_PTR(type,member_name) \ + union { type member_name; uint64_t IB_CONCAT(member_name,_padding) ; } + + + +/****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.2 +* +*********/ + +/****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_HTON16(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_DEFAULT_PARTIAL_PKEY +* NAME +* IB_DEFAULT_PARTIAL_PKEY +* +* DESCRIPTION +* 0x7FFF in network order +* +* SOURCE +*/ +#define IB_DEFAULT_PARTIAL_PKEY (CL_HTON16(0x7FFF)) +/**********/ + +/****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_DEV_ADM +* NAME +* IB_MCLASS_DEV_ADM +* +* DESCRIPTION +* Subnet Management Class, Device Administration +* +* SOURCE +*/ +#define IB_MCLASS_DEV_ADM 0x10 +/**********/ + +/****d* IBA Base: Constants/IB_MCLASS_BIS +* NAME +* IB_MCLASS_BIS +* +* DESCRIPTION +* Subnet Management Class, BIS +* +* SOURCE +*/ +#define IB_MCLASS_BIS 0x12 +/**********/ + +/****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 +* Indicates if the Class Code if a vendor specific class from +* the low range +* +* SYNOPSIS +*/ +static inline boolean_t OSM_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 +* Indicates if the Class Code if a vendor specific class from +* the high range +* +* SYNOPSIS +*/ +static inline boolean_t OSM_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 +* Indicates if the Class Code if a vendor specific class +* +* SYNOPSIS +*/ +static inline boolean_t OSM_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 +*********/ + +/****f* IBA Base: Types/ib_class_is_rmpp +* NAME +* ib_class_is_rmpp +* +* DESCRIPTION +* Indicates if the Class Code supports RMPP +* +* SYNOPSIS +*/ +static inline boolean_t OSM_API +ib_class_is_rmpp( + IN const uint8_t class_code ) +{ + return( (class_code == IB_MCLASS_SUBN_ADM) || + (class_code == IB_MCLASS_DEV_MGMT) || + (class_code == IB_MCLASS_DEV_ADM) || + (class_code == IB_MCLASS_BIS) || + ib_class_is_vendor_specific_high( class_code ) ); +} +/* +* PARAMETERS +* class_code +* [in] The Management Datagram Class Code +* +* RETURN VALUE +* TRUE if the class supports RMPP +* FALSE otherwise. +* +* NOTES +* +*********/ + +/* + * 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_SWITCH_INFO_RECORD +* NAME +* IB_MAD_ATTR_SWITCH_INFO_RECORD +* +* DESCRIPTION +* SwitchInfoRecord attribute (15.2.5) +* +* SOURCE +*/ +#define IB_MAD_ATTR_SWITCH_INFO_RECORD (CL_NTOH16(0x0014)) +/**********/ + +/****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_GUIDINFO_RECORD +* NAME +* IB_MAD_ATTR_GUIDINFO_RECORD +* +* DESCRIPTION +* GuidInfoRecord attribute (15.2.5) +* +* SOURCE +*/ +#define IB_MAD_ATTR_GUIDINFO_RECORD (CL_NTOH16(0x0030)) +/**********/ + +/****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 +* LinearForwardingTableRecord attribute (15.2.5.6) +* +* SOURCE +*/ +#define IB_MAD_ATTR_LFT_RECORD (CL_NTOH16(0x0015)) +/**********/ + +/****d* IBA Base: Constants/IB_MAD_ATTR_MFT_RECORD +* NAME +* IB_MAD_ATTR_MFT_RECORD +* +* DESCRIPTION +* MulticastForwardingTableRecord attribute (15.2.5.8) +* +* SOURCE +*/ +#define IB_MAD_ATTR_MFT_RECORD (CL_NTOH16(0x0017)) +/**********/ + +/****d* IBA Base: Constants/IB_MAD_ATTR_PKEYTBL_RECORD +* NAME +* IB_MAD_ATTR_PKEYTBL_RECORD +* +* DESCRIPTION +* PKEY Table Record 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 Record 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 +* SLtoVL Mapping Table Record 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_TRACE_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 +* MultiPathRecord 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 Record attribute (15.2.5) +* +* SOURCE +*/ +#define IB_MAD_ATTR_SVC_ASSOCIATION_RECORD (CL_NTOH16(0x003B)) +/**********/ + +/****d* IBA Base: Constants/IB_MAD_ATTR_INFORM_INFO_RECORD +* NAME +* IB_MAD_ATTR_INFORM_INFO_RECORD +* +* DESCRIPTION +* InformInfo Record attribute (15.2.5) +* +* SOURCE +*/ +#define IB_MAD_ATTR_INFORM_INFO_RECORD (CL_NTOH16(0x00F3)) + +/****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 Record 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_MIN_MTU IB_MTU_LEN_256 +#define IB_MAX_MTU IB_MTU_LEN_4096 + +/**********/ + +/****d* IBA Base: Constants/IB_PATH_SELECTOR_TYPE +* NAME +* IB_PATH_SELECTOR_TYPE +* +* DESCRIPTION +* Path selector. +* 0: greater than specified +* 1: less than specified +* 2: exactly the specified +* 3: largest 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_SL_MASK +* NAME +* IB_PATH_REC_SL_MASK +* +* DESCRIPTION +* Mask for the sl field for path record +* +* SOURCE +*/ +#define IB_PATH_REC_SL_MASK 0x000F + +/****d* IBA Base: Constants/IB_MULTIPATH_REC_SL_MASK +* NAME +* IB_MILTIPATH_REC_SL_MASK +* +* DESCRIPTION +* Mask for the sl field for MultiPath record +* +* SOURCE +*/ +#define IB_MULTIPATH_REC_SL_MASK 0x000F + +/****d* IBA Base: Constants/IB_PATH_REC_QOS_CLASS_MASK +* NAME +* IB_PATH_REC_QOS_CLASS_MASK +* +* DESCRIPTION +* Mask for the QoS class field for path record +* +* SOURCE +*/ +#define IB_PATH_REC_QOS_CLASS_MASK 0xFFF0 + +/****d* IBA Base: Constants/IB_MULTIPATH_REC_QOS_CLASS_MASK +* NAME +* IB_MULTIPATH_REC_QOS_CLASS_MASK +* +* DESCRIPTION +* Mask for the QoS class field for MultiPath record +* +* SOURCE +*/ +#define IB_MULTIPATH_REC_QOS_CLASS_MASK 0xFFF0 + +/****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_MULTIPATH_REC_SELECTOR_MASK +* NAME +* IB_MULTIPATH_REC_SELECTOR_MASK +* +* DESCRIPTION +* Mask for the selector field for multipath record MTU, rate, +* and packet lifetime. +* +* SOURCE +*/ +#define IB_MULTIPATH_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 +/**********/ + +/****d* IBA Base: Constants/IB_MULTIPATH_REC_BASE_MASK +* NAME +* IB_MULTIPATH_REC_BASE_MASK +* +* DESCRIPTION +* Mask for the base value field for multipath record MTU, rate, +* and packet lifetime. +* +* SOURCE +*/ +#define IB_MULTIPATH_REC_BASE_MASK 0x3F +/**********/ + +/****h* IBA Base/Type Definitions +* NAME +* Type Definitions +* +* DESCRIPTION +* Definitions are from the InfiniBand Architecture Specification v1.2 +* +*********/ + +/****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 +*/ +static inline const char* OSM_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 +*/ +static inline const char* OSM_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 +*/ +static inline uint8_t OSM_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 +*/ +static inline ib_net16_t OSM_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 +* Indicates if the port is a full member of the parition. +* +* SYNOPSIS +*/ +static inline boolean_t OSM_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 +*/ +static inline boolean_t OSM_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 +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 +/* +* 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 +*********/ + +/****f* IBA Base: Types/ib_gid_is_multicast +* NAME +* ib_gid_is_multicast +* +* DESCRIPTION +* Returns a boolean indicating whether a GID is a multicast GID. +* +* SYNOPSIS +*/ +static inline boolean_t OSM_API +ib_gid_is_multicast( + IN const ib_gid_t* p_gid ) +{ + return( p_gid->raw[0] == 0xFF ); +} + +/****f* IBA Base: Types/ib_gid_get_scope +* NAME +* ib_gid_get_scope +* +* DESCRIPTION +* Returns scope of (assumed) multicast GID. +* +* SYNOPSIS +*/ +static inline uint8_t OSM_API +ib_mgid_get_scope( + IN const ib_gid_t* p_gid ) +{ + return( p_gid->raw[1] & 0x0F ); +} + +/****f* IBA Base: Types/ib_gid_set_scope +* NAME +* ib_gid_set_scope +* +* DESCRIPTION +* Sets scope of (assumed) multicast GID. +* +* SYNOPSIS +*/ +static inline void OSM_API +ib_mgid_set_scope( + IN ib_gid_t* const p_gid, + IN const uint8_t scope ) +{ + p_gid->raw[1] &= 0xF0; + p_gid->raw[1] |= scope & 0x0F; +} + +/****f* IBA Base: Types/ib_gid_set_default +* NAME +* ib_gid_set_default +* +* DESCRIPTION +* Sets a GID to the default value. +* +* SYNOPSIS +*/ +static inline void OSM_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 +*/ +static inline ib_net64_t OSM_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 +*/ +static inline boolean_t OSM_API +ib_gid_is_link_local( + IN const ib_gid_t* const p_gid ) +{ + return( ( ib_gid_get_subnet_prefix( p_gid ) & + CL_HTON64( 0xFFC0000000000000ULL ) ) == 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 +*/ +static inline boolean_t OSM_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 site 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 +*/ +static inline ib_net64_t OSM_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 +typedef struct _ib_path_rec +{ + ib_net64_t service_id; + 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 qos_class_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 +/* +* 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_path [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)) + +/* Switch Info Record Masks */ +#define IB_SWIR_COMPMASK_LID (CL_HTON64(((uint64_t)1)<<0)) +#define IB_SWIR_COMPMASK_RESERVED1 (CL_HTON64(((uint64_t)1)<<1)) + +/* 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)) + +/* MFT Record Masks */ +#define IB_MFTR_COMPMASK_LID (CL_HTON64(((uint64_t)1)<<0)) +#define IB_MFTR_COMPMASK_POSITION (CL_HTON64(((uint64_t)1)<<1)) +#define IB_MFTR_COMPMASK_RESERVED1 (CL_HTON64(((uint64_t)1)<<2)) +#define IB_MFTR_COMPMASK_BLOCK (CL_HTON64(((uint64_t)1)<<3)) +#define IB_MFTR_COMPMASK_RESERVED2 (CL_HTON64(((uint64_t)1)<<4)) + +/* NodeInfo 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 Masks 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)) + +/* GUID Info Record Component Masks */ +#define IB_GIR_COMPMASK_LID (CL_HTON64(((uint64_t)1)<<0)) +#define IB_GIR_COMPMASK_BLOCKNUM (CL_HTON64(((uint64_t)1)<<1)) +#define IB_GIR_COMPMASK_RESV1 (CL_HTON64(((uint64_t)1)<<2)) +#define IB_GIR_COMPMASK_RESV2 (CL_HTON64(((uint64_t)1)<<3)) +#define IB_GIR_COMPMASK_GID0 (CL_HTON64(((uint64_t)1)<<4)) +#define IB_GIR_COMPMASK_GID1 (CL_HTON64(((uint64_t)1)<<5)) +#define IB_GIR_COMPMASK_GID2 (CL_HTON64(((uint64_t)1)<<6)) +#define IB_GIR_COMPMASK_GID3 (CL_HTON64(((uint64_t)1)<<7)) +#define IB_GIR_COMPMASK_GID4 (CL_HTON64(((uint64_t)1)<<8)) +#define IB_GIR_COMPMASK_GID5 (CL_HTON64(((uint64_t)1)<<9)) +#define IB_GIR_COMPMASK_GID6 (CL_HTON64(((uint64_t)1)<<10)) +#define IB_GIR_COMPMASK_GID7 (CL_HTON64(((uint64_t)1)<<11)) + +/* MultiPath Record Component Masks */ +#define IB_MPR_COMPMASK_RAWTRAFFIC (CL_HTON64(((uint64_t)1)<<0)) +#define IB_MPR_COMPMASK_RESV0 (CL_HTON64(((uint64_t)1)<<1)) +#define IB_MPR_COMPMASK_FLOWLABEL (CL_HTON64(((uint64_t)1)<<2)) +#define IB_MPR_COMPMASK_HOPLIMIT (CL_HTON64(((uint64_t)1)<<3)) +#define IB_MPR_COMPMASK_TCLASS (CL_HTON64(((uint64_t)1)<<4)) +#define IB_MPR_COMPMASK_REVERSIBLE (CL_HTON64(((uint64_t)1)<<5)) +#define IB_MPR_COMPMASK_NUMBPATH (CL_HTON64(((uint64_t)1)<<6)) +#define IB_MPR_COMPMASK_PKEY (CL_HTON64(((uint64_t)1)<<7)) +#define IB_MPR_COMPMASK_RESV1 (CL_HTON64(((uint64_t)1)<<8)) +#define IB_MPR_COMPMASK_SL (CL_HTON64(((uint64_t)1)<<9)) +#define IB_MPR_COMPMASK_MTUSELEC (CL_HTON64(((uint64_t)1)<<10)) +#define IB_MPR_COMPMASK_MTU (CL_HTON64(((uint64_t)1)<<11)) +#define IB_MPR_COMPMASK_RATESELEC (CL_HTON64(((uint64_t)1)<<12)) +#define IB_MPR_COMPMASK_RATE (CL_HTON64(((uint64_t)1)<<13)) +#define IB_MPR_COMPMASK_PKTLIFETIMESELEC (CL_HTON64(((uint64_t)1)<<14)) +#define IB_MPR_COMPMASK_PKTLIFETIME (CL_HTON64(((uint64_t)1)<<15)) +#define IB_MPR_COMPMASK_RESV2 (CL_HTON64(((uint64_t)1)<<16)) +#define IB_MPR_COMPMASK_INDEPSELEC (CL_HTON64(((uint64_t)1)<<17)) +#define IB_MPR_COMPMASK_RESV3 (CL_HTON64(((uint64_t)1)<<18)) +#define IB_MPR_COMPMASK_SGIDCOUNT (CL_HTON64(((uint64_t)1)<<19)) +#define IB_MPR_COMPMASK_DGIDCOUNT (CL_HTON64(((uint64_t)1)<<20)) +#define IB_MPR_COMPMASK_RESV4 (CL_HTON64(((uint64_t)1)<<21)) + +/* SMInfo Record Component Masks */ +#define IB_SMIR_COMPMASK_LID (CL_HTON64(((uint64_t)1)<<0)) +#define IB_SMIR_COMPMASK_RESV0 (CL_HTON64(((uint64_t)1)<<1)) +#define IB_SMIR_COMPMASK_GUID (CL_HTON64(((uint64_t)1)<<2)) +#define IB_SMIR_COMPMASK_SMKEY (CL_HTON64(((uint64_t)1)<<3)) +#define IB_SMIR_COMPMASK_ACTCOUNT (CL_HTON64(((uint64_t)1)<<4)) +#define IB_SMIR_COMPMASK_PRIORITY (CL_HTON64(((uint64_t)1)<<5)) +#define IB_SMIR_COMPMASK_SMSTATE (CL_HTON64(((uint64_t)1)<<6)) + +/* InformInfo Record Component Masks */ +#define IB_IIR_COMPMASK_SUBSCRIBERGID (CL_HTON64(((uint64_t)1)<<0)) +#define IB_IIR_COMPMASK_ENUM (CL_HTON64(((uint64_t)1)<<1)) +#define IB_IIR_COMPMASK_RESV0 (CL_HTON64(((uint64_t)1)<<2)) +#define IB_IIR_COMPMASK_GID (CL_HTON64(((uint64_t)1)<<3)) +#define IB_IIR_COMPMASK_LIDRANGEBEGIN (CL_HTON64(((uint64_t)1)<<4)) +#define IB_IIR_COMPMASK_LIDRANGEEND (CL_HTON64(((uint64_t)1)<<5)) +#define IB_IIR_COMPMASK_RESV1 (CL_HTON64(((uint64_t)1)<<6)) +#define IB_IIR_COMPMASK_ISGENERIC (CL_HTON64(((uint64_t)1)<<7)) +#define IB_IIR_COMPMASK_SUBSCRIBE (CL_HTON64(((uint64_t)1)<<8)) +#define IB_IIR_COMPMASK_TYPE (CL_HTON64(((uint64_t)1)<<9)) +#define IB_IIR_COMPMASK_TRAPNUMB (CL_HTON64(((uint64_t)1)<<10)) +#define IB_IIR_COMPMASK_DEVICEID (CL_HTON64(((uint64_t)1)<<10)) +#define IB_IIR_COMPMASK_QPN (CL_HTON64(((uint64_t)1)<<11)) +#define IB_IIR_COMPMASK_RESV2 (CL_HTON64(((uint64_t)1)<<12)) +#define IB_IIR_COMPMASK_RESPTIME (CL_HTON64(((uint64_t)1)<<13)) +#define IB_IIR_COMPMASK_RESV3 (CL_HTON64(((uint64_t)1)<<14)) +#define IB_IIR_COMPMASK_PRODTYPE (CL_HTON64(((uint64_t)1)<<15)) +#define IB_IIR_COMPMASK_VENDID (CL_HTON64(((uint64_t)1)<<15)) + +/****f* IBA Base: Types/ib_path_rec_init_local +* NAME +* ib_path_rec_init_local +* +* DESCRIPTION +* Initializes a subnet local path record. +* +* SYNOPSIS +*/ +static inline void OSM_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->qos_class_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->service_id) = 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_path [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 +*/ +static inline uint8_t OSM_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 to return 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 +*/ +static inline uint8_t OSM_API +ib_path_rec_sl( + IN const ib_path_rec_t* const p_rec ) +{ + return( (uint8_t)((cl_ntoh16( p_rec->qos_class_sl )) & 0xF) ); +} +/* +* PARAMETERS +* p_rec +* [in] Pointer to the path record object. +* +* RETURN VALUES +* SL. +* +* NOTES +* +* SEE ALSO +* ib_path_rec_t +*********/ + +/****f* IBA Base: Types/ib_path_rec_set_qos_class +* NAME +* ib_path_rec_set_qos_class +* +* DESCRIPTION +* Set path QoS class. +* +* SYNOPSIS +*/ +static inline void OSM_API +ib_path_rec_set_qos_class(IN ib_path_rec_t * const p_rec, + IN const uint16_t qos_class) +{ + p_rec->qos_class_sl = + (p_rec->qos_class_sl & CL_HTON16(IB_PATH_REC_SL_MASK)) | + cl_hton16(qos_class << 4); +} + +/* +* PARAMETERS +* p_rec +* [in] Pointer to the path record object. +* +* qos_class +* [in] QoS class to set. +* +* RETURN VALUES +* None +* +* NOTES +* +* SEE ALSO +* ib_path_rec_t +*********/ + +/****f* IBA Base: Types/ib_path_rec_qos_class +* NAME +* ib_path_rec_qos_class +* +* DESCRIPTION +* Get QoS class. +* +* SYNOPSIS +*/ +static inline uint16_t OSM_API +ib_path_rec_qos_class(IN const ib_path_rec_t * const p_rec) +{ + return (cl_ntoh16(p_rec->qos_class_sl) >> 4); +} + +/* +* PARAMETERS +* p_rec +* [in] Pointer to the path record object. +* +* RETURN VALUES +* QoS class of the path record. +* +* 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 +*/ +static inline uint8_t OSM_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 +*/ +static inline uint8_t OSM_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 +*/ +static inline uint8_t OSM_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. +* 5: 5 Gb/sec. +* 6: 20 Gb/sec. +* 7: 40 Gb/sec. +* 8: 60 Gb/sec. +* 9: 80 Gb/sec. +* 10: 120 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 +*/ +static inline uint8_t OSM_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 +*/ +static inline uint8_t OSM_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 +*/ +static inline uint8_t OSM_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 +*/ +static inline uint32_t OSM_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 +*/ +static inline uint8_t OSM_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_RESP_TIME_MASK +* NAME +* IB_CLASS_RESP_TIME_MASK +* +* 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 +typedef struct _ib_class_port_info +{ + uint8_t base_ver; + uint8_t class_ver; + ib_net16_t cap_mask; + ib_net32_t cap_mask2_resp_time; + 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 +/* +* FIELDS +* base_ver +* Maximum supported MAD Base Version. +* +* class_ver +* Maximum supported management class version. +* +* cap_mask +* Supported capabilities of this management class. +* +* cap_mask2_resp_time +* Maximum expected response time and additional +* supported capabilities of this management class. +* +* 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 +* +*********/ + +/****f* IBA Base: Types/ib_class_set_resp_time_val +* NAME +* ib_class_set_resp_time_val +* +* DESCRIPTION +* Set maximum expected response time. +* +* SYNOPSIS +*/ +static inline void OSM_API +ib_class_set_resp_time_val(IN ib_class_port_info_t * const p_cpi, + IN const uint8_t val) +{ + p_cpi->cap_mask2_resp_time = + (p_cpi->cap_mask2_resp_time & CL_HTON32(~IB_CLASS_RESP_TIME_MASK)) | + cl_hton32(val & IB_CLASS_RESP_TIME_MASK); +} + +/* +* PARAMETERS +* p_cpi +* [in] Pointer to the class port info object. +* +* val +* [in] Response time value to set. +* +* RETURN VALUES +* None +* +* NOTES +* +* SEE ALSO +* ib_class_port_info_t +*********/ + +/****f* IBA Base: Types/ib_class_resp_time_val +* NAME +* ib_class_resp_time_val +* +* DESCRIPTION +* Get response time value. +* +* SYNOPSIS +*/ +static inline uint8_t OSM_API +ib_class_resp_time_val(IN ib_class_port_info_t * const p_cpi) +{ + return (uint8_t)(cl_ntoh32(p_cpi->cap_mask2_resp_time) & + IB_CLASS_RESP_TIME_MASK); +} + +/* +* PARAMETERS +* p_cpi +* [in] Pointer to the class port info object. +* +* RETURN VALUES +* Response time value. +* +* NOTES +* +* SEE ALSO +* ib_class_port_info_t +*********/ + +/****f* IBA Base: Types/ib_class_set_cap_mask2 +* NAME +* ib_class_set_cap_mask2 +* +* DESCRIPTION +* Set ClassPortInfo:CapabilityMask2. +* +* SYNOPSIS +*/ +static inline void OSM_API +ib_class_set_cap_mask2(IN ib_class_port_info_t * const p_cpi, + IN const uint32_t cap_mask2) +{ + p_cpi->cap_mask2_resp_time = (p_cpi->cap_mask2_resp_time & + CL_HTON32(IB_CLASS_RESP_TIME_MASK)) | + cl_hton32(cap_mask2 << 5); +} + +/* +* PARAMETERS +* p_cpi +* [in] Pointer to the class port info object. +* +* cap_mask2 +* [in] CapabilityMask2 value to set. +* +* RETURN VALUES +* None +* +* NOTES +* +* SEE ALSO +* ib_class_port_info_t +*********/ + +/****f* IBA Base: Types/ib_class_cap_mask2 +* NAME +* ib_class_cap_mask2 +* +* DESCRIPTION +* Get ClassPortInfo:CapabilityMask2. +* +* SYNOPSIS +*/ +static inline uint32_t OSM_API +ib_class_cap_mask2(IN const ib_class_port_info_t * const p_cpi) +{ + return (cl_ntoh32(p_cpi->cap_mask2_resp_time) >> 5); +} + +/* +* PARAMETERS +* p_cpi +* [in] Pointer to the class port info object. +* +* RETURN VALUES +* CapabilityMask2 of the ClassPortInfo. +* +* NOTES +* +* SEE ALSO +* ib_class_port_info_t +*********/ + +/****s* IBA Base: Types/ib_sm_info_t +* NAME +* ib_sm_info_t +* +* DESCRIPTION +* SMInfo structure (14.2.5.13). +* +* SYNOPSIS +*/ +#include +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 +/* +* 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 +*/ +static inline uint8_t OSM_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 +*/ +static inline uint8_t OSM_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 +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 +/* +* 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 +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 +/* +* 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 +*/ +static inline void OSM_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 +*/ +static inline void OSM_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 +*/ +static inline boolean_t OSM_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 +*/ +static inline boolean_t OSM_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 +*********/ + +static inline void OSM_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); +} + + +static inline uint8_t OSM_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 +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 +/* +* 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 +*/ +static inline ib_net16_t OSM_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 +*/ +static inline boolean_t OSM_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 +*/ +static inline boolean_t OSM_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 +*/ +static inline void OSM_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; + + memset( p_smp->resv1, 0, + sizeof(p_smp->resv1) + + sizeof(p_smp->data) + + sizeof(p_smp->initial_path) + + sizeof(p_smp->return_path) ); + + /* copy the path */ + 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 +*/ +static inline void* OSM_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 +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 +/************/ + +/****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 +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 +/**********/ +#define IB_SA_MAD_HDR_SIZE (sizeof(ib_sa_mad_t) - IB_SA_DATA_SIZE) + +static inline uint32_t OSM_API +ib_get_attr_size( + IN const ib_net16_t attr_offset ) +{ + return( ((uint32_t)cl_ntoh16( attr_offset )) << 3 ); +} + +static inline ib_net16_t OSM_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 +*/ +static inline void* OSM_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 +*/ +static inline uint8_t OSM_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 +*/ +static inline ib_net32_t OSM_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 +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 + +#include +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 + +/****s* IBA Base: Types/ib_port_info_t +* NAME +* ib_port_info_t +* +* DESCRIPTION +* IBA defined PortInfo. (14.2.5.6) +* +* SYNOPSIS +*/ +#include +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 +/************/ + +#define IB_PORT_STATE_MASK 0x0F +#define IB_PORT_LMC_MASK 0x07 +#define IB_PORT_LMC_MAX 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 +*/ +static inline uint8_t OSM_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 +*/ +static inline void OSM_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 +*/ +static inline uint8_t OSM_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_init_type +* NAME +* ib_port_info_get_init_type +* +* DESCRIPTION +* Gets the init type of a port. +* +* SYNOPSIS +*/ +static inline uint8_t OSM_API +ib_port_info_get_init_type( + IN const ib_port_info_t* const p_pi) +{ + return (uint8_t) (p_pi->vl_cap & 0x0F); +} +/* +* PARAMETERS +* p_pi +* [in] Pointer to a PortInfo attribute. +* +* RETURN VALUES +* InitType 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 +*/ +static inline uint8_t OSM_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 +*/ +static inline void OSM_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 +*/ +static inline void OSM_API +ib_port_info_set_state_no_change( + IN ib_port_info_t* const p_pi ) +{ + ib_port_info_set_port_state( p_pi, IB_LINK_NO_CHANGE ); + 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 +*/ +static inline uint8_t OSM_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 +*/ +static inline void OSM_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 +*/ +static inline uint8_t OSM_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 +*/ +static inline void OSM_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 +*/ +static inline uint8_t OSM_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 +*/ +static inline void OSM_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 +*/ +static inline uint8_t OSM_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_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 + +#define IB_MIN_RATE IB_PATH_RECORD_RATE_2_5_GBS +#define IB_MAX_RATE IB_PATH_RECORD_RATE_120_GBS + +/****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 +*/ +static inline uint8_t OSM_API +ib_port_info_compute_rate( + IN const ib_port_info_t* const p_pi ) +{ + uint8_t rate = 0; + + 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: + rate = IB_PATH_RECORD_RATE_2_5_GBS; + break; + + case IB_LINK_WIDTH_ACTIVE_4X: + rate = IB_PATH_RECORD_RATE_10_GBS; + break; + + case IB_LINK_WIDTH_ACTIVE_12X: + rate = IB_PATH_RECORD_RATE_30_GBS; + break; + + default: + rate = IB_PATH_RECORD_RATE_2_5_GBS; + break; + } + break; + case IB_LINK_SPEED_ACTIVE_5: + switch (p_pi->link_width_active) + { + case IB_LINK_WIDTH_ACTIVE_1X: + rate = IB_PATH_RECORD_RATE_5_GBS; + break; + + case IB_LINK_WIDTH_ACTIVE_4X: + rate = IB_PATH_RECORD_RATE_20_GBS; + break; + + case IB_LINK_WIDTH_ACTIVE_12X: + rate = IB_PATH_RECORD_RATE_60_GBS; + break; + + default: + rate = IB_PATH_RECORD_RATE_5_GBS; + break; + } + break; + case IB_LINK_SPEED_ACTIVE_10: + switch (p_pi->link_width_active) + { + case IB_LINK_WIDTH_ACTIVE_1X: + rate = IB_PATH_RECORD_RATE_10_GBS; + break; + + case IB_LINK_WIDTH_ACTIVE_4X: + rate = IB_PATH_RECORD_RATE_40_GBS; + break; + + case IB_LINK_WIDTH_ACTIVE_12X: + rate =IB_PATH_RECORD_RATE_120_GBS; + break; + + default: + rate = IB_PATH_RECORD_RATE_10_GBS; + break; + } + break; + default: + rate = IB_PATH_RECORD_RATE_2_5_GBS; + break; + } + + return rate; +} +/* +* 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 +*/ +static inline uint8_t OSM_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 +*/ +static inline uint8_t OSM_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 +*/ +static inline uint8_t OSM_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 +*/ +static inline void OSM_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_get_master_smsl +* NAME +* ib_port_info_get_master_smsl +* +* DESCRIPTION +* Returns the encoded value for the Master SMSL at this port. +* +* SYNOPSIS +*/ +static inline uint8_t OSM_API +ib_port_info_get_master_smsl( + IN const ib_port_info_t* const p_pi ) +{ + return (uint8_t) (p_pi->mtu_smsl & 0x0F); +} +/* +* PARAMETERS +* p_pi +* [in] Pointer to a PortInfo attribute. +* +* RETURN VALUES +* Returns the encoded value for the Master SMSL at this port. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* IBA Base: Types/ib_port_info_set_master_smsl +* NAME +* ib_port_info_set_master_smsl +* +* DESCRIPTION +* Sets the Master SMSL value in the PortInfo attribute. +* +* SYNOPSIS +*/ +static inline void OSM_API +ib_port_info_set_master_smsl( + IN ib_port_info_t* const p_pi, + IN const uint8_t smsl ) +{ + p_pi->mtu_smsl = (uint8_t)((p_pi->mtu_smsl & 0xF0) | smsl ); +} +/* +* PARAMETERS +* p_pi +* [in] Pointer to a PortInfo attribute. +* +* mtu +* [in] Encoded Master SMSL 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 +*/ +static inline void OSM_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 +*/ +static inline void OSM_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 +*/ +static inline uint8_t OSM_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 +*/ +static inline uint8_t OSM_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. +* +* RETURN VALUES +* Client reregistration value (either 1 or 0). +* +* 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 +*/ +static inline void OSM_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 +*/ +static inline uint8_t OSM_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 contiguous +* HLL (hoq) drops that will put the VL into stalled mode. +* +* SYNOPSIS +*/ +static inline void OSM_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 contiguous +* HLL (hoq) drops that will put the VL into stalled mode +* +* SYNOPSIS +*/ +static inline uint8_t OSM_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 +*/ +static inline uint8_t OSM_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 +*/ +static inline void OSM_API +ib_port_info_set_lmc( + IN ib_port_info_t* const p_pi, + IN const uint8_t lmc ) +{ + CL_ASSERT( lmc <= IB_PORT_LMC_MAX ); + 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 +*/ +static inline uint8_t OSM_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 +*/ +static inline void OSM_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 +*/ +static inline uint8_t OSM_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 +*/ +static inline void OSM_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_get_local_phy_err_thd +* NAME +* ib_port_info_get_local_phy_err_thd +* +* DESCRIPTION +* Returns the Phy Link Threshold +* +* SYNOPSIS +*/ +static inline uint8_t OSM_API +ib_port_info_get_local_phy_err_thd( + IN const ib_port_info_t* const p_pi ) +{ + return (uint8_t)( (p_pi->error_threshold & 0xF0) >> 4); +} +/* +* PARAMETERS +* p_pi +* [in] Pointer to a PortInfo attribute. +* +* RETURN VALUES +* Returns the Phy Link error threshold assigned to this port. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* IBA Base: Types/ib_port_info_get_overrun_err_thd +* NAME +* ib_port_info_get_local_overrun_err_thd +* +* DESCRIPTION +* Returns the Credits Overrun Errors Threshold +* +* SYNOPSIS +*/ +static inline uint8_t OSM_API +ib_port_info_get_overrun_err_thd( + IN const ib_port_info_t* const p_pi ) +{ + return (uint8_t)(p_pi->error_threshold & 0x0F); +} +/* +* PARAMETERS +* p_pi +* [in] Pointer to a PortInfo attribute. +* +* RETURN VALUES +* Returns the Credits Overrun errors threshold assigned to this port. +* +* 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 +*/ +static inline void OSM_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 +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 + +#include +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 + +#include +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 + +#include +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 + +/****s* IBA Base: Types/ib_lft_record_t +* NAME +* ib_lft_record_t +* +* DESCRIPTION +* IBA defined LinearForwardingTableRecord (15.2.5.6) +* +* SYNOPSIS +*/ +#include +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 +/************/ + +/****s* IBA Base: Types/ib_mft_record_t +* NAME +* ib_mft_record_t +* +* DESCRIPTION +* IBA defined MulticastForwardingTableRecord (15.2.5.8) +* +* SYNOPSIS +*/ +#include +typedef struct _ib_mft_record +{ + ib_net16_t lid; + ib_net16_t position_block_num; + uint32_t resv0; + ib_net16_t mft[IB_MCAST_BLOCK_SIZE]; +} PACK_SUFFIX ib_mft_record_t; +#include +/************/ + +/****s* IBA Base: Types/ib_switch_info_t +* NAME +* ib_switch_info_t +* +* DESCRIPTION +* IBA defined SwitchInfo. (14.2.5.4) +* +* SYNOPSIS +*/ +#include +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 +/************/ + +#include +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 + +#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 +*/ +static inline boolean_t OSM_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 +*/ +static inline void OSM_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_port0 +* NAME +* ib_switch_info_is_enhanced_port0 +* +* DESCRIPTION +* Returns TRUE if the enhancedPort0 bit is on (meaning the switch +* port zero supports enhanced functions). +* Returns FALSE otherwise. +* +* SYNOPSIS +*/ +static inline boolean_t OSM_API +ib_switch_info_is_enhanced_port0( + 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 +typedef struct _ib_guid_info +{ + ib_net64_t guid[GUID_TABLE_MAX_ENTRIES]; + +} PACK_SUFFIX ib_guid_info_t; +#include +/************/ + +#include +typedef struct _ib_guidinfo_record +{ + ib_net16_t lid; + uint8_t block_num; + uint8_t resv; + uint32_t reserved; + ib_guid_info_t guid_info; +} PACK_SUFFIX ib_guidinfo_record_t; +#include + +#define IB_MULTIPATH_MAX_GIDS 11 /* Support max that can fit into first MAD (for now) */ + +#include +typedef struct _ib_multipath_rec_t +{ + ib_net32_t hop_flow_raw; + uint8_t tclass; + uint8_t num_path; + ib_net16_t pkey; + uint8_t resv0; + uint8_t sl; + uint8_t mtu; + uint8_t rate; + uint8_t pkt_life; + uint8_t resv1; + uint8_t independence; /* formerly resv2 */ + uint8_t sgid_count; + uint8_t dgid_count; + uint8_t resv3[7]; + ib_gid_t gids[IB_MULTIPATH_MAX_GIDS]; +} PACK_SUFFIX ib_multipath_rec_t; +#include +/* +* FIELDS +* 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_path [6:0] In queries, maximum number of paths to return. +* In responses, undefined. +* +* pkey +* Partition key (P_Key) to use on this path. +* +* 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. +* +* SEE ALSO +*********/ + +/****f* IBA Base: Types/ib_multipath_rec_num_path +* NAME +* ib_multipath_rec_num_path +* +* DESCRIPTION +* Get max number of paths to return. +* +* SYNOPSIS +*/ +static inline uint8_t OSM_API +ib_multipath_rec_num_path( + IN const ib_multipath_rec_t* const p_rec ) +{ + return( p_rec->num_path &0x7F ); +} +/* +* PARAMETERS +* p_rec +* [in] Pointer to the multipath record object. +* +* RETURN VALUES +* Maximum number of paths to return for each unique SGID_DGID combination. +* +* NOTES +* +* SEE ALSO +* ib_multipath_rec_t +*********/ + +/****f* IBA Base: Types/ib_multipath_rec_sl +* NAME +* ib_multipath_rec_sl +* +* DESCRIPTION +* Get multipath service level. +* +* SYNOPSIS +*/ +static inline uint8_t OSM_API +ib_multipath_rec_sl( + IN const ib_multipath_rec_t* const p_rec ) +{ + return( (uint8_t)((cl_ntoh16( p_rec->sl )) & 0xF) ); +} +/* +* PARAMETERS +* p_rec +* [in] Pointer to the multipath record object. +* +* RETURN VALUES +* SL. +* +* NOTES +* +* SEE ALSO +* ib_multipath_rec_t +*********/ + +/****f* IBA Base: Types/ib_multipath_rec_mtu +* NAME +* ib_multipath_rec_mtu +* +* DESCRIPTION +* Get encoded path MTU. +* +* SYNOPSIS +*/ +static inline uint8_t OSM_API +ib_multipath_rec_mtu( + IN const ib_multipath_rec_t* const p_rec ) +{ + return( (uint8_t)(p_rec->mtu & IB_MULTIPATH_REC_BASE_MASK) ); +} +/* +* PARAMETERS +* p_rec +* [in] Pointer to the multipath record object. +* +* RETURN VALUES +* Encoded path MTU. +* 1: 256 +* 2: 512 +* 3: 1024 +* 4: 2048 +* 5: 4096 +* others: reserved +* +* NOTES +* +* SEE ALSO +* ib_multipath_rec_t +*********/ + +/****f* IBA Base: Types/ib_multipath_rec_mtu_sel +* NAME +* ib_multipath_rec_mtu_sel +* +* DESCRIPTION +* Get encoded multipath MTU selector. +* +* SYNOPSIS +*/ +static inline uint8_t OSM_API +ib_multipath_rec_mtu_sel( + IN const ib_multipath_rec_t* const p_rec ) +{ + return( (uint8_t)((p_rec->mtu & IB_MULTIPATH_REC_SELECTOR_MASK) >> 6) ); +} +/* +* PARAMETERS +* p_rec +* [in] Pointer to the multipath 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_multipath_rec_t +*********/ + +/****f* IBA Base: Types/ib_multipath_rec_rate +* NAME +* ib_multipath_rec_rate +* +* DESCRIPTION +* Get encoded multipath rate. +* +* SYNOPSIS +*/ +static inline uint8_t OSM_API +ib_multipath_rec_rate( + IN const ib_multipath_rec_t* const p_rec ) +{ + return( (uint8_t)(p_rec->rate & IB_MULTIPATH_REC_BASE_MASK) ); +} +/* +* PARAMETERS +* p_rec +* [in] Pointer to the multipath record object. +* +* RETURN VALUES +* Encoded multipath rate. +* 2: 2.5 Gb/sec. +* 3: 10 Gb/sec. +* 4: 30 Gb/sec. +* others: reserved +* +* NOTES +* +* SEE ALSO +* ib_multipath_rec_t +*********/ + +/****f* IBA Base: Types/ib_multipath_rec_rate_sel +* NAME +* ib_multipath_rec_rate_sel +* +* DESCRIPTION +* Get encoded multipath rate selector. +* +* SYNOPSIS +*/ +static inline uint8_t OSM_API +ib_multipath_rec_rate_sel( + IN const ib_multipath_rec_t* const p_rec ) +{ + return( (uint8_t)((p_rec->rate & IB_MULTIPATH_REC_SELECTOR_MASK) >> 6) ); +} +/* +* PARAMETERS +* p_rec +* [in] Pointer to the multipath 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_multipath_rec_t +*********/ + +/****f* IBA Base: Types/ib_multipath_rec_pkt_life +* NAME +* ib_multipath_rec_pkt_life +* +* DESCRIPTION +* Get encoded multipath pkt_life. +* +* SYNOPSIS +*/ +static inline uint8_t OSM_API +ib_multipath_rec_pkt_life( + IN const ib_multipath_rec_t* const p_rec ) +{ + return( (uint8_t)(p_rec->pkt_life & IB_MULTIPATH_REC_BASE_MASK) ); +} +/* +* PARAMETERS +* p_rec +* [in] Pointer to the multipath record object. +* +* RETURN VALUES +* Encoded multipath pkt_life = 4.096 µsec * 2 ** PacketLifeTime. +* +* NOTES +* +* SEE ALSO +* ib_multipath_rec_t +*********/ + +/****f* IBA Base: Types/ib_multipath_rec_pkt_life_sel +* NAME +* ib_multipath_rec_pkt_life_sel +* +* DESCRIPTION +* Get encoded multipath pkt_lifetime selector. +* +* SYNOPSIS +*/ +static inline uint8_t OSM_API +ib_multipath_rec_pkt_life_sel( + IN const ib_multipath_rec_t* const p_rec ) +{ + return( (uint8_t)((p_rec->pkt_life & IB_MULTIPATH_REC_SELECTOR_MASK) >> 6 )); +} +/* +* PARAMETERS +* p_rec +* [in] Pointer to the multipath 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_multipath_rec_t +*********/ + +#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 +typedef struct _ib_pkey_table +{ + ib_net16_t pkey_entry[IB_NUM_PKEY_ELEMENTS_IN_BLOCK]; + +} PACK_SUFFIX ib_pkey_table_t; +#include +/************/ + +/****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 +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 switch: 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 +/************/ + +#define IB_DROP_VL 15 +#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 +typedef struct _ib_slvl_table +{ + uint8_t raw_vl_by_sl[IB_MAX_NUM_VLS/2]; +} PACK_SUFFIX ib_slvl_table_t; +#include +/************/ + +/****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 +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 CAs + uint8_t out_port_num; // reserved for CAs + uint32_t resv; + ib_slvl_table_t slvl_tbl; + +} PACK_SUFFIX ib_slvl_table_record_t; +#include +/************/ + +/****f* IBA Base: Types/ib_slvl_table_set +* NAME +* ib_slvl_table_set +* +* DESCRIPTION +* Set slvl table entry. +* +* SYNOPSIS +*/ +static inline void OSM_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 +*/ +static inline uint8_t OSM_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 for the requested sl_index. +* +* 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 +typedef struct _ib_vl_arb_element +{ + uint8_t vl; + uint8_t weight; +} PACK_SUFFIX ib_vl_arb_element_t; +#include +/************/ + +#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 +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 +/************/ + +/****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 +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 +/************/ + +/* + * Global route header information received with unreliable datagram messages + */ +#include +typedef struct _ib_grh +{ + ib_net32_t ver_class_flow; + uint16_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 + +/****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 +*/ +static inline void OSM_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 +*/ +static inline ib_net32_t OSM_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 +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; + uint8_t reserved[2]; + uint8_t pad[4]; + +} PACK_SUFFIX ib_member_rec_t; +#include +/* +* FIELDS +* mgid +* Multicast GID address for this multicast group. +* +* port_gid +* Valid GID of the endpoint joining this multicast group. +* +* 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 +*/ +static inline void OSM_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 ) +{ + uint32_t tmp; + + tmp = cl_ntoh32(sl_flow_hop); + if (p_hop) + *p_hop = (uint8_t)tmp; + tmp >>= 8; + + if (p_flow_lbl) + *p_flow_lbl = (uint32_t)(tmp & 0xfffff); + tmp >>= 20; + + if (p_sl) + *p_sl = (uint8_t)tmp; +} +/* +* 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 sl, flow label, and hop limit +* +* SYNOPSIS +*/ +static inline ib_net32_t OSM_API +ib_member_set_sl_flow_hop( + IN const uint8_t sl, + IN const uint32_t flow_label, + IN const uint8_t hop_limit ) +{ + uint32_t tmp; + + tmp = (sl << 28) | ((flow_label & 0xfffff) << 8) | hop_limit; + return cl_hton32(tmp); +} +/* +* 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 encoded 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 +*/ +static inline void OSM_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 +*/ +static inline uint8_t OSM_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 +*/ +static inline void OSM_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 +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 + +/****f* IBA Base: Types/ib_notice_is_generic +* NAME +* ib_notice_is_generic +* +* DESCRIPTION +* Check if the notice is generic +* +* SYNOPSIS +*/ +static inline boolean_t OSM_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 +*/ +static inline uint8_t OSM_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 +*/ +static inline ib_net32_t OSM_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 +*/ +static inline void OSM_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_set_prod_type_ho +* NAME +* ib_notice_set_prod_type_ho +* +* DESCRIPTION +* Set the notice Producer Type of Generic Notice given Host Order +* +* SYNOPSIS +*/ +static inline void OSM_API +ib_notice_set_prod_type_ho( + IN ib_mad_notice_attr_t *p_ntc, + IN uint32_t prod_type_val_ho ) +{ + p_ntc->g_or_v.generic.prod_type_lsb = + cl_hton16( (uint16_t)(prod_type_val_ho & 0x0000ffff) ); + p_ntc->g_or_v.generic.prod_type_msb = + (uint8_t)( (prod_type_val_ho & 0x00ff0000) >> 16); +} +/* +* PARAMETERS +* p_ntc +* [in] Pointer to the notice MAD attribute +* +* prod_type +* [in] The producer Type code in host order +* +* 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 +*/ +static inline ib_net32_t OSM_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 +*/ +static inline void OSM_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 +*********/ + +/****f* IBA Base: Types/ib_notice_set_vend_id_ho +* NAME +* ib_notice_set_vend_id_ho +* +* DESCRIPTION +* Set the notice Producer Type of Generic Notice given a host order value +* +* SYNOPSIS +*/ +static inline void OSM_API +ib_notice_set_vend_id_ho( + IN ib_mad_notice_attr_t *p_ntc, + IN uint32_t vend_id_ho ) +{ + p_ntc->g_or_v.vend.vend_id_lsb = + cl_hton16((uint16_t)(vend_id_ho & 0x0000ffff)); + p_ntc->g_or_v.vend.vend_id_msb = + (uint8_t)((vend_id_ho & 0x00ff0000) >> 16); +} +/* +* PARAMETERS +* p_ntc +* [in] Pointer to the notice MAD attribute +* +* vend_id_ho +* [in] The producer Type code in host order +* +* RETURN VALUES +* None +* +* SEE ALSO +* ib_mad_notice_attr_t +*********/ + +#include +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 + +/****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 +*/ +static inline void OSM_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 +*/ +static inline void OSM_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_prod_type +* NAME +* ib_inform_info_get_prod_type +* +* DESCRIPTION +* Get Producer Type of the Inform Info +* 13.4.8.3 InformInfo +* +* SYNOPSIS +*/ +static inline ib_net32_t OSM_API +ib_inform_info_get_prod_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 producer type +* +* 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 +*/ +static inline ib_net32_t OSM_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 +*/ +static inline ib_net32_t OSM_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 +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; + uint8_t pad[4]; +} PACK_SUFFIX ib_inform_info_record_t; +#include + +/****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 +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 +/* +* 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 +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 +/* +* 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 +*/ +static inline uint8_t OSM_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 +*/ +static inline uint8_t OSM_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 +*/ +static inline uint8_t OSM_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 +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 +/* +* 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 +*********/ + +static inline uint32_t OSM_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 ); +} + + +static inline void OSM_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 +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 +/* +* 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 +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 +/* +* FIELDS +* service_entry +* An array of IO controller service entries. +* +* SEE ALSO +* ib_dm_mad_t, ib_svc_entry_t +*********/ + +static inline void OSM_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 +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 + +/* + * 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_CM_RDMA_PDATA_SIZE 56 +#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* ib_ca_handle_t ; +typedef struct _ib_pd* ib_pd_handle_t ; +typedef struct _ib_rdd* ib_rdd_handle_t; +typedef struct _ib_mr* ib_mr_handle_t; +typedef struct _ib_mw* ib_mw_handle_t; +typedef struct _ib_qp* ib_qp_handle_t; +typedef struct _ib_eec* ib_eec_handle_t; +typedef struct _ib_cq* ib_cq_handle_t; +typedef struct _ib_av* ib_av_handle_t; +typedef struct _ib_mcast* ib_mcast_handle_t; +/* Currently for windows branch, 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_GUID_MASK, + 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; +/*****/ + +OSM_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 +*/ +static inline const char* OSM_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. +* +*****/ + +OSM_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 +*/ +static inline const char* OSM_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; + uint64_t fw_ver; + + /* + * 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; + uint64_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; + uint32_t max_fmr; + uint32_t max_map_per_fmr; + + /* + * 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 +* +* fw_ver +* Device Firmware version. +* +* 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; + +TO_LONG_PTR( struct _ib_rdd* , h_rdd) ; + + uint32_t sq_depth; + uint32_t rq_depth; + uint32_t sq_sge; + uint32_t rq_sge; + +TO_LONG_PTR( ib_cq_handle_t , h_sq_cq) ; +TO_LONG_PTR( 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 +{ +TO_LONG_PTR( struct _ib_pd* , 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; + +TO_LONG_PTR( ib_cq_handle_t , h_sq_cq) ; +TO_LONG_PTR( ib_cq_handle_t , h_rq_cq) ; +TO_LONG_PTR( struct _ib_rdd* , 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; +TO_LONG_PTR( struct _ib_rdd* , 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; +TO_LONG_PTR( 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; + +TO_LONG_PTR( struct _ib_mr* , 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_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_BAD_RESP_ERR, + IB_WCS_LOCAL_ACCESS_ERR, + IB_WCS_GENERAL_ERR, + IB_WCS_UNMATCHED_RESPONSE, /* InfiniBand Access Layer */ + IB_WCS_CANCELED, /* InfiniBand Access Layer */ + IB_WCS_REM_ABORT_ERR, + 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_REM_ABORT_ERR, +* The operation was aborted (e.g., For UD QPs associated with an SRQ, +* the responder aborted the operation). +* +* 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. +*****/ + +OSM_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 +*/ +static inline const char* OSM_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 +{ +TO_LONG_PTR( struct _ib_pd* , 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 +* Path 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 /* ndef WIN */ +#if defined( __WIN__ ) + #include +#endif + +#endif /* __IB_TYPES_H__ */ + + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/iba/ib_types_extended.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/iba/ib_types_extended.h new file mode 100644 index 00000000..af81fdec --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/iba/ib_types_extended.h @@ -0,0 +1,2809 @@ +/* + * 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. + * Portions Copyright (c) 2008 Microsoft Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: ib_types_extended.h 2165 2009-05-12 13:05:24Z leonidk $ + */ + + +#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 static 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 + + + +typedef struct _ib_srq* ib_srq_handle_t ; + +/* + * 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_SRQ_SIZE, + IB_INVALID_SERVICE_TYPE, + IB_INVALID_GID, + IB_INVALID_LID, + IB_INVALID_GUID, + IB_INVALID_GUID_MASK, + IB_INVALID_CA_HANDLE, + IB_INVALID_AV_HANDLE, + IB_INVALID_CQ_HANDLE, + IB_INVALID_QP_HANDLE, + IB_INVALID_SRQ_HANDLE, + IB_INVALID_PD_HANDLE, + IB_INVALID_MR_HANDLE, + IB_INVALID_FMR_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_EE_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_CLIENT_REREGISTER, + IB_AE_SRQ_LIMIT_REACHED, + IB_AE_SRQ_CATAS_ERROR, + IB_AE_SRQ_QP_LAST_WQE_REACHED, + IB_AE_RESET_DRIVER, + IB_AE_RESET_CLIENT, + IB_AE_RESET_END, + IB_AE_RESET_FAILED, + IB_AE_LID_CHANGE, + IB_AE_PKEY_CHANGE, + IB_AE_SM_CHANGE, + IB_AE_GID_CHANGE, + 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_CLIENT_REREGISTER +* The SM idicate to client to reregister its SA records. +* +* IB_AE_SRQ_LIMIT_REACHED +* Reached SRQ low watermark +* +* IB_AE_SRQ_CATAS_ERROR +* An error occurred while processing or accessing the SRQ that prevents +* dequeuing a WQE from the SRQ and reporting of receive completions. +* +* IB_AE_SRQ_QP_LAST_WQE_REACHED +* An event, issued for a QP, associated with a shared receive queue, when +* a CQE is generated for the last WQE, or +* the QP gets in the Error State and there are no more WQEs on the RQ. +* +* 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 +{ + TO_LONG_PTR(void*, context); + ib_async_event_t type; + + /* HCA vendor specific event information. */ + uint64_t vendor_specific; + uint8_t port_number; + +} 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; + uint8_t active_speed; + uint8_t phys_state; + + 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. + */ + TO_LONG_PTR(ib_gid_t*, p_gid_table); + TO_LONG_PTR(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; + uint64_t fw_ver; + + /* + * 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; + uint64_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; + uint32_t max_fmr; + uint32_t max_map_per_fmr; + uint32_t max_srq; + uint32_t max_srq_wrs; + uint32_t max_srq_sges; + + /* + * 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 modify_srq_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; + boolean_t ipoib_csum; + + ib_net64_t system_image_guid; + + uint32_t num_page_sizes; + uint8_t num_ports; + + TO_LONG_PTR(uint32_t*, p_page_size); + TO_LONG_PTR(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 +* +* fw_ver +* Device Firmware version. +* +* 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_fmr +* Maximum number of Fast Memory Regions supported. +* +* max_map_per_fmr +* Maximum number of mappings, supported by a Fast Memory Region. +* +* max_srq +* Maximum number of Shared Receive Queues supported. +* +* max_srq_wrs +* Maximum number of work requests supported by this SRQ. +* +* max_srq_sges +* Maximum number of scatter gather elements supported per work request on SRQ. +* +* 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. +* +* modify_srq_depth +* Indicates ability to modify SRQ depth during a modify SRQ 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_PDT_UD + +} 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. +* +* IB_PDT_UD +* Protection domain for UD 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_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_QPT_UNKNOWN +} 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. +*****/ + + +/****f* IBA Base: Types/ib_get_qp_type_str +* NAME +* ib_get_qp_type_str +* +* DESCRIPTION +* Returns a string for the specified QP type +* +* SYNOPSIS +*/ +AL_EXPORT const char* AL_API +ib_get_qp_type_str( + IN uint8_t qp_type ); + +/* +* PARAMETERS +* qp_type +* [in] Encoded QP type as defined in the +QP attribute. + +* RETURN VALUES +* Pointer to the QP type string. +* +* NOTES +* +* SEE ALSO +* ib_qp_type_t +*********/ + +/****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; +/*****/ + +/****d* Access Layer/ib_srq_attr_mask_t +* NAME +* ib_srq_attr_mask_t +* +* DESCRIPTION +* Indicates valid fields in ib_srq_attr_t structure +* +* SYNOPSIS +*/ +typedef enum _ib_srq_attr_mask { + IB_SRQ_MAX_WR = 1 << 0, + IB_SRQ_LIMIT = 1 << 1, +} ib_srq_attr_mask_t; +/*****/ + + +/****s* Access Layer/ib_srq_attr_t +* NAME +* ib_srq_attr_t +* +* DESCRIPTION +* Attributes used to initialize a shared queue pair at creation time. +* +* SYNOPSIS +*/ +typedef struct _ib_srq_attr { + uint32_t max_wr; + uint32_t max_sge; + uint32_t srq_limit; +} ib_srq_attr_t; +/* +* FIELDS +* max_wr +* Specifies the max number of work request on SRQ. +* +* max_sge +* Specifies the max number of scatter/gather elements in one work request. +* +* srq_limit +* Specifies the low water mark for SRQ. +* +* SEE ALSO +* ib_qp_type_t, ib_srq_attr_mask_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_max_inline; + uint32_t sq_depth; + uint32_t rq_depth; + uint32_t sq_sge; + uint32_t rq_sge; + + TO_LONG_PTR(ib_cq_handle_t, h_sq_cq); + TO_LONG_PTR(ib_cq_handle_t, h_rq_cq); + TO_LONG_PTR(ib_srq_handle_t, h_srq); + + boolean_t sq_signaled; + +} ib_qp_create_t; +/* +* FIELDS +* type +* Specifies the type of queue pair to create. +* +* sq_max_inline +* Maximum payload that can be inlined directly in a WQE, eliminating +* protection checks and additional DMA operations. +* +* 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. +* +* h_srq +* A handle to an SRQ to get receive completions via. Must be coded NULL +* when QP is not associated with SRQ +* +* 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 +{ + TO_LONG_PTR(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; + + TO_LONG_PTR(ib_cq_handle_t, h_sq_cq); + TO_LONG_PTR(ib_cq_handle_t, h_rq_cq); + TO_LONG_PTR(ib_srq_handle_t,h_srq); + + 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 + { + 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, + WR_RDMA_WRITE, + WR_RDMA_READ, + WR_COMPARE_SWAP, + WR_FETCH_ADD, + WR_LSO, + WR_UNKNOWN + +} ib_wr_type_t; +/*****/ + + +/****f* IBA Base: Types/ib_get_wr_type_str +* NAME +* ib_get_wr_type_str +* +* DESCRIPTION +* Returns a string for the specified work request type +* +* SYNOPSIS +*/ +AL_EXPORT const char* AL_API +ib_get_wr_type_str( + IN uint8_t wr_type ); + +/* +* PARAMETERS +* wr_type +* [in] Encoded work request type as defined in the +work request attribute. + +* RETURN VALUES +* Pointer to the work request type string. +* +* NOTES +* +* SEE ALSO +* 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_TX_IP_CSUM 0x00000040 +#define IB_SEND_OPT_TX_TCP_UDP_CSUM 0x00000080 + +#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 +{ + uint64_t wr_id; + struct _ib_send_wr* p_next; + ib_local_ds_t* ds_array; + uint32_t num_ds; + ib_wr_type_t wr_type; + ib_send_opt_t send_opt; + ib_net32_t immediate_data; + + union + { + union _send_dgrm + { + struct _send_ud + { + ib_av_handle_t h_av; + ib_net32_t remote_qp; + ib_net32_t remote_qkey; + void* rsvd; + uint16_t pkey_index; + void* header; + int hlen; + int mss; + } 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; + 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 +{ + TO_LONG_PTR(struct _ib_recv_wr*, p_next); + uint64_t wr_id; + uint32_t num_ds; + TO_LONG_PTR(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; + + TO_LONG_PTR(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_BAD_RESP_ERR, + IB_WCS_LOCAL_ACCESS_ERR, + IB_WCS_GENERAL_ERR, + IB_WCS_UNMATCHED_RESPONSE, /* InfiniBand Access Layer */ + IB_WCS_CANCELED, /* InfiniBand Access Layer */ + IB_WCS_REM_ABORT_ERR, + 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_BAD_RESP_ERR, +* An unexpected transport layer opcode was returned +* by the responder. +* +* IB_WCS_LOCAL_ACCESS_ERR, +* A protection error occurred on a local data buffer +* during the processing of a RDMA Write with Immediate Data +* operation sent from the remote node. +* +* IB_WCS_REM_ABORT_ERR, +* The operation was aborted (e.g., For UD QPs associated with an SRQ, +* the responder aborted the operation). +* +* IB_WCS_REM_ABORT_ERR, +* The operation was aborted (e.g., For UD QPs associated with an SRQ, +* the responder aborted the operation). +* +* 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. + * + * IB_WCS_GENERAL_ERR, + * Any other error + * +*****/ + + + +/****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_RDMA_READ, + IB_WC_COMPARE_SWAP, + IB_WC_FETCH_ADD, + IB_WC_MW_BIND, + IB_WC_UNKNOWN1, + IB_WC_RECV = (1 << 7), + IB_WC_RECV_RDMA_WRITE, + IB_WR_LSO, + IB_WC_UNKNOWN2 + +} 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 +{ + TO_LONG_PTR(struct _ib_wc*, p_next); + uint64_t wr_id; + ib_wc_type_t wc_type; + + uint32_t length; + uint64_t vendor_specific; + ib_wc_status_t status; + + 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; + uint8_t csum_ok; + + } 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 +{ + TO_LONG_PTR(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 +*****/ + +#ifdef CL_KERNEL + +/****s* Access Layer/mlnx_fmr_create_t +* NAME +* mlnx_fmr_create_t +* +* DESCRIPTION +* Information required to create a Mellanox fast memory region. +* +* SYNOPSIS +*/ +typedef struct _mlnx_fmr_create +{ + int max_pages; + int max_maps; + uint8_t page_size; + ib_access_t access_ctrl; + +} mlnx_fmr_create_t; +/* +* FIELDS +* max_pages +* max pages in the region. +* +* max_maps +* max times, the region can be mapped before remapping. +* +* page_size +* log2 of the page size (e.g. 12 for 4KB). +* +* access_ctrl +* Access rights of the registered region. +* +* NOTES +* This is a Mellanox specific extension to verbs. +* +* SEE ALSO +* ib_access_t +*****/ + + +/****s* Access Layer/mlnx_fmr_pool_create_t +* NAME +* mlnx_fmr_pool_create_t +* +* DESCRIPTION +* Information required to create a Mellanox fast memory region pool. +* +* SYNOPSIS +*/ +typedef struct _mlnx_fmr_pool_create +{ + int max_pages_per_fmr; + uint8_t page_size; /* really - page_shift, log2 of page_size */ + enum ib_access_flags access_ctrl; + int pool_size; + int dirty_watermark; + void (*flush_function)(mlnx_fmr_pool_handle_t h_pool, void *arg); + void *flush_arg; + boolean_t cache; +} mlnx_fmr_pool_create_t; +/* +* FIELDS +* max_pages +* max pages in the region. +* +* max_maps +* max times, the region can be mapped before remapping. +* +* page_size +* log2 of the page size (e.g. 12 for 4KB). +* +* access_ctrl +* Access rights of the registered region. +* +* NOTES +* This is a Mellanox specific extension to verbs. +* +* SEE ALSO +* ib_access_t +*****/ +#endif + +/****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* 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 +{ + TO_LONG_PTR(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 +#define IB_CA_MOD_IS_CLIENT_REREGISTER_SUPPORTED 0x00800000 +#define IB_CA_MOD_RESERVED_MASK 0xFF000000 +/* +* 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 +* Path 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. +* +* IB_CA_MOD_IS_CLIENT_REREGISTER_SUPPORTED +* Used to modify the system image GUID for the port. +* +* IB_CA_MOD_RESERVED_MASK +* Mask of all the reserved bits. If any of these bits are set +* ib_modify_ca will return IB_INVALID_PARAMETER. +*****/ + + +/****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; + IN OUT TO_LONG_PTR(void*, p_buf) OPTIONAL; // Do not put it last in the structure, because of memory alignment + OUT uint32_t num_bytes_ret; + + +} 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/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/cl_dispatcher.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/cl_dispatcher.h new file mode 100644 index 00000000..b402ef57 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/cl_dispatcher.h @@ -0,0 +1,673 @@ +/* + * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: cl_dispatcher.h 474 2006-08-31 08:57:19Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of dispatcher abstraction. + * + * Environment: + * All + * + * $Revision: 1.4 $ + */ + + +#ifndef _CL_DISPATCHER_H_ +#define _CL_DISPATCHER_H_ + + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* Component Library/Dispatcher +* NAME +* Dispatcher +* +* DESCRIPTION +* The Dispatcher provides a facility for message routing to +* asynchronous worker threads. +* +* The Dispatcher functions operate on a cl_dispatcher_t structure +* which should be treated as opaque and should be manipulated +* only through the provided functions. +* +* SEE ALSO +* Structures: +* cl_dispatcher_t +* +* Initialization/Destruction: +* cl_disp_construct, cl_disp_init, cl_disp_shutdown, cl_disp_destroy +* +* Manipulation: +* cl_disp_post, cl_disp_reset, cl_disp_wait_on +*********/ + + +/****s* Component Library: Dispatcher/cl_disp_msgid_t +* NAME +* cl_disp_msgid_t +* +* DESCRIPTION +* Defines the type of dispatcher messages. +* +* SYNOPSIS +*/ +typedef uint32_t cl_disp_msgid_t; +/**********/ + + +/****s* Component Library: Dispatcher/CL_DISP_MSGID_NONE +* NAME +* CL_DISP_MSGID_NONE +* +* DESCRIPTION +* Defines a message value that means "no message". +* This value is used during registration by Dispatcher clients +* that do not wish to receive messages. +* +* No Dispatcher message is allowed to have this value. +* +* SYNOPSIS +*/ +#define CL_DISP_MSGID_NONE 0xFFFFFFFF +/**********/ + +/****s* Component Library: Dispatcher/CL_DISP_INVALID_HANDLE +* NAME +* CL_DISP_INVALID_HANDLE +* +* DESCRIPTION +* Defines the value of an invalid Dispatcher registration handle. +* +* SYNOPSIS +*/ +#define CL_DISP_INVALID_HANDLE ((cl_disp_reg_handle_t)0) +/*********/ + +/****f* Component Library: Dispatcher/cl_pfn_msgrcv_cb_t +* NAME +* cl_pfn_msgrcv_cb_t +* +* DESCRIPTION +* This typedef defines the prototype for client functions invoked +* by the Dispatcher. The Dispatcher calls the corresponding +* client function when delivering a message to the client. +* +* The client function must be reentrant if the user creates a +* Dispatcher with more than one worker thread. +* +* SYNOPSIS +*/ +typedef void +(*cl_pfn_msgrcv_cb_t)( + IN void* context, + IN void* p_data ); +/* +* PARAMETERS +* context +* [in] Client specific context specified in a call to +* cl_disp_register +* +* p_data +* [in] Pointer to the client specific data payload +* of this message. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* This typedef provides a function prototype reference for +* the function provided by Dispatcher clients as a parameter +* to the cl_disp_register function. +* +* SEE ALSO +* Dispatcher, cl_disp_register +*********/ + + +/****f* Component Library: Dispatcher/cl_pfn_msgdone_cb_t +* NAME +* cl_pfn_msgdone_cb_t +* +* DESCRIPTION +* This typedef defines the prototype for client functions invoked +* by the Dispatcher. The Dispatcher calls the corresponding +* client function after completing delivery of a message. +* +* The client function must be reentrant if the user creates a +* Dispatcher with more than one worker thread. +* +* SYNOPSIS +*/ +typedef void +(*cl_pfn_msgdone_cb_t)( + IN void* context, + IN void* p_data ); +/* +* PARAMETERS +* context +* [in] Client specific context specified in a call to +* cl_disp_post +* +* p_data +* [in] Pointer to the client specific data payload +* of this message. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* This typedef provides a function prototype reference for +* the function provided by Dispatcher clients as a parameter +* to the cl_disp_post function. +* +* SEE ALSO +* Dispatcher, cl_disp_post +*********/ + + +/****s* Component Library: Dispatcher/cl_dispatcher_t +* NAME +* cl_dispatcher_t +* +* DESCRIPTION +* Dispatcher structure. +* +* The Dispatcher is thread safe. +* +* The cl_dispatcher_t structure should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _cl_dispatcher +{ + cl_spinlock_t lock; + cl_ptr_vector_t reg_vec; + cl_qlist_t reg_list; + cl_thread_pool_t worker_threads; + cl_qlist_t msg_fifo; + cl_qpool_t msg_pool; + uint64_t last_msg_queue_time_us; +} cl_dispatcher_t; +/* +* FIELDS +* reg_vec +* Vector of registration info objects. Indexed by message msg_id. +* +* lock +* Spinlock to guard internal structures. +* +* msg_fifo +* FIFO of messages being processed by the Dispatcher. New +* messages are posted to the tail of the FIFO. Worker threads +* pull messages from the front. +* +* worker_threads +* Thread pool of worker threads to dispose of posted messages. +* +* msg_pool +* Pool of message objects to be processed through the FIFO. +* +* reg_count +* Count of the number of registrants. +* +* state +* Indicates the state of the object. +* +* last_msg_queue_time_us +* The time that the last message spent in the Q in usec +* +* SEE ALSO +* Dispatcher +*********/ + + +/****s* Component Library: Dispatcher/cl_disp_reg_info_t +* NAME +* cl_disp_reg_info_t +* +* DESCRIPTION +* Defines the dispatcher registration object structure. +* +* The cl_disp_reg_info_t structure is for internal use by the +* Dispatcher only. +* +* SYNOPSIS +*/ +typedef struct _cl_disp_reg_info +{ + cl_list_item_t list_item; + cl_pfn_msgrcv_cb_t pfn_rcv_callback; + const void *context; + atomic32_t ref_cnt; + cl_disp_msgid_t msg_id; + cl_dispatcher_t *p_disp; + +} cl_disp_reg_info_t; +/* +* FIELDS +* pfn_rcv_callback +* Client's message receive callback. +* +* context +* Client's context for message receive callback. +* +* rcv_thread_count +* Number of threads currently in the receive callback. +* +* msg_done_thread_count +* Number of threads currently in the message done callback. +* +* state +* State of this registration object. +* DISP_REGSTATE_INIT: initialized and inactive +* DISP_REGSTATE_ACTIVE: in active use +* DISP_REGSTATE_UNREGPEND: unregistration is pending +* +* msg_id +* Dispatcher message msg_id value for this registration object. +* +* p_disp +* Pointer to parent Dispatcher. +* +* SEE ALSO +*********/ + + +/****s* Component Library: Dispatcher/cl_disp_msg_t +* NAME +* cl_disp_msg_t +* +* DESCRIPTION +* Defines the dispatcher message structure. +* +* The cl_disp_msg_t structure is for internal use by the +* Dispatcher only. +* +* SYNOPSIS +*/ +typedef struct _cl_disp_msg +{ + cl_pool_item_t item; + const void *p_data; + cl_disp_reg_info_t *p_src_reg; + cl_disp_reg_info_t *p_dest_reg; + cl_pfn_msgdone_cb_t pfn_xmt_callback; + uint64_t in_time; + const void *context; +} cl_disp_msg_t; +/* +* FIELDS +* item +* List & Pool linkage. Must be first element in the structure!! +* +* msg_id +* The message's numberic ID value. +* +* p_data +* Pointer to the data payload for this message. The payload +* is opaque to the Dispatcher. +* +* p_reg_info +* Pointer to the registration info of the sender. +* +* pfn_xmt_callback +* Client's message done callback. +* +* in_time +* The absolute time the message was inserted into the queue +* +* context +* Client's message done callback context. +* +* SEE ALSO +*********/ + + +/****s* Component Library: Dispatcher/cl_disp_reg_info_t +* NAME +* cl_disp_reg_info_t +* +* DESCRIPTION +* Defines the Dispatcher registration handle. This handle +* should be treated as opaque by the client. +* +* SYNOPSIS +*/ +typedef const struct _cl_disp_reg_info *cl_disp_reg_handle_t; +/**********/ + + +/****f* Component Library: Dispatcher/cl_disp_construct +* NAME +* cl_disp_construct +* +* DESCRIPTION +* This function constructs a Dispatcher object. +* +* SYNOPSIS +*/ +void +cl_disp_construct( + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_disp +* [in] Pointer to a Dispatcher. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling cl_disp_init and cl_disp_destroy. +* +* SEE ALSO +* Dispatcher, cl_disp_init, cl_disp_destroy +*********/ + + +/****f* Component Library: Dispatcher/cl_disp_init +* NAME +* cl_disp_init +* +* DESCRIPTION +* This function initializes a Dispatcher object. +* +* SYNOPSIS +*/ +cl_status_t +cl_disp_init( + IN cl_dispatcher_t* const p_disp, + IN const uint32_t thread_count, + IN const char* const name ); +/* +* PARAMETERS +* p_disp +* [in] Pointer to a Dispatcher. +* +* thread_count +* [in] The number of worker threads to create in this Dispatcher. +* A value of 0 causes the Dispatcher to create one worker thread +* per CPU in the system. When the Dispatcher is created with +* only one thread, the Dispatcher guarantees to deliver posted +* messages in order. When the Dispatcher is created with more +* than one thread, messages may be delivered out of order. +* +* name +* [in] Name to associate with the threads. The name may be up to 16 +* characters, including a terminating null character. All threads +* created in the Dispatcher have the same name. +* +* RETURN VALUE +* CL_SUCCESS if the operation is successful. +* +* SEE ALSO +* Dispatcher, cl_disp_destoy, cl_disp_register, cl_disp_unregister, +* cl_disp_post +*********/ + +/****f* Component Library: Dispatcher/cl_disp_shutdown +* NAME +* cl_disp_shutdown +* +* DESCRIPTION +* This function shutdown a Dispatcher object. So it unreg all messages and +* clears the fifo and waits for the threads to exit +* +* SYNOPSIS +*/ +void +cl_disp_shutdown( + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_disp +* [in] Pointer to a Dispatcher. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* This function does not returns until all worker threads +* have exited client callback functions and been successfully +* shutdowned. +* +* SEE ALSO +* Dispatcher, cl_disp_construct, cl_disp_init +*********/ + +/****f* Component Library: Dispatcher/cl_disp_destroy +* NAME +* cl_disp_destroy +* +* DESCRIPTION +* This function destroys a Dispatcher object. +* +* SYNOPSIS +*/ +void +cl_disp_destroy( + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_disp +* [in] Pointer to a Dispatcher. +* +* RETURN VALUE +* This function does not return a value. +* +* SEE ALSO +* Dispatcher, cl_disp_construct, cl_disp_init +*********/ + + +/****f* Component Library: Dispatcher/cl_disp_register +* NAME +* cl_disp_register +* +* DESCRIPTION +* This function registers a client with a Dispatcher object. +* +* SYNOPSIS +*/ +cl_disp_reg_handle_t +cl_disp_register( + IN cl_dispatcher_t* const p_disp, + IN const cl_disp_msgid_t msg_id, + IN cl_pfn_msgrcv_cb_t pfn_callback OPTIONAL, + IN const void* const context ); +/* +* PARAMETERS +* p_disp +* [in] Pointer to a Dispatcher. +* +* msg_id +* [in] Numberic message ID for which the client is registering. +* If the client does not wish to receive any messages, +* (a send-only client) then the caller should set this value +* to CL_DISP_MSGID_NONE. For efficiency, numeric message msg_id +* values should start with 0 and should be contiguous, or nearly so. +* +* pfn_callback +* [in] Message receive callback. The Dispatcher calls this +* function after receiving a posted message with the +* appropriate message msg_id value. Send-only clients may specify +* NULL for this value. +* +* context +* [in] Client context value passed to the cl_pfn_msgrcv_cb_t +* function. +* +* RETURN VALUE +* On success a Dispatcher registration handle. +* CL_CL_DISP_INVALID_HANDLE otherwise. +* +* SEE ALSO +* Dispatcher, cl_disp_unregister, cl_disp_post +*********/ + + +/****f* Component Library: Dispatcher/cl_disp_unregister +* NAME +* cl_disp_unregister +* +* DESCRIPTION +* This function unregisters a client from a Dispatcher. +* +* SYNOPSIS +*/ +void +cl_disp_unregister( + IN const cl_disp_reg_handle_t handle ); +/* +* PARAMETERS +* handle +* [in] cl_disp_reg_handle_t value return by cl_disp_register. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* This function will not return until worker threads have exited +* the callback functions for this client. Do not invoke this +* function from a callback. +* +* SEE ALSO +* Dispatcher, cl_disp_register +*********/ + + +/****f* Component Library: Dispatcher/cl_disp_post +* NAME +* cl_disp_post +* +* DESCRIPTION +* This function posts a message to a Dispatcher object. +* +* SYNOPSIS +*/ +cl_status_t +cl_disp_post( + IN const cl_disp_reg_handle_t handle, + IN const cl_disp_msgid_t msg_id, + IN const void* const p_data, + IN cl_pfn_msgdone_cb_t pfn_callback OPTIONAL, + IN const void* const context ); +/* +* PARAMETERS +* handle +* [in] cl_disp_reg_handle_t value return by cl_disp_register. +* +* msg_id +* [in] Numeric message msg_id value associated with this message. +* +* p_data +* [in] Data payload for this message. +* +* pfn_callback +* [in] Pointer to a cl_pfn_msgdone_cb_t function. +* The Dispatcher calls this function after the message has been +* processed by the recipient. +* The caller may pass NULL for this value, which indicates no +* message done callback is necessary. +* +* context +* [in] Client context value passed to the cl_pfn_msgdone_cb_t +* function. +* +* RETURN VALUE +* CL_SUCCESS if the message was successfully queued in the Dispatcher. +* +* NOTES +* The caller must not modify the memory pointed to by p_data until +* the Dispatcher call the pfn_callback function. +* +* SEE ALSO +* Dispatcher +*********/ + +/****f* Component Library: Dispatcher/cl_disp_get_queue_status +* NAME +* cl_disp_get_queue_status +* +* DESCRIPTION +* This function posts a message to a Dispatcher object. +* +* SYNOPSIS +*/ +void +cl_disp_get_queue_status( + IN const cl_disp_reg_handle_t handle, + OUT uint32_t *p_num_queued_msgs, + OUT uint64_t *p_last_msg_queue_time_ms); +/* +* PARAMETERS +* handle +* [in] cl_disp_reg_handle_t value return by cl_disp_register. +* +* p_last_msg_queue_time_ms +* [out] pointer to a variable to hold the time the last popped up message +* spent in the queue +* +* p_num_queued_msgs +* [out] number of messages in the queue +* +* RETURN VALUE +* Thr time the last popped up message stayed in the queue, in msec +* +* NOTES +* Extarnel Locking is not required. +* +* SEE ALSO +* Dispatcher +*********/ + +END_C_DECLS + +#endif /* !defined(_CL_DISPATCHER_H_) */ diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/cl_event_wheel.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/cl_event_wheel.h new file mode 100644 index 00000000..2972c71e --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/cl_event_wheel.h @@ -0,0 +1,497 @@ +/* + * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: cl_event_wheel.h 474 2006-08-31 08:57:19Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of event wheel abstraction. + * + * Environment: + * All + * + * $Revision: 1.4 $ + */ + + +#ifndef _CL_EVENT_WHEEL_H_ +#define _CL_EVENT_WHEEL_H_ + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* Component Library/Event_Wheel +* NAME +* Event_Wheel +* +* DESCRIPTION +* The Event_Wheel provides a facility for registering delayed events +* and getting called once they timeout. +* +* The Event_Wheel functions operate on a cl_event_wheel_t structure +* which should be treated as opaque and should be manipulated +* only through the provided functions. +* +* SEE ALSO +* Structures: +* cl_event_wheel_t +* +* Initialization/Destruction: +* cl_event_wheel_construct, cl_event_wheel_init, cl_event_wheel_destroy +* +* Manipulation: +* cl_event_wheel_reg, cl_event_wheel_unreg +* +*********/ + +/****f* Component Library: Event_Wheel/cl_pfn_event_aged_cb_t +* NAME +* cl_pfn_event_aged_cb_t +* +* DESCRIPTION +* This typedef defines the prototype for client functions invoked +* by the Event_Wheel. The Event_Wheel calls the corresponding +* client function when the specific item has aged. +* +* SYNOPSIS +*/ +typedef uint64_t +(*cl_pfn_event_aged_cb_t)( + IN uint64_t key, + IN uint32_t num_regs, + IN void* context); +/* +* PARAMETERS +* key +* [in] The key used for registering the item in the call to +* cl_event_wheel_reg +* +* num_regs +* [in] The number of times this event was registered (pushed in time). +* +* context +* [in] Client specific context specified in a call to +* cl_event_wheel_reg +* +* RETURN VALUE +* This function returns the abosolute time the event should fire in [usec]. +* If lower then current time means the event should be unregistered +* immediatly. +* +* NOTES +* This typedef provides a function prototype reference for +* the function provided by Event_Wheel clients as a parameter +* to the cl_event_wheel_reg function. +* +* SEE ALSO +* Event_Wheel, cl_event_wheel_reg +*********/ + +/****s* Component Library: Event_Wheel/cl_event_wheel_t +* NAME +* cl_event_wheel_t +* +* DESCRIPTION +* Event_Wheel structure. +* +* The Event_Wheel is thread safe. +* +* The cl_event_wheel_t structure should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _cl_event_wheel +{ + cl_spinlock_t lock; + cl_spinlock_t *p_external_lock; + + cl_qmap_t events_map; + boolean_t closing; + cl_qlist_t events_wheel; + cl_timer_t timer; + osm_log_t *p_log; +} cl_event_wheel_t; +/* +* FIELDS +* lock +* Spinlock to guard internal structures. +* +* p_external_lock +* Reference to external spinlock to guard internal structures +* if the event wheel is part of a larger object protected by its own lock +* +* events_map +* A Map holding all registered event items by their key. +* +* closing +* A flag indicating the event wheel is closing. This means that +* callbacks that are called when closing == TRUE should just be ignored. +* +* events_wheel +* A list of the events sorted by expiration time. +* +* timer +* The timer scheduling event time propagation. +* +* p_log +* Pointer to opensm log object. +* +* SEE ALSO +* Event_Wheel +*********/ + +/****s* Component Library: Event_Wheel/cl_event_wheel_reg_info_t +* NAME +* cl_event_wheel_reg_info_t +* +* DESCRIPTION +* Defines the event_wheel registration object structure. +* +* The cl_event_wheel_reg_info_t structure is for internal use by the +* Event_Wheel only. +* +* SYNOPSIS +*/ +typedef struct _cl_event_wheel_reg_info +{ + cl_map_item_t map_item; + cl_list_item_t list_item; + uint64_t key; + cl_pfn_event_aged_cb_t pfn_aged_callback; + uint64_t aging_time; + uint32_t num_regs; + void *context; + cl_event_wheel_t *p_event_wheel; +} cl_event_wheel_reg_info_t; +/* +* FIELDS +* map_item +* The map item of this event +* +* list_item +* The sorted by aging time list item +* +* key +* The key by which one can find the event +* +* pfn_aged_callback +* The clients Event-Aged callback +* +* aging_time +* The delta time [msec] for which the event should age. +* +* num_regs +* The number of times the same event (key) was registered +* +* context +* Client's context for event-aged callback. +* +* p_event_wheel +* Pointer to this event wheel object +* +* SEE ALSO +*********/ + + +/****f* Component Library: Event_Wheel/cl_event_wheel_construct +* NAME +* cl_event_wheel_construct +* +* DESCRIPTION +* This function constructs a Event_Wheel object. +* +* SYNOPSIS +*/ +void +cl_event_wheel_construct( + IN cl_event_wheel_t* const p_event_wheel ); +/* +* PARAMETERS +* p_event_wheel +* [in] Pointer to a Event_Wheel. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling cl_event_wheel_init and cl_event_wheel_destroy. +* +* SEE ALSO +* Event_Wheel, cl_event_wheel_init, cl_event_wheel_destroy +*********/ + + +/****f* Component Library: Event_Wheel/cl_event_wheel_init +* NAME +* cl_event_wheel_init +* +* DESCRIPTION +* This function initializes a Event_Wheel object. +* +* SYNOPSIS +*/ +cl_status_t +cl_event_wheel_init( + IN cl_event_wheel_t* const p_event_wheel, + IN osm_log_t *p_log); + +/* +* PARAMETERS +* p_event_wheel +* [in] Pointer to a Event_Wheel. +* +* p_log +* [in] Pointer to opensm log object to be used for logging +* +* RETURN VALUE +* CL_SUCCESS if the operation is successful. +* +* SEE ALSO +* Event_Wheel, cl_event_wheel_destoy, cl_event_wheel_reg, cl_event_wheel_unreg +* +*********/ + +/****f* Component Library: Event_Wheel/cl_event_wheel_init +* NAME +* cl_event_wheel_init +* +* DESCRIPTION +* This function initializes a Event_Wheel object. +* +* SYNOPSIS +*/ +cl_status_t +cl_event_wheel_init_ex( + IN cl_event_wheel_t* const p_event_wheel, + IN osm_log_t *p_log, + IN cl_spinlock_t *p_external_lock); + +/* +* PARAMETERS +* p_event_wheel +* [in] Pointer to a Event_Wheel. +* +* p_log +* [in] Pointer to opensm log object to be used for logging +* +* p_external_lock +* [in] Reference to external spinlock to guard internal structures +* if the event wheel is part of a larger object protected by its own lock +* +* RETURN VALUE +* CL_SUCCESS if the operation is successful. +* +* SEE ALSO +* Event_Wheel, cl_event_wheel_destoy, cl_event_wheel_reg, cl_event_wheel_unreg +* +*********/ + + +/****f* Component Library: Event_Wheel/cl_event_wheel_destroy +* NAME +* cl_event_wheel_destroy +* +* DESCRIPTION +* This function destroys a Event_Wheel object. +* +* SYNOPSIS +*/ +void +cl_event_wheel_destroy( + IN cl_event_wheel_t* const p_event_wheel ); +/* +* PARAMETERS +* p_event_wheel +* [in] Pointer to a Event_Wheel. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* This function does not returns until all client callback functions +* been successfully finished. +* +* SEE ALSO +* Event_Wheel, cl_event_wheel_construct, cl_event_wheel_init +*********/ + +/****f* Component Library: Event_Wheel/cl_event_wheel_dump +* NAME +* cl_event_wheel_dump +* +* DESCRIPTION +* This function dumps the details of an Event_Whell object. +* +* SYNOPSIS +*/ +void +cl_event_wheel_dump( + IN cl_event_wheel_t* const p_event_wheel ); +/* +* PARAMETERS +* p_event_wheel +* [in] Pointer to a Event_Wheel. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Note that this function should be called inside a lock of the event wheel! +* It doesn't aquire the lock by itself. +* +* SEE ALSO +* Event_Wheel, cl_event_wheel_construct, cl_event_wheel_init +*********/ + +/****f* Component Library: Event_Wheel/cl_event_wheel_reg +* NAME +* cl_event_wheel_reg +* +* DESCRIPTION +* This function registers a client with a Event_Wheel object. +* +* SYNOPSIS +*/ +cl_status_t +cl_event_wheel_reg( + IN cl_event_wheel_t* const p_event_wheel, + IN const uint64_t key, + IN const uint64_t aging_time_usec, + IN cl_pfn_event_aged_cb_t pfn_callback, + IN void* const context ); +/* +* PARAMETERS +* p_event_wheel +* [in] Pointer to a Event_Wheel. +* +* key +* [in] The specifc Key by which events are registered. +* +* aging_time_usec +* [in] The absolute time this event should age in usec +* +* pfn_callback +* [in] Event Aging callback. The Event_Wheel calls this +* function after the time the event has registed for has come. +* +* context +* [in] Client context value passed to the cl_pfn_event_aged_cb_t +* function. +* +* RETURN VALUE +* On success a Event_Wheel CL_SUCCESS or CL_ERROR otherwise. +* +* SEE ALSO +* Event_Wheel, cl_event_wheel_unreg +*********/ + + +/****f* Component Library: Event_Wheel/cl_event_wheel_unreg +* NAME +* cl_event_wheel_unreg +* +* DESCRIPTION +* This function unregisters a client event from a Event_Wheel. +* +* SYNOPSIS +*/ +void +cl_event_wheel_unreg( + IN cl_event_wheel_t* const p_event_wheel, + IN uint64_t key ); +/* +* PARAMETERS +* p_event_wheel +* [in] Pointer to a Event_Wheel. +* +* key +* [in] The key used for registering the event +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* After the event has aged it is automatically removed from +* the event wheel. So it should only be invoked when the need arises +* to remove existing events before they age. +* +* SEE ALSO +* Event_Wheel, cl_event_wheel_reg +*********/ + +/****f* Component Library: Event_Wheel/cl_event_wheel_num_regs +* NAME +* cl_event_wheel_num_regs +* +* DESCRIPTION +* This function returns the number of times an event was registered. +* +* SYNOPSIS +*/ +uint32_t +cl_event_wheel_num_regs( + IN cl_event_wheel_t* const p_event_wheel, + IN uint64_t key ); +/* +* PARAMETERS +* p_event_wheel +* [in] Pointer to a Event_Wheel. +* +* key +* [in] The key used for registering the event +* +* RETURN VALUE +* The number of times the event was registered. +* 0 if never registered or eventually aged. +* +* SEE ALSO +* Event_Wheel, cl_event_wheel_reg, cl_event_wheel_unreg +*********/ + +END_C_DECLS + +#endif /* !defined(_CL_EVENT_WHEEL_H_) */ diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_attrib_req.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_attrib_req.h new file mode 100644 index 00000000..80c29b9b --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_attrib_req.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_attrib_req.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +#ifndef _OSM_ATTRIB_REQ_H_ +#define _OSM_ATTRIB_REQ_H_ + +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/* + * Abstract: + * Declaration of the attribute request object. This object + * encapsulates information needed by the generic request controller + * to request an attribute from a node. + * These objects are part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +/****h* OpenSM/Attribute Request +* NAME +* Attribute Request +* +* DESCRIPTION +* The Attribute Request structure encapsulates +* encapsulates information needed by the generic request controller +* to request an attribute from a node. +* +* This structure allows direct access to member variables. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: Attribute Request/osm_attrib_req_t +* NAME +* osm_attrib_req_t +* +* DESCRIPTION +* Attribute request structure. +* +* This structure allows direct access to member variables. +* +* SYNOPSIS +*/ +typedef struct _osm_attrib_req +{ + uint16_t attrib_id; + uint32_t attrib_mod; + osm_madw_context_t context; + osm_dr_path_t path; + cl_disp_msgid_t err_msg; + +} osm_attrib_req_t; +/* +* FIELDS +* attrib_id +* Attribute ID for this request. +* +* attrib_mod +* Attribute modifier for this request. +* +* context +* Context to insert in outbound mad wrapper context. +* +* path +* The directed route path to the node. +* +* SEE ALSO +*********/ + +END_C_DECLS + +#endif /* _OSM_ATTRIB_REQ_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_base.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_base.h new file mode 100644 index 00000000..8aa3bd15 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_base.h @@ -0,0 +1,823 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_base.h 1927 2009-02-04 15:20:41Z tzachid $ + */ + + +/* + * 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 +#define OSM_CDECL __cdecl +#else +#define OSM_CDECL +#endif + +#include + +#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_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 1 +/********/ + +/****s* OpenSM: Base/OSM_DEFAULT_SA_KEY +* NAME +* OSM_DEFAULT_SA_KEY +* +* DESCRIPTION +* Subnet Adminstration key value. +* +* SYNOPSIS +*/ +#define OSM_DEFAULT_SA_KEY OSM_DEFAULT_SM_KEY +/********/ + +/****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 lowest priority. +* +* SYNOPSIS +*/ +#define OSM_DEFAULT_SM_PRIORITY 1 +/********/ + +/****d* OpenSM: Base/OSM_DEFAULT_TMP_DIR +* NAME +* OSM_DEFAULT_TMP_DIR +* +* DESCRIPTION +* Specifies the default temporary directory for the log file, +* osm-subnet.lst, and other log files. +* +* SYNOPSIS +*/ +#ifdef __WIN__ +#define OSM_DEFAULT_TMP_DIR GetOsmTempPath() +#else +#define OSM_DEFAULT_TMP_DIR "/var/log/" +#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 GetOsmCachePath() +#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(GetOsmTempPath(), "osm.log") +#else +#define OSM_DEFAULT_LOG_FILE "/var/log/osm.log" +#endif +/***********/ + +/****d* OpenSM: Base/OSM_DEFAULT_PARTITION_CONFIG_FILE +* NAME +* OSM_DEFAULT_PARTITION_CONFIG_FILE +* +* DESCRIPTION +* Specifies the default partition config file name +* +* SYNOPSIS +*/ +#ifdef __WIN__ +#define OSM_DEFAULT_PARTITION_CONFIG_FILE strcat(GetOsmCachePath(), "osm-partitions.conf") +#else +#define OSM_DEFAULT_PARTITION_CONFIG_FILE "/etc/osm-partitions.conf" +#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 200 +/***********/ + +/****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_VL_STALL_COUNT +* NAME +* OSM_DEFAULT_LEAF_VL_COUNT +* +* DESCRIPTION +* Sets the number of consecutive head of queue life time drops that +* puts the VL into stalled state. In stalled state, the port is supposed +* to drop everything for 8*(head of queue lifetime) +* +* SYNOPSIS +*/ +#define OSM_DEFAULT_VL_STALL_COUNT 0x7 +/***********/ + +/****d* OpenSM: Base/OSM_DEFAULT_LEAF_VL_STALL_COUNT +* NAME +* OSM_DEFAULT_LEAF_VL_STALL_COUNT +* +* DESCRIPTION +* Sets the number of consecutive head of queue life time drops that +* puts the VL into stalled state. In stalled state, the port is supposed +* to drop everything for 8*(head of queue lifetime). This value is for +* switch ports driving a CA port. +* We use the value of 1 here - 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 unhealthy. +* 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 4 +/***********/ + +/****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 default total time for handoff is 40 sec. +* +* SYNOPSIS +*/ +#define OSM_SM_DEFAULT_POLLING_RETRY_NUMBER 4 +/**********/ + +/****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 from Table 117 and C15-0.1.7 Table 186 + */ + +/****d* OpenSM: Base/OSM_CAP_IS_TRAP_SUP +* Name +* OSM_CAP_IS_SUBN_TRAP_SUP +* +* DESCRIPTION +* Management class generates Trap() MADs +* +* SYNOPSIS +*/ +#define OSM_CAP_IS_SUBN_TRAP_SUP (1 << 0) +/***********/ + +/****d* OpenSM: Base/OSM_CAP_IS_GET_SET_NOTICE_SUP +* Name +* OSM_CAP_IS_GET_SET_NOTICE_SUP +* +* DESCRIPTION +* Management class supports Get/Set(Notice) +* +* SYNOPSIS +*/ +#define OSM_CAP_IS_SUBN_GET_SET_NOTICE_SUP (1 << 1) +/***********/ + +/****d* OpenSM: Base/OSM_CAP_IS_SUBN_OPT_RECS_SUP +* Name +* OSM_CAP_IS_SUBN_OPT_RECS_SUP +* +* DESCRIPTION +* Support all optional attributes except: +* MCMemberRecord, TraceRecord, MultiPathRecord +* +* 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_MULTIPATH_SUP +* Name +* OSM_CAP_IS_MULTIPATH_SUP +* +* DESCRIPTION +* MultiPathRecord and TraceRecord are supported +* +* SYNOPSIS +*/ +#define OSM_CAP_IS_MULTIPATH_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_CAP_IS_PORT_INFO_CAPMASK_MATCH_SUPPORTED +* Name +* OSM_CAP_IS_PORT_INFO_CAPMASK_MATCH_SUPPORTED +* +* DESCRIPTION +* SM/SA supports enhanced SA PortInfoRecord searches per 1.2 Errata: +* ClassPortInfo:CapabilityMask.IsPortInfoCapMaskMatchSupported is 1, +* then the AttributeModifier of the SubnAdmGet() and SubnAdmGetTable() +* methods affects the matching behavior on the PortInfo:CapabilityMask +* component. If the high-order bit (bit 31) of the AttributeModifier +* is set to 1, matching on the CapabilityMask component will not be an +* exact bitwise match as described in . Instead, +* matching will only be performed on those bits which are set to 1 in +* the PortInfo:CapabilityMask embedded in the query. +* +* SYNOPSIS +*/ +#define OSM_CAP_IS_PORT_INFO_CAPMASK_MATCH_SUPPORTED (1 << 13) +/***********/ + +/****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_SET_PKEY, + OSM_SM_STATE_SET_PKEY_WAIT, + OSM_SM_STATE_SET_PKEY_DONE, + 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). +* +**********/ + +/****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 +/**********/ + +/****s* OpenSM: Base/VendorOUIs +* NAME +* VendorOUIs +* +* DESCRIPTION +* Known device vendor ID and GUID OUIs +* +* SYNOPSIS +*/ +#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 +#define OSM_VENDOR_ID_YOTTAYOTTA 0x000453 +#define OSM_VENDOR_ID_PATHSCALE 0x001175 +#define OSM_VENDOR_ID_IBM 0x000255 +#define OSM_VENDOR_ID_DIVERGENET 0x00084E +#define OSM_VENDOR_ID_FLEXTRONICS 0x000B8C +#define OSM_VENDOR_ID_AGILENT 0x0030D3 +#define OSM_VENDOR_ID_OBSIDIAN 0x001777 +#define OSM_VENDOR_ID_BAYMICRO 0x000BC1 +#define OSM_VENDOR_ID_LSILOGIC 0x00A0B8 +#define OSM_VENDOR_ID_DDN 0x0001FF +#define OSM_VENDOR_ID_PANTA 0x001393 +#define OSM_VENDOR_ID_HP 0x001708 +#define OSM_VENDOR_ID_RIOWORKS 0x005045 + +/**********/ + +END_C_DECLS + +#endif /* _OSM_BASE_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_console.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_console.h new file mode 100644 index 00000000..4dfcb138 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_console.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_console.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +#ifndef _OSM_CONSOLE_H_ +#define _OSM_CONSOLE_H_ + +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +void osm_console(osm_opensm_t *p_osm); +void osm_console_prompt(void); + +END_C_DECLS + +#endif /* _OSM_CONSOLE_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_db.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_db.h new file mode 100644 index 00000000..3f1f9288 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_db.h @@ -0,0 +1,455 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_db.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +#ifndef _OSM_DB_H_ +#define _OSM_DB_H_ + +/* + * Abstract: + * Declaration of the DB interface. + * + * $Revision: 1.4 $ + */ + +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Database +* NAME +* Database +* +* DESCRIPTION +* The OpenSM database interface provide the means to restore persistat +* data, query, modify, delete and evemtually commit it back to the +* persistent media. +* +* The interface is defined such that it can is not "data dependant": +* All keys and data items are texts. +* +* The DB implementation should be thread safe, thus callers do not need to +* provide serialization. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Eitan Zahavi, Mellanox Technologies LTD +* +*********/ + +/****s* OpenSM: Database/osm_db_domain_t +* NAME +* osm_db_domain_t +* +* DESCRIPTION +* A domain of the database. Can be viewed as a database table. +* +* The osm_db_domain_t object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_db_domain { + struct _osm_db *p_db; + void *p_domain_imp; +} osm_db_domain_t; +/* +* FIELDS +* p_db +* Pointer to the parent database object. +* +* p_domain_imp +* Pointer to the db implementation object +* +* SEE ALSO +* osm_db_t +*********/ + +/****s* OpenSM: Database/osm_db_t +* NAME +* osm_db_t +* +* DESCRIPTION +* The main database object. +* +* The osm_db_t object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_db +{ + void *p_db_imp; + osm_log_t *p_log; + cl_list_t domains; +} osm_db_t; +/* +* FIELDS +* p_db_imp +* Pointer to the database implementation object +* +* p_log +* Pointer to the OSM logging facility +* +* domains +* List of initialize domains +* +* SEE ALSO +*********/ + +/****f* OpenSM: Database/osm_db_construct +* NAME +* osm_db_construct +* +* DESCRIPTION +* Construct a database. +* +* SYNOPSIS +*/ +void +osm_db_construct( + IN osm_db_t* const p_db ); +/* +* PARAMETERS +* p_db +* [in] Pointer to the database object to custruct +* +* RETURN VALUES +* NONE +* +* SEE ALSO +* Database, osm_db_init, osm_db_destroy +*********/ + +/****f* OpenSM: Database/osm_db_destroy +* NAME +* osm_db_destroy +* +* DESCRIPTION +* Destroys the osm_db_t structure. +* +* SYNOPSIS +*/ +void +osm_db_destroy( + IN osm_db_t* const p_db ); +/* +* PARAMETERS +* p_db +* [in] Pointer to osm_db_t structure to destroy +* +* SEE ALSO +* Database, osm_db_construct, osm_db_init +*********/ + +/****f* OpenSM: Database/osm_db_init +* NAME +* osm_db_init +* +* DESCRIPTION +* Initializes the osm_db_t structure. +* +* SYNOPSIS +*/ +int +osm_db_init( + IN osm_db_t* const p_db, + IN osm_log_t *p_log ); +/* +* PARAMETERS +* +* p_db +* [in] Pointer to the database object to initialize +* +* p_log +* [in] Pointer to the OSM logging facility +* +* RETURN VALUES +* 0 on success 1 otherwise +* +* SEE ALSO +* Database, osm_db_construct, osm_db_destroy +*********/ + +/****f* OpenSM: Database/osm_db_domain_init +* NAME +* osm_db_domain_init +* +* DESCRIPTION +* Initializes the osm_db_domain_t structure. +* +* SYNOPSIS +*/ +osm_db_domain_t* +osm_db_domain_init( + IN osm_db_t* const p_db, + IN char *domain_name); +/* +* PARAMETERS +* +* p_db +* [in] Pointer to the database object to initialize +* +* domain_name +* [in] a char array with the domain name. +* +* RETURN VALUES +* pointer to the new domain object or NULL if failed. +* +* SEE ALSO +* Database, osm_db_construct, osm_db_destroy +*********/ + +/****f* OpenSM: Database/osm_db_restore +* NAME +* osm_db_restore +* +* DESCRIPTION +* Reads the entire domain from persistent storage - overrides all +* existing cached data (if any). +* +* SYNOPSIS +*/ +int +osm_db_restore( + IN osm_db_domain_t *p_domain); +/* +* PARAMETERS +* +* p_domain +* [in] Pointer to the database domain object to restore from persistent db +* +* RETURN VALUES +* 0 if successful 1 otherwize +* +* SEE ALSO +* Database, osm_db_domain_init, osm_db_clear, osm_db_store, +* osm_db_keys, osm_db_lookup, osm_db_update, osm_db_delete +*********/ + +/****f* OpenSM: Database/osm_db_clear +* NAME +* osm_db_clear +* +* DESCRIPTION +* Clears the entire domain values from/in the cache +* +* SYNOPSIS +*/ +int +osm_db_clear( + IN osm_db_domain_t *p_domain); +/* +* PARAMETERS +* +* p_domain +* [in] Pointer to the database domain object to clear +* +* RETURN VALUES +* 0 if successful 1 otherwize +* +* SEE ALSO +* Database, osm_db_domain_init, osm_db_restore, osm_db_store, +* osm_db_keys, osm_db_lookup, osm_db_update, osm_db_delete +*********/ + +/****f* OpenSM: Database/osm_db_store +* NAME +* osm_db_store +* +* DESCRIPTION +* Store the domain cache back to the database (commit) +* +* SYNOPSIS +*/ +int osm_db_store( + IN osm_db_domain_t *p_domain); +/* +* PARAMETERS +* +* p_domain +* [in] Pointer to the database domain object to restore from persistent db +* +* RETURN VALUES +* 0 if successful 1 otherwize +* +* SEE ALSO +* Database, osm_db_domain_init, osm_db_restore, osm_db_clear, +* osm_db_keys, osm_db_lookup, osm_db_update, osm_db_delete +*********/ + +/****f* OpenSM: Database/osm_db_keys +* NAME +* osm_db_keys +* +* DESCRIPTION +* Retrive all keys of the domain +* +* SYNOPSIS +*/ +int +osm_db_keys( + IN osm_db_domain_t *p_domain, + OUT cl_list_t* p_key_list); +/* +* PARAMETERS +* +* p_domain +* [in] Pointer to the database domain object +* +* p_key_list +* [out] List of key values. It should be PRE constructed and initialized. +* +* RETURN VALUES +* 0 if successful 1 otherwize +* +* NOTE: the caller needs to free and destruct the list, +* the keys returned are intrnal to the hash and should NOT be free'ed +* +* SEE ALSO +* Database, osm_db_domain_init, osm_db_restore, osm_db_clear, osm_db_store, +* osm_db_lookup, osm_db_update, osm_db_delete +*********/ + +/****f* OpenSM: Database/osm_db_lookup +* NAME +* osm_db_lookup +* +* DESCRIPTION +* Lookup an entry in the domain by the given key +* +* SYNOPSIS +*/ +/* lookup value by key */ +char *osm_db_lookup( + IN osm_db_domain_t *p_domain, + IN char *const p_key); +/* +* PARAMETERS +* +* p_domain +* [in] Pointer to the database domain object +* +* key +* [in] The key to look for +* +* RETURN VALUES +* the value as char * or NULL if not found +* +* SEE ALSO +* Database, osm_db_domain_init, osm_db_restore, osm_db_clear, osm_db_store, +* osm_db_keys, osm_db_update, osm_db_delete +*********/ + +/****f* OpenSM: Database/osm_db_update +* NAME +* osm_db_update +* +* DESCRIPTION +* Set the value of the given key +* +* SYNOPSIS +*/ +int +osm_db_update( + IN osm_db_domain_t *p_domain, + IN char *const p_key, + IN char *const p_val); +/* +* PARAMETERS +* +* p_domain +* [in] Pointer to the database domain object +* +* p_key +* [in] The key to update +* +* p_val +* [in] The value to update +* +* RETURN VALUES +* 0 on success +* +* NOTE: the value will be duplicated so can be free'ed +* +* SEE ALSO +* Database, osm_db_domain_init, osm_db_restore, osm_db_clear, osm_db_store, +* osm_db_keys, osm_db_lookup, osm_db_delete +*********/ + +/****f* OpenSM: Database/osm_db_delete +* NAME +* osm_db_delete +* +* DESCRIPTION +* Delete an entry by the given key +* +* SYNOPSIS +*/ +int +osm_db_delete( + IN osm_db_domain_t *p_domain, + IN char *const p_key); +/* +* PARAMETERS +* +* p_domain +* [in] Pointer to the database domain object +* +* p_key +* [in] The key to look for +* +* RETURN VALUES +* 0 on success +* +* SEE ALSO +* Database, osm_db_domain_init, osm_db_restore, osm_db_clear, osm_db_store, +* osm_db_keys, osm_db_lookup, osm_db_update +*********/ + +END_C_DECLS + +#endif /* _OSM_DB_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_db_pack.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_db_pack.h new file mode 100644 index 00000000..5074273b --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_db_pack.h @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_db_pack.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/****h* OpenSM/DB-Pack +* NAME +* Database Types +* +* DESCRIPTION +* This module provides packing and unpacking of the database +* storage into specific types. +* +* The following domains/conversions are supported: +* guid2lid - key is a guid and data is a lid. +* +* AUTHOR +* Eitan Zahavi, Mellanox Technologies LTD +* +*********/ + +#ifndef _OSM_DB_PACK_H_ +#define _OSM_DB_PACK_H_ + +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****f* OpenSM: DB-Pack/osm_db_guid2lid_init +* NAME +* osm_db_guid2lid_init +* +* DESCRIPTION +* Initialize a domain for the guid2lid table +* +* SYNOPSIS +*/ +static inline osm_db_domain_t* +osm_db_guid2lid_init( + IN osm_db_t* const p_db ) +{ + return( osm_db_domain_init( p_db, "guid2lid" ) ); +} +/* +* PARAMETERS +* p_db +* [in] Pointer to the database object to construct +* +* RETURN VALUES +* The pointer to the new allocated domain object or NULL. +* +* NOTE: DB domains are destroyed by the osm_db_destroy +* +* SEE ALSO +* Database, osm_db_init, osm_db_destroy +*********/ + +/****f* OpenSM: DB-Pack/osm_db_guid2lid_init +* NAME +* osm_db_guid2lid_init +* +* DESCRIPTION +* Initialize a domain for the guid2lid table +* +* SYNOPSIS +*/ +typedef struct _osm_db_guid_elem { + cl_list_item_t item; + uint64_t guid; +} osm_db_guid_elem_t; +/* +* FIELDS +* item +* required for list manipulations +* +* guid +* +************/ + +/****f* OpenSM: DB-Pack/osm_db_guid2lid_guids +* NAME +* osm_db_guid2lid_guids +* +* DESCRIPTION +* Provides back a list of guid elements. +* +* SYNOPSIS +*/ +int +osm_db_guid2lid_guids( + IN osm_db_domain_t* const p_g2l, + OUT cl_qlist_t* p_guid_list ); +/* +* PARAMETERS +* p_g2l +* [in] Pointer to the guid2lid domain +* +* p_guid_list +* [out] A quick list of guid elements of type osm_db_guid_elem_t +* +* RETURN VALUES +* 0 if successful +* +* NOTE: the output qlist should be initialized and each item freed +* by the caller, then destroyed. +* +* SEE ALSO +* osm_db_guid2lid_init, osm_db_guid2lid_guids, osm_db_guid2lid_get +* osm_db_guid2lid_set, osm_db_guid2lid_delete +*********/ + +/****f* OpenSM: DB-Pack/osm_db_guid2lid_get +* NAME +* osm_db_guid2lid_get +* +* DESCRIPTION +* Get a lid range by given guid. +* +* SYNOPSIS +*/ +int +osm_db_guid2lid_get( + IN osm_db_domain_t* const p_g2l, + IN uint64_t guid, + OUT uint16_t *p_min_lid, + OUT uint16_t *p_max_lid); +/* +* PARAMETERS +* p_g2l +* [in] Pointer to the guid2lid domain +* +* guid +* [in] The guid to look for +* +* p_min_lid +* [out] Pointer to the resulting min lid in host order. +* +* p_max_lid +* [out] Pointer to the resulting max lid in host order. +* +* RETURN VALUES +* 0 if successful. The lid will be set to 0 if not found. +* +* SEE ALSO +* osm_db_guid2lid_init, osm_db_guid2lid_guids +* osm_db_guid2lid_set, osm_db_guid2lid_delete +*********/ + +/****f* OpenSM: DB-Pack/osm_db_guid2lid_set +* NAME +* osm_db_guid2lid_set +* +* DESCRIPTION +* Set a lid range for the given guid. +* +* SYNOPSIS +*/ +int +osm_db_guid2lid_set( + IN osm_db_domain_t* const p_g2l, + IN uint64_t guid, + IN uint16_t min_lid, + IN uint16_t max_lid); +/* +* PARAMETERS +* p_g2l +* [in] Pointer to the guid2lid domain +* +* guid +* [in] The guid to look for +* +* min_lid +* [in] The min lid value to set +* +* max_lid +* [in] The max lid value to set +* +* RETURN VALUES +* 0 if successful +* +* SEE ALSO +* osm_db_guid2lid_init, osm_db_guid2lid_guids +* osm_db_guid2lid_get, osm_db_guid2lid_delete +*********/ + +/****f* OpenSM: DB-Pack/osm_db_guid2lid_delete +* NAME +* osm_db_guid2lid_delete +* +* DESCRIPTION +* Delete the entry by the given guid +* +* SYNOPSIS +*/ +int +osm_db_guid2lid_delete( + IN osm_db_domain_t* const p_g2l, + IN uint64_t guid ); +/* +* PARAMETERS +* p_g2l +* [in] Pointer to the guid2lid domain +* +* guid +* [in] The guid to look for +* +* RETURN VALUES +* 0 if successful otherwise 1 +* +* SEE ALSO +* osm_db_guid2lid_init, osm_db_guid2lid_guids +* osm_db_guid2lid_get, osm_db_guid2lid_set +*********/ + +END_C_DECLS + +#endif /* _OSM_DB_PACK_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_drop_mgr.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_drop_mgr.h new file mode 100644 index 00000000..48c6acea --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_drop_mgr.h @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_drop_mgr.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_drop_mgr_t. + * This object represents the Drop Manager object. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_DROP_MGR_H_ +#define _OSM_DROP_MGR_H_ + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Drop Manager +* NAME +* Drop Manager +* +* DESCRIPTION +* The Drop Manager object encapsulates the information +* needed to receive the SwitchInfo attribute from a node. +* +* The Drop Manager object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: Drop Manager/osm_drop_mgr_t +* NAME +* osm_drop_mgr_t +* +* DESCRIPTION +* Drop Manager structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_drop_mgr +{ + osm_subn_t *p_subn; + osm_log_t *p_log; + osm_req_t *p_req; + cl_plock_t *p_lock; + +} osm_drop_mgr_t; +/* +* FIELDS +* p_subn +* Pointer to the Subnet object for this subnet. +* +* p_log +* Pointer to the log object. +* +* p_req +* Pointer to the Request object. +* +* p_lock +* Pointer to the serializing lock. +* +* SEE ALSO +* Drop Manager object +*********/ + +/****f* OpenSM: Drop Manager/osm_drop_mgr_construct +* NAME +* osm_drop_mgr_construct +* +* DESCRIPTION +* This function constructs a Drop Manager object. +* +* SYNOPSIS +*/ +void osm_drop_mgr_construct( + IN osm_drop_mgr_t* const p_mgr ); +/* +* PARAMETERS +* p_mgr +* [in] Pointer to a Drop Manager object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_drop_mgr_init, osm_drop_mgr_destroy +* +* Calling osm_drop_mgr_construct is a prerequisite to calling any other +* method except osm_drop_mgr_init. +* +* SEE ALSO +* Drop Manager object, osm_drop_mgr_init, +* osm_drop_mgr_destroy +*********/ + +/****f* OpenSM: Drop Manager/osm_drop_mgr_destroy +* NAME +* osm_drop_mgr_destroy +* +* DESCRIPTION +* The osm_drop_mgr_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_drop_mgr_destroy( + IN osm_drop_mgr_t* const p_mgr ); +/* +* PARAMETERS +* p_mgr +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* Drop Manager object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_drop_mgr_construct or osm_drop_mgr_init. +* +* SEE ALSO +* Drop Manager object, osm_drop_mgr_construct, +* osm_drop_mgr_init +*********/ + +/****f* OpenSM: Drop Manager/osm_drop_mgr_init +* NAME +* osm_drop_mgr_init +* +* DESCRIPTION +* The osm_drop_mgr_init function initializes a +* Drop Manager object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_drop_mgr_init( + IN osm_drop_mgr_t* const p_mgr, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN osm_req_t* const p_req, + IN cl_plock_t* const p_lock ); +/* +* PARAMETERS +* p_mgr +* [in] Pointer to an osm_drop_mgr_t object to initialize. +* +* p_subn +* [in] Pointer to the Subnet object for this subnet. +* +* p_log +* [in] Pointer to the log object. +* +* p_req +* [in] Pointer to an osm_req_t object. +* +* p_lock +* [in] Pointer to the OpenSM serializing lock. +* +* RETURN VALUES +* IB_SUCCESS if the Drop Manager object was initialized +* successfully. +* +* NOTES +* Allows calling other Drop Manager methods. +* +* SEE ALSO +* Drop Manager object, osm_drop_mgr_construct, +* osm_drop_mgr_destroy +*********/ + +/****f* OpenSM: Drop Manager/osm_drop_mgr_process +* NAME +* osm_drop_mgr_process +* +* DESCRIPTION +* Process the SwitchInfo attribute. +* +* SYNOPSIS +*/ +void osm_drop_mgr_process( + IN const osm_drop_mgr_t* const p_mgr ); +/* +* PARAMETERS +* p_mgr +* [in] Pointer to an osm_drop_mgr_t object. +* +* RETURN VALUES +* None +* +* NOTES +* This function processes a SwitchInfo attribute. +* +* SEE ALSO +* Drop Manager, Switch Info Response Controller +*********/ + +END_C_DECLS + +#endif /* _OSM_DROP_MGR_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_errors.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_errors.h new file mode 100644 index 00000000..d323cdf6 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_errors.h @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_errors.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of error code ranges for the various OpenSM modules. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_ERRORS_H_ +#define _OSM_ERRORS_H_ + +/* + Generic Request Controller + 0100 - 01FF + + Node Info Receive Controller + 0200 - 02FF + + Generic Requester + 0300 - 03FF + + Node Info Receiver + 0400 - 04FF + + Node Description Receiver + 0500 - 05FF + + Node Description Receive Controller + 0600 - 06FF + + Port Info Receiver + 0700 - 07FF + + Port Info Receive Controller + 0800 - 08FF + + Mad Pool + 0900 - 09FF + + SM + 1000 - 10FF + + SM MAD Controller + 1100 - 11FF + + VL15 Interface + 1200 - 12FF + + Switch Info Receive Controller + 1300 - 13FF + + Switch Info Receiver + 1400 - 14FF + + State Manager + 1500 - 15FF + + State Manager Controller + 1600 - 16FF + + LID Manager + 1700 - 17FF + + Link Manager + 1800 - 18FF + + Drop Manager + 1900 - 19FF + + Linear Forwarding Receive Controller + 2000 - 20FF + + Linear Forwarding Receiver + 2100 - 21FF + + Vendor Specific + 2200 - 22FF + + SMInfo Receive Controller + 2300 - 23FF + + SMInfo Info Receiver + 2400 - 24FF + + Generic Responder + 2500 - 25FF + + Linear Forwarding Receive Controller + 2600 - 26FF + + Linear Forwarding Receiver + 2700 - 27FF + + SA MAD controller + 2800 - 28FF + + Node Record Controller + 2900 - 29FF + + PortInfo Record Controller + 3000 - 30FF + + Link Record Controller + 3100 - 31FF + + Path Record Controller + 3200 - 32FF + + SMInfo Record Controller + 3300 - 33FF + + Multicast Record Controller + 3400 - 34FF + + Unicast Manager + 3500 - 35FF + + Multicast Manager + 3600 - 36FF + + SA Response + 3700 - 37FF + + Link Record Receiver + 3800 - 38FF + + Multicast Forwarding Receive Controller + 3900 - 39FF + + Multicast Forwarding Receiver + 4000 - 40FF + + SMInfo Record Receiver + 4100 - 41FF + + PortInfo Record Receiver + 4200 - 42FF + + Service Record Receiver + 4300 - 43FF + +*/ + +#endif /* _OSM_ERRORS_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_fwd_tbl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_fwd_tbl.h new file mode 100644 index 00000000..7b05384f --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_fwd_tbl.h @@ -0,0 +1,388 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_fwd_tbl.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_fwd_tbl_t. + * This object represents a unicast forwarding table. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_FWD_TBL_H_ +#define _OSM_FWD_TBL_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Forwarding Table +* NAME +* Forwarding Table +* +* DESCRIPTION +* The Forwarding Table objects encapsulate the information +* needed by the OpenSM to manage forwarding tables. The OpenSM +* allocates one Forwarding Table object per switch in the +* IBA subnet. +* +* The Forwarding Table objects are not thread safe, thus +* callers must provide serialization. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: Forwarding Table/osm_fwd_tbl_t +* NAME +* osm_fwd_tbl_t +* +* DESCRIPTION +* Forwarding Table structure. This object hides the type +* of fowarding table (linear or random) actually used by +* the switch. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_fwd_tbl_t +{ + osm_rand_fwd_tbl_t *p_rnd_tbl; + osm_lin_fwd_tbl_t *p_lin_tbl; + +} osm_fwd_tbl_t; +/* +* FIELDS +* p_rnd_tbl +* Pointer to the switch's Random Forwarding Table object. +* If the switch does not use a Random Forwarding Table, +* then this pointer is NULL. +* +* p_lin_tbl +* Pointer to the switch's Linear Forwarding Table object. +* If the switch does not use a Linear Forwarding Table, +* then this pointer is NULL. +* +* SEE ALSO +* Forwarding Table object, Random Forwarding Table object. +*********/ + +/****f* OpenSM: Forwarding Table/osm_fwd_tbl_init +* NAME +* osm_fwd_tbl_init +* +* DESCRIPTION +* Initializes a Forwarding Table object. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_fwd_tbl_init( + IN osm_fwd_tbl_t* const p_tbl, + IN const ib_switch_info_t* const p_si ); +/* +* PARAMETERS +* p_tbl +* [in] Pointer to the Forwarding Table object. +* +* p_si +* [in] Pointer to the SwitchInfo attribute of the associated +* switch. +* +* RETURN VALUE +* IB_SUCCESS if the operation is successful. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Forwarding Table/osm_fwd_tbl_destroy +* NAME +* osm_fwd_tbl_destroy +* +* DESCRIPTION +* Destroys a Forwarding Table object. +* +* SYNOPSIS +*/ +void +osm_fwd_tbl_destroy( + IN osm_fwd_tbl_t* const p_tbl ); +/* +* PARAMETERS +* p_tbl +* [in] Pointer to the Forwarding Table object. +* +* RETURN VALUE +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Forwarding Table/osm_fwd_tbl_get +* NAME +* osm_fwd_tbl_get +* +* DESCRIPTION +* Returns the port that routes the specified LID. +* +* SYNOPSIS +*/ +static inline uint8_t +osm_fwd_tbl_get( + IN const osm_fwd_tbl_t* const p_tbl, + IN uint16_t const lid_ho ) +{ + if( p_tbl->p_lin_tbl ) + return( osm_lin_fwd_tbl_get( p_tbl->p_lin_tbl, lid_ho ) ); + else + return( osm_rand_fwd_tbl_get( p_tbl->p_rnd_tbl, lid_ho ) ); +} +/* +* PARAMETERS +* p_tbl +* [in] Pointer to the Forwarding Table object. +* +* lid_ho +* [in] LID (host order) for which to find the route. +* +* RETURN VALUE +* Returns the port that routes the specified LID. +* IB_INVALID_PORT_NUM if the table does not have a route for this LID. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Forwarding Table/osm_fwd_tbl_set +* NAME +* osm_fwd_tbl_set +* +* DESCRIPTION +* Sets the port to route the specified LID. +* +* SYNOPSIS +*/ +static inline void +osm_fwd_tbl_set( + IN osm_fwd_tbl_t* const p_tbl, + IN const uint16_t lid_ho, + IN const uint8_t port ) +{ + CL_ASSERT( p_tbl ); + if( p_tbl->p_lin_tbl ) + osm_lin_fwd_tbl_set( p_tbl->p_lin_tbl, lid_ho, port ); + else + osm_rand_fwd_tbl_set( p_tbl->p_rnd_tbl, lid_ho, port ); +} +/* +* PARAMETERS +* p_tbl +* [in] Pointer to the Forwarding Table object. +* +* lid_ho +* [in] LID value (host order) for which to set the route. +* +* port +* [in] Port to route the specified LID value. +* +* RETURN VALUE +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Forwarding Table/osm_fwd_tbl_set_block +* NAME +* osm_fwd_tbl_set_block +* +* DESCRIPTION +* Copies the specified block into the Forwarding Table. +* +* SYNOPSIS +*/ +static inline ib_api_status_t +osm_fwd_tbl_set_block( + IN osm_fwd_tbl_t* const p_tbl, + IN const uint8_t* const p_block, + IN const uint32_t block_num ) +{ + CL_ASSERT( p_tbl ); + if( p_tbl->p_lin_tbl ) + return( osm_lin_fwd_tbl_set_block( p_tbl->p_lin_tbl, + p_block, block_num ) ); + else + return( osm_rand_fwd_tbl_set_block( p_tbl->p_rnd_tbl, + p_block, block_num ) ); +} +/* +* PARAMETERS +* p_tbl +* [in] Pointer to the Forwarding Table object. +* +* RETURN VALUE +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Forwarding Table/osm_fwd_tbl_get_size +* NAME +* osm_fwd_tbl_get_size +* +* DESCRIPTION +* Returns the number of entries available in the forwarding table. +* +* SYNOPSIS +*/ +static inline uint16_t +osm_fwd_tbl_get_size( + IN const osm_fwd_tbl_t* const p_tbl ) +{ + CL_ASSERT( p_tbl ); + if( p_tbl->p_lin_tbl ) + return( osm_lin_fwd_tbl_get_size( p_tbl->p_lin_tbl ) ); + else + return( osm_rand_fwd_tbl_get_size( p_tbl->p_rnd_tbl ) ); +} +/* +* PARAMETERS +* p_tbl +* [in] Pointer to the Forwarding Table object. +* +* RETURN VALUE +* Returns the number of entries available in the forwarding table. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Forwarding Table/osm_fwd_tbl_get_lids_per_block +* NAME +* osm_fwd_tbl_get_lids_per_block +* +* DESCRIPTION +* Returns the number of LIDs per LID block. +* +* SYNOPSIS +*/ +static inline uint16_t +osm_fwd_tbl_get_lids_per_block( + IN const osm_fwd_tbl_t* const p_tbl ) +{ + CL_ASSERT( p_tbl ); + if( p_tbl->p_lin_tbl ) + return( osm_lin_fwd_tbl_get_lids_per_block( p_tbl->p_lin_tbl ) ); + else + return( osm_rand_fwd_tbl_get_lids_per_block( p_tbl->p_rnd_tbl ) ); +} +/* +* PARAMETERS +* p_tbl +* [in] Pointer to the Forwarding Table object. +* +* RETURN VALUE +* Returns the number of LIDs per LID block. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Forwarding Table/osm_fwd_tbl_get_max_block_id_in_use +* NAME +* osm_fwd_tbl_get_max_block_id_in_use +* +* DESCRIPTION +* Returns the number of LIDs per LID block. +* +* SYNOPSIS +*/ +static inline uint16_t +osm_fwd_tbl_get_max_block_id_in_use( + IN const osm_fwd_tbl_t* const p_tbl, + IN const uint16_t lid_top_ho ) +{ + CL_ASSERT( p_tbl ); + if( p_tbl->p_lin_tbl ) + return( osm_lin_fwd_tbl_get_max_block_id_in_use( + p_tbl->p_lin_tbl, lid_top_ho ) ); + else + return( osm_rand_fwd_tbl_get_max_block_id_in_use( + p_tbl->p_rnd_tbl, lid_top_ho ) ); +} +/* +* PARAMETERS +* p_tbl +* [in] Pointer to the Forwarding Table object. +* +* RETURN VALUE +* Returns the number of LIDs per LID block. +* +* NOTES +* +* SEE ALSO +*********/ + +END_C_DECLS + +#endif /* _OSM_FWD_TBL_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_helper.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_helper.h new file mode 100644 index 00000000..90931bb1 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_helper.h @@ -0,0 +1,620 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_helper.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +#ifndef _OSM_HELPER_H_ +#define _OSM_HELPER_H_ + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/* + * Abstract: + * Declaration of helpful functions. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.7 $ + */ + +/****f* OpenSM: Helper/ib_get_sa_method_str + * NAME + * ib_get_sa_method_str + * + * DESCRIPTION + * Returns a string for the specified SA Method value. + * + * SYNOPSIS + */ +const char* +ib_get_sa_method_str( + IN uint8_t method ); +/* + * PARAMETERS + * method + * [in] Network order METHOD ID value. + * + * RETURN VALUES + * Pointer to the method string. + * + * NOTES + * + * SEE ALSO + *********/ + +/****f* OpenSM: Helper/ib_get_sm_method_str +* NAME +* ib_get_sm_method_str +* +* DESCRIPTION +* Returns a string for the specified SM Method value. +* +* SYNOPSIS +*/ +const char* +ib_get_sm_method_str( + IN uint8_t method ); +/* +* PARAMETERS +* method +* [in] Network order METHOD ID value. +* +* RETURN VALUES +* Pointer to the method string. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Helper/ib_get_sm_attr_str +* NAME +* ib_get_sm_attr_str +* +* DESCRIPTION +* Returns a string for the specified SM attribute value. +* +* SYNOPSIS +*/ +const char* +ib_get_sm_attr_str( + IN ib_net16_t attr ); +/* +* PARAMETERS +* attr +* [in] Network order attribute ID value. +* +* RETURN VALUES +* Pointer to the attribute string. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Helper/ib_get_sa_attr_str +* NAME +* ib_get_sa_attr_str +* +* DESCRIPTION +* Returns a string for the specified SA attribute value. +* +* SYNOPSIS +*/ +const char* +ib_get_sa_attr_str( + IN ib_net16_t attr ); +/* +* PARAMETERS +* attr +* [in] Network order attribute ID value. +* +* RETURN VALUES +* Pointer to the attribute string. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Helper/osm_dump_port_info +* NAME +* osm_dump_port_info +* +* DESCRIPTION +* Dumps the PortInfo attribute to the log. +* +* SYNOPSIS +*/ +void osm_dump_port_info( + IN osm_log_t* const p_log, + IN const ib_net64_t node_guid, + IN const ib_net64_t port_guid, + IN const uint8_t port_num, + IN const ib_port_info_t* const p_pi, + IN const osm_log_level_t log_level ); +/* +* PARAMETERS +* p_log +* [in] Pointer to the osm_log_t object +* +* node_guid +* [in] Node GUID that owns this port. +* +* port_guid +* [in] Port GUID for this port. +* +* port_num +* [in] Port number for this port. +* +* p_pi +* [in] Pointer to the PortInfo attribute +* +* log_level +* [in] Log verbosity level with which to dump the data. +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +void +osm_dump_path_record( + IN osm_log_t* const p_log, + IN const ib_path_rec_t* const p_pr, + IN const osm_log_level_t log_level ); + +void +osm_dump_multipath_record( + IN osm_log_t* const p_log, + IN const ib_multipath_rec_t* const p_mpr, + IN const osm_log_level_t log_level ); + +void +osm_dump_node_record( + IN osm_log_t* const p_log, + IN const ib_node_record_t* const p_nr, + IN const osm_log_level_t log_level ); + +void +osm_dump_mc_record( + IN osm_log_t* const p_log, + IN const ib_member_rec_t* const p_mcmr, + IN const osm_log_level_t log_level ); + +void +osm_dump_link_record( + IN osm_log_t* const p_log, + IN const ib_link_record_t* const p_lr, + IN const osm_log_level_t log_level ); + +void +osm_dump_service_record( + IN osm_log_t* const p_log, + IN const ib_service_record_t* const p_sr, + IN const osm_log_level_t log_level ); + +void +osm_dump_portinfo_record( + IN osm_log_t* const p_log, + IN const ib_portinfo_record_t* const p_pir, + IN const osm_log_level_t log_level ); + +void +osm_dump_guidinfo_record( + IN osm_log_t* const p_log, + IN const ib_guidinfo_record_t* const p_gir, + IN const osm_log_level_t log_level ); + +void +osm_dump_inform_info( + IN osm_log_t* const p_log, + IN const ib_inform_info_t* const p_ii, + IN const osm_log_level_t log_level ); + +void +osm_dump_inform_info_record( + IN osm_log_t* const p_log, + IN const ib_inform_info_record_t* const p_iir, + IN const osm_log_level_t log_level ); + +void +osm_dump_switch_info_record( + IN osm_log_t* const p_log, + IN const ib_switch_info_record_t* const p_sir, + IN const osm_log_level_t log_level ); + +void +osm_dump_sm_info_record( + IN osm_log_t* const p_log, + IN const ib_sminfo_record_t* const p_smir, + IN const osm_log_level_t log_level ); + +void +osm_dump_pkey_block( + IN osm_log_t* const p_log, + IN uint64_t port_guid, + IN uint16_t block_num, + IN uint8_t port_num, + IN const ib_pkey_table_t* const p_pkey_tbl, + IN const osm_log_level_t log_level ); + +void +osm_dump_slvl_map_table( + IN osm_log_t* const p_log, + IN uint64_t port_guid, + IN uint8_t in_port_num, + IN uint8_t out_port_num, + IN const ib_slvl_table_t* const p_slvl_tbl, + IN const osm_log_level_t log_level ); + +void +osm_dump_vl_arb_table( + IN osm_log_t* const p_log, + IN uint64_t port_guid, + IN uint8_t block_num, + IN uint8_t port_num, + IN const ib_vl_arb_table_t* const p_vla_tbl, + IN const osm_log_level_t log_level ); + +/****f* OpenSM: Helper/osm_dump_port_info +* NAME +* osm_dump_port_info +* +* DESCRIPTION +* Dumps the PortInfo attribute to the log. +* +* SYNOPSIS +*/ +void osm_dump_node_info( + IN osm_log_t* const p_log, + IN const ib_node_info_t* const p_ni, + IN const osm_log_level_t log_level ); +/* +* PARAMETERS +* p_log +* [in] Pointer to the osm_log_t object +* +* p_ni +* [in] Pointer to the NodeInfo attribute +* +* log_level +* [in] Log verbosity level with which to dump the data. +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Helper/osm_dump_sm_info +* NAME +* osm_dump_sm_info +* +* DESCRIPTION +* Dumps the SMInfo attribute to the log. +* +* SYNOPSIS +*/ +void +osm_dump_sm_info( + IN osm_log_t* const p_log, + IN const ib_sm_info_t* const p_smi, + IN const osm_log_level_t log_level ); +/* +* PARAMETERS +* p_log +* [in] Pointer to the osm_log_t object +* +* p_smi +* [in] Pointer to the SMInfo attribute +* +* log_level +* [in] Log verbosity level with which to dump the data. +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Helper/osm_dump_switch_info +* NAME +* osm_dump_switch_info +* +* DESCRIPTION +* Dumps the SwitchInfo attribute to the log. +* +* SYNOPSIS +*/ +void +osm_dump_switch_info( + IN osm_log_t* const p_log, + IN const ib_switch_info_t* const p_si, + IN const osm_log_level_t log_level ); +/* +* PARAMETERS +* p_log +* [in] Pointer to the osm_log_t object +* +* p_si +* [in] Pointer to the SwitchInfo attribute +* +* log_level +* [in] Log verbosity level with which to dump the data. +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Helper/osm_dump_notice +* NAME +* osm_dump_notice +* +* DESCRIPTION +* Dumps the Notice attribute to the log. +* +* SYNOPSIS +*/ +void +osm_dump_notice( + IN osm_log_t* const p_log, + IN const ib_mad_notice_attr_t *p_ntci, + IN const osm_log_level_t log_level ); +/* +* PARAMETERS +* p_log +* [in] Pointer to the osm_log_t object +* +* p_ntci +* [in] Pointer to the Notice attribute +* +* log_level +* [in] Log verbosity level with which to dump the data. +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* IBA Base: Types/osm_get_disp_msg_str +* NAME +* osm_get_disp_msg_str +* +* DESCRIPTION +* Returns a string for the specified Dispatcher message. +* +* SYNOPSIS +*/ +const char* +osm_get_disp_msg_str( + IN cl_disp_msgid_t msg ); +/* +* PARAMETERS +* msg +* [in] Dispatcher message ID value. +* +* RETURN VALUES +* Pointer to the message discription string. +* +* NOTES +* +* SEE ALSO +*********/ + +void osm_dump_dr_path( + IN osm_log_t* const p_log, + IN const osm_dr_path_t* const p_path, + IN const osm_log_level_t level ); + +void osm_dump_smp_dr_path( + IN osm_log_t* const p_log, + IN const ib_smp_t* const p_smp, + IN const osm_log_level_t level ); + +void osm_dump_dr_smp( + IN osm_log_t* const p_log, + IN const ib_smp_t* const p_smp, + IN const osm_log_level_t level ); + +void osm_dump_sa_mad( + IN osm_log_t* const p_log, + IN const ib_sa_mad_t* const p_smp, + IN const osm_log_level_t level ); + +/****f* IBA Base: Types/osm_get_sm_state_str +* NAME +* osm_get_sm_state_str +* +* DESCRIPTION +* Returns a string for the specified SM state. +* +* SYNOPSIS +*/ +const char* +osm_get_sm_state_str( + IN osm_sm_state_t state ); +/* +* PARAMETERS +* state +* [in] SM State value +* +* RETURN VALUES +* Pointer to the state discription string. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* IBA Base: Types/osm_get_sm_signal_str +* NAME +* osm_get_sm_signal_str +* +* DESCRIPTION +* Returns a string for the specified SM state. +* +* SYNOPSIS +*/ +const char* +osm_get_sm_signal_str( + IN osm_signal_t signal ); +/* +* PARAMETERS +* state +* [in] Signal value +* +* RETURN VALUES +* Pointer to the signal discription string. +* +* NOTES +* +* SEE ALSO +*********/ + +const char* +osm_get_port_state_str_fixed_width( + IN uint8_t port_state ); + +const char* +osm_get_node_type_str_fixed_width( + IN uint32_t node_type ); + +const char* +osm_get_manufacturer_str( + IN uint64_t const guid_ho ); + +const char* +osm_get_mtu_str( + IN uint8_t const mtu ); + +const char* +osm_get_lwa_str( + IN uint8_t const lwa ); + +const char* +osm_get_mtu_str( + IN uint8_t const mtu ); + +const char* +osm_get_lwa_str( + IN uint8_t const lwa ); + +const char* +osm_get_lsa_str( + IN uint8_t const lsa ); + + +/****f* IBA Base: Types/osm_get_sm_mgr_signal_str +* NAME +* osm_get_sm_mgr_signal_str +* +* DESCRIPTION +* Returns a string for the specified SM manager signal. +* +* SYNOPSIS +*/ +const char* +osm_get_sm_mgr_signal_str( + IN osm_sm_signal_t signal ); +/* +* PARAMETERS +* signal +* [in] SM manager signal +* +* RETURN VALUES +* Pointer to the signal discription string. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* IBA Base: Types/osm_get_sm_mgr_state_str +* NAME +* osm_get_sm_mgr_state_str +* +* DESCRIPTION +* Returns a string for the specified SM manager state. +* +* SYNOPSIS +*/ +const char* +osm_get_sm_mgr_state_str( + IN uint16_t state ); +/* +* PARAMETERS +* state +* [in] SM manager state +* +* RETURN VALUES +* Pointer to the state discription string. +* +* NOTES +* +* SEE ALSO +*********/ + +END_C_DECLS + +#endif /* _OSM_HELPER_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_inform.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_inform.h new file mode 100644 index 00000000..e0d53584 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_inform.h @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_inform.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_inform_rec_t. + * This object represents an IBA Inform Record. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * Author: + * Eitan Zahavi, Mellanox + * + * $Revision: 1.5 $ + */ + +#ifndef _OSM_INFR_H_ +#define _OSM_INFR_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Inform Record +* NAME +* Inform Record +* +* DESCRIPTION +* The Inform record encapsulates the information needed by the +* SA to manage InformInfo registrations and sending Reports(Notice) +* when SM receives Traps for registered LIDs. +* +* The inform records is not thread safe, thus callers must provide +* serialization. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Eitan Zahavi, Mellanox +* +*********/ + +/****s* OpenSM: Inform Record/osm_infr_t +* NAME +* osm_infr_t +* +* DESCRIPTION +* Inform Record structure. +* +* The osm_infr_t object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_infr_t +{ + cl_list_item_t list_item; + osm_bind_handle_t h_bind; + osm_infr_rcv_t* p_infr_rcv; + osm_mad_addr_t report_addr; + ib_inform_info_record_t inform_record; +} osm_infr_t; +/* +* FIELDS +* list_item +* List Item for qlist linkage. Must be first element!! +* +* h_bind +* A handle of lower level mad srvc +* +* p_infr_rcv +* The receiver of inform_info's +* +* report_addr +* Report address +* +* inform_record +* The Inform Info Record +* +* SEE ALSO +*********/ + +/****f* OpenSM: Inform Record/osm_infr_new +* NAME +* osm_infr_new +* +* DESCRIPTION +* Allocates and initializes a Inform Record for use. +* +* SYNOPSIS +*/ +osm_infr_t* +osm_infr_new( + IN const osm_infr_t *p_infr_rec ); +/* +* PARAMETERS +* p_inf_rec +* [in] Pointer to IB Inform Record +* +* RETURN VALUES +* pointer to osm_infr_t structure. +* +* NOTES +* Allows calling other service record methods. +* +* SEE ALSO +* Inform Record, osm_infr_construct, osm_infr_destroy +*********/ + +/****f* OpenSM: Inform Record/osm_infr_init +* NAME +* osm_infr_new +* +* DESCRIPTION +* Initializes the osm_infr_t structure. +* +* SYNOPSIS +*/ +void +osm_infr_init( + IN osm_infr_t* const p_infr, + IN const osm_infr_t *p_infr_rec ); +/* +* PARAMETERS +* p_infr +* [in] Pointer to osm_infr_t structure +* p_inf_rec +* [in] Pointer to the ib_inform_info_record_t +* +* SEE ALSO +* Inform Record, osm_infr_construct, osm_infr_destroy +*********/ + +/****f* OpenSM: Inform Record/osm_infr_construct +* NAME +* osm_infr_construct +* +* DESCRIPTION +* Constructs the osm_infr_t structure. +* +* SYNOPSIS +*/ +void +osm_infr_construct( + IN osm_infr_t* const p_infr ); +/* +* PARAMETERS +* p_infr +* [in] Pointer to osm_infr_t structure +* +* SEE ALSO +* Inform Record, osm_infr_construct, osm_infr_destroy +*********/ + +/****f* OpenSM: Inform Record/osm_infr_destroy +* NAME +* osm_infr_destroy +* +* DESCRIPTION +* Constructs the osm_infr_t structure. +* +* SYNOPSIS +*/ +void +osm_infr_destroy( + IN osm_infr_t* const p_infr ); +/* +* PARAMETERS +* p_infr +* [in] Pointer to osm_infr_t structure +* +* SEE ALSO +* Inform Record, osm_infr_construct, osm_infr_destroy +*********/ + +/****f* OpenSM: Inform Record/osm_infr_get_by_rec +* NAME +* osm_infr_get_by_rec +* +* DESCRIPTION +* Find a matching osm_infr_t in the subnet DB by inform_info_record +* +* SYNOPSIS +*/ +osm_infr_t* +osm_infr_get_by_rec( + IN osm_subn_t const *p_subn, + IN osm_log_t *p_log, + IN osm_infr_t* const p_infr_rec ); +/* +* PARAMETERS +* p_subn +* [in] Pointer to the subnet object +* +* p_log +* [in] Pointer to the log object +* +* p_inf_rec +* [in] Pointer to an inform_info record +* +* RETURN +* The matching osm_infr_t +* SEE ALSO +* Inform Record, osm_infr_construct, osm_infr_destroy +*********/ + +void +osm_infr_insert_to_db( + IN osm_subn_t *p_subn, + IN osm_log_t *p_log, + IN osm_infr_t *p_infr); + +void +osm_infr_remove_from_db( + IN osm_subn_t *p_subn, + IN osm_log_t *p_log, + IN osm_infr_t *p_infr); + +/****f* OpenSM: Inform Record/osm_report_notice +* NAME +* osm_report_notice +* +* DESCRIPTION +* Once a Trap was received by the osm_trap_rcv, or a Trap sourced in +* the SM was sent (Traps 64-67) this routine is called with a copy of +* the notice data. +* Given a notice attribute - compare and see if it matches the InformInfo +* Element and if it does - call the Report(Notice) for the +* target QP registered by the address stored in the InformInfo element +* +* SYNOPSIS +*/ +ib_api_status_t +osm_report_notice( + IN osm_log_t* const p_log, + IN osm_subn_t* p_subn, + IN ib_mad_notice_attr_t* p_ntc ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to the trap receiver +* +* p_ntc +* [in] Pointer to a copy of the incoming trap notice attribute. +* +* RETURN +* IB_SUCCESS on good completion +* +* SEE ALSO +* Inform Record, osm_trap_rcv +*********/ + +END_C_DECLS + +#endif /* _OSM_INFR_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_lid_mgr.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_lid_mgr.h new file mode 100644 index 00000000..4a2a99a5 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_lid_mgr.h @@ -0,0 +1,322 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_lid_mgr.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_lid_mgr_t. + * This object represents the LID Manager object. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_LID_MGR_H_ +#define _OSM_LID_MGR_H_ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +#define OSM_LID_MGR_LIST_SIZE_MIN 256 + +/****h* OpenSM/LID Manager +* NAME +* LID Manager +* +* DESCRIPTION +* The LID Manager object encapsulates the information +* needed to control LID assignments on the subnet. +* +* The LID Manager object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: LID Manager/osm_lid_mgr_t +* NAME +* osm_lid_mgr_t +* +* DESCRIPTION +* LID Manager structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_lid_mgr +{ + osm_subn_t *p_subn; + osm_db_t *p_db; + osm_req_t *p_req; + osm_log_t *p_log; + cl_plock_t *p_lock; + boolean_t send_set_reqs; + osm_db_domain_t *p_g2l; + cl_ptr_vector_t used_lids; + cl_qlist_t free_ranges; +} osm_lid_mgr_t; +/* +* FIELDS +* p_subn +* Pointer to the Subnet object for this subnet. +* +* p_db +* Pointer to the database (persistency) object +* +* p_req +* Pointer to the Requester object sending SMPs. +* +* p_log +* Pointer to the log object. +* +* p_lock +* Pointer to the serializing lock. +* +* p_g2l +* Pointer to the database domain storing guid to lid mapping. +* +* used_lids +* A vector the maps from the lid to its guid. keeps track of +* existing and non existing mapping of guid->lid +* +* free_ranges +* A list of available free lid ranges. The list is initialized +* by the code that initializes the lid assignment and is consumed +* by the procedure that finds a free range. It holds elements of +* type osm_lid_mgr_range_t +* +* SEE ALSO +* LID Manager object +*********/ + +/****f* OpenSM: LID Manager/osm_lid_mgr_construct +* NAME +* osm_lid_mgr_construct +* +* DESCRIPTION +* This function constructs a LID Manager object. +* +* SYNOPSIS +*/ +void +osm_lid_mgr_construct( + IN osm_lid_mgr_t* const p_mgr ); +/* +* PARAMETERS +* p_mgr +* [in] Pointer to a LID Manager object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows osm_lid_mgr_destroy +* +* Calling osm_lid_mgr_construct is a prerequisite to calling any other +* method except osm_lid_mgr_init. +* +* SEE ALSO +* LID Manager object, osm_lid_mgr_init, +* osm_lid_mgr_destroy +*********/ + +/****f* OpenSM: LID Manager/osm_lid_mgr_destroy +* NAME +* osm_lid_mgr_destroy +* +* DESCRIPTION +* The osm_lid_mgr_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_lid_mgr_destroy( + IN osm_lid_mgr_t* const p_mgr ); +/* +* PARAMETERS +* p_mgr +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* LID Manager object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_lid_mgr_construct or osm_lid_mgr_init. +* +* SEE ALSO +* LID Manager object, osm_lid_mgr_construct, +* osm_lid_mgr_init +*********/ + +/****f* OpenSM: LID Manager/osm_lid_mgr_init +* NAME +* osm_lid_mgr_init +* +* DESCRIPTION +* The osm_lid_mgr_init function initializes a +* LID Manager object for use. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_lid_mgr_init( + IN osm_lid_mgr_t* const p_mgr, + IN osm_req_t* const p_req, + IN osm_subn_t* const p_subn, + IN osm_db_t* const p_db, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ); +/* +* PARAMETERS +* p_mgr +* [in] Pointer to an osm_lid_mgr_t object to initialize. +* +* p_req +* [in] Pointer to the attribute Requester object. +* +* p_subn +* [in] Pointer to the Subnet object for this subnet. +* +* p_db +* [in] Pointer to the database object. +* +* p_log +* [in] Pointer to the log object. +* +* p_lock +* [in] Pointer to the OpenSM serializing lock. +* +* RETURN VALUES +* CL_SUCCESS if the LID Manager object was initialized +* successfully. +* +* NOTES +* Allows calling other LID Manager methods. +* +* SEE ALSO +* LID Manager object, osm_lid_mgr_construct, +* osm_lid_mgr_destroy +*********/ + +/****f* OpenSM: LID Manager/osm_lid_mgr_process_sm +* NAME +* osm_lid_mgr_process_sm +* +* DESCRIPTION +* Configures the SM's port with its designated LID values. +* +* SYNOPSIS +*/ +osm_signal_t +osm_lid_mgr_process_sm( + IN osm_lid_mgr_t* const p_mgr ); +/* +* PARAMETERS +* p_mgr +* [in] Pointer to an osm_lid_mgr_t object. +* +* RETURN VALUES +* Returns the appropriate signal to the caller: +* OSM_SIGNAL_DONE - operation is complete +* OSM_SIGNAL_DONE_PENDING - local operations are complete, but +* transactions are still pending on the wire. +* +* NOTES +* +* SEE ALSO +* LID Manager +*********/ + +/****f* OpenSM: LID Manager/osm_lid_mgr_process_subnet +* NAME +* osm_lid_mgr_process_subnet +* +* DESCRIPTION +* Configures subnet ports (except the SM port itself) with their +* designated LID values. +* +* SYNOPSIS +*/ +osm_signal_t +osm_lid_mgr_process_subnet( + IN osm_lid_mgr_t* const p_mgr ); +/* +* PARAMETERS +* p_mgr +* [in] Pointer to an osm_lid_mgr_t object. +* +* RETURN VALUES +* Returns the appropriate signal to the caller: +* OSM_SIGNAL_DONE - operation is complete +* OSM_SIGNAL_DONE_PENDING - local operations are complete, but +* transactions are still pending on the wire. +* +* NOTES +* +* SEE ALSO +* LID Manager +*********/ + +END_C_DECLS + +#endif /* _OSM_LID_MGR_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_lin_fwd_rcv.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_lin_fwd_rcv.h new file mode 100644 index 00000000..5acbc53d --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_lin_fwd_rcv.h @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_lin_fwd_rcv.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_lft_rcv_t. + * This object represents the LFT Receiver object. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_LFT_RCV_H_ +#define _OSM_LFT_RCV_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/LFT Receiver +* NAME +* LFT Receiver +* +* DESCRIPTION +* The LFT Receiver object encapsulates the information +* needed to receive the LFT attribute from a node. +* +* The LFT Receiver object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: LFT Receiver/osm_lft_rcv_t +* NAME +* osm_lft_rcv_t +* +* DESCRIPTION +* LFT Receiver structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_lft_rcv +{ + osm_subn_t *p_subn; + osm_log_t *p_log; + cl_plock_t *p_lock; + +} osm_lft_rcv_t; +/* +* FIELDS +* p_subn +* Pointer to the Subnet object for this subnet. +* +* p_log +* Pointer to the log object. +* +* p_lock +* Pointer to the serializing lock. +* +* SEE ALSO +* LFT Receiver object +*********/ + +/****f* OpenSM: LFT Receiver/osm_lft_rcv_construct +* NAME +* osm_lft_rcv_construct +* +* DESCRIPTION +* This function constructs a LFT Receiver object. +* +* SYNOPSIS +*/ +void osm_lft_rcv_construct( + IN osm_lft_rcv_t* const p_rcv ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to a LFT Receiver object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_lft_rcv_init, osm_lft_rcv_destroy +* +* Calling osm_lft_rcv_construct is a prerequisite to calling any other +* method except osm_lft_rcv_init. +* +* SEE ALSO +* LFT Receiver object, osm_lft_rcv_init, +* osm_lft_rcv_destroy +*********/ + +/****f* OpenSM: LFT Receiver/osm_lft_rcv_destroy +* NAME +* osm_lft_rcv_destroy +* +* DESCRIPTION +* The osm_lft_rcv_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_lft_rcv_destroy( + IN osm_lft_rcv_t* const p_rcv ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* LFT Receiver object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_lft_rcv_construct or osm_lft_rcv_init. +* +* SEE ALSO +* LFT Receiver object, osm_lft_rcv_construct, +* osm_lft_rcv_init +*********/ + +/****f* OpenSM: LFT Receiver/osm_lft_rcv_init +* NAME +* osm_lft_rcv_init +* +* DESCRIPTION +* The osm_lft_rcv_init function initializes a +* LFT Receiver object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_lft_rcv_init( + IN osm_lft_rcv_t* const p_rcv, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to an osm_lft_rcv_t object to initialize. +* +* p_subn +* [in] Pointer to the Subnet object for this subnet. +* +* p_log +* [in] Pointer to the log object. +* +* p_lock +* [in] Pointer to the OpenSM serializing lock. +* +* RETURN VALUES +* CL_SUCCESS if the LFT Receiver object was initialized +* successfully. +* +* NOTES +* Allows calling other LFT Receiver methods. +* +* SEE ALSO +* LFT Receiver object, osm_lft_rcv_construct, +* osm_lft_rcv_destroy +*********/ + +/****f* OpenSM: LFT Receiver/osm_lft_rcv_process +* NAME +* osm_lft_rcv_process +* +* DESCRIPTION +* Process the LFT attribute. +* +* SYNOPSIS +*/ +void osm_lft_rcv_process( + IN const osm_lft_rcv_t* const p_rcv, + IN osm_madw_t* const p_madw ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to an osm_lft_rcv_t object. +* +* p_madw +* [in] Pointer to the MAD Wrapper containing the MAD +* that contains the node's LFT attribute. +* +* RETURN VALUES +* CL_SUCCESS if the LFT processing was successful. +* +* NOTES +* This function processes a LFT attribute. +* +* SEE ALSO +* LFT Receiver, Node Description Response Controller +*********/ + +END_C_DECLS + +#endif /* _OSM_LFT_RCV_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_lin_fwd_rcv_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_lin_fwd_rcv_ctrl.h new file mode 100644 index 00000000..8cfa14bf --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_lin_fwd_rcv_ctrl.h @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_lin_fwd_rcv_ctrl.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_lft_rcv_ctrl_t. + * This object represents a controller that receives the IBA + * LFT attribute from a node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_LFT_RCV_CTRL_H_ +#define _OSM_LFT_RCV_CTRL_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/LFT Receive Controller +* NAME +* LFT Receive Controller +* +* DESCRIPTION +* The LFT Receive Controller object +* encapsulates the information +* needed to receive the NodeDescription attribute from a node. +* +* The LFT Receive Controller object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: LFT Receive Controller/osm_lft_rcv_ctrl_t +* NAME +* osm_lft_rcv_ctrl_t +* +* DESCRIPTION +* LFT Receive Controller structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_lft_rcv_ctrl +{ + osm_lft_rcv_t *p_rcv; + osm_log_t *p_log; + cl_dispatcher_t *p_disp; + cl_disp_reg_handle_t h_disp; + +} osm_lft_rcv_ctrl_t; +/* +* FIELDS +* p_rcv +* Pointer to the LFT Receiver object. +* +* p_log +* Pointer to the log object. +* +* p_disp +* Pointer to the Dispatcher. +* +* h_disp +* Handle returned from dispatcher registration. +* +* SEE ALSO +* LFT Receive Controller object +*********/ + +/****f* OpenSM: LFT Receive Controller/osm_lft_rcv_ctrl_construct +* NAME +* osm_lft_rcv_ctrl_construct +* +* DESCRIPTION +* This function constructs a LFT Receive Controller object. +* +* SYNOPSIS +*/ +void +osm_lft_rcv_ctrl_construct( + IN osm_lft_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a LFT Receive Controller object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_lft_rcv_ctrl_init, osm_lft_rcv_ctrl_destroy +* +* Calling osm_lft_rcv_ctrl_construct is a prerequisite to calling any other +* method except osm_lft_rcv_ctrl_init. +* +* SEE ALSO +* LFT Receive Controller object, osm_lft_rcv_ctrl_init, +* osm_lft_rcv_ctrl_destroy +*********/ + +/****f* OpenSM: LFT Receive Controller/osm_lft_rcv_ctrl_destroy +* NAME +* osm_lft_rcv_ctrl_destroy +* +* DESCRIPTION +* The osm_lft_rcv_ctrl_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_lft_rcv_ctrl_destroy( + IN osm_lft_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* LFT Receive Controller object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_lft_rcv_ctrl_construct or osm_lft_rcv_ctrl_init. +* +* SEE ALSO +* LFT Receive Controller object, osm_lft_rcv_ctrl_construct, +* osm_lft_rcv_ctrl_init +*********/ + +/****f* OpenSM: LFT Receive Controller/osm_lft_rcv_ctrl_init +* NAME +* osm_lft_rcv_ctrl_init +* +* DESCRIPTION +* The osm_lft_rcv_ctrl_init function initializes a +* LFT Receive Controller object for use. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_lft_rcv_ctrl_init( + IN osm_lft_rcv_ctrl_t* const p_ctrl, + IN osm_lft_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_lft_rcv_ctrl_t object to initialize. +* +* p_rcv +* [in] Pointer to an osm_lft_rcv_t object. +* +* p_log +* [in] Pointer to the log object. +* +* p_disp +* [in] Pointer to the OpenSM central Dispatcher. +* +* RETURN VALUES +* CL_SUCCESS if the LFT Receive Controller object was initialized +* successfully. +* +* NOTES +* Allows calling other LFT Receive Controller methods. +* +* SEE ALSO +* LFT Receive Controller object, osm_lft_rcv_ctrl_construct, +* osm_lft_rcv_ctrl_destroy +*********/ + +END_C_DECLS + +#endif /* OSM_LFT_RCV_CTRL_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_lin_fwd_tbl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_lin_fwd_tbl.h new file mode 100644 index 00000000..5d778242 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_lin_fwd_tbl.h @@ -0,0 +1,379 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_lin_fwd_tbl.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_lin_fwd_tbl_t. + * This object represents a linear forwarding table. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_LIN_FWD_TBL_H_ +#define _OSM_LIN_FWD_TBL_H_ + +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Linear Forwarding Table +* NAME +* Linear Forwarding Table +* +* DESCRIPTION +* The Linear Forwarding Table objects encapsulate the information +* needed by the OpenSM to manage linear forwarding tables. The OpenSM +* allocates one Linear Forwarding Table object per switch in the +* IBA subnet, if that switch uses a linear table. +* +* The Linear Forwarding Table objects are not thread safe, thus +* callers must provide serialization. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: Forwarding Table/osm_lin_fwd_tbl_t +* NAME +* osm_lin_fwd_tbl_t +* +* DESCRIPTION +* Linear Forwarding Table structure. +* +* Callers may directly access this object. +* +* SYNOPSIS +*/ +typedef struct _osm_lin_fwd_tbl +{ + uint16_t size; + uint8_t port_tbl[1]; + +} osm_lin_fwd_tbl_t; +/* +* FIELDS +* Size +* Number of entries in the linear forwarding table. This value +* is taken from the SwitchInfo attribute. +* +* port_tbl +* The array that specifies the port number which routes the +* corresponding LID. Index is by LID. +* +* SEE ALSO +* Forwarding Table object, Random Forwarding Table object. +*********/ + +/****f* OpenSM: Forwarding Table/osm_lin_tbl_new +* NAME +* osm_lin_tbl_new +* +* DESCRIPTION +* This function creates and initializes a Linear Forwarding Table object. +* +* SYNOPSIS +*/ +osm_lin_fwd_tbl_t* +osm_lin_tbl_new( + IN uint16_t const size ); +/* +* PARAMETERS +* size +* [in] Number of entries in the Linear Forwarding Table. +* +* RETURN VALUE +* On success, returns a pointer to a new Linear Forwarding Table object +* of the specified size. +* NULL otherwise. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Forwarding Table/osm_lin_tbl_delete +* NAME +* osm_lin_tbl_delete +* +* DESCRIPTION +* This destroys and deallocates a Linear Forwarding Table object. +* +* SYNOPSIS +*/ +void +osm_lin_tbl_delete( + IN osm_lin_fwd_tbl_t** const pp_tbl ); +/* +* PARAMETERS +* pp_tbl +* [in] Pointer a Pointer to the Linear Forwarding Table object. +* +* RETURN VALUE +* On success, returns a pointer to a new Linear Forwarding Table object +* of the specified size. +* NULL otherwise. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Forwarding Table/osm_lin_fwd_tbl_set +* NAME +* osm_lin_fwd_tbl_set +* +* DESCRIPTION +* Sets the port to route the specified LID. +* +* SYNOPSIS +*/ +static inline void +osm_lin_fwd_tbl_set( + IN osm_lin_fwd_tbl_t* const p_tbl, + IN const uint16_t lid_ho, + IN const uint8_t port ) +{ + CL_ASSERT( lid_ho < p_tbl->size ); + if( lid_ho < p_tbl->size ) + p_tbl->port_tbl[lid_ho] = port; +} +/* +* PARAMETERS +* p_tbl +* [in] Pointer to the Linear Forwarding Table object. +* +* lid_ho +* [in] LID value (host order) for which to set the route. +* +* port +* [in] Port to route the specified LID value. +* +* RETURN VALUE +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Forwarding Table/osm_lin_fwd_tbl_get +* NAME +* osm_lin_fwd_tbl_get +* +* DESCRIPTION +* Returns the port that routes the specified LID. +* +* SYNOPSIS +*/ +static inline uint8_t +osm_lin_fwd_tbl_get( + IN const osm_lin_fwd_tbl_t* const p_tbl, + IN const uint16_t lid_ho ) +{ + if( lid_ho < p_tbl->size ) + return( p_tbl->port_tbl[lid_ho] ); + else + return( 0xFF ); +} +/* +* PARAMETERS +* p_tbl +* [in] Pointer to the Linear Forwarding Table object. +* +* lid_ho +* [in] LID value (host order) for which to get the route. +* +* RETURN VALUE +* Returns the port that routes the specified LID. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Forwarding Table/osm_lin_fwd_tbl_get_size +* NAME +* osm_lin_fwd_tbl_get_size +* +* DESCRIPTION +* Returns the number of entries available in the forwarding table. +* +* SYNOPSIS +*/ +static inline uint16_t +osm_lin_fwd_tbl_get_size( + IN const osm_lin_fwd_tbl_t* const p_tbl ) +{ + return( p_tbl->size ); +} +/* +* PARAMETERS +* p_tbl +* [in] Pointer to the Forwarding Table object. +* +* RETURN VALUE +* Returns the number of entries available in the forwarding table. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Forwarding Table/osm_lin_fwd_tbl_get_lids_per_block +* NAME +* osm_lin_fwd_tbl_get_lids_per_block +* +* DESCRIPTION +* Returns the number of LIDs per LID block. +* +* SYNOPSIS +*/ +static inline uint16_t +osm_lin_fwd_tbl_get_lids_per_block( + IN const osm_lin_fwd_tbl_t* const p_tbl ) +{ + UNUSED_PARAM( p_tbl ); + return( 64 ); +} +/* +* PARAMETERS +* p_tbl +* [in] Pointer to the Forwarding Table object. +* +* RETURN VALUE +* Returns the number of LIDs per LID block. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Forwarding Table/osm_lin_fwd_tbl_get_max_block_id_in_use +* NAME +* osm_lin_fwd_tbl_get_max_block_id_in_use +* +* DESCRIPTION +* Returns the maximum block ID in actual use by the forwarding table. +* +* SYNOPSIS +*/ +static inline uint16_t +osm_lin_fwd_tbl_get_max_block_id_in_use( + IN const osm_lin_fwd_tbl_t* const p_tbl, + IN const uint16_t lid_top_ho ) +{ + return( (uint16_t)(lid_top_ho / + osm_lin_fwd_tbl_get_lids_per_block( p_tbl ) ) ); +} +/* +* PARAMETERS +* p_tbl +* [in] Pointer to the Forwarding Table object. +* +* RETURN VALUE +* Returns the maximum block ID in actual use by the forwarding table. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Forwarding Table/osm_lin_fwd_tbl_set_block +* NAME +* osm_lin_fwd_tbl_set_block +* +* DESCRIPTION +* Copies the specified block into the Linear Forwarding Table. +* +* SYNOPSIS +*/ +static inline ib_api_status_t +osm_lin_fwd_tbl_set_block( + IN osm_lin_fwd_tbl_t* const p_tbl, + IN const uint8_t* const p_block, + IN const uint32_t block_num ) +{ + uint16_t lid_start; + uint16_t num_lids; + + CL_ASSERT( p_tbl ); + CL_ASSERT( p_block ); + + num_lids = osm_lin_fwd_tbl_get_lids_per_block( p_tbl ); + lid_start = (uint16_t)(block_num * num_lids); + + if( lid_start + num_lids > p_tbl->size ) + return( IB_INVALID_PARAMETER ); + + memcpy( &p_tbl->port_tbl[lid_start], p_block, num_lids ); + return( IB_SUCCESS ); +} +/* +* PARAMETERS +* p_tbl +* [in] Pointer to the Linear Forwarding Table object. +* +* p_block +* [in] Pointer to the Forwarding Table block. +* +* block_num +* [in] Block number of this block. +* +* RETURN VALUE +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +END_C_DECLS + +#endif /* _OSM_LIN_FWD_TBL_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_link_mgr.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_link_mgr.h new file mode 100644 index 00000000..26c16572 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_link_mgr.h @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_link_mgr.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_link_mgr_t. + * This object represents the Link Manager object. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_LINK_MGR_H_ +#define _OSM_LINK_MGR_H_ + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Link Manager +* NAME +* Link Manager +* +* DESCRIPTION +* The Link Manager object encapsulates the information +* needed to control unicast LID forwarding on the subnet. +* +* The Link Manager object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: Link Manager/osm_link_mgr_t +* NAME +* osm_link_mgr_t +* +* DESCRIPTION +* Link Manager structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_link_mgr +{ + osm_subn_t *p_subn; + osm_req_t *p_req; + osm_log_t *p_log; + cl_plock_t *p_lock; + boolean_t send_set_reqs; + +} osm_link_mgr_t; +/* +* FIELDS +* p_subn +* Pointer to the Subnet object for this subnet. +* +* p_req +* Pointer to the Requester object sending SMPs. +* +* p_log +* Pointer to the log object. +* +* p_lock +* Pointer to the serializing lock. +* +* SEE ALSO +* Link Manager object +*********/ + +/****f* OpenSM: Link Manager/osm_link_mgr_construct +* NAME +* osm_link_mgr_construct +* +* DESCRIPTION +* This function constructs a Link Manager object. +* +* SYNOPSIS +*/ +void +osm_link_mgr_construct( + IN osm_link_mgr_t* const p_mgr ); +/* +* PARAMETERS +* p_mgr +* [in] Pointer to a Link Manager object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows osm_link_mgr_destroy +* +* Calling osm_link_mgr_construct is a prerequisite to calling any other +* method except osm_link_mgr_init. +* +* SEE ALSO +* Link Manager object, osm_link_mgr_init, +* osm_link_mgr_destroy +*********/ + +/****f* OpenSM: Link Manager/osm_link_mgr_destroy +* NAME +* osm_link_mgr_destroy +* +* DESCRIPTION +* The osm_link_mgr_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_link_mgr_destroy( + IN osm_link_mgr_t* const p_mgr ); +/* +* PARAMETERS +* p_mgr +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* Link Manager object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_link_mgr_construct or osm_link_mgr_init. +* +* SEE ALSO +* Link Manager object, osm_link_mgr_construct, +* osm_link_mgr_init +*********/ + +/****f* OpenSM: Link Manager/osm_link_mgr_init +* NAME +* osm_link_mgr_init +* +* DESCRIPTION +* The osm_link_mgr_init function initializes a +* Link Manager object for use. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_link_mgr_init( + IN osm_link_mgr_t* const p_mgr, + IN osm_req_t* const p_req, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ); +/* +* PARAMETERS +* p_mgr +* [in] Pointer to an osm_link_mgr_t object to initialize. +* +* p_req +* [in] Pointer to the attribute Requester object. +* +* p_subn +* [in] Pointer to the Subnet object for this subnet. +* +* p_log +* [in] Pointer to the log object. +* +* p_lock +* [in] Pointer to the OpenSM serializing lock. +* +* RETURN VALUES +* IB_SUCCESS if the Link Manager object was initialized +* successfully. +* +* NOTES +* Allows calling other Link Manager methods. +* +* SEE ALSO +* Link Manager object, osm_link_mgr_construct, +* osm_link_mgr_destroy +*********/ + +/****f* OpenSM: Link Manager/osm_link_mgr_process +* NAME +* osm_link_mgr_process +* +* DESCRIPTION +* Processes all ports in the subnet per the link manager command. +* +* SYNOPSIS +*/ +osm_signal_t +osm_link_mgr_process( + IN osm_link_mgr_t* const p_mgr, + IN const uint8_t link_state ); +/* +* PARAMETERS +* p_mgr +* [in] Pointer to an osm_link_mgr_t object. +* +* link_state +* [in] state to which to the set the port. +* +* +* RETURN VALUES +* Returns the appropriate signal to the caller: +* OSM_SIGNAL_DONE - operation is complete +* OSM_SIGNAL_DONE_PENDING - local operations are complete, but +* transactions are still pending on the wire. +* +* NOTES +* +* SEE ALSO +* Link Manager, Node Info Response Controller +*********/ + +END_C_DECLS + +#endif /* _OSM_LINK_MGR_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_log.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_log.h new file mode 100644 index 00000000..e8abd3e5 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_log.h @@ -0,0 +1,474 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_log.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_log_t. + * This object represents the log file. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.6 $ + */ + +#ifndef _OSM_LOG_H_ +#define _OSM_LOG_H_ + +#ifndef __WIN__ +#include +#endif +#include +#include +#include +#include +#include + +#ifdef __GNUC__ +#define STRICT_OSM_LOG_FORMAT __attribute__((format(printf, 3, 4))) +#else +#define STRICT_OSM_LOG_FORMAT +#endif + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +#define LOG_ENTRY_SIZE_MAX 4096 +#define BUF_SIZE LOG_ENTRY_SIZE_MAX + +#define __func__ __FUNCTION__ + +#define OSM_LOG_ENTER( OSM_LOG_PTR, NAME ) \ + osm_log( OSM_LOG_PTR, OSM_LOG_FUNCS, \ + "%s: [\n", __func__); + +#define OSM_LOG_EXIT( OSM_LOG_PTR ) \ + osm_log( OSM_LOG_PTR, OSM_LOG_FUNCS, \ + "%s: ]\n", __func__); + +/****h* OpenSM/Log +* NAME +* Log +* +* DESCRIPTION +* +* AUTHOR +* +*********/ +typedef uint8_t osm_log_level_t; + +#define OSM_LOG_NONE 0x00 +#define OSM_LOG_ERROR 0x01 +#define OSM_LOG_INFO 0x02 +#define OSM_LOG_VERBOSE 0x04 +#define OSM_LOG_DEBUG 0x08 +#define OSM_LOG_FUNCS 0x10 +#define OSM_LOG_FRAMES 0x20 +#define OSM_LOG_ROUTING 0x40 +#define OSM_LOG_SYS 0x80 + +/* + DEFAULT - turn on ERROR and INFO only +*/ +#define OSM_LOG_DEFAULT_LEVEL OSM_LOG_ERROR | OSM_LOG_INFO + +/****s* OpenSM: MAD Wrapper/osm_log_t +* NAME +* osm_log_t +* +* DESCRIPTION +* +* SYNOPSIS +*/ +typedef struct _osm_log +{ + osm_log_level_t level; + cl_spinlock_t lock; + unsigned long count; + unsigned long max_size; + boolean_t flush; + FILE* out_port; +} osm_log_t; +/*********/ + +/****f* OpenSM: Log/osm_log_construct +* NAME +* osm_log_construct +* +* DESCRIPTION +* This function constructs a Log object. +* +* SYNOPSIS +*/ +static inline void +osm_log_construct( + IN osm_log_t* const p_log ) +{ + cl_spinlock_construct( &p_log->lock ); +} +/* +* PARAMETERS +* p_log +* [in] Pointer to a Log object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_log_init, osm_log_init_v2, osm_log_destroy +* +* Calling osm_log_construct is a prerequisite to calling any other +* method except osm_log_init or osm_log_init_v2. +* +* SEE ALSO +* Log object, osm_log_init, osm_log_init_v2, +* osm_log_destroy +*********/ + +/****f* OpenSM: Log/osm_log_destroy +* NAME +* osm_log_destroy +* +* DESCRIPTION +* The osm_log_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +static inline void +osm_log_destroy( + IN osm_log_t* const p_log ) +{ + cl_spinlock_destroy( &p_log->lock ); + if (p_log->out_port != stdout) { + fclose(p_log->out_port); + p_log->out_port = stdout; + } + closelog(); +} +/* +* PARAMETERS +* p_log +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* Log object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_log_construct, osm_log_init, or osm_log_init_v2. +* +* SEE ALSO +* Log object, osm_log_construct, +* osm_log_init, osm_log_init_v2 +*********/ + +/****f* OpenSM: Log/osm_log_init_v2 +* NAME +* osm_log_init_v2 +* +* DESCRIPTION +* The osm_log_init_v2 function initializes a +* Log object for use. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_log_init_v2( + IN osm_log_t* const p_log, + IN const boolean_t flush, + IN const uint8_t log_flags, + IN const char *log_file, + IN const unsigned long max_size, + IN const boolean_t accum_log_file ); +/* +* PARAMETERS +* p_log +* [in] Pointer to the log object. +* +* flush +* [in] Set to TRUE directs the log to flush all log messages +* immediately. This severely degrades log performance, +* and is normally used for debugging only. +* +* log_flags +* [in] The log verbosity level to be used. +* +* log_file +* [in] if not NULL defines the name of the log file. Otherwise it is stdout. +* +* RETURN VALUES +* CL_SUCCESS if the Log object was initialized +* successfully. +* +* NOTES +* Allows calling other Log methods. +* +* SEE ALSO +* Log object, osm_log_construct, +* osm_log_destroy +*********/ + +/****f* OpenSM: Log/osm_log_init +* NAME +* osm_log_init +* +* DESCRIPTION +* The osm_log_init function initializes a +* Log object for use. It is a wrapper for osm_log_init_v2(). +* +* SYNOPSIS +*/ +ib_api_status_t +osm_log_init( + IN osm_log_t* const p_log, + IN const boolean_t flush, + IN const uint8_t log_flags, + IN const char *log_file, + IN const boolean_t accum_log_file ); +/* + * Same as osm_log_init_v2() but without max_size parameter + */ + +/****f* OpenSM: Log/osm_log_get_level +* NAME +* osm_log_get_level +* +* DESCRIPTION +* Returns the current log level. +* +* SYNOPSIS +*/ +static inline osm_log_level_t +osm_log_get_level( + IN const osm_log_t* const p_log ) +{ + return( p_log->level ); +} +/* +* PARAMETERS +* p_log +* [in] Pointer to the log object. +* +* RETURN VALUES +* Returns the current log level. +* +* NOTES +* +* SEE ALSO +* Log object, osm_log_construct, +* osm_log_destroy +*********/ + +/****f* OpenSM: Log/osm_log_set_level +* NAME +* osm_log_set_level +* +* DESCRIPTION +* Sets the current log level. +* +* SYNOPSIS +*/ +static inline void +osm_log_set_level( + IN osm_log_t* const p_log, + IN const osm_log_level_t level ) +{ + p_log->level = level; +} +/* +* PARAMETERS +* p_log +* [in] Pointer to the log object. +* +* level +* [in] New level to set. +* +* RETURN VALUES +* Returns the current log level. +* +* NOTES +* +* SEE ALSO +* Log object, osm_log_construct, +* osm_log_destroy +*********/ + +/****f* OpenSM: Log/osm_log_is_active +* NAME +* osm_log_is_active +* +* DESCRIPTION +* Returns TRUE if the specified log level would be logged. +* FALSE otherwise. +* +* SYNOPSIS +*/ +static inline boolean_t +osm_log_is_active( + IN const osm_log_t* const p_log, + IN const osm_log_level_t level ) +{ + return( (p_log->level & level) != 0 ); +} +/* +* PARAMETERS +* p_log +* [in] Pointer to the log object. +* +* level +* [in] Level to check. +* +* RETURN VALUES +* Returns TRUE if the specified log level would be logged. +* FALSE otherwise. +* +* NOTES +* +* SEE ALSO +* Log object, osm_log_construct, +* osm_log_destroy +*********/ + +extern int osm_log_printf(osm_log_t *p_log, osm_log_level_t level, + const char *fmt, ...); + +void +osm_log( + IN osm_log_t* const p_log, + IN const osm_log_level_t verbosity, + IN const char *p_str, ... ) STRICT_OSM_LOG_FORMAT; + +void +osm_log_raw( + IN osm_log_t* const p_log, + IN const osm_log_level_t verbosity, + IN const char *p_buf ); + +#define DBG_CL_LOCK 0 + +#define CL_PLOCK_EXCL_ACQUIRE( __exp__ ) \ +{ \ + if (DBG_CL_LOCK) \ + printf("cl_plock_excl_acquire: Acquiring %p file %s, line %d\n", \ + __exp__,__FILE__, __LINE__); \ + cl_plock_excl_acquire( __exp__ ); \ + if (DBG_CL_LOCK) \ + printf("cl_plock_excl_acquire: Acquired %p file %s, line %d\n", \ + __exp__,__FILE__, __LINE__); \ +} + +#define CL_PLOCK_ACQUIRE( __exp__ ) \ +{ \ + if (DBG_CL_LOCK) \ + printf("cl_plock_acquire: Acquiring %p file %s, line %d\n", \ + __exp__,__FILE__, __LINE__); \ + cl_plock_acquire( __exp__ ); \ + if (DBG_CL_LOCK) \ + printf("cl_plock_acquire: Acquired %p file %s, line %d\n", \ + __exp__,__FILE__, __LINE__); \ +} + +#define CL_PLOCK_RELEASE( __exp__ ) \ +{ \ + if (DBG_CL_LOCK) \ + printf("cl_plock_release: Releasing %p file %s, line %d\n", \ + __exp__,__FILE__, __LINE__); \ + cl_plock_release( __exp__ ); \ + if (DBG_CL_LOCK) \ + printf("cl_plock_release: Released %p file %s, line %d\n", \ + __exp__,__FILE__, __LINE__); \ +} + +#define DBG_CL_SPINLOCK 0 +#define CL_SPINLOCK_RELEASE( __exp__ ) \ +{ \ + if (DBG_CL_SPINLOCK) \ + printf("cl_spinlock_release: Releasing %p file %s, line %d\n", \ + __exp__,__FILE__, __LINE__); \ + cl_spinlock_release( __exp__ ); \ + if (DBG_CL_SPINLOCK) \ + printf("cl_spinlock_release: Released %p file %s, line %d\n", \ + __exp__,__FILE__, __LINE__); \ +} + +#define CL_SPINLOCK_ACQUIRE( __exp__ ) \ +{ \ + if (DBG_CL_SPINLOCK) \ + printf("cl_spinlock_acquire: Acquiring %p file %s, line %d\n", \ + __exp__,__FILE__, __LINE__); \ + cl_spinlock_acquire( __exp__ ); \ + if (DBG_CL_SPINLOCK) \ + printf("cl_spinlock_acquire: Acquired %p file %s, line %d\n", \ + __exp__,__FILE__, __LINE__); \ +} + +/****f* OpenSM: Helper/osm_is_debug +* NAME +* osm_is_debug +* +* DESCRIPTION +* The osm_is_debug function returns TRUE if the opensm was compiled +* in debug mode, and FALSE otherwise. +* +* SYNOPSIS +*/ +boolean_t +osm_is_debug(void); +/* +* PARAMETERS +* None +* +* RETURN VALUE +* TRUE if compiled in debug version. FALSE otherwise. +* +* NOTES +* +*********/ + +END_C_DECLS + +#endif /* _OSM_LOG_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mad_pool.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mad_pool.h new file mode 100644 index 00000000..e3c0993c --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mad_pool.h @@ -0,0 +1,405 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_mad_pool.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_mad_pool_t. + * This object represents a pool of management datagram (MAD) objects. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + +#ifndef _OSM_MAD_POOL_H_ +#define _OSM_MAD_POOL_H_ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/MAD Pool +* NAME +* MAD Pool +* +* DESCRIPTION +* The MAD Pool encapsulates the information needed by the +* OpenSM to manage a pool of MAD objects. The OpenSM allocates +* one MAD Pool per IBA subnet. +* +* The MAD Pool is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: MAD Pool/osm_mad_pool_t +* NAME +* osm_mad_pool_t +* +* DESCRIPTION +* MAD Pool structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_mad_pool +{ + osm_log_t *p_log; + cl_qlock_pool_t madw_pool; + atomic32_t mads_out; +} osm_mad_pool_t; +/* +* FIELDS +* p_log +* Pointer to the log object. +* +* lock +* Spinlock guarding the pool. +* +* mads_out +* Running total of the number of MADs outstanding. +* +* SEE ALSO +* MAD Pool +*********/ + +/****f* OpenSM: MAD Pool/osm_mad_pool_construct +* NAME +* osm_mad_pool_construct +* +* DESCRIPTION +* This function constructs a MAD Pool. +* +* SYNOPSIS +*/ +void osm_mad_pool_construct( + IN osm_mad_pool_t* const p_pool ); +/* +* PARAMETERS +* p_pool +* [in] Pointer to a MAD Pool to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_mad_pool_init, osm_mad_pool_destroy +* +* Calling osm_mad_pool_construct is a prerequisite to calling any other +* method except osm_mad_pool_init. +* +* SEE ALSO +* MAD Pool, osm_mad_pool_init, osm_mad_pool_destroy +*********/ + +/****f* OpenSM: MAD Pool/osm_mad_pool_destroy +* NAME +* osm_mad_pool_destroy +* +* DESCRIPTION +* The osm_mad_pool_destroy function destroys a node, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_mad_pool_destroy( + IN osm_mad_pool_t* const p_pool ); +/* +* PARAMETERS +* p_pool +* [in] Pointer to a MAD Pool to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified MAD Pool. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to osm_mad_pool_construct or +* osm_mad_pool_init. +* +* SEE ALSO +* MAD Pool, osm_mad_pool_construct, osm_mad_pool_init +*********/ + +/****f* OpenSM: MAD Pool/osm_mad_pool_init +* NAME +* osm_mad_pool_init +* +* DESCRIPTION +* The osm_mad_pool_init function initializes a MAD Pool for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_mad_pool_init( + IN osm_mad_pool_t* const p_pool, + IN osm_log_t* const p_log ); +/* +* PARAMETERS +* p_pool +* [in] Pointer to an osm_mad_pool_t object to initialize. +* +* p_log +* [in] Pointer to the log object. +* +* +* RETURN VALUES +* CL_SUCCESS if the MAD Pool was initialized successfully. +* +* NOTES +* Allows calling other MAD Pool methods. +* +* SEE ALSO +* MAD Pool, osm_mad_pool_construct, osm_mad_pool_destroy +*********/ + +/****f* OpenSM: MAD Pool/osm_mad_pool_get +* NAME +* osm_mad_pool_get +* +* DESCRIPTION +* Gets a MAD wrapper and wire MAD from the pool. +* +* SYNOPSIS +*/ +osm_madw_t* +osm_mad_pool_get( + IN osm_mad_pool_t* const p_pool, + IN osm_bind_handle_t h_bind, + IN const uint32_t total_size, + IN const osm_mad_addr_t* const p_mad_addr ); +/* +* PARAMETERS +* p_pool +* [in] Pointer to an osm_mad_pool_t object. +* +* h_bind +* [in] Handle returned from osm_vendor_bind() call to the +* port over which this mad will be sent. +* +* total_size +* [in] Total size, including MAD header of the requested MAD. +* +* p_mad_addr +* [in] Pointer to the MAD address structure. This parameter +* may be NULL for directed route MADs. +* +* RETURN VALUES +* Returns a pointer to a MAD wrapper containing the MAD. +* A return value of NULL means no MADs are available. +* +* NOTES +* The MAD must eventually be returned to the pool with a call to +* osm_mad_pool_put. +* +* The osm_mad_pool_construct or osm_mad_pool_init must be called before +* using this function. +* +* SEE ALSO +* MAD Pool, osm_mad_pool_put +*********/ + +/****f* OpenSM: MAD Pool/osm_mad_pool_put +* NAME +* osm_mad_pool_put +* +* DESCRIPTION +* Returns a MAD to the pool. +* +* SYNOPSIS +*/ +void osm_mad_pool_put( + IN osm_mad_pool_t* const p_pool, + IN osm_madw_t* const p_madw ); +/* +* PARAMETERS +* p_pool +* [in] Pointer to an osm_mad_pool_t object. +* +* p_madw +* [in] Pointer to a MAD Wrapper for a MAD that was previously +* retrieved from the pool. +* +* RETURN VALUES +* This function does not return a value. +* +* NOTES +* The osm_mad_pool_construct or osm_mad_pool_init must be called before +* using this function. +* +* SEE ALSO +* MAD Pool, osm_mad_pool_get +*********/ + +/****f* OpenSM: MAD Pool/osm_mad_pool_get_wrapper +* NAME +* osm_mad_pool_get_wrapper +* +* DESCRIPTION +* Gets a only MAD wrapper from the pool (no wire MAD). +* +* SYNOPSIS +*/ +osm_madw_t* +osm_mad_pool_get_wrapper( + IN osm_mad_pool_t* const p_pool, + IN osm_bind_handle_t h_bind, + IN const uint32_t total_size, + IN const ib_mad_t* const p_mad, + IN const osm_mad_addr_t* const p_mad_addr ); +/* +* PARAMETERS +* p_pool +* [in] Pointer to an osm_mad_pool_t object. +* +* h_bind +* [in] Handle returned from osm_vendor_bind() call to the +* port for which this mad wrapper will be used. +* +* total_size +* [in] Total size, including MAD header of the MAD that will +* be attached to this wrapper. +* +* p_mad +* [in] Pointer to the MAD to attach to this wrapper. +* +* p_mad_addr +* [in] Pointer to the MAD address structure. This parameter +* may be NULL for directed route MADs. +* +* RETURN VALUES +* Returns a pointer to a MAD wrapper. +* A return value of NULL means no MAD wrappers are available. +* +* NOTES +* The MAD must eventually be returned to the pool with a call to +* osm_mad_pool_put. +* +* The osm_mad_pool_construct or osm_mad_pool_init must be called before +* using this function. +* +* SEE ALSO +* MAD Pool, osm_mad_pool_put +*********/ + +/****f* OpenSM: MAD Pool/osm_mad_pool_get_wrapper_raw +* NAME +* osm_mad_pool_get_wrapper_raw +* +* DESCRIPTION +* Gets a only an uninitialized MAD wrapper from the pool (no wire MAD). +* +* SYNOPSIS +*/ +osm_madw_t* +osm_mad_pool_get_wrapper_raw( + IN osm_mad_pool_t* const p_pool ); +/* +* PARAMETERS +* p_pool +* [in] Pointer to an osm_mad_pool_t object. +* +* RETURN VALUES +* Returns a pointer to a MAD wrapper. +* A return value of NULL means no MAD wrappers are available. +* +* NOTES +* The MAD must eventually be returned to the pool with a call to +* osm_mad_pool_put. +* +* The osm_mad_pool_construct or osm_mad_pool_init must be called before +* using this function. +* +* SEE ALSO +* MAD Pool, osm_mad_pool_put +*********/ + +/****f* OpenSM: MAD Pool/osm_mad_pool_get_outstanding +* NAME +* osm_mad_pool_get_count +* +* DESCRIPTION +* Returns the running count of MADs currently outstanding from the pool. +* +* SYNOPSIS +*/ +static inline uint32_t +osm_mad_pool_get_outstanding( + IN const osm_mad_pool_t* const p_pool ) +{ + return( p_pool->mads_out ); +} +/* +* PARAMETERS +* p_pool +* [in] Pointer to an osm_mad_pool_t object. +* +* RETURN VALUES +* Returns the running count of MADs currently outstanding from the pool. +* +* NOTES +* The osm_mad_pool_construct or osm_mad_pool_init must be called before +* using this function. +* +* SEE ALSO +* MAD Pool, osm_mad_pool_get +*********/ + +END_C_DECLS + +#endif /* _OSM_MAD_POOL_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_madw.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_madw.h new file mode 100644 index 00000000..dfd6f918 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_madw.h @@ -0,0 +1,1160 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_madw.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_mad_wrapper_t. + * This object represents the context wrapper for OpenSM MAD processing. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + +#ifndef _OSM_MADW_H_ +#define _OSM_MADW_H_ + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****s* OpenSM: MAD Wrapper/osm_bind_info_t +* NAME +* osm_bind_info_t +* +* DESCRIPTION +* +* SYNOPSIS +*/ +typedef struct _osm_bind_info +{ + ib_net64_t port_guid; + uint8_t mad_class; + uint8_t class_version; + boolean_t is_responder; + boolean_t is_trap_processor; + boolean_t is_report_processor; + uint32_t send_q_size; + uint32_t recv_q_size; +} osm_bind_info_t; +/* +* FIELDS +* portguid +* PortGuid of local port +* +* class +* Mgmt Class ID +* +* class_version +* Mgmt Class version +* +* is_responder +* True if this is a GSI Agent +* +* is_trap_processor +* True if GSI Trap msgs are handled +* +* is_report_processo +* True if GSI Report msgs are handled +* +* send_q_size +* SendQueueSize +* +* recv_q_size +* Receive Queue Size +* +* SEE ALSO +*********/ + +/****h* OpenSM/MAD Wrapper +* NAME +* MAD Wrapper +* +* DESCRIPTION +* The MAD Wrapper object encapsulates the information needed by the +* OpenSM to manage individual MADs. The OpenSM allocates one MAD Wrapper +* per MAD. +* +* The MAD Wrapper is not thread safe, thus callers must provide +* serialization. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: MAD Wrapper/osm_ni_context_t +* NAME +* osm_ni_context_t +* +* DESCRIPTION +* Context needed by recipient of NodeInfo attribute. +* +* SYNOPSIS +*/ +typedef struct _osm_ni_context +{ + ib_net64_t node_guid; + uint8_t port_num; +} osm_ni_context_t; +/* +* FIELDS +* p_node +* Pointer to the node thru which we got to this node. +* +* p_sw +* Pointer to the switch object (if any) of the switch +* thru which we got to this node. +* +* port_num +* Port number on the node or switch thru which we got +* to this node. +* +* SEE ALSO +*********/ + +/****s* OpenSM: MAD Wrapper/osm_pi_context_t +* NAME +* osm_pi_context_t +* +* DESCRIPTION +* Context needed by recipient of PortInfo attribute. +* +* SYNOPSIS +*/ +typedef struct _osm_pi_context +{ + ib_net64_t node_guid; + ib_net64_t port_guid; + boolean_t set_method; + boolean_t light_sweep; + boolean_t update_master_sm_base_lid; + boolean_t ignore_errors; + boolean_t active_transition; +} osm_pi_context_t; +/*********/ + +/****s* OpenSM: MAD Wrapper/osm_nd_context_t +* NAME +* osm_nd_context_t +* +* DESCRIPTION +* Context needed by recipient of NodeDescription attribute. +* +* SYNOPSIS +*/ +typedef struct _osm_nd_context +{ + ib_net64_t node_guid; +} osm_nd_context_t; +/*********/ + +/****s* OpenSM: MAD Wrapper/osm_si_context_t +* NAME +* osm_si_context_t +* +* DESCRIPTION +* Context needed by recipient of SwitchInfo attribute. +* +* SYNOPSIS +*/ +typedef struct _osm_si_context +{ + ib_net64_t node_guid; + boolean_t set_method; + boolean_t light_sweep; +} osm_si_context_t; +/*********/ + +/****s* OpenSM: MAD Wrapper/osm_lft_context_t +* NAME +* osm_lft_context_t +* +* DESCRIPTION +* Context needed by recipient of LinearForwardingTable attribute. +* +* SYNOPSIS +*/ +typedef struct _osm_lft_context +{ + ib_net64_t node_guid; + boolean_t set_method; +} osm_lft_context_t; +/*********/ + +/****s* OpenSM: MAD Wrapper/osm_mft_context_t +* NAME +* osm_mft_context_t +* +* DESCRIPTION +* Context needed by recipient of MulticastForwardingTable attribute. +* +* SYNOPSIS +*/ +typedef struct _osm_mft_context +{ + ib_net64_t node_guid; + boolean_t set_method; +} osm_mft_context_t; +/*********/ + +/****s* OpenSM: MAD Wrapper/osm_smi_context_t +* NAME +* osm_smi_context_t +* +* DESCRIPTION +* Context needed by recipient of SMInfo attribute. +* +* SYNOPSIS +*/ +typedef struct _osm_smi_context +{ + ib_net64_t port_guid; + boolean_t set_method; +} osm_smi_context_t; +/*********/ + +/****s* OpenSM: MAD Wrapper/osm_pkey_context_t +* NAME +* osm_pkey_context_t +* +* DESCRIPTION +* Context needed by recipient of P_Key attribute. +* +* SYNOPSIS +*/ +typedef struct _osm_pkey_context +{ + ib_net64_t node_guid; + ib_net64_t port_guid; + boolean_t set_method; +} osm_pkey_context_t; +/*********/ + +/****s* OpenSM: MAD Wrapper/osm_slvl_context_t +* NAME +* osm_slvl_context_t +* +* DESCRIPTION +* Context needed by recipient of PortInfo attribute. +* +* SYNOPSIS +*/ +typedef struct _osm_slvl_context +{ + ib_net64_t node_guid; + ib_net64_t port_guid; + boolean_t set_method; +} osm_slvl_context_t; +/*********/ + +/****s* OpenSM: MAD Wrapper/osm_vla_context_t +* NAME +* osm_vla_context_t +* +* DESCRIPTION +* Context needed by recipient of VL Arb attribute. +* +* SYNOPSIS +*/ +typedef struct _osm_vla_context +{ + ib_net64_t node_guid; + ib_net64_t port_guid; + boolean_t set_method; +} osm_vla_context_t; +/*********/ + +#ifndef OSM_VENDOR_INTF_OPENIB +/****s* OpenSM: MAD Wrapper/osm_arbitrary_context_t +* NAME +* osm_arbitrary_context_t +* +* DESCRIPTION +* Context needed by arbitrary recipient. +* +* SYNOPSIS +*/ +typedef struct _osm_arbitrary_context +{ + void* context1; + void* context2; +} osm_arbitrary_context_t; +/*********/ +#endif + +/****s* OpenSM: MAD Wrapper/osm_madw_context_t +* NAME +* osm_madw_context_t +* +* DESCRIPTION +* Context needed by recipients of MAD responses. +* +* SYNOPSIS +*/ +typedef union _osm_madw_context +{ + osm_ni_context_t ni_context; + osm_pi_context_t pi_context; + osm_nd_context_t nd_context; + osm_si_context_t si_context; + osm_lft_context_t lft_context; + osm_mft_context_t mft_context; + osm_smi_context_t smi_context; + osm_slvl_context_t slvl_context; + osm_pkey_context_t pkey_context; + osm_vla_context_t vla_context; +#ifndef OSM_VENDOR_INTF_OPENIB + osm_arbitrary_context_t arb_context; +#endif +} osm_madw_context_t; +/*********/ + +/****s* OpenSM: MAD Wrapper/osm_mad_addr_t +* NAME +* osm_mad_addr_t +* +* DESCRIPTION +* +* SYNOPSIS +*/ +typedef struct _osm_mad_addr +{ + ib_net16_t dest_lid; + uint8_t path_bits; + uint8_t static_rate; + + union addr_type + { + struct _smi + { + ib_net16_t source_lid; + uint8_t port_num; + } smi; + + struct _gsi + { + ib_net32_t remote_qp; + ib_net32_t remote_qkey; + ib_net16_t pkey; + uint8_t service_level; + boolean_t global_route; + ib_grh_t grh_info; + } gsi; + } addr_type; + +} osm_mad_addr_t; +/* +* FIELDS +* +* SEE ALSO +*********/ + +/****s* OpenSM: MAD Wrapper/osm_madw_t +* NAME +* osm_madw_t +* +* DESCRIPTION +* Context needed for processing individual MADs +* +* SYNOPSIS +*/ +typedef struct _osm_madw +{ + cl_pool_item_t pool_item; + osm_bind_handle_t h_bind; + osm_vend_wrap_t vend_wrap; + osm_mad_addr_t mad_addr; + osm_bind_info_t bind_info; + osm_madw_context_t context; + uint32_t mad_size; + ib_api_status_t status; + cl_disp_msgid_t fail_msg; + boolean_t resp_expected; + const ib_mad_t *p_mad; +} osm_madw_t; +/* +* FIELDS +* pool_item +* List linkage for pools and lists. MUST BE FIRST MEMBER! +* +* h_bind +* Bind handle for the port on which this MAD will be sent +* or was received. +* +* vend_wrap +* Transport vendor specific context. This structure is not +* used outside MAD transport vendor specific code. +* +* context +* Union of controller specific contexts needed for this MAD. +* This structure allows controllers to indirectly communicate +* with each other through the dispatcher. +* +* mad_size +* Size of this MAD in bytes. +* +* status +* Status of completed operation on the MAD. +* CL_SUCCESS if the operation was successful. +* +* fail_msg +* Dispatcher message with which to post this MAD on failure. +* This value is set by the originator of the MAD. +* If an operation on this MAD fails, for example due to a timeout, +* then the transport layer will dispose of the MAD by sending +* it through the Dispatcher with this message type. Presumably, +* there is a controller listening for the failure message that can +* properly clean up. +* +* resp_expected +* TRUE if a response is expected to this MAD. +* FALSE otherwise. +* +* p_mad +* Pointer to the wire MAD. The MAD itself cannot be part of the +* wrapper, since wire MADs typically reside in special memory +* registered with the local HCA. +* +* SEE ALSO +*********/ + +/****f* OpenSM: MAD Wrapper/osm_madw_construct +* NAME +* osm_madw_construct +* +* DESCRIPTION +* This function constructs a MAD Wrapper object. +* +* SYNOPSIS +*/ +static inline void +osm_madw_construct( + IN osm_madw_t* const p_madw ) +{ + /* + Don't touch the pool_item since that is an opaque object. + Clear all other objects in the mad wrapper. + */ + memset( ((uint8_t *)p_madw) + sizeof( cl_pool_item_t ), 0, + sizeof(*p_madw) - sizeof( cl_pool_item_t ) ); +} +/* +* PARAMETERS +* p_madw +* [in] Pointer to a MAD Wrapper object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_madw_init, osm_madw_destroy +* +* Calling osm_madw_construct is a prerequisite to calling any other +* method except osm_madw_init. +* +* SEE ALSO +* MAD Wrapper object, osm_madw_init, osm_madw_destroy +*********/ + +/****f* OpenSM: MAD Wrapper/osm_madw_destroy +* NAME +* osm_madw_destroy +* +* DESCRIPTION +* The osm_madw_destroy function destroys a node, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_madw_destroy( + IN osm_madw_t* const p_madw ); +/* +* PARAMETERS +* p_madw +* [in] Pointer to a MAD Wrapper object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified MAD Wrapper object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to osm_madw_construct or +* osm_madw_init. +* +* SEE ALSO +* MAD Wrapper object, osm_madw_construct, osm_madw_init +*********/ + +/****f* OpenSM: MAD Wrapper/osm_madw_init +* NAME +* osm_madw_init +* +* DESCRIPTION +* Initializes a MAD Wrapper object for use. +* +* SYNOPSIS +*/ +static inline void +osm_madw_init( + IN osm_madw_t* const p_madw, + IN osm_bind_handle_t h_bind, + IN const uint32_t mad_size, + IN const osm_mad_addr_t* const p_mad_addr ) +{ + osm_madw_construct( p_madw ); + p_madw->h_bind = h_bind; + p_madw->fail_msg = CL_DISP_MSGID_NONE; + p_madw->mad_size = mad_size; + if( p_mad_addr ) + p_madw->mad_addr = *p_mad_addr; + p_madw->resp_expected = FALSE; +} +/* +* PARAMETERS +* p_madw +* [in] Pointer to an osm_madw_t object to initialize. +* +* h_bind +* [in] Pointer to the wire MAD. +* +* p_mad_addr +* [in] Pointer to the MAD address structure. This parameter may +* be NULL for directed route MADs. +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: MAD Wrapper/osm_madw_get_smp_ptr +* NAME +* osm_madw_get_smp_ptr +* +* DESCRIPTION +* Gets a pointer to the SMP in this MAD. +* +* SYNOPSIS +*/ +static inline ib_smp_t* +osm_madw_get_smp_ptr( + IN const osm_madw_t* const p_madw ) +{ + return( (ib_smp_t*)p_madw->p_mad ); +} +/* +* PARAMETERS +* p_madw +* [in] Pointer to an osm_madw_t object to initialize. +* +* RETURN VALUES +* Pointer to the start of the SMP MAD. +* +* NOTES +* +* SEE ALSO +* MAD Wrapper object, osm_madw_construct, osm_madw_destroy +*********/ + +/****f* OpenSM: MAD Wrapper/osm_madw_get_sa_mad_ptr +* NAME +* osm_madw_get_sa_mad_ptr +* +* DESCRIPTION +* Gets a pointer to the SA MAD in this MAD wrapper. +* +* SYNOPSIS +*/ +static inline ib_sa_mad_t* +osm_madw_get_sa_mad_ptr( + IN const osm_madw_t* const p_madw ) +{ + return( (ib_sa_mad_t*)p_madw->p_mad ); +} +/* +* PARAMETERS +* p_madw +* [in] Pointer to an osm_madw_t object to initialize. +* +* RETURN VALUES +* Pointer to the start of the SMP MAD. +* +* NOTES +* +* SEE ALSO +* MAD Wrapper object, osm_madw_construct, osm_madw_destroy +*********/ + +/****f* OpenSM: MAD Wrapper/osm_madw_get_ni_context_ptr +* NAME +* osm_madw_get_ni_context_ptr +* +* DESCRIPTION +* Gets a pointer to the NodeInfo context in this MAD. +* +* SYNOPSIS +*/ +static inline osm_ni_context_t* +osm_madw_get_ni_context_ptr( + IN const osm_madw_t* const p_madw ) +{ + return( (osm_ni_context_t*)&p_madw->context ); +} +/* +* PARAMETERS +* p_madw +* [in] Pointer to an osm_madw_t object. +* +* RETURN VALUES +* Pointer to the start of the context structure. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: MAD Wrapper/osm_madw_get_pi_context_ptr +* NAME +* osm_madw_get_pi_context_ptr +* +* DESCRIPTION +* Gets a pointer to the PortInfo context in this MAD. +* +* SYNOPSIS +*/ +static inline osm_pi_context_t* +osm_madw_get_pi_context_ptr( + IN const osm_madw_t* const p_madw ) +{ + return( (osm_pi_context_t*)&p_madw->context ); +} +/* +* PARAMETERS +* p_madw +* [in] Pointer to an osm_madw_t object. +* +* RETURN VALUES +* Pointer to the start of the context structure. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: MAD Wrapper/osm_madw_get_nd_context_ptr +* NAME +* osm_madw_get_nd_context_ptr +* +* DESCRIPTION +* Gets a pointer to the NodeDescription context in this MAD. +* +* SYNOPSIS +*/ +static inline osm_nd_context_t* +osm_madw_get_nd_context_ptr( + IN const osm_madw_t* const p_madw ) +{ + return( (osm_nd_context_t*)&p_madw->context ); +} +/* +* PARAMETERS +* p_madw +* [in] Pointer to an osm_madw_t object. +* +* RETURN VALUES +* Pointer to the start of the context structure. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: MAD Wrapper/osm_madw_get_lft_context_ptr +* NAME +* osm_madw_get_lft_context_ptr +* +* DESCRIPTION +* Gets a pointer to the LFT context in this MAD. +* +* SYNOPSIS +*/ +static inline osm_lft_context_t* +osm_madw_get_lft_context_ptr( + IN const osm_madw_t* const p_madw ) +{ + return( (osm_lft_context_t*)&p_madw->context ); +} +/* +* PARAMETERS +* p_madw +* [in] Pointer to an osm_madw_t object. +* +* RETURN VALUES +* Pointer to the start of the context structure. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: MAD Wrapper/osm_madw_get_mft_context_ptr +* NAME +* osm_madw_get_mft_context_ptr +* +* DESCRIPTION +* Gets a pointer to the MFT context in this MAD. +* +* SYNOPSIS +*/ +static inline osm_mft_context_t* +osm_madw_get_mft_context_ptr( + IN const osm_madw_t* const p_madw ) +{ + return( (osm_mft_context_t*)&p_madw->context ); +} +/* +* PARAMETERS +* p_madw +* [in] Pointer to an osm_madw_t object. +* +* RETURN VALUES +* Pointer to the start of the context structure. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: MAD Wrapper/osm_madw_get_si_context_ptr +* NAME +* osm_madw_get_si_context_ptr +* +* DESCRIPTION +* Gets a pointer to the SwitchInfo context in this MAD. +* +* SYNOPSIS +*/ +static inline osm_si_context_t* +osm_madw_get_si_context_ptr( + IN const osm_madw_t* const p_madw ) +{ + return( (osm_si_context_t*)&p_madw->context ); +} +/* +* PARAMETERS +* p_madw +* [in] Pointer to an osm_madw_t object. +* +* RETURN VALUES +* Pointer to the start of the context structure. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: MAD Wrapper/osm_madw_get_smi_context_ptr +* NAME +* osm_madw_get_smi_context_ptr +* +* DESCRIPTION +* Gets a pointer to the SMInfo context in this MAD. +* +* SYNOPSIS +*/ +static inline osm_smi_context_t* +osm_madw_get_smi_context_ptr( + IN const osm_madw_t* const p_madw ) +{ + return( (osm_smi_context_t*)&p_madw->context ); +} +/* +* PARAMETERS +* p_madw +* [in] Pointer to an osm_madw_t object. +* +* RETURN VALUES +* Pointer to the start of the context structure. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: MAD Wrapper/osm_madw_get_pkey_context_ptr +* NAME +* osm_madw_get_pkey_context_ptr +* +* DESCRIPTION +* Gets a pointer to the P_Key context in this MAD. +* +* SYNOPSIS +*/ +static inline osm_pkey_context_t* +osm_madw_get_pkey_context_ptr( + IN const osm_madw_t* const p_madw ) +{ + return( (osm_pkey_context_t*)&p_madw->context ); +} +/* +* PARAMETERS +* p_madw +* [in] Pointer to an osm_madw_t object. +* +* RETURN VALUES +* Pointer to the start of the context structure. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: MAD Wrapper/osm_madw_get_slvl_context_ptr +* NAME +* osm_madw_get_slvl_context_ptr +* +* DESCRIPTION +* Gets a pointer to the PortInfo context in this MAD. +* +* SYNOPSIS +*/ +static inline osm_slvl_context_t* +osm_madw_get_slvl_context_ptr( + IN const osm_madw_t* const p_madw ) +{ + return( (osm_slvl_context_t*)&p_madw->context ); +} +/* +* PARAMETERS +* p_madw +* [in] Pointer to an osm_madw_t object. +* +* RETURN VALUES +* Pointer to the start of the context structure. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: MAD Wrapper/osm_madw_get_vla_context_ptr +* NAME +* osm_madw_get_vla_context_ptr +* +* DESCRIPTION +* Gets a pointer to the Vl Arb context in this MAD. +* +* SYNOPSIS +*/ +static inline osm_vla_context_t* +osm_madw_get_vla_context_ptr( + IN const osm_madw_t* const p_madw ) +{ + return( (osm_vla_context_t*)&p_madw->context ); +} +/* +* PARAMETERS +* p_madw +* [in] Pointer to an osm_madw_t object. +* +* RETURN VALUES +* Pointer to the start of the context structure. +* +* NOTES +* +* SEE ALSO +*********/ + +#ifndef OSM_VENDOR_INTF_OPENIB +/****f* OpenSM: MAD Wrapper/osm_madw_get_arbitrary_context_ptr +* NAME +* osm_madw_get_arbitrary_context_ptr +* +* DESCRIPTION +* Gets a pointer to the arbitrary context in this MAD. +* +* SYNOPSIS +*/ +static inline osm_arbitrary_context_t* +osm_madw_get_arbitrary_context_ptr( + IN const osm_madw_t* const p_madw ) +{ + return( (osm_arbitrary_context_t*)&p_madw->context ); +} +/* +* PARAMETERS +* p_madw +* [in] Pointer to an osm_madw_t object. +* +* RETURN VALUES +* Pointer to the start of the context structure. +* +* NOTES +* +* SEE ALSO +*********/ +#endif + +/****f* OpenSM: MAD Wrapper/osm_madw_get_vend_ptr +* NAME +* osm_madw_get_vend_ptr +* +* DESCRIPTION +* Gets a pointer to the vendor specific MAD wrapper component. +* +* SYNOPSIS +*/ +static inline osm_vend_wrap_t* +osm_madw_get_vend_ptr( + IN const osm_madw_t* const p_madw ) +{ + return( (osm_vend_wrap_t*)&p_madw->vend_wrap ); +} +/* +* PARAMETERS +* p_madw +* [in] Pointer to an osm_madw_t object. +* +* RETURN VALUES +* Gets a pointer to the vendor specific MAD wrapper component. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: MAD Wrapper/osm_madw_get_vend_ptr +* NAME +* osm_madw_get_vend_ptr +* +* DESCRIPTION +* Returns the bind handle associated with this MAD. +* +* SYNOPSIS +*/ +static inline osm_bind_handle_t +osm_madw_get_bind_handle( + IN const osm_madw_t* const p_madw ) +{ + return( (osm_bind_handle_t)p_madw->h_bind ); +} +/* +* PARAMETERS +* p_madw +* [in] Pointer to an osm_madw_t object. +* +* RETURN VALUES +* Returns the bind handle associated with this MAD. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: MAD Wrapper/osm_madw_get_mad_addr_ptr +* NAME +* osm_madw_get_mad_addr_ptr +* +* DESCRIPTION +* Returns the mad address structure associated with this MAD. +* +* SYNOPSIS +*/ +static inline osm_mad_addr_t* +osm_madw_get_mad_addr_ptr( + IN const osm_madw_t* const p_madw ) +{ + return( (osm_mad_addr_t*)&p_madw->mad_addr ); +} +/* +* PARAMETERS +* p_madw +* [in] Pointer to an osm_madw_t object. +* +* RETURN VALUES +* Returns the mad address structure associated with this MAD. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: MAD Wrapper/osm_madw_get_mad_ptr +* NAME +* osm_madw_get_mad_ptr +* +* DESCRIPTION +* Returns the mad address structure associated with this MAD. +* +* SYNOPSIS +*/ +static inline ib_mad_t* +osm_madw_get_mad_ptr( + IN const osm_madw_t* const p_madw ) +{ + return( (ib_mad_t*)p_madw->p_mad ); +} +/* +* PARAMETERS +* p_madw +* [in] Pointer to an osm_madw_t object. +* +* RETURN VALUES +* Returns the mad address structure associated with this MAD. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: MAD Wrapper/osm_madw_get_err_msg +* NAME +* osm_madw_get_err_msg +* +* DESCRIPTION +* Returns the message with which to post this mad wrapper if +* an error occurs during processing the mad. +* +* SYNOPSIS +*/ +static inline cl_disp_msgid_t +osm_madw_get_err_msg( + IN const osm_madw_t* const p_madw ) +{ + return( (cl_disp_msgid_t)p_madw->fail_msg ); +} +/* +* PARAMETERS +* p_madw +* [in] Pointer to an osm_madw_t object. +* +* RETURN VALUES +* Returns the message with which to post this mad wrapper if +* an error occurs during processing the mad. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: MAD Wrapper/osm_madw_set_mad +* NAME +* osm_madw_set_mad +* +* DESCRIPTION +* Associates a wire MAD with this MAD Wrapper object. +* +* SYNOPSIS +*/ +static inline void +osm_madw_set_mad( + IN osm_madw_t* const p_madw, + IN const ib_mad_t* const p_mad ) +{ + p_madw->p_mad = p_mad; +} +/* +* PARAMETERS +* p_madw +* [in] Pointer to an osm_madw_t object. +* +* p_mad +* [in] Pointer to the wire MAD to attach to this wrapper. +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: MAD Wrapper/osm_madw_copy_context +* NAME +* osm_madw_copy_context +* +* DESCRIPTION +* Copies the controller context from one MAD Wrapper to another. +* +* SYNOPSIS +*/ +static inline void +osm_madw_copy_context( + IN osm_madw_t* const p_dest, + IN const osm_madw_t* const p_src ) +{ + p_dest->context = p_src->context; +} +/* +* PARAMETERS +* p_dest +* [in] Pointer to the destination osm_madw_t object. +* +* p_src +* [in] Pointer to the source osm_madw_t object. +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +END_C_DECLS + +#endif /* _OSM_MADW_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_matrix.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_matrix.h new file mode 100644 index 00000000..51ff3c0f --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_matrix.h @@ -0,0 +1,454 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_matrix.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_lid_matrix_t. + * This object represents a two dimensional array of port numbers + * and LID values. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + + +#ifndef _OSM_MATRIX_H_ +#define _OSM_MATRIX_H_ + +#include +#include +#include + +#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 lid_vec) ); + return( ((uint8_t *)cl_vector_get_ptr( + &p_lmx->lid_vec, lid_ho ))[port_num] ); +} +/* +* PARAMETERS +* p_lmx +* [in] Pointer to an osm_lid_matrix_t object. +* +* lid_ho +* [in] LID value (host order) for which to return the hop count +* +* port_num +* [in] Port number in the switch +* +* RETURN VALUES +* Returns the hop count at the specified LID/Port intersection. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: LID Matrix/osm_lid_matrix_get_max_lid_ho +* NAME +* osm_lid_matrix_get_max_lid_ho +* +* DESCRIPTION +* Returns the maximum LID (host order) value contained +* in the matrix. +* +* SYNOPSIS +*/ +static inline uint16_t +osm_lid_matrix_get_max_lid_ho( + IN const osm_lid_matrix_t* const p_lmx ) +{ + return( (uint16_t)(cl_vector_get_size( &p_lmx->lid_vec ) - 1 ) ); +} +/* +* PARAMETERS +* p_lmx +* [in] Pointer to an osm_lid_matrix_t object. +* +* RETURN VALUES +* Returns the maximum LID (host order) value contained +* in the matrix. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: LID Matrix/osm_lid_matrix_get_num_ports +* NAME +* osm_lid_matrix_get_num_ports +* +* DESCRIPTION +* Returns the number of ports in this lid matrix. +* +* SYNOPSIS +*/ +static inline uint8_t +osm_lid_matrix_get_num_ports( + IN const osm_lid_matrix_t* const p_lmx ) +{ + return( p_lmx->num_ports ); +} +/* +* PARAMETERS +* p_lmx +* [in] Pointer to an osm_lid_matrix_t object. +* +* RETURN VALUES +* Returns the number of ports in this lid matrix. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: LID Matrix/osm_lid_matrix_get_least_hops +* NAME +* osm_lid_matrix_get_least_hops +* +* DESCRIPTION +* Returns the least number of hops for specified lid +* +* SYNOPSIS +*/ +static inline uint8_t +osm_lid_matrix_get_least_hops( + IN const osm_lid_matrix_t* const p_lmx, + IN const uint16_t lid_ho ) +{ + if( lid_ho > osm_lid_matrix_get_max_lid_ho( p_lmx ) ) + return( OSM_NO_PATH ); + + return( ((uint8_t *)cl_vector_get_ptr( + &p_lmx->lid_vec, lid_ho ))[p_lmx->num_ports] ); +} +/* +* PARAMETERS +* p_lmx +* [in] Pointer to an osm_lid_matrix_t object. +* +* lid_ho +* [in] LID (host order) for which to retrieve the shortest hop count. +* +* RETURN VALUES +* Returns the least number of hops for specified lid +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: LID Matrix/osm_lid_matrix_set +* NAME +* osm_lid_matrix_set +* +* DESCRIPTION +* Sets the hop count at the specified LID/Port intersection. +* +* SYNOPSIS +*/ +cl_status_t +osm_lid_matrix_set( + IN osm_lid_matrix_t* const p_lmx, + IN const uint16_t lid_ho, + IN const uint8_t port_num, + IN const uint8_t val ); +/* +* PARAMETERS +* p_lmx +* [in] Pointer to an osm_lid_matrix_t object. +* +* lid_ho +* [in] LID value (host order) to index into the vector. +* +* port_num +* [in] port number index into the vector entry. +* +* val +* [in] value (number of hops) to assign to this entry. +* +* RETURN VALUES +* Returns the hop count at the specified LID/Port intersection. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: LID Matrix/osm_lid_matrix_set_min_lid_size +* NAME +* osm_lid_matrix_set_min_lid_size +* +* DESCRIPTION +* Sets the size of the matrix to at least accomodate the +* specified LID value (host ordered) +* +* SYNOPSIS +*/ +static inline cl_status_t +osm_lid_matrix_set_min_lid_size( + IN osm_lid_matrix_t* const p_lmx, + IN const uint16_t lid_ho ) +{ + return( cl_vector_set_min_size( &p_lmx->lid_vec, lid_ho + 1 ) ); +} +/* +* PARAMETERS +* p_lmx +* [in] Pointer to an osm_lid_matrix_t object. +* +* lid_ho +* [in] Minimum LID value (host order) to accomodate. +* +* RETURN VALUES +* Sets the size of the matrix to at least accomodate the +* specified LID value (host ordered) +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: LID Matrix/osm_lid_matrix_clear +* NAME +* osm_lid_matrix_clear +* +* DESCRIPTION +* Clears a LID Matrix object in anticipation of a rebuild. +* +* SYNOPSIS +*/ +void +osm_lid_matrix_clear( + IN osm_lid_matrix_t* const p_lmx ); +/* +* PARAMETERS +* p_lmx +* [in] Pointer to an osm_lid_matrix_t object to clear. +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +END_C_DECLS + +#endif /* _OSM_MATRIX_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcast_fwd_rcv.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcast_fwd_rcv.h new file mode 100644 index 00000000..ddc92dc8 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcast_fwd_rcv.h @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_mcast_fwd_rcv.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_mft_rcv_t. + * This object represents the Multicast Forwarding Table Receiver object. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_MFT_RCV_H_ +#define _OSM_MFT_RCV_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/MFT Receiver +* NAME +* MFT Receiver +* +* DESCRIPTION +* The MFT Receiver object encapsulates the information +* needed to receive the MFT attribute from a node. +* +* The MFT Receiver object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: MFT Receiver/osm_mft_rcv_t +* NAME +* osm_mft_rcv_t +* +* DESCRIPTION +* MFT Receiver structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_mft_rcv +{ + osm_subn_t *p_subn; + osm_log_t *p_log; + cl_plock_t *p_lock; + +} osm_mft_rcv_t; +/* +* FIELDS +* p_subn +* Pointer to the Subnet object for this subnet. +* +* p_log +* Pointer to the log object. +* +* p_lock +* Pointer to the serializing lock. +* +* SEE ALSO +* MFT Receiver object +*********/ + +/****f* OpenSM: MFT Receiver/osm_mft_rcv_construct +* NAME +* osm_mft_rcv_construct +* +* DESCRIPTION +* This function constructs a MFT Receiver object. +* +* SYNOPSIS +*/ +void +osm_mft_rcv_construct( + IN osm_mft_rcv_t* const p_rcv ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to a MFT Receiver object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_mft_rcv_init, osm_mft_rcv_destroy +* +* Calling osm_mft_rcv_construct is a prerequisite to calling any other +* method except osm_mft_rcv_init. +* +* SEE ALSO +* MFT Receiver object, osm_mft_rcv_init, +* osm_mft_rcv_destroy +*********/ + +/****f* OpenSM: MFT Receiver/osm_mft_rcv_destroy +* NAME +* osm_mft_rcv_destroy +* +* DESCRIPTION +* The osm_mft_rcv_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_mft_rcv_destroy( + IN osm_mft_rcv_t* const p_rcv ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* MFT Receiver object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_mft_rcv_construct or osm_mft_rcv_init. +* +* SEE ALSO +* MFT Receiver object, osm_mft_rcv_construct, +* osm_mft_rcv_init +*********/ + +/****f* OpenSM: MFT Receiver/osm_mft_rcv_init +* NAME +* osm_mft_rcv_init +* +* DESCRIPTION +* The osm_mft_rcv_init function initializes a +* MFT Receiver object for use. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_mft_rcv_init( + IN osm_mft_rcv_t* const p_rcv, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to an osm_mft_rcv_t object to initialize. +* +* p_subn +* [in] Pointer to the Subnet object for this subnet. +* +* p_log +* [in] Pointer to the log object. +* +* p_lock +* [in] Pointer to the OpenSM serializing lock. +* +* RETURN VALUES +* CL_SUCCESS if the MFT Receiver object was initialized +* successfully. +* +* NOTES +* Allows calling other MFT Receiver methods. +* +* SEE ALSO +* MFT Receiver object, osm_mft_rcv_construct, +* osm_mft_rcv_destroy +*********/ + +/****f* OpenSM: MFT Receiver/osm_mft_rcv_process +* NAME +* osm_mft_rcv_process +* +* DESCRIPTION +* Process the MFT attribute. +* +* SYNOPSIS +*/ +void +osm_mft_rcv_process( + IN const osm_mft_rcv_t* const p_rcv, + IN osm_madw_t* const p_madw ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to an osm_mft_rcv_t object. +* +* p_madw +* [in] Pointer to the MAD Wrapper containing the MAD +* that contains the node's MFT attribute. +* +* RETURN VALUES +* CL_SUCCESS if the MFT processing was successful. +* +* NOTES +* This function processes a MFT attribute. +* +* SEE ALSO +* MFT Receiver, Node Description Response Controller +*********/ + +END_C_DECLS + +#endif /* _OSM_MFT_RCV_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcast_fwd_rcv_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcast_fwd_rcv_ctrl.h new file mode 100644 index 00000000..11f3bcb1 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcast_fwd_rcv_ctrl.h @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_mcast_fwd_rcv_ctrl.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_mft_rcv_ctrl_t. + * This object represents a controller that receives the IBA + * Multicast Forwarding Table attribute from a node (specifically, a + * switch). + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_MFT_RCV_CTRL_H_ +#define _OSM_MFT_RCV_CTRL_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/MFT Receive Controller +* NAME +* MFT Receive Controller +* +* DESCRIPTION +* The MFT Receive Controller object +* encapsulates the information +* needed to receive the Multicast Forwarding Table +* attribute from a node. +* +* The MFT Receive Controller object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: MFT Receive Controller/osm_mft_rcv_ctrl_t +* NAME +* osm_mft_rcv_ctrl_t +* +* DESCRIPTION +* MFT Receive Controller structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_mft_rcv_ctrl +{ + osm_mft_rcv_t *p_rcv; + osm_log_t *p_log; + cl_dispatcher_t *p_disp; + cl_disp_reg_handle_t h_disp; + +} osm_mft_rcv_ctrl_t; +/* +* FIELDS +* p_rcv +* Pointer to the MFT Receiver object. +* +* p_log +* Pointer to the log object. +* +* p_disp +* Pointer to the Dispatcher. +* +* h_disp +* Handle returned from dispatcher registration. +* +* SEE ALSO +* MFT Receive Controller object +*********/ + +/****f* OpenSM: MFT Receive Controller/osm_mft_rcv_ctrl_construct +* NAME +* osm_mft_rcv_ctrl_construct +* +* DESCRIPTION +* This function constructs a MFT Receive Controller object. +* +* SYNOPSIS +*/ +void +osm_mft_rcv_ctrl_construct( + IN osm_mft_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a MFT Receive Controller object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_mft_rcv_ctrl_init, osm_mft_rcv_ctrl_destroy +* +* Calling osm_mft_rcv_ctrl_construct is a prerequisite to calling any other +* method except osm_mft_rcv_ctrl_init. +* +* SEE ALSO +* MFT Receive Controller object, osm_mft_rcv_ctrl_init, +* osm_mft_rcv_ctrl_destroy +*********/ + +/****f* OpenSM: MFT Receive Controller/osm_mft_rcv_ctrl_destroy +* NAME +* osm_mft_rcv_ctrl_destroy +* +* DESCRIPTION +* The osm_mft_rcv_ctrl_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_mft_rcv_ctrl_destroy( + IN osm_mft_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* MFT Receive Controller object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_mft_rcv_ctrl_construct or osm_mft_rcv_ctrl_init. +* +* SEE ALSO +* MFT Receive Controller object, osm_mft_rcv_ctrl_construct, +* osm_mft_rcv_ctrl_init +*********/ + +/****f* OpenSM: MFT Receive Controller/osm_mft_rcv_ctrl_init +* NAME +* osm_mft_rcv_ctrl_init +* +* DESCRIPTION +* The osm_mft_rcv_ctrl_init function initializes a +* MFT Receive Controller object for use. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_mft_rcv_ctrl_init( + IN osm_mft_rcv_ctrl_t* const p_ctrl, + IN osm_mft_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_mft_rcv_ctrl_t object to initialize. +* +* p_rcv +* [in] Pointer to an osm_mft_rcv_t object. +* +* p_log +* [in] Pointer to the log object. +* +* p_disp +* [in] Pointer to the OpenSM central Dispatcher. +* +* RETURN VALUES +* CL_SUCCESS if the MFT Receive Controller object was initialized +* successfully. +* +* NOTES +* Allows calling other MFT Receive Controller methods. +* +* SEE ALSO +* MFT Receive Controller object, osm_mft_rcv_ctrl_construct, +* osm_mft_rcv_ctrl_destroy +*********/ + +END_C_DECLS + +#endif /* OSM_MFT_RCV_CTRL_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcast_mgr.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcast_mgr.h new file mode 100644 index 00000000..d0adc6be --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcast_mgr.h @@ -0,0 +1,339 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_mcast_mgr.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_mcast_mgr_t. + * This object represents the Multicast Manager object. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_MCAST_MGR_H_ +#define _OSM_MCAST_MGR_H_ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +#define OSM_MCAST_MGR_LIST_SIZE_MIN 256 + +/****h* OpenSM/Multicast Manager +* NAME +* Multicast Manager +* +* DESCRIPTION +* The Multicast Manager object encapsulates the information +* needed to control multicast LID forwarding on the subnet. +* +* The Multicast Manager object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: Multicast Manager/osm_mcast_mgr_t +* NAME +* osm_mcast_mgr_t +* +* DESCRIPTION +* Multicast Manager structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_mcast_mgr +{ + osm_subn_t *p_subn; + osm_req_t *p_req; + osm_log_t *p_log; + cl_plock_t *p_lock; + +} osm_mcast_mgr_t; +/* +* FIELDS +* p_subn +* Pointer to the Subnet object for this subnet. +* +* p_req +* Pointer to the Requester object sending SMPs. +* +* p_log +* Pointer to the log object. +* +* p_lock +* Pointer to the serializing lock. +* +* SEE ALSO +* Multicast Manager object +*********/ + +/****f* OpenSM: Multicast Manager/osm_mcast_mgr_construct +* NAME +* osm_mcast_mgr_construct +* +* DESCRIPTION +* This function constructs a Multicast Manager object. +* +* SYNOPSIS +*/ +void +osm_mcast_mgr_construct( + IN osm_mcast_mgr_t* const p_mgr ); +/* +* PARAMETERS +* p_mgr +* [in] Pointer to a Multicast Manager object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows osm_mcast_mgr_destroy +* +* Calling osm_mcast_mgr_construct is a prerequisite to calling any other +* method except osm_mcast_mgr_init. +* +* SEE ALSO +* Multicast Manager object, osm_mcast_mgr_init, +* osm_mcast_mgr_destroy +*********/ + +/****f* OpenSM: Multicast Manager/osm_mcast_mgr_destroy +* NAME +* osm_mcast_mgr_destroy +* +* DESCRIPTION +* The osm_mcast_mgr_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_mcast_mgr_destroy( + IN osm_mcast_mgr_t* const p_mgr ); +/* +* PARAMETERS +* p_mgr +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* Multicast Manager object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_mcast_mgr_construct or osm_mcast_mgr_init. +* +* SEE ALSO +* Multicast Manager object, osm_mcast_mgr_construct, +* osm_mcast_mgr_init +*********/ + +/****f* OpenSM: Multicast Manager/osm_mcast_mgr_init +* NAME +* osm_mcast_mgr_init +* +* DESCRIPTION +* The osm_mcast_mgr_init function initializes a +* Multicast Manager object for use. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_mcast_mgr_init( + IN osm_mcast_mgr_t* const p_mgr, + IN osm_req_t* const p_req, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ); +/* +* PARAMETERS +* p_mgr +* [in] Pointer to an osm_mcast_mgr_t object to initialize. +* +* p_req +* [in] Pointer to the attribute Requester object. +* +* p_subn +* [in] Pointer to the Subnet object for this subnet. +* +* p_log +* [in] Pointer to the log object. +* +* p_lock +* [in] Pointer to the OpenSM serializing lock. +* +* RETURN VALUES +* IB_SUCCESS if the Multicast Manager object was initialized +* successfully. +* +* NOTES +* Allows calling other Multicast Manager methods. +* +* SEE ALSO +* Multicast Manager object, osm_mcast_mgr_construct, +* osm_mcast_mgr_destroy +*********/ + +/****f* OpenSM: Multicast Manager/osm_mcast_mgr_process +* NAME +* osm_mcast_mgr_process +* +* DESCRIPTION +* Process and configure the subnet's multicast forwarding tables. +* +* SYNOPSIS +*/ +osm_signal_t +osm_mcast_mgr_process( + IN osm_mcast_mgr_t* const p_mgr ); +/* +* PARAMETERS +* p_mgr +* [in] Pointer to an osm_mcast_mgr_t object. +* +* RETURN VALUES +* Returns the appropriate signal to the caller: +* OSM_SIGNAL_DONE - operation is complete +* OSM_SIGNAL_DONE_PENDING - local operations are complete, but +* transactions are still pending on the wire. +* +* NOTES +* This function processes the subnet, configuring switch +* multicast forwarding tables. +* +* SEE ALSO +* Multicast Manager, Node Info Response Controller +*********/ + +/****f* OpenSM: Multicast Manager/osm_mcast_mgr_process_mgrp_cb +* NAME +* osm_mcast_mgr_process_mgrp_cb +* +* DESCRIPTION +* Callback entry point for the osm_mcast_mgr_process_mgrp function. +* +* SYNOPSIS +*/ +osm_signal_t +osm_mcast_mgr_process_mgrp_cb( + IN void* const Context1, + IN void* const Context2 ); +/* +* PARAMETERS +* (Context1) p_mgr +* [in] Pointer to an osm_mcast_mgr_t object. +* +* (Context2) p_mgrp +* [in] Pointer to the multicast group to process. +* +* RETURN VALUES +* IB_SUCCESS +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Multicast Manager/osm_mcast_mgr_process +* NAME +* osm_mcast_mgr_process_single +* +* DESCRIPTION +* Attempts to add a single port to an existing multicast spanning tree. +* This function can only succeed if the port to be added is connected +* to a switch that is already routing traffic for this multicast group. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_mcast_mgr_process_single( + IN osm_mcast_mgr_t* const p_mgr, + IN const ib_net16_t mlid, + IN const ib_net64_t port_guid, + IN const uint8_t join_state ); +/* +* PARAMETERS +* p_mgr +* [in] Pointer to an osm_mcast_mgr_t object. +* +* mlid +* [in] Multicast LID of relevent multicast group. +* +* port_guid +* [in] GUID of port to attempt to add to the group. +* +* join_state +* [in] Specifies the join state for this port per the spec. +* +* RETURN VALUES +* IB_SUCCESS +* IB_NOT_DONE +* +* NOTES +* +* SEE ALSO +*********/ + +END_C_DECLS + +#endif /* _OSM_MCAST_MGR_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcast_tbl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcast_tbl.h new file mode 100644 index 00000000..efb6d23e --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcast_tbl.h @@ -0,0 +1,484 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_mcast_tbl.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_mcast_tbl_t. + * This object represents a multicast forwarding table. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + +#ifndef _OSM_MCAST_TBL_H_ +#define _OSM_MCAST_TBL_H_ + +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****s* OpenSM: Forwarding Table/osm_mcast_tbl_t +* NAME +* osm_mcast_tbl_t +* +* DESCRIPTION +* Multicast Forwarding Table structure. +* +* Callers may directly access this object. +* +* SYNOPSIS +*/ +typedef struct _osm_mcast_fwd_tbl +{ + uint8_t num_ports; + uint8_t max_position; + uint16_t max_block; + int16_t max_block_in_use; + uint16_t num_entries; + uint16_t max_mlid_ho; + uint16_t (*p_mask_tbl)[][IB_MCAST_POSITION_MAX]; +} osm_mcast_tbl_t; +/* +* FIELDS +* num_ports +* The number of ports in the port mask. This value +* is the same as the number of ports on the switch +* +* max_position +* Maximum bit mask position for this table. This value +* is computed from the number of ports on the switch. +* +* max_block +* Maximum block number supported in the table. This value +* is approximately the number of MLID entries divided by the +* number of MLIDs per block +* +* num_entries +* Number of entries in the table (aka number of MLIDs supported). +* +* max_mlid_ho +* Maximum MLID value (host order). +* +* pp_mask_tbl +* Pointer to a two dimensional array of port_masks for this switch. +* The first dimension is MLID, the second dimension is mask position. +* This pointer is null for switches that do not support multicast. +* +* SEE ALSO +*********/ + +/****f* OpenSM: Forwarding Table/osm_mcast_tbl_init +* NAME +* osm_mcast_tbl_init +* +* DESCRIPTION +* This function initializes a Multicast Forwarding Table object. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_mcast_tbl_init( + IN osm_mcast_tbl_t* const p_tbl, + IN uint8_t const num_ports, + IN uint16_t const capacity ); +/* +* PARAMETERS +* num_ports +* [in] Number of ports in the switch owning this table. +* +* capacity +* [in] The number of MLID entries (starting at 0xC000) supported +* by this switch. +* +* RETURN VALUE +* IB_SUCCESS on success. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Forwarding Table/osm_mcast_tbl_delete +* NAME +* osm_mcast_tbl_delete +* +* DESCRIPTION +* This destroys and deallocates a Multicast Forwarding Table object. +* +* SYNOPSIS +*/ +void +osm_mcast_tbl_delete( + IN osm_mcast_tbl_t** const pp_tbl ); +/* +* PARAMETERS +* pp_tbl +* [in] Pointer a Pointer to the Multicast Forwarding Table object. +* +* RETURN VALUE +* On success, returns a pointer to a new Multicast Forwarding Table object +* of the specified size. +* NULL otherwise. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Forwarding Table/osm_mcast_tbl_destroy +* NAME +* osm_mcast_tbl_destroy +* +* DESCRIPTION +* This destroys and deallocates a Multicast Forwarding Table object. +* +* SYNOPSIS +*/ +void +osm_mcast_tbl_destroy( + IN osm_mcast_tbl_t* const p_tbl ); +/* +* PARAMETERS +* p_tbl +* [in] Pointer to the Multicast Forwarding Table object. +* +* RETURN VALUE +* None +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Forwarding Table/osm_mcast_tbl_set +* NAME +* osm_mcast_tbl_set +* +* DESCRIPTION +* Adds the port to the multicast group. +* +* SYNOPSIS +*/ +void +osm_mcast_tbl_set( + IN osm_mcast_tbl_t* const p_tbl, + IN const uint16_t mlid_ho, + IN const uint8_t port_num ); +/* +* PARAMETERS +* p_tbl +* [in] Pointer to the Multicast Forwarding Table object. +* +* mlid_ho +* [in] MLID value (host order) for which to set the route. +* +* port_num +* [in] Port to add to the multicast group. +* +* RETURN VALUE +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Forwarding Table/osm_mcast_tbl_clear_mlid +* NAME +* osm_mcast_tbl_clear_mlid +* +* DESCRIPTION +* Removes all multicast paths for the specified MLID. +* +* SYNOPSIS +*/ +void +osm_mcast_tbl_clear_mlid( + IN osm_mcast_tbl_t* const p_tbl, + IN const uint16_t mlid_ho ); +/* +* PARAMETERS +* p_tbl +* [in] Pointer to the Multicast Forwarding Table object. +* +* mlid_ho +* [in] MLID value (host order) for which to clear. +* +* RETURN VALUE +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Forwarding Table/osm_mcast_tbl_is_port +* NAME +* osm_mcast_tbl_is_port +* +* DESCRIPTION +* Returns TRUE if the port is in the multicast group. +* +* SYNOPSIS +*/ +boolean_t +osm_mcast_tbl_is_port( + IN const osm_mcast_tbl_t* const p_tbl, + IN const uint16_t mlid_ho, + IN const uint8_t port_num ); +/* +* PARAMETERS +* p_tbl +* [in] Pointer to the Multicast Forwarding Table object. +* +* mlid_ho +* [in] MLID value (host order). +* +* port_num +* [in] Port number on the switch +* +* RETURN VALUE +* Returns the port that routes the specified LID. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Forwarding Table/osm_mcast_tbl_is_any_port +* NAME +* osm_mcast_tbl_is_any_port +* +* DESCRIPTION +* Returns TRUE if any port is in the multicast group. +* +* SYNOPSIS +*/ +boolean_t +osm_mcast_tbl_is_any_port( + IN const osm_mcast_tbl_t* const p_tbl, + IN const uint16_t mlid_ho ); +/* +* PARAMETERS +* p_tbl +* [in] Pointer to the Multicast Forwarding Table object. +* +* mlid_ho +* [in] MLID value (host order). +* +* RETURN VALUE +* Returns TRUE if any port is in the multicast group. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Forwarding Table/osm_mcast_tbl_set_block +* NAME +* osm_mcast_tbl_set_block +* +* DESCRIPTION +* Copies the specified block into the Multicast Forwarding Table. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_mcast_tbl_set_block( + IN osm_mcast_tbl_t* const p_tbl, + IN const ib_net16_t* const p_block, + IN const int16_t block_num, + IN const uint8_t position ); +/* +* PARAMETERS +* p_tbl +* [in] Pointer to the Multicast Forwarding Table object. +* +* p_block +* [in] Pointer to the Forwarding Table block. +* +* block_num +* [in] Block number of this block. +* +* RETURN VALUE +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Forwarding Table/osm_mcast_get_tbl_block +* NAME +* osm_mcast_get_tbl_block +* +* DESCRIPTION +* Retrieve a multicast forwarding table block. +* +* SYNOPSIS +*/ +boolean_t +osm_mcast_tbl_get_block( + IN osm_mcast_tbl_t* const p_tbl, + IN const int16_t block_num, + IN const uint8_t position, + OUT ib_net16_t* const p_block ); +/* +* PARAMETERS +* p_tbl +* [in] Pointer to an osm_mcast_tbl_t object. +* +* p_block +* [in] Pointer to the Forwarding Table block. +* +* block_num +* [in] Block number of this block. +* +* p_block +* [out] Pointer to the 32 entry array to store the +* forwarding table clock specified by block_id. +* +* RETURN VALUES +* Returns true if there are more blocks necessary to +* configure all the MLIDs reachable from this switch. +* FALSE otherwise. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Forwarding Table/osm_mcast_tbl_get_max_block +* NAME +* osm_mcast_tbl_get_max_block +* +* DESCRIPTION +* Returns the maximum block ID in this table. +* +* SYNOPSIS +*/ +static inline uint16_t +osm_mcast_tbl_get_max_block( + IN osm_mcast_tbl_t* const p_tbl ) +{ + return( p_tbl->max_block ); +} +/* +* PARAMETERS +* p_tbl +* [in] Pointer to an osm_mcast_tbl_t object. +* +* RETURN VALUES +* Returns the maximum block ID in this table. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Forwarding Table/osm_mcast_tbl_get_max_block_in_use +* NAME +* osm_mcast_tbl_get_max_block_in_use +* +* DESCRIPTION +* Returns the maximum block ID in use in this table. +* A value of -1 indicates no blocks are in use. +* +* SYNOPSIS +*/ +static inline int16_t +osm_mcast_tbl_get_max_block_in_use( + IN osm_mcast_tbl_t* const p_tbl ) +{ + return( p_tbl->max_block_in_use ); +} +/* +* PARAMETERS +* p_tbl +* [in] Pointer to an osm_mcast_tbl_t object. +* +* RETURN VALUES +* Returns the maximum block ID in use in this table. +* A value of -1 indicates no blocks are in use. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Forwarding Table/osm_mcast_tbl_get_max_position +* NAME +* osm_mcast_tbl_get_max_position +* +* DESCRIPTION +* Returns the maximum position in this table. +* +* SYNOPSIS +*/ +static inline uint8_t +osm_mcast_tbl_get_max_position( + IN osm_mcast_tbl_t* const p_tbl ) +{ + return( p_tbl->max_position ); +} +/* +* PARAMETERS +* p_tbl +* [in] Pointer to an osm_mcast_tbl_t object. +* +* RETURN VALUES +* Returns the maximum position in this table. +* +* NOTES +* +* SEE ALSO +*********/ + +END_C_DECLS + +#endif /* _OSM_MCAST_TBL_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcm_info.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcm_info.h new file mode 100644 index 00000000..e2a7f7cd --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcm_info.h @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_mcm_info.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_mcm_info_t. + * This object represents a Multicast Forwarding Information object. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_MCM_INFO_H_ +#define _OSM_MCM_INFO_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****s* OpenSM: Multicast Member Info/osm_mcm_info_t +* NAME +* osm_mcm_info_t +* +* DESCRIPTION +* Multicast Membership Info object. +* This object contains information about a nodes membership +* in a particular multicast group. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_mcm_info +{ + cl_list_item_t list_item; + ib_net16_t mlid; + +} osm_mcm_info_t; +/* +* FIELDS +* list_item +* Linkage structure for cl_qlist. MUST BE FIRST MEMBER! +* +* mlid +* MLID of this multicast group. +* +* SEE ALSO +*********/ + +/****f* OpenSM: Multicast Member Info/osm_mcm_info_construct +* NAME +* osm_mcm_info_construct +* +* DESCRIPTION +* This function constructs a Multicast Member Info object. +* +* SYNOPSIS +*/ +static inline void +osm_mcm_info_construct( + IN osm_mcm_info_t* const p_mcm ) +{ + memset( p_mcm, 0, sizeof(*p_mcm) ); +} +/* +* PARAMETERS +* p_mcm +* [in] Pointer to a Multicast Member Info object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Multicast Member Info/osm_mcm_info_destroy +* NAME +* osm_mcm_info_destroy +* +* DESCRIPTION +* The osm_mcm_info_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_mcm_info_destroy( + IN osm_mcm_info_t* const p_mcm ); +/* +* PARAMETERS +* p_mcm +* [in] Pointer to a Multicast Member Info object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified Multicast Member Info object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to osm_mtree_construct or +* osm_mtree_init. +* +* SEE ALSO +* Multicast Member Info object, osm_mtree_construct, osm_mtree_init +*********/ + +/****f* OpenSM: Multicast Member Info/osm_mcm_info_init +* NAME +* osm_mcm_info_init +* +* DESCRIPTION +* Initializes a Multicast Member Info object for use. +* +* SYNOPSIS +*/ +void +osm_mcm_info_init( + IN osm_mcm_info_t* const p_mcm, + IN const ib_net16_t mlid ); +/* +* PARAMETERS +* p_mcm +* [in] Pointer to an osm_mcm_info_t object to initialize. +* +* mlid +* [in] MLID value for this multicast group. +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Multicast Member Info/osm_mcm_info_new +* NAME +* osm_mcm_info_new +* +* DESCRIPTION +* Returns an initialized a Multicast Member Info object for use. +* +* SYNOPSIS +*/ +osm_mcm_info_t* +osm_mcm_info_new( + IN const ib_net16_t mlid ); +/* +* PARAMETERS +* mlid +* [in] MLID value for this multicast group. +* +* RETURN VALUES +* Pointer to an initialized tree node. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Multicast Member Info/osm_mcm_info_delete +* NAME +* osm_mcm_info_delete +* +* DESCRIPTION +* Destroys and deallocates the specified object. +* +* SYNOPSIS +*/ +void +osm_mcm_info_delete( + IN osm_mcm_info_t* const p_mcm ); +/* +* PARAMETERS +* p_mcm +* Pointer to the object to destroy. +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +END_C_DECLS + +#endif /* _OSM_MCM_INFO_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcm_port.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcm_port.h new file mode 100644 index 00000000..006c5713 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcm_port.h @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_mcm_port.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_mcm_port_t. + * This object represents the membership of a port in a multicast group. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_MCM_PORT_H_ +#define _OSM_MCM_PORT_H_ + +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****s* OpenSM: MCM Port Object/osm_mcm_port_t +* NAME +* osm_mcm_port_t +* +* DESCRIPTION +* This object represents a particular port as a member of a +* multicast group. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_mcm_port +{ + cl_map_item_t map_item; + ib_gid_t port_gid; + uint8_t scope_state; + boolean_t proxy_join; +} osm_mcm_port_t; +/* +* FIELDS +* map_item +* Map Item for qmap linkage. Must be first element!! +* +* port_gid +* GID of the member port. +* +* scope_state +* ??? +* +* proxy_join +* If FALSE - Join was performed by the endport identified +* by PortGID. If TRUE - Join was performed on behalf of +* the endport identified by PortGID by another port within +* the same partition. +* +* SEE ALSO +* MCM Port Object +*********/ + +/****f* OpenSM: MCM Port Object/osm_mcm_port_construct +* NAME +* osm_mcm_port_construct +* +* DESCRIPTION +* This function constructs a MCM Port object. +* +* SYNOPSIS +*/ +void +osm_mcm_port_construct( + IN osm_mcm_port_t* const p_mcm ); +/* +* PARAMETERS +* p_mcm +* [in] Pointer to a MCM Port Object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_mcm_port_init, osm_mcm_port_destroy. +* +* Calling osm_mcm_port_construct is a prerequisite to calling any other +* method except osm_mcm_port_init. +* +* SEE ALSO +* MCM Port Object, osm_mcm_port_init, osm_mcm_port_destroy +*********/ + +/****f* OpenSM: MCM Port Object/osm_mcm_port_destroy +* NAME +* osm_mcm_port_destroy +* +* DESCRIPTION +* The osm_mcm_port_destroy function destroys a MCM Port Object, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_mcm_port_destroy( + IN osm_mcm_port_t* const p_mcm ); +/* +* PARAMETERS +* p_mcm +* [in] Pointer to a MCM Port Object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified MCM Port Object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_mcm_port_construct or osm_mcm_port_init. +* +* SEE ALSO +* MCM Port Object, osm_mcm_port_construct, osm_mcm_port_init +*********/ + +/****f* OpenSM: MCM Port Object/osm_mcm_port_init +* NAME +* osm_mcm_port_init +* +* DESCRIPTION +* The osm_mcm_port_init function initializes a MCM Port Object for use. +* +* SYNOPSIS +*/ +void +osm_mcm_port_init( + IN osm_mcm_port_t* const p_mcm, + IN const ib_gid_t* const p_port_gid, + IN const uint8_t scope_state, + IN const boolean_t proxy_join ); +/* +* PARAMETERS +* p_mcm +* [in] Pointer to an osm_mcm_port_t object to initialize. +* +* p_port_gid +* [in] Pointer to the GID of the port to add to the multicast group. +* +* scope_state +* [in] scope state of the join request +* +* proxy_join +* [in] proxy_join state analyzed from the request +* +* RETURN VALUES +* None. +* +* NOTES +* Allows calling other MCM Port Object methods. +* +* SEE ALSO +* MCM Port Object, osm_mcm_port_construct, osm_mcm_port_destroy, +*********/ + +/****f* OpenSM: MCM Port Object/osm_mcm_port_init +* NAME +* osm_mcm_port_init +* +* DESCRIPTION +* The osm_mcm_port_init function initializes a MCM Port Object for use. +* +* SYNOPSIS +*/ +osm_mcm_port_t* +osm_mcm_port_new( + IN const ib_gid_t* const p_port_gid, + IN const uint8_t scope_state, + IN const boolean_t proxy_join ); +/* +* PARAMETERS +* p_port_gid +* [in] Pointer to the GID of the port to add to the multicast group. +* +* scope_state +* [in] scope state of the join request +* +* proxy_join +* [in] proxy_join state analyzed from the request +* +* RETURN VALUES +* Pointer to the allocated and initialized MCM Port object. +* +* NOTES +* +* SEE ALSO +* MCM Port Object, osm_mcm_port_construct, osm_mcm_port_destroy, +*********/ + +/****f* OpenSM: MCM Port Object/osm_mcm_port_destroy +* NAME +* osm_mcm_port_destroy +* +* DESCRIPTION +* The osm_mcm_port_destroy function destroys and dellallocates an +* MCM Port Object, releasing all resources. +* +* SYNOPSIS +*/ +void +osm_mcm_port_delete( + IN osm_mcm_port_t* const p_mcm ); +/* +* PARAMETERS +* p_mcm +* [in] Pointer to a MCM Port Object to delete. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* +* SEE ALSO +* MCM Port Object, osm_mcm_port_construct, osm_mcm_port_init +*********/ + +END_C_DECLS + +#endif /* _OSM_MCM_PORT_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_msgdef.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_msgdef.h new file mode 100644 index 00000000..efd672db --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_msgdef.h @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_msgdef.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of Dispatcher message values. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + +#ifndef _OSM_MSGDEF_H_ +#define _OSM_MSGDEF_H_ + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Dispatcher Messages +* NAME +* Dispatcher Messages +* +* DESCRIPTION +* These constants define the messages sent between OpenSM controllers +* attached to the Dispatcher. +* +* Each message description contains the following information: +* Sent by: which controller(s) send this message +* Received by: which controller receives this message +* Delivery notice: Indicates if the sender requires confirmation +* that the message has been delivered. Typically a "yes" here +* means that some resources associated with sending the +* message must be freed. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: Dispatcher Messages/OSM_MSG_REQ +* NAME +* OSM_MSG_REQ +* +* DESCRIPTION +* Initiates a QP0 attribute request. +* +* NOTES +* Sent by: osm_sm_t +* Received by: osm_req_ctrl_t +* Delivery notice: yes +* +***********/ + +/****s* OpenSM: Dispatcher Messages/OSM_MSG_MAD_NODE_INFO +* NAME +* OSM_MSG_MAD_NODE_INFO +* +* DESCRIPTION +* Message for received NodeInfo MADs. +* +* NOTES +* Sent by: osm_mad_ctrl_t +* Received by: osm_ni_rcv_ctrl_t +* Delivery notice: yes +* +* +***********/ + +/****s* OpenSM: Dispatcher Messages/OSM_MSG_MAD_PORT_INFO +* NAME +* OSM_MSG_MAD_PORT_INFO +* +* DESCRIPTION +* Message for received PortInfo MADs. +* +* NOTES +* Sent by: osm_mad_ctrl_t +* Received by: osm_pi_rcv_ctrl_t +* Delivery notice: yes +* +* +***********/ + +/****s* OpenSM: Dispatcher Messages/OSM_MSG_MAD_SWITCH_INFO +* NAME +* OSM_MSG_MAD_SWITCH_INFO +* +* DESCRIPTION +* Message for received SwitchInfo MADs. +* +* NOTES +* Sent by: osm_mad_ctrl_t +* Received by: osm_si_rcv_ctrl_t +* Delivery notice: yes +* +***********/ + +/****s* OpenSM: Dispatcher Messages/OSM_MSG_MAD_NODE_DESC +* NAME +* OSM_MSG_MAD_NODE_DESC +* +* DESCRIPTION +* Message for received NodeDescription MADs. +* +* NOTES +* Sent by: osm_mad_ctrl_t +* Received by: osm_nd_rcv_ctrl_t +* Delivery notice: yes +* +* SOURCE +***********/ + +/****d* OpenSM: Dispatcher Messages/OSM_MSG_NO_SMPS_OUTSTANDING +* NAME +* OSM_MSG_NO_SMPS_OUTSTANDING +* +* DESCRIPTION +* Message indicating that there are no outstanding SMPs on the subnet. +* +* NOTES +* Sent by: osm_mad_ctrl_t +* Received by: osm_state_mgr_ctrl_t +* Delivery notice: no +* +* SOURCE +***********/ +enum +{ + OSM_MSG_REQ = 0, + OSM_MSG_MAD_NODE_INFO, + OSM_MSG_MAD_PORT_INFO, + OSM_MSG_MAD_SWITCH_INFO, + OSM_MSG_MAD_NODE_DESC, + OSM_MSG_NO_SMPS_OUTSTANDING, + OSM_MSG_MAD_NODE_RECORD, + OSM_MSG_MAD_PORTINFO_RECORD, + OSM_MSG_MAD_SERVICE_RECORD, + OSM_MSG_MAD_PATH_RECORD, + OSM_MSG_MAD_MCMEMBER_RECORD, + OSM_MSG_MAD_LINK_RECORD, + OSM_MSG_MAD_SMINFO_RECORD, + OSM_MSG_MAD_CLASS_PORT_INFO, + OSM_MSG_MAD_INFORM_INFO, + OSM_MSG_MAD_LFT_RECORD, + OSM_MSG_MAD_LFT, + OSM_MSG_MAD_SM_INFO, + OSM_MSG_MAD_NOTICE, + OSM_MSG_LIGHT_SWEEP_FAIL, + OSM_MSG_MAD_MFT, + OSM_MSG_MAD_PKEY_TBL_RECORD, + OSM_MSG_MAD_VL_ARB_RECORD, + OSM_MSG_MAD_SLVL_TBL_RECORD, + OSM_MSG_MAD_PKEY, + OSM_MSG_MAD_VL_ARB, + OSM_MSG_MAD_SLVL, + OSM_MSG_MAD_GUIDINFO_RECORD, + OSM_MSG_MAD_INFORM_INFO_RECORD, + OSM_MSG_MAD_SWITCH_INFO_RECORD, + OSM_MSG_MAD_MFT_RECORD, +#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP) + OSM_MSG_MAD_MULTIPATH_RECORD, +#endif + OSM_MSG_MAX +}; + +END_C_DECLS + +#endif /* _OSM_MSGDEF_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mtl_bind.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mtl_bind.h new file mode 100644 index 00000000..021b22a5 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mtl_bind.h @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_mtl_bind.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +#ifndef _OSM_BIND_H_ +#define _OSM_BIND_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****s* OpenSM: Vendor/osm_vendor_mgt_bind +* NAME +* osm_vendor_mgt_bind_t +* +* DESCRIPTION +* Tracks the handles returned by IB_MGT to the SMI and GSI +* Nulled on init of the vendor obj. Populated on first bind. +* +* SYNOPSIS +*/ +typedef struct _osm_vendor_mgt_bind +{ + boolean_t smi_init, gsi_init; + IB_MGT_mad_hndl_t smi_mads_hdl; + IB_MGT_mad_hndl_t gsi_mads_hdl; + struct _osm_mtl_bind_info *smi_p_bind; +} +osm_vendor_mgt_bind_t; + +/* +* FIELDS +* smi_mads_hdl +* Handle returned by IB_MGT_get_handle to the IB_MGT_SMI +* +* gsi_mads_hdl +* Handle returned by IB_MGT_get_handle to the IB_MGT_GSI +* +* SEE ALSO +*********/ + +/****s* OpenSM: Vendor osm_mtl_bind_info_t +* NAME +* osm_mtl_bind_info_t +* +* DESCRIPTION +* Handle to the result of binding a class callbacks to IB_MGT. +* +* SYNOPSIS +*/ +typedef struct _osm_mtl_bind_info +{ + IB_MGT_mad_hndl_t mad_hndl; + osm_vendor_t *p_vend; + void *client_context; + VAPI_hca_hndl_t hca_hndl; + VAPI_hca_id_t hca_id; + uint8_t port_num; + osm_vend_mad_recv_callback_t rcv_callback; + osm_vend_mad_send_err_callback_t send_err_callback; + osm_mad_pool_t *p_osm_pool; +} +osm_mtl_bind_info_t; + +/* +* FIELDS +* mad_hndl +* the handle returned from the registration in IB_MGT +* +* p_vend +* Pointer to the vendor object. +* +* client_context +* User's context passed during osm_bind +* +* hca_id +* HCA Id we bind to. +* +* port_num +* Port number (within the HCA) of the bound port. +* +* rcv_callback +* OSM Callback function to be called on receive of MAD. +* +* send_err_callback +* OSM Callback to be called on send error. +* +* p_osm_pool +* Points to the MAD pool used by OSM +* +* +* SEE ALSO +*********/ +ib_api_status_t +osm_mtl_send_mad( + IN osm_mtl_bind_info_t *p_bind, + IN osm_madw_t * const p_madw); + +END_C_DECLS + +#endif // _OSM_BIND_H_ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mtree.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mtree.h new file mode 100644 index 00000000..8365a977 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mtree.h @@ -0,0 +1,378 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_mtree.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_mtree_t. + * This object represents multicast spanning tree. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_MTREE_H_ +#define _OSM_MTREE_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +#define OSM_MTREE_LEAF ((void*)-1) + +/****h* OpenSM/Multicast Tree +* NAME +* Multicast Tree +* +* DESCRIPTION +* The Multicast Tree object encapsulates the information needed by the +* OpenSM to manage multicast fabric routes. It is a tree structure +* in which each node in the tree represents a switch, and may have a +* varying number of children. +* +* Multicast trees do not contain loops. +* +* The Multicast Tree is not thread safe, thus callers must provide +* serialization. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: Multicast Tree/osm_mtree_node_t +* NAME +* osm_mtree_node_t +* +* DESCRIPTION +* The MTree Node object encapsulates the information needed by the +* OpenSM for a particular switch in the multicast tree. +* +* The MTree Node object is not thread safe, thus callers must provide +* serialization. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_mtree_node +{ + cl_map_item_t map_item; + osm_switch_t *p_sw; + uint8_t max_children; + struct _osm_mtree_node *p_up; + struct _osm_mtree_node *child_array[1]; +} osm_mtree_node_t; +/* +* FIELDS +* map_item +* Linkage for quick map. MUST BE FIRST ELEMENT!!! +* +* p_sw +* Pointer to the switch represented by this tree node. +* +* max_children +* Maximum number of child nodes of this node. Equal to the +* the number of ports on the switch if the switch supports +* multicast. Equal to 1 (default route) if the switch does +* not support multicast. +* +* p_up +* Pointer to the parent of this node. If this pointer is +* NULL, the node is at the root of the tree. +* +* child_array +* Array (indexed by port number) of pointers to the +* child osm_mtree_node_t objects of this tree node, if any. +* +* SEE ALSO +*********/ + +/****f* OpenSM: Multicast Tree/osm_mtree_node_construct +* NAME +* osm_mtree_node_construct +* +* DESCRIPTION +* This function constructs a Multicast Tree Node object. +* +* SYNOPSIS +*/ +static inline void +osm_mtree_node_construct( + IN osm_mtree_node_t* const p_mtn ) +{ + memset( p_mtn, 0, sizeof(*p_mtn) ); +} +/* +* PARAMETERS +* p_mtn +* [in] Pointer to a Multicast Tree Node object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Multicast Tree/osm_mtree_node_destroy +* NAME +* osm_mtree_node_destroy +* +* DESCRIPTION +* The osm_mtree_node_destroy function destroys a node, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_mtree_node_destroy( + IN osm_mtree_node_t* const p_mtn ); +/* +* PARAMETERS +* p_mtn +* [in] Pointer to a Multicast Tree Node object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified Multicast Tree object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to osm_mtree_construct or +* osm_mtree_init. +* +* SEE ALSO +* Multicast Tree object, osm_mtree_construct, osm_mtree_init +*********/ + +/****f* OpenSM: Multicast Tree/osm_mtree_node_init +* NAME +* osm_mtree_node_init +* +* DESCRIPTION +* Initializes a Multicast Tree Node object for use. +* +* SYNOPSIS +*/ +void +osm_mtree_node_init( + IN osm_mtree_node_t* const p_mtn, + IN const osm_switch_t* const p_sw ); +/* +* PARAMETERS +* p_mtn +* [in] Pointer to an osm_mtree_node_t object to initialize. +* +* p_sw +* [in] Pointer to the switch represented by this node. +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Multicast Tree/osm_mtree_node_new +* NAME +* osm_mtree_node_new +* +* DESCRIPTION +* Returns an initialized a Multicast Tree object for use. +* +* SYNOPSIS +*/ +osm_mtree_node_t* +osm_mtree_node_new( + IN const osm_switch_t* const p_sw ); +/* +* PARAMETERS +* p_sw +* [in] Pointer to the switch represented by this node. +* +* RETURN VALUES +* Pointer to an initialized tree node. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Multicast Tree/osm_mtree_destroy +* NAME +* osm_mtree_destroy +* +* DESCRIPTION +* Destroys a Multicast Tree object given by the p_mtn +* +* SYNOPSIS +*/ +void +osm_mtree_destroy( + IN osm_mtree_node_t *p_mtn ); +/* +* PARAMETERS +* p_mtn +* [in] Pointer to an osm_mtree_node_t object to destroy. +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Multicast Tree/osm_mtree_node_get_max_children +* NAME +* osm_mtree_node_get_max_children +* +* DESCRIPTION +* Returns the number maximum number of children of this node. +* The return value is 1 greater than the highest valid port +* number on the switch. +* +* +* SYNOPSIS +*/ +static inline uint8_t +osm_mtree_node_get_max_children( + IN const osm_mtree_node_t* const p_mtn ) +{ + return( p_mtn->max_children ); +} +/* +* PARAMETERS +* p_mtn +* [in] Pointer to the multicast tree node. +* +* RETURN VALUES +* See description. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Multicast Tree/osm_mtree_node_get_child +* NAME +* osm_mtree_node_get_child +* +* DESCRIPTION +* Returns the specified child node of this node. +* +* SYNOPSIS +*/ +static inline osm_mtree_node_t* +osm_mtree_node_get_child( + IN const osm_mtree_node_t* const p_mtn, + IN const uint8_t child ) +{ + CL_ASSERT( child < p_mtn->max_children ); + return( p_mtn->child_array[child] ); +} +/* +* PARAMETERS +* p_mtn +* [in] Pointer to the multicast tree node. +* +* child +* [in] Index of the child to retrieve. +* +* RETURN VALUES +* Returns the specified child node of this node. +* +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Multicast Tree/osm_mtree_node_get_switch_ptr +* NAME +* osm_mtree_node_get_switch_ptr +* +* DESCRIPTION +* Returns a pointer to the switch object represented by this tree node. +* +* SYNOPSIS +*/ +static inline osm_switch_t* +osm_mtree_node_get_switch_ptr( + IN const osm_mtree_node_t* const p_mtn ) +{ + return( p_mtn->p_sw ); +} +/* +* PARAMETERS +* p_mtn +* [in] Pointer to the multicast tree node. +* +* child +* [in] Index of the child to retrieve. +* +* RETURN VALUES +* Returns a pointer to the switch object represented by this tree node. +* +* +* NOTES +* +* SEE ALSO +*********/ + +END_C_DECLS + +#endif /* _OSM_MTREE_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_multicast.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_multicast.h new file mode 100644 index 00000000..90a3b57c --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_multicast.h @@ -0,0 +1,769 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_multicast.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_mgrp_t. + * This object represents an IBA Multicast Group. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_MULTICAST_H_ +#define _OSM_MULTICAST_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Multicast Group +* NAME +* Multicast Group +* +* DESCRIPTION +* The Multicast Group encapsulates the information needed by the +* OpenSM to manage Multicast Groups. The OpenSM allocates one +* Multicast Group object per Multicast Group in the IBA subnet. +* +* The Multicast Group is not thread safe, thus callers must provide +* serialization. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****f* IBA Base: OpneSM: Multicast Group/osm_get_mcast_req_type_str +* NAME +* osm_get_mcast_req_type_str +* +* DESCRIPTION +* Returns a string for the specified osm_mcast_req_type_t value. +* +* SYNOPSIS +*/ +const char* +osm_get_mcast_req_type_str( + IN osm_mcast_req_type_t req_type ); +/* +* PARAMETERS +* req_type +* [in] osm_mcast_req_type value +* +* RETURN VALUES +* Pointer to the request type description string. +* +* NOTES +* +* SEE ALSO +*********/ + +/****s* OpenSM: Multicast Group/osm_mcast_mgr_ctxt_t +* NAME +* osm_mcast_mgr_ctxt_t +* +* DESCRIPTION +* Struct for passing context arguments to the multicast manager. +* +* The osm_mcast_mgr_ctxt_t object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct osm_mcast_mgr_ctxt +{ + ib_net16_t mlid; + osm_mcast_req_type_t req_type; + ib_net64_t port_guid; +} osm_mcast_mgr_ctxt_t; +/* +* FIELDS +* +* mlid +* The network ordered LID of this Multicast Group (must be >= 0xC000). +* +* req_type +* The type of the request that caused this call +* (multicast create/join/leave). +* +* port_guid +* The port guid of the port that is being added/removed from +* the multicast group due to this call. +* +* SEE ALSO +*********/ + +/****s* OpenSM: Multicast Group/osm_mgrp_t +* NAME +* osm_mgrp_t +* +* DESCRIPTION +* Multicast Group structure. +* +* The osm_mgrp_t object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_mgrp +{ + cl_map_item_t map_item; + ib_net16_t mlid; + osm_mtree_node_t *p_root; + cl_qmap_t mcm_port_tbl; + ib_member_rec_t mcmember_rec; + boolean_t well_known; + boolean_t to_be_deleted; + uint32_t last_change_id; + uint32_t last_tree_id; +} osm_mgrp_t; +/* +* FIELDS +* map_item +* Map Item for qmap linkage. Must be first element!! +* +* mlid +* The network ordered LID of this Multicast Group (must be +* >= 0xC000). +* +* p_root +* Pointer to the root "tree node" in the single spanning tree +* for this multicast group. The nodes of the tree represent +* switches. Member ports are not represented in the tree. +* +* mcm_port_tbl +* Table (sorted by port GUID) of osm_mcm_port_t objects +* representing the member ports of this multicast group. +* +* mcmember_rec +* Hold the parameters of the Multicast Group. +* +* well_known +* Indicates that this is the wellknow multicast group which +* is created during the initialization of SM/SA and will be +* present even if there are no ports for this group +* +* to_be_deleted +* Since groups are deleted only after re-route we need to +* track the fact the group is about to be deleted so we can +* track the fact a new join is actually a create request. +* +* last_change_id +* a counter for the number of changes applied to the group. +* This counter shuold be incremented on any modification +* to the group: joining or leaving of ports. +* +* last_tree_id +* the last change id used for building the current tree. +* +* SEE ALSO +*********/ + +/****f* OpenSM: Vendor API/osm_mgrp_func_t +* NAME +* osm_mgrp_func_t +* +* DESCRIPTION +* Callback for the osm_mgrp_apply_func function. +* The callback function must not modify the tree linkage. +* +* SYNOPSIS +*/ +typedef void (*osm_mgrp_func_t)( + IN const osm_mgrp_t* const p_mgrp, + IN const osm_mtree_node_t* const p_mtn, + IN void* context ); +/* +* PARAMETERS +* p_mgrp +* [in] Pointer to the multicast group object. +* +* p_mtn +* [in] Pointer to the multicast tree node. +* +* context +* [in] User context. +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Multicast Group/osm_mgrp_construct +* NAME +* osm_mgrp_construct +* +* DESCRIPTION +* This function constructs a Multicast Group. +* +* SYNOPSIS +*/ +void +osm_mgrp_construct( + IN osm_mgrp_t* const p_mgrp ); +/* +* PARAMETERS +* p_mgrp +* [in] Pointer to a Multicast Group to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_mgrp_init, osm_mgrp_destroy. +* +* Calling osm_mgrp_construct is a prerequisite to calling any other +* method except osm_mgrp_init. +* +* SEE ALSO +* Multicast Group, osm_mgrp_init, osm_mgrp_destroy +*********/ + +/****f* OpenSM: Multicast Group/osm_mgrp_destroy +* NAME +* osm_mgrp_destroy +* +* DESCRIPTION +* The osm_mgrp_destroy function destroys a Multicast Group, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_mgrp_destroy( + IN osm_mgrp_t* const p_mgrp ); +/* +* PARAMETERS +* p_mgrp +* [in] Pointer to a Muticast Group to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified Multicast Group. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to osm_mgrp_construct or +* osm_mgrp_init. +* +* SEE ALSO +* Multicast Group, osm_mgrp_construct, osm_mgrp_init +*********/ + +/****f* OpenSM: Multicast Group/osm_mgrp_init +* NAME +* osm_mgrp_init +* +* DESCRIPTION +* The osm_mgrp_init function initializes a Multicast Group for use. +* +* SYNOPSIS +*/ +void +osm_mgrp_init( + IN osm_mgrp_t* const p_mgrp, + IN const ib_net16_t mlid ); +/* +* PARAMETERS +* p_mgrp +* [in] Pointer to an osm_mgrp_t object to initialize. +* +* mlid +* [in] Multicast LID for this multicast group. +* +* RETURN VALUES +* None. +* +* NOTES +* Allows calling other Multicast Group methods. +* +* SEE ALSO +* Multicast Group, osm_mgrp_construct, osm_mgrp_destroy, +*********/ + +/****f* OpenSM: Multicast Group/osm_mgrp_new +* NAME +* osm_mgrp_new +* +* DESCRIPTION +* Allocates and initializes a Multicast Group for use. +* +* SYNOPSIS +*/ +osm_mgrp_t* +osm_mgrp_new( + IN const ib_net16_t mlid ); +/* +* PARAMETERS +* mlid +* [in] Multicast LID for this multicast group. +* +* RETURN VALUES +* IB_SUCCESS if initialization was successful. +* +* NOTES +* Allows calling other Multicast Group methods. +* +* SEE ALSO +* Multicast Group, osm_mgrp_construct, osm_mgrp_destroy, +*********/ + +/****f* OpenSM: Multicast Group/osm_mgrp_delete +* NAME +* osm_mgrp_delete +* +* DESCRIPTION +* Destroys and de-allocates a Multicast Group. +* +* SYNOPSIS +*/ +void +osm_mgrp_delete( + IN osm_mgrp_t* const p_mgrp ); +/* +* PARAMETERS +* p_mgrp +* [in] Pointer to an osm_mgrp_t object. +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +* Multicast Group, osm_mgrp_construct, osm_mgrp_destroy, +*********/ + +/****f* OpenSM: Multicast Group/osm_mgrp_is_guid +* NAME +* osm_mgrp_is_guid +* +* DESCRIPTION +* Indicates if the specified port GUID is a member of the Multicast Group. +* +* SYNOPSIS +*/ +static inline boolean_t +osm_mgrp_is_guid( + IN const osm_mgrp_t* const p_mgrp, + IN const ib_net64_t port_guid ) +{ + return( cl_qmap_get( &p_mgrp->mcm_port_tbl, port_guid ) != + cl_qmap_end( &p_mgrp->mcm_port_tbl ) ); +} +/* +* PARAMETERS +* p_mgrp +* [in] Pointer to an osm_mgrp_t object. +* +* port_guid +* [in] Port GUID. +* +* RETURN VALUES +* TRUE if the port GUID is a member of the group, +* FALSE otherwise. +* +* NOTES +* +* SEE ALSO +* Multicast Group +*********/ + +/****f* OpenSM: Multicast Group/osm_mgrp_is_empty +* NAME +* osm_mgrp_is_empty +* +* DESCRIPTION +* Indicates if the multicast group has any member ports. +* +* SYNOPSIS +*/ +static inline boolean_t +osm_mgrp_is_empty( + IN const osm_mgrp_t* const p_mgrp ) +{ + return( cl_qmap_count( &p_mgrp->mcm_port_tbl ) == 0 ); +} +/* +* PARAMETERS +* p_mgrp +* [in] Pointer to an osm_mgrp_t object. +* +* RETURN VALUES +* TRUE if there are no ports in the multicast group. +* FALSE otherwise. +* +* NOTES +* +* SEE ALSO +* Multicast Group +*********/ + +/****f* OpenSM: Multicast Group/osm_mgrp_get_mlid +* NAME +* osm_mgrp_get_mlid +* +* DESCRIPTION +* The osm_mgrp_get_mlid function returns the multicast LID of this group. +* +* SYNOPSIS +*/ +static inline ib_net16_t +osm_mgrp_get_mlid( + IN const osm_mgrp_t* const p_mgrp ) +{ + return( p_mgrp->mlid ); +} +/* +* PARAMETERS +* p_mgrp +* [in] Pointer to an osm_mgrp_t object. +* +* RETURN VALUES +* MLID of the Multicast Group. +* +* NOTES +* +* SEE ALSO +* Multicast Group +*********/ + +/****f* OpenSM: Multicast Group/osm_mgrp_add_port +* NAME +* osm_mgrp_add_port +* +* DESCRIPTION +* Adds a port to the multicast group. +* +* SYNOPSIS +*/ +osm_mcm_port_t* +osm_mgrp_add_port( + IN osm_mgrp_t* const p_mgrp, + IN const ib_gid_t* const p_port_gid, + IN const uint8_t join_state, + IN boolean_t proxy_join); +/* +* PARAMETERS +* p_mgrp +* [in] Pointer to an osm_mgrp_t object to initialize. +* +* p_port_gid +* [in] Pointer to the GID of the port to add to the multicast group. +* +* join_state +* [in] The join state for this port in the group. +* +* RETURN VALUES +* IB_SUCCESS +* IB_INSUFFICIENT_MEMORY +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Multicast Group/osm_mgrp_is_port_present +* NAME +* osm_mgrp_is_port_present +* +* DESCRIPTION +* checks a port from the multicast group. +* +* SYNOPSIS +*/ + +boolean_t +osm_mgrp_is_port_present( + IN const osm_mgrp_t* const p_mgrp, + IN const ib_net64_t port_guid, + OUT osm_mcm_port_t ** const pp_mcm_port); +/* +* PARAMETERS +* p_mgrp +* [in] Pointer to an osm_mgrp_t object. +* +* port_guid +* [in] Port guid of the departing port. +* +* pp_mcm_port +* [out] Pointer to a pointer to osm_mcm_port_t +* Updated to the member on success or NULLed +* +* RETURN VALUES +* TRUE if port present +* FALSE if port is not present. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Multicast Group/osm_mgrp_remove_port +* NAME +* osm_mgrp_remove_port +* +* DESCRIPTION +* Removes a port from the multicast group. +* +* SYNOPSIS +*/ +void +osm_mgrp_remove_port( + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN osm_mgrp_t* const p_mgrp, + IN const ib_net64_t port_guid ); +/* +* PARAMETERS +* +* p_subn +* [in] Pointer to the subnet object +* +* p_log +* [in] The log object pointer +* +* p_mgrp +* [in] Pointer to an osm_mgrp_t object. +* +* port_guid +* [in] Port guid of the departing port. +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Multicast Group/osm_mgrp_get_root_switch +* NAME +* osm_mgrp_get_root_switch +* +* DESCRIPTION +* Returns the "root" switch of this multicast group. The root switch +* is at the trunk of the multicast single spanning tree. +* +* SYNOPSIS +*/ +static inline osm_switch_t* +osm_mgrp_get_root_switch( + IN const osm_mgrp_t* const p_mgrp ) +{ + if( p_mgrp->p_root ) + return( p_mgrp->p_root->p_sw ); + else + return( NULL ); +} +/* +* PARAMETERS +* p_mgrp +* [in] Pointer to an osm_mgrp_t object. +* +* RETURN VALUES +* Returns the "root" switch of this multicast group. The root switch +* is at the trunk of the multicast single spanning tree. +* +* NOTES +* +* SEE ALSO +* Multicast Group +*********/ + +/****f* OpenSM: Multicast Group/osm_mgrp_compute_avg_hops +* NAME +* osm_mgrp_compute_avg_hops +* +* DESCRIPTION +* Returns the average number of hops from the given to switch +* to all member of a multicast group. +* +* SYNOPSIS +*/ +float +osm_mgrp_compute_avg_hops( + const osm_mgrp_t* const p_mgrp, + const osm_switch_t* const p_sw ); +/* +* PARAMETERS +* p_mgrp +* [in] Pointer to an osm_mgrp_t object. +* +* p_sw +* [in] Pointer to the switch from which to measure. +* +* RETURN VALUES +* Returns the average number of hops from the given to switch +* to all member of a multicast group. +* +* NOTES +* +* SEE ALSO +* Multicast Group +*********/ + +/****f* OpenSM: Multicast Group/osm_mgrp_apply_func +* NAME +* osm_mgrp_apply_func +* +* DESCRIPTION +* Calls the specified function for each element in the tree. +* Elements are passed to the callback function in no particular order. +* +* SYNOPSIS +*/ +void +osm_mgrp_apply_func( + const osm_mgrp_t* const p_mgrp, + osm_mgrp_func_t p_func, + void* context ); +/* +* PARAMETERS +* p_mgrp +* [in] Pointer to an osm_mgrp_t object. +* +* p_func +* [in] Pointer to the users callback function. +* +* context +* [in] User context passed to the callback function. +* +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +* Multicast Group +*********/ + +/****f* OpenSM: Multicast Group/osm_mgrp_send_delete_notice +* NAME +* osm_mgrp_send_delete_notice +* +* DESCRIPTION +* Sends a notice that the given multicast group is now deleted. +* +* SYNOPSIS +*/ +void +osm_mgrp_send_delete_notice( + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN osm_mgrp_t *p_mgrp ); +/* +* PARAMETERS +* p_subn +* Pointer to the Subnet object for this subnet. +* +* p_log +* Pointer to the log object. +* +* p_mgrp +* [in] Pointer to an osm_mgrp_t object. +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +* Multicast Group +*********/ + +/****f* OpenSM: Multicast Group/osm_mgrp_send_create_notice +* NAME +* osm_mgrp_send_create_notice +* +* DESCRIPTION +* Sends a notice that the given multicast group is now created. +* +* SYNOPSIS +*/ +void +osm_mgrp_send_create_notice( + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN osm_mgrp_t *p_mgrp ); +/* +* PARAMETERS +* p_subn +* Pointer to the Subnet object for this subnet. +* +* p_log +* Pointer to the log object. +* +* p_mgrp +* [in] Pointer to an osm_mgrp_t object. +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +* Multicast Group +*********/ + +END_C_DECLS + +#endif /* _OSM_MULTICAST_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_node.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_node.h new file mode 100644 index 00000000..1bcc0f9e --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_node.h @@ -0,0 +1,957 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_node.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_node_t. + * This object represents an IBA node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_NODE_H_ +#define _OSM_NODE_H_ + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +struct _osm_switch; + +/****h* OpenSM/Node +* NAME +* Node +* +* DESCRIPTION +* The Node object encapsulates the information needed by the +* OpenSM to manage nodes. The OpenSM allocates one Node object +* per node in the IBA subnet. +* +* The Node object is not thread safe, thus callers must provide +* serialization. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: Node/osm_node_t +* NAME +* osm_node_t +* +* DESCRIPTION +* Node structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_node +{ + cl_map_item_t map_item; + struct _osm_switch *sw; + ib_node_info_t node_info; + ib_node_desc_t node_desc; + uint32_t discovery_count; + uint32_t physp_tbl_size; + osm_physp_t physp_table[1]; +} osm_node_t; +/* +* FIELDS +* map_item +* Linkage structure for cl_qmap. MUST BE FIRST MEMBER! +* +* sw +* For switch node contains pointer to appropriate osm_switch +* structure. NULL for non-switch nodes. Can be used for fast +* access to switch object and for simple node type detection +* +* node_info +* The IBA defined NodeInfo data for this node. +* +* node_desc +* The IBA defined NodeDescription data for this node. +* +* discovery_count +* The number of times this node has been discovered +* during the current fabric sweep. This number is reset +* to zero at the start of a sweep. +* +* phsyp_tbl_size +* The size of the physp_table array. This value is one greater +* than the number of ports in the node, since port numbers +* start with 1 for some bizzare reason. +* +* phsyp_table +* Array of physical port objects belonging to this node. +* Index is contiguous by local port number. +* For switches, port 0 is the always the management port (14.2.5.6). +* MUST BE LAST MEMBER! - Since it grows !!!! +* +* SEE ALSO +* Node object +*********/ + +/****f* OpenSM: Node/osm_node_destroy +* NAME +* osm_node_destroy +* +* DESCRIPTION +* The osm_node_destroy function destroys a node, releasing +* all resources. +* +* SYNOPSIS +*/void +osm_node_destroy( + IN osm_node_t *p_node ); +/* +* PARAMETERS +* p_node +* [in] Pointer a Node object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified Node object. +* This function should only be called after a call to osm_node_new. +* +* SEE ALSO +* Node object, osm_node_new +*********/ + +/****f* OpenSM: Node/osm_node_delete +* NAME +* osm_node_delete +* +* DESCRIPTION +* The osm_node_delete function destroys a node, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_node_delete( + IN OUT osm_node_t** const p_node ); +/* +* PARAMETERS +* p_node +* [in][out] Pointer to a Pointer a Node object to destroy. +* On return, the pointer to set to NULL. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified Node object. +* This function should only be called after a call to osm_node_new. +* +* SEE ALSO +* Node object, osm_node_new +*********/ + +/****f* OpenSM: Node/osm_node_new +* NAME +* osm_node_new +* +* DESCRIPTION +* The osm_node_new function initializes a Node object for use. +* +* SYNOPSIS +*/ +osm_node_t* +osm_node_new( + IN const osm_madw_t* const p_madw ); +/* +* PARAMETERS +* p_madw +* [in] Pointer to a osm_madw_t object containing a mad with +* the node's NodeInfo attribute. The caller may discard the +* osm_madw_t structure after calling osm_node_new. +* +* RETURN VALUES +* On success, a pointer to the new initialized osm_node_t structure. +* NULL otherwise. +* +* NOTES +* +* SEE ALSO +* Node object +*********/ + +/****f* OpenSM: Node/osm_node_is_lid +* NAME +* osm_node_is_lid +* +* DESCRIPTION +* Indicates if the specified LID belongs to this node. +* +* SYNOPSIS +*/ +boolean_t osm_node_is_lid( + IN const osm_node_t* const p_node, + IN const uint16_t lid ); +/* +* PARAMETERS +* p_node +* [in] Pointer to an osm_node_t object. +* +* lid +* [in] LID value. +* +* RETURN VALUES +* TRUE if the specified LID belongs to the node, +* FALSE otherwise. +* +* NOTES +* +* SEE ALSO +* Node object +*********/ + +/****f* OpenSM: Node/osm_node_get_physp_ptr +* NAME +* osm_node_get_physp_ptr +* +* DESCRIPTION +* Returns a pointer to the physical port object at the +* specified local port number. +* +* SYNOPSIS +*/ +static inline osm_physp_t* +osm_node_get_physp_ptr( + IN const osm_node_t* const p_node, + IN const uint32_t port_num ) +{ + + CL_ASSERT( port_num < p_node->physp_tbl_size ); + return( (osm_physp_t*)&p_node->physp_table[port_num] ); +} +/* +* PARAMETERS +* p_node +* [in] Pointer to an osm_node_t object. +* +* port_num +* [in] Local port number. +* +* RETURN VALUES +* Returns a pointer to the physical port object at the +* specified local port number. +* A return value of zero means the port number was out of range. +* +* NOTES +* +* SEE ALSO +* Node object +*********/ + +/****f* OpenSM: Node/osm_node_get_any_physp_ptr +* NAME +* osm_node_get_any_physp_ptr +* +* DESCRIPTION +* Returns a pointer to any valid physical port object associated +* with this node. This operation is mostly meaningful for switches, +* in which case all the Physical Ports share the same GUID. +* +* SYNOPSIS +*/ +static inline osm_physp_t* +osm_node_get_any_physp_ptr( + IN const osm_node_t* const p_node ) +{ + CL_ASSERT( p_node ); + return( (osm_physp_t*)&p_node->physp_table[ + ib_node_info_get_local_port_num( &p_node->node_info )] ); +} +/* +* PARAMETERS +* p_node +* [in] Pointer to an osm_node_t object. +* +* RETURN VALUES +* Returns a pointer to any valid physical port object associated +* with this node. This operation is mostly meaningful for switches, +* in which case all the Physical Ports share the same GUID. +* +* NOTES +* +* SEE ALSO +* Node object +*********/ + +/****f* OpenSM: Node/osm_node_get_any_path +* NAME +* osm_node_get_any_path +* +* DESCRIPTION +* Returns a pointer to the physical port object at the +* specified local port number. +* +* SYNOPSIS +*/ +static inline osm_dr_path_t* +osm_node_get_any_dr_path_ptr( + IN const osm_node_t* const p_node ) +{ + CL_ASSERT( p_node ); + return( osm_physp_get_dr_path_ptr( &p_node->physp_table[ + ib_node_info_get_local_port_num( &p_node->node_info )] ) ); +} +/* +* PARAMETERS +* p_node +* [in] Pointer to an osm_node_t object. +* +* port_num +* [in] Local port number. +* +* RETURN VALUES +* Returns a pointer to the physical port object at the +* specified local port number. +* A return value of zero means the port number was out of range. +* +* NOTES +* +* SEE ALSO +* Node object +*********/ + +/****f* OpenSM: Node/osm_node_get_type +* NAME +* osm_node_get_type +* +* DESCRIPTION +* Returns the type of this node. +* +* SYNOPSIS +*/ +static inline uint8_t +osm_node_get_type( + IN const osm_node_t* const p_node ) +{ + return( p_node->node_info.node_type ); +} +/* +* PARAMETERS +* p_node +* [in] Pointer to an osm_node_t object. +* +* RETURN VALUES +* Returns the IBA defined type of this node. +* +* NOTES +* +* SEE ALSO +* Node object +*********/ + +/****f* OpenSM: Node/osm_node_get_num_physp +* NAME +* osm_node_get_num_physp +* +* DESCRIPTION +* Returns the type of this node. +* +* SYNOPSIS +*/ +static inline uint8_t +osm_node_get_num_physp( + IN const osm_node_t* const p_node ) +{ + return( (uint8_t)p_node->physp_tbl_size ); +} +/* +* PARAMETERS +* p_node +* [in] Pointer to an osm_node_t object. +* +* RETURN VALUES +* Returns the IBA defined type of this node. +* +* NOTES +* +* SEE ALSO +* Node object +*********/ + +/****f* OpenSM: Node/osm_node_get_remote_node +* NAME +* osm_node_get_remote_node +* +* DESCRIPTION +* Returns a pointer to the node on the other end of the +* specified port. +* Returns NULL if no remote node exists. +* +* SYNOPSIS +*/ +osm_node_t* +osm_node_get_remote_node( + IN const osm_node_t* const p_node, + IN const uint8_t port_num, + OUT uint8_t *p_remote_port_num ); +/* +* PARAMETERS +* p_node +* [in] Pointer to an osm_node_t object. +* +* port_num +* [in] Port number in p_node through which to get the remote node. +* +* p_remote_port_num +* [out] Port number in the remote's node through which this +* link exists. The caller may specify NULL for this pointer +* if the port number isn't needed. +* +* RETURN VALUES +* Returns a pointer to the node on the other end of the +* specified port. +* Returns NULL if no remote node exists. +* +* NOTES +* +* SEE ALSO +* Node object +*********/ + +/****f* OpenSM: Node/osm_node_get_base_lid +* NAME +* osm_node_get_base_lid +* +* DESCRIPTION +* Returns the LID value of the specified port on this node. +* +* SYNOPSIS +*/ +static inline ib_net16_t +osm_node_get_base_lid( + IN const osm_node_t* const p_node, + IN const uint32_t port_num ) +{ + CL_ASSERT( port_num < p_node->physp_tbl_size ); + return( osm_physp_get_base_lid( &p_node->physp_table[port_num] ) ); +} +/* +* PARAMETERS +* p_node +* [in] Pointer to an osm_node_t object. +* +* port_num +* [in] Local port number. +* +* RETURN VALUES +* Returns a pointer to the physical port object at the +* specified local port number. +* A return value of zero means the port number was out of range. +* +* NOTES +* +* SEE ALSO +* Node object +*********/ + +/****f* OpenSM: Node/osm_node_get_remote_base_lid +* NAME +* osm_node_get_remote_base_lid +* +* DESCRIPTION +* Returns the base LID value of the port on the other side +* of the wire from the specified port on this node. +* +* SYNOPSIS +*/ +ib_net16_t +osm_node_get_remote_base_lid( + IN const osm_node_t* const p_node, + IN const uint32_t port_num ); +/* +* PARAMETERS +* p_node +* [in] Pointer to an osm_node_t object. +* +* port_num +* [in] Local port number. +* +* RETURN VALUES +* Returns a pointer to the physical port object at the +* specified local port number. +* A return value of zero means the port number was out of range. +* +* NOTES +* +* SEE ALSO +* Node object +*********/ + +/****f* OpenSM: Node/osm_node_get_remote_type +* NAME +* osm_node_get_remote_type +* +* DESCRIPTION +* Returns the type of the node on the other side +* of the wire from the specified port on this node. +* The remote node must exist. +* +* SYNOPSIS +*/ +static inline uint8_t +osm_node_get_remote_type( + IN const osm_node_t* const p_node, + IN const uint8_t port_num ) +{ + osm_node_t *p_remote_node; + + p_remote_node = osm_node_get_remote_node( p_node, port_num, NULL ); + CL_ASSERT( p_remote_node ); + return( osm_node_get_type( p_remote_node ) ); +} +/* +* PARAMETERS +* p_node +* [in] Pointer to an osm_node_t object. +* +* port_num +* [in] Local port number. +* +* RETURN VALUES +* Returns the type of the node on the other side +* of the wire from the specified port on this node. +* +* NOTES +* +* SEE ALSO +* Node object +*********/ + +/****f* OpenSM: Node/osm_node_get_lmc +* NAME +* osm_node_get_lmc +* +* DESCRIPTION +* Returns the LMC value of the specified port on this node. +* +* SYNOPSIS +*/ +static inline uint8_t +osm_node_get_lmc( + IN const osm_node_t* const p_node, + IN const uint32_t port_num ) +{ + CL_ASSERT( port_num < p_node->physp_tbl_size ); + return( osm_physp_get_lmc( &p_node->physp_table[port_num] ) ); +} +/* +* PARAMETERS +* p_node +* [in] Pointer to an osm_node_t object. +* +* port_num +* [in] Local port number. +* +* RETURN VALUES +* Returns the LMC value of the specified port on this node. +* +* NOTES +* +* SEE ALSO +* Node object +*********/ + +/****f* OpenSM: Node/osm_node_init_physp +* NAME +* osm_node_init_physp +* +* DESCRIPTION +* Initializes a physical port for the given node. +* +* SYNOPSIS +*/ +void +osm_node_init_physp( + IN osm_node_t* const p_node, + IN const osm_madw_t* const p_madw ); +/* +* PARAMETERS +* p_node +* [in] Pointer to an osm_node_t object. +* +* p_madw +* [in] Pointer to a osm_madw_t object containing a mad with +* the node's NodeInfo attribute as discovered through the +* Physical Port to add to the node. The caller may discard the +* osm_madw_t structure after calling osm_node_new. +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +* Node object, Physical Port object. +*********/ + +/****f* OpenSM: Node/osm_node_discovery_count_get +* NAME +* osm_node_discovery_count_get +* +* DESCRIPTION +* Returns a pointer to the physical port object at the +* specified local port number. +* +* SYNOPSIS +*/ +static inline uint32_t +osm_node_discovery_count_get( + IN const osm_node_t* const p_node ) +{ + return( p_node->discovery_count ); +} +/* +* PARAMETERS +* p_node +* [in] Pointer to an osm_node_t object. +* +* RETURN VALUES +* Returns the discovery count for this node. +* +* NOTES +* +* SEE ALSO +* Node object +*********/ + +/****f* OpenSM: Node/osm_node_discovery_count_reset +* NAME +* osm_node_discovery_count_reset +* +* DESCRIPTION +* Resets the discovery count for this node to zero. +* This operation should be performed at the start of a sweep. +* +* SYNOPSIS +*/ +static inline void +osm_node_discovery_count_reset( + IN osm_node_t* const p_node ) +{ + p_node->discovery_count = 0; +} +/* +* PARAMETERS +* p_node +* [in] Pointer to an osm_node_t object. +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +* Node object +*********/ + +/****f* OpenSM: Node/osm_node_discovery_count_inc +* NAME +* osm_node_discovery_count_inc +* +* DESCRIPTION +* Increments the discovery count for this node. +* +* SYNOPSIS +*/ +static inline void +osm_node_discovery_count_inc( + IN osm_node_t* const p_node ) +{ + p_node->discovery_count++; +} +/* +* PARAMETERS +* p_node +* [in] Pointer to an osm_node_t object. +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +* Node object +*********/ + +/****f* OpenSM: Node/osm_node_get_node_guid +* NAME +* osm_node_get_node_guid +* +* DESCRIPTION +* Returns the node GUID of this node. +* +* SYNOPSIS +*/ +static inline ib_net64_t +osm_node_get_node_guid( + IN const osm_node_t* const p_node ) +{ + return( p_node->node_info.node_guid ); +} +/* +* PARAMETERS +* p_node +* [in] Pointer to an osm_node_t object. +* +* RETURN VALUES +* Returns the node GUID of this node. +* +* NOTES +* +* SEE ALSO +* Node object +*********/ + +/****f* OpenSM: Node/osm_node_link +* NAME +* osm_node_link +* +* DESCRIPTION +* Logically connects a node to another node through the specified port. +* +* SYNOPSIS +*/ +void +osm_node_link( + IN osm_node_t* const p_node, + IN const uint8_t port_num, + IN osm_node_t* const p_remote_node, + IN const uint8_t remote_port_num ); +/* +* PARAMETERS +* p_node +* [in] Pointer to an osm_node_t object. +* +* port_num +* [in] Port number in p_node through which to create the link. +* +* p_remote_node +* [in] Pointer to the remote port object. +* +* remote_port_num +* [in] Port number in the remote's node through which to +* create this link. +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +* Node object +*********/ + +/****f* OpenSM: Node/osm_node_unlink +* NAME +* osm_node_unlink +* +* DESCRIPTION +* Logically disconnects a node from another node through +* the specified port. +* +* SYNOPSIS +*/ +void +osm_node_unlink( + IN osm_node_t* const p_node, + IN const uint8_t port_num, + IN osm_node_t* const p_remote_node, + IN const uint8_t remote_port_num ); +/* +* PARAMETERS +* p_node +* [in] Pointer to an osm_node_t object. +* +* port_num +* [in] Port number in p_node through which to unlink. +* +* p_remote_node +* [in] Pointer to the remote port object. +* +* remote_port_num +* [in] Port number in the remote's node through which to unlink. +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +* Node object +*********/ + +/****f* OpenSM: Node/osm_node_link_exists +* NAME +* osm_node_link_exists +* +* DESCRIPTION +* Return TRUE if a link exists between the specified nodes on +* the specified ports. +* Returns FALSE otherwise. +* +* SYNOPSIS +*/ +boolean_t +osm_node_link_exists( + IN osm_node_t* const p_node, + IN const uint8_t port_num, + IN osm_node_t* const p_remote_node, + IN const uint8_t remote_port_num ); +/* +* PARAMETERS +* p_node +* [in] Pointer to an osm_node_t object. +* +* port_num +* [in] Port number in p_node through which to check the link. +* +* p_remote_node +* [in] Pointer to the remote port object. +* +* remote_port_num +* [in] Port number in the remote's node through which to +* check this link. +* +* RETURN VALUES +* Return TRUE if a link exists between the specified nodes on +* the specified ports. +* Returns FALSE otherwise. +* +* NOTES +* +* SEE ALSO +* Node object +*********/ + +/****f* OpenSM: Node/osm_node_has_any_link +* NAME +* osm_node_has_any_link +* +* DESCRIPTION +* Return TRUE if a any link exists from the specified nodes on +* the specified port. +* Returns FALSE otherwise. +* +* SYNOPSIS +*/ +boolean_t +osm_node_has_any_link( + IN osm_node_t* const p_node, + IN const uint8_t port_num ); +/* +* PARAMETERS +* p_node +* [in] Pointer to an osm_node_t object. +* +* port_num +* [in] Port number in p_node through which to check the link. +* +* RETURN VALUES +* Return TRUE if a any link exists from the specified nodes on +* the specified port. +* Returns FALSE otherwise. +* +* NOTES +* +* SEE ALSO +* Node object +*********/ + +/****f* OpenSM: Node/osm_node_link_has_valid_ports +* NAME +* osm_node_link_has_valid_ports +* +* DESCRIPTION +* Return TRUE if both ports in the link are valid (initialized). +* Returns FALSE otherwise. +* +* SYNOPSIS +*/ +boolean_t +osm_node_link_has_valid_ports( + IN osm_node_t* const p_node, + IN const uint8_t port_num, + IN osm_node_t* const p_remote_node, + IN const uint8_t remote_port_num ); +/* +* PARAMETERS +* p_node +* [in] Pointer to an osm_node_t object. +* +* port_num +* [in] Port number in p_node through which to check the link. +* +* RETURN VALUES +* Return TRUE if both ports in the link are valid (initialized). +* Returns FALSE otherwise. +* +* NOTES +* +* SEE ALSO +* Node object +*********/ + +END_C_DECLS + +#endif /* _OSM_NODE_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_node_desc_rcv.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_node_desc_rcv.h new file mode 100644 index 00000000..413fdf3f --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_node_desc_rcv.h @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_node_desc_rcv.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_nd_rcv_t. + * This object represents the NodeInfo Receiver object. + * attribute from a node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_ND_RCV_H_ +#define _OSM_ND_RCV_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Node Description Receiver +* NAME +* Node Description Receiver +* +* DESCRIPTION +* The Node Description Receiver object encapsulates the information +* needed to receive the NodeInfo attribute from a node. +* +* The Node Description Receiver object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: Node Description Receiver/osm_nd_rcv_t +* NAME +* osm_nd_rcv_t +* +* DESCRIPTION +* Node Description Receiver structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_nd_rcv +{ + osm_subn_t *p_subn; + osm_log_t *p_log; + cl_plock_t *p_lock; + +} osm_nd_rcv_t; +/* +* FIELDS +* p_subn +* Pointer to the Subnet object for this subnet. +* +* p_log +* Pointer to the log object. +* +* p_lock +* Pointer to the serializing lock. +* +* SEE ALSO +* Node Description Receiver object +*********/ + +/****f* OpenSM: Node Description Receiver/osm_nd_rcv_construct +* NAME +* osm_nd_rcv_construct +* +* DESCRIPTION +* This function constructs a Node Description Receiver object. +* +* SYNOPSIS +*/ +void osm_nd_rcv_construct( + IN osm_nd_rcv_t* const p_rcv ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to a Node Description Receiver object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_nd_rcv_init, osm_nd_rcv_destroy +* +* Calling osm_nd_rcv_construct is a prerequisite to calling any other +* method except osm_nd_rcv_init. +* +* SEE ALSO +* Node Description Receiver object, osm_nd_rcv_init, +* osm_nd_rcv_destroy +*********/ + +/****f* OpenSM: Node Description Receiver/osm_nd_rcv_destroy +* NAME +* osm_nd_rcv_destroy +* +* DESCRIPTION +* The osm_nd_rcv_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_nd_rcv_destroy( + IN osm_nd_rcv_t* const p_rcv ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* Node Description Receiver object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_nd_rcv_construct or osm_nd_rcv_init. +* +* SEE ALSO +* Node Description Receiver object, osm_nd_rcv_construct, +* osm_nd_rcv_init +*********/ + +/****f* OpenSM: Node Description Receiver/osm_nd_rcv_init +* NAME +* osm_nd_rcv_init +* +* DESCRIPTION +* The osm_nd_rcv_init function initializes a +* Node Description Receiver object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_nd_rcv_init( + IN osm_nd_rcv_t* const p_rcv, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to an osm_nd_rcv_t object to initialize. +* +* p_subn +* [in] Pointer to the Subnet object for this subnet. +* +* p_log +* [in] Pointer to the log object. +* +* p_lock +* [in] Pointer to the OpenSM serializing lock. +* +* RETURN VALUES +* CL_SUCCESS if the Node Description Receiver object was initialized +* successfully. +* +* NOTES +* Allows calling other Node Description Receiver methods. +* +* SEE ALSO +* Node Description Receiver object, osm_nd_rcv_construct, +* osm_nd_rcv_destroy +*********/ + +/****f* OpenSM: Node Description Receiver/osm_nd_rcv_process +* NAME +* osm_nd_rcv_process +* +* DESCRIPTION +* Process the NodeInfo attribute. +* +* SYNOPSIS +*/ +void osm_nd_rcv_process( + IN const osm_nd_rcv_t* const p_rcv, + IN osm_madw_t* const p_madw ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to an osm_nd_rcv_t object. +* +* p_madw +* [in] Pointer to the MAD Wrapper containing the MAD +* that contains the node's NodeInfo attribute. +* +* RETURN VALUES +* CL_SUCCESS if the NodeInfo processing was successful. +* +* NOTES +* This function processes a NodeInfo attribute. +* +* SEE ALSO +* Node Description Receiver, Node Description Response Controller +*********/ + +END_C_DECLS + +#endif /* _OSM_ND_RCV_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_node_desc_rcv_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_node_desc_rcv_ctrl.h new file mode 100644 index 00000000..0fbc4f87 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_node_desc_rcv_ctrl.h @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_node_desc_rcv_ctrl.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_nd_rcv_ctrl_t. + * This object represents a controller that receives the IBA NodeDescription + * attribute from a node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_ND_RCV_CTRL_H_ +#define _OSM_ND_RCV_CTRL_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Node Description Receive Controller +* NAME +* Node Description Receive Controller +* +* DESCRIPTION +* The Node Description Receive Controller object encapsulates the information +* needed to receive the NodeDescription attribute from a node. +* +* The Node Description Receive Controller object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: Node Description Receive Controller/osm_nd_rcv_ctrl_t +* NAME +* osm_nd_rcv_ctrl_t +* +* DESCRIPTION +* Node Description Receive Controller structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_nd_rcv_ctrl +{ + osm_nd_rcv_t *p_rcv; + osm_log_t *p_log; + cl_dispatcher_t *p_disp; + cl_disp_reg_handle_t h_disp; + +} osm_nd_rcv_ctrl_t; +/* +* FIELDS +* p_rcv +* Pointer to the Node Description Receiver object. +* +* p_log +* Pointer to the log object. +* +* p_disp +* Pointer to the Dispatcher. +* +* h_disp +* Handle returned from dispatcher registration. +* +* SEE ALSO +* Node Description Receive Controller object +*********/ + +/****f* OpenSM: Node Description Receive Controller/osm_nd_rcv_ctrl_construct +* NAME +* osm_nd_rcv_ctrl_construct +* +* DESCRIPTION +* This function constructs a Node Description Receive Controller object. +* +* SYNOPSIS +*/ +void +osm_nd_rcv_ctrl_construct( + IN osm_nd_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a Node Description Receive Controller object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_nd_rcv_ctrl_init, osm_nd_rcv_ctrl_destroy +* +* Calling osm_nd_rcv_ctrl_construct is a prerequisite to calling any other +* method except osm_nd_rcv_ctrl_init. +* +* SEE ALSO +* Node Description Receive Controller object, osm_nd_rcv_ctrl_init, +* osm_nd_rcv_ctrl_destroy +*********/ + +/****f* OpenSM: Node Description Receive Controller/osm_nd_rcv_ctrl_destroy +* NAME +* osm_nd_rcv_ctrl_destroy +* +* DESCRIPTION +* The osm_nd_rcv_ctrl_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_nd_rcv_ctrl_destroy( + IN osm_nd_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* Node Description Receive Controller object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_nd_rcv_ctrl_construct or osm_nd_rcv_ctrl_init. +* +* SEE ALSO +* Node Description Receive Controller object, osm_nd_rcv_ctrl_construct, +* osm_nd_rcv_ctrl_init +*********/ + +/****f* OpenSM: Node Description Receive Controller/osm_nd_rcv_ctrl_init +* NAME +* osm_nd_rcv_ctrl_init +* +* DESCRIPTION +* The osm_nd_rcv_ctrl_init function initializes a +* Node Description Receive Controller object for use. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_nd_rcv_ctrl_init( + IN osm_nd_rcv_ctrl_t* const p_ctrl, + IN osm_nd_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_nd_rcv_ctrl_t object to initialize. +* +* p_rcv +* [in] Pointer to an osm_nd_rcv_t object. +* +* p_log +* [in] Pointer to the log object. +* +* p_disp +* [in] Pointer to the OpenSM central Dispatcher. +* +* RETURN VALUES +* CL_SUCCESS if the Node Description Receive Controller object was initialized +* successfully. +* +* NOTES +* Allows calling other Node Description Receive Controller methods. +* +* SEE ALSO +* Node Description Receive Controller object, osm_nd_rcv_ctrl_construct, +* osm_nd_rcv_ctrl_destroy +*********/ + +END_C_DECLS + +#endif /* OSM_ND_RCV_CTRL_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_node_info_rcv.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_node_info_rcv.h new file mode 100644 index 00000000..f6f0b99d --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_node_info_rcv.h @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_node_info_rcv.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_ni_rcv_t. + * This object represents the NodeInfo Receiver object. + * attribute from a node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_NI_RCV_H_ +#define _OSM_NI_RCV_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Node Info Receiver +* NAME +* Node Info Receiver +* +* DESCRIPTION +* The Node Info Receiver object encapsulates the information +* needed to receive the NodeInfo attribute from a node. +* +* The Node Info Receiver object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: Node Info Receiver/osm_ni_rcv_t +* NAME +* osm_ni_rcv_t +* +* DESCRIPTION +* Node Info Receiver structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_ni_rcv +{ + osm_subn_t *p_subn; + osm_req_t *p_gen_req; + osm_log_t *p_log; + osm_state_mgr_t *p_state_mgr; + cl_plock_t *p_lock; + +} osm_ni_rcv_t; +/* +* FIELDS +* p_subn +* Pointer to the Subnet object for this subnet. +* +* p_gen_req_ctrl +* Pointer to the generic request controller. +* +* p_log +* Pointer to the log object. +* +* p_state_mgr +* Pointer to the State Manager object. +* +* p_lock +* Pointer to the serializing lock. +* +* SEE ALSO +* Node Info Receiver object +*********/ + +/****f* OpenSM: Node Info Receiver/osm_ni_rcv_construct +* NAME +* osm_ni_rcv_construct +* +* DESCRIPTION +* This function constructs a Node Info Receiver object. +* +* SYNOPSIS +*/ +void osm_ni_rcv_construct( + IN osm_ni_rcv_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a Node Info Receiver object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_ni_rcv_init, osm_ni_rcv_destroy, +* and osm_ni_rcv_is_inited. +* +* Calling osm_ni_rcv_construct is a prerequisite to calling any other +* method except osm_ni_rcv_init. +* +* SEE ALSO +* Node Info Receiver object, osm_ni_rcv_init, +* osm_ni_rcv_destroy, osm_ni_rcv_is_inited +*********/ + +/****f* OpenSM: Node Info Receiver/osm_ni_rcv_destroy +* NAME +* osm_ni_rcv_destroy +* +* DESCRIPTION +* The osm_ni_rcv_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_ni_rcv_destroy( + IN osm_ni_rcv_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* Node Info Receiver object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_ni_rcv_construct or osm_ni_rcv_init. +* +* SEE ALSO +* Node Info Receiver object, osm_ni_rcv_construct, +* osm_ni_rcv_init +*********/ + +/****f* OpenSM: Node Info Receiver/osm_ni_rcv_init +* NAME +* osm_ni_rcv_init +* +* DESCRIPTION +* The osm_ni_rcv_init function initializes a +* Node Info Receiver object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_ni_rcv_init( + IN osm_ni_rcv_t* const p_ctrl, + IN osm_req_t* const p_req, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN osm_state_mgr_t* const p_state_mgr, + IN cl_plock_t* const p_lock ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_ni_rcv_t object to initialize. +* +* p_req +* [in] Pointer to an osm_req_t object. +* +* p_subn +* [in] Pointer to the Subnet object for this subnet. +* +* p_log +* [in] Pointer to the log object. +* +* p_state_mgr +* [in] Pointer to the State Manager object. +* +* p_lock +* [in] Pointer to the OpenSM serializing lock. +* +* RETURN VALUES +* CL_SUCCESS if the Node Info Receiver object was initialized +* successfully. +* +* NOTES +* Allows calling other Node Info Receiver methods. +* +* SEE ALSO +* Node Info Receiver object, osm_ni_rcv_construct, +* osm_ni_rcv_destroy, osm_ni_rcv_is_inited +*********/ + +/****f* OpenSM: Node Info Receiver/osm_ni_rcv_is_inited +* NAME +* osm_ni_rcv_is_inited +* +* DESCRIPTION +* Indicates if the object has been initialized with osm_ni_rcv_init. +* +* SYNOPSIS +*/ +boolean_t osm_ni_rcv_is_inited( + IN const osm_ni_rcv_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_ni_rcv_t object. +* +* RETURN VALUES +* TRUE if the object was initialized successfully, +* FALSE otherwise. +* +* NOTES +* The osm_ni_rcv_construct or osm_ni_rcv_init must be +* called before using this function. +* +* SEE ALSO +* Node Info Receiver object, osm_ni_rcv_construct, +* osm_ni_rcv_init +*********/ + +/****f* OpenSM: Node Info Receiver/osm_ni_rcv_process +* NAME +* osm_ni_rcv_process +* +* DESCRIPTION +* Process the NodeInfo attribute. +* +* SYNOPSIS +*/ +void osm_ni_rcv_process( + IN const osm_ni_rcv_t* const p_ctrl, + IN osm_madw_t* const p_madw ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_ni_rcv_t object. +* +* p_madw +* [in] Pointer to the MAD Wrapper containing the MAD +* that contains the node's NodeInfo attribute. +* +* RETURN VALUES +* CL_SUCCESS if the NodeInfo processing was successful. +* +* NOTES +* This function processes a NodeInfo attribute. +* +* SEE ALSO +* Node Info Receiver, Node Info Response Controller +*********/ + +END_C_DECLS + +#endif /* _OSM_NI_RCV_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_node_info_rcv_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_node_info_rcv_ctrl.h new file mode 100644 index 00000000..3f2a71d5 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_node_info_rcv_ctrl.h @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_node_info_rcv_ctrl.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_ni_rcv_ctrl_t. + * This object represents a controller that receives the IBA NodeInfo + * attribute from a node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_NI_RCV_CTRL_H_ +#define _OSM_NI_RCV_CTRL_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Node Info Receive Controller +* NAME +* Node Info Receive Controller +* +* DESCRIPTION +* The Node Info Receive Controller object encapsulates +* the information needed to receive the NodeInfo attribute from a node. +* +* The Node Info Receive Controller object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: Node Info Receive Controller/osm_ni_rcv_ctrl_t +* NAME +* osm_ni_rcv_ctrl_t +* +* DESCRIPTION +* Node Info Receive Controller structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_ni_rcv_ctrl +{ + osm_ni_rcv_t *p_rcv; + osm_log_t *p_log; + cl_dispatcher_t *p_disp; + cl_disp_reg_handle_t h_disp; + +} osm_ni_rcv_ctrl_t; +/* +* FIELDS +* p_rcv +* Pointer to the Node Info Receiver object. +* +* p_log +* Pointer to the log object. +* +* p_disp +* Pointer to the Dispatcher. +* +* h_disp +* Handle returned from dispatcher registration. +* +* SEE ALSO +* Node Info Receive Controller object +* Node Info Receiver object +*********/ + +/****f* OpenSM: Node Info Receive Controller/osm_ni_rcv_ctrl_construct +* NAME +* osm_ni_rcv_ctrl_construct +* +* DESCRIPTION +* This function constructs a Node Info Receive Controller object. +* +* SYNOPSIS +*/ +void osm_ni_rcv_ctrl_construct( + IN osm_ni_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a Node Info Receive Controller +* object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_ni_rcv_ctrl_init, osm_ni_rcv_ctrl_destroy, +* and osm_ni_rcv_ctrl_is_inited. +* +* Calling osm_ni_rcv_ctrl_construct is a prerequisite to calling any other +* method except osm_ni_rcv_ctrl_init. +* +* SEE ALSO +* Node Info Receive Controller object, osm_ni_rcv_ctrl_init, +* osm_ni_rcv_ctrl_destroy, osm_ni_rcv_ctrl_is_inited +*********/ + +/****f* OpenSM: Node Info Receive Controller/osm_ni_rcv_ctrl_destroy +* NAME +* osm_ni_rcv_ctrl_destroy +* +* DESCRIPTION +* The osm_ni_rcv_ctrl_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_ni_rcv_ctrl_destroy( + IN osm_ni_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* Node Info Receive Controller object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_ni_rcv_ctrl_construct or osm_ni_rcv_ctrl_init. +* +* SEE ALSO +* Node Info Receive Controller object, osm_ni_rcv_ctrl_construct, +* osm_ni_rcv_ctrl_init +*********/ + +/****f* OpenSM: Node Info Receive Controller/osm_ni_rcv_ctrl_init +* NAME +* osm_ni_rcv_ctrl_init +* +* DESCRIPTION +* The osm_ni_rcv_ctrl_init function initializes a +* Node Info Receive Controller object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_ni_rcv_ctrl_init( + IN osm_ni_rcv_ctrl_t* const p_ctrl, + IN osm_ni_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_ni_rcv_ctrl_t object to initialize. +* +* p_rcv +* [in] Pointer to an osm_ni_rcv_t object. +* +* p_log +* [in] Pointer to the log object. +* +* p_disp +* [in] Pointer to the OpenSM central Dispatcher. +* +* RETURN VALUES +* CL_SUCCESS if the Node Info Receive Controller object was initialized +* successfully. +* +* NOTES +* Allows calling other Node Info Receive Controller methods. +* +* SEE ALSO +* Node Info Receive Controller object, osm_ni_rcv_ctrl_construct, +* osm_ni_rcv_ctrl_destroy, osm_ni_rcv_ctrl_is_inited +*********/ + +/****f* OpenSM: Node Info Receive Controller/osm_ni_rcv_ctrl_is_inited +* NAME +* osm_ni_rcv_ctrl_is_inited +* +* DESCRIPTION +* Indicates if the object has been initialized with osm_ni_rcv_ctrl_init. +* +* SYNOPSIS +*/ +boolean_t osm_ni_rcv_ctrl_is_inited( + IN const osm_ni_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_ni_rcv_ctrl_t object. +* +* RETURN VALUES +* TRUE if the object was initialized successfully, +* FALSE otherwise. +* +* NOTES +* The osm_ni_rcv_ctrl_construct or osm_ni_rcv_ctrl_init must be +* called before using this function. +* +* SEE ALSO +* Node Info Receive Controller object, osm_ni_rcv_ctrl_construct, +* osm_ni_rcv_ctrl_init +*********/ + +END_C_DECLS + +#endif /* _OSM_NI_RCV_CTRL_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_opensm.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_opensm.h new file mode 100644 index 00000000..488d43b7 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_opensm.h @@ -0,0 +1,440 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_opensm.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_opensm_t. + * This object represents the OpenSM super object. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.6 $ + */ + +#ifndef _OSM_OPENSM_H_ +#define _OSM_OPENSM_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/OpenSM +* NAME +* OpenSM +* +* DESCRIPTION +* The OpenSM object encapsulates the information needed by the +* OpenSM to govern itself. The OpenSM is one OpenSM object. +* +* The OpenSM object is thread safe. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: OpenSM/osm_routing_engine +* NAME +* struct osm_routing_engine +* +* DESCRIPTION +* OpenSM routing engine module definition. +* NOTES +* routing engine structure - yet limited by ucast_fdb_assign and +* ucast_build_fwd_tables (multicast callbacks may be added later) +*/ +struct osm_routing_engine { + const char *name; + void *context; + int (*build_lid_matrices)(void *context); + int (*ucast_build_fwd_tables)(void *context); + void (*ucast_dump_tables)(void *context); + void (*delete)(void *context); +}; +/* +* FIELDS +* name +* The routing engine name (will be used in logs). +* +* context +* The routing engine context. Will be passed as parameter +* to the callback functions. +* +* build_lid_matrices +* The callback for lid matrices generation. +* +* ucast_build_fwd_tables +* The callback for unicast forwarding table generation. +* +* ucast_dump_tables +* The callback for dumping unicast routing tables. +* +* delete +* The delete method, may be used for routing engine +* internals cleanup. +*/ + +/****s* OpenSM: OpenSM/osm_opensm_t +* NAME +* osm_opensm_t +* +* DESCRIPTION +* OpenSM structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_opensm_t +{ + osm_subn_t subn; + osm_sm_t sm; + osm_sa_t sa; + osm_db_t db; + osm_mad_pool_t mad_pool; + osm_vendor_t *p_vendor; + osm_vl15_t vl15; + osm_log_t log; + cl_dispatcher_t disp; + cl_plock_t lock; + struct osm_routing_engine routing_engine; + osm_stats_t stats; +} osm_opensm_t; +/* +* FIELDS +* subn +* Subnet object for this subnet. +* +* sm +* The Subnet Manager (SM) object for this subnet. +* +* sa +* The Subnet Administration (SA) object for this subnet. +* +* db +* Persistant storage of some data required between sessions. +* +* mad_pool +* Pool of Management Datagram (MAD) objects. +* +* p_vendor +* Pointer to the Vendor specific adapter for various +* transport interfaces, such as UMADT, AL, etc. The +* particular interface is set at compile time. +* +* vl15 +* The VL15 interface. +* +* log +* Log facility used by all OpenSM components. +* +* disp +* Central dispatcher containing the OpenSM worker threads. +* +* lock +* Shared lock guarding most OpenSM structures. +* +* routing_engine +* Routing engine; will be initialized then used. +* +* stats +* Open SM statistics block +* +* SEE ALSO +*********/ + +/****f* OpenSM: OpenSM/osm_opensm_construct +* NAME +* osm_opensm_construct +* +* DESCRIPTION +* This function constructs an OpenSM object. +* +* SYNOPSIS +*/ +void osm_opensm_construct( + IN osm_opensm_t* const p_osm ); +/* +* PARAMETERS +* p_osm +* [in] Pointer to a OpenSM object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_opensm_init, osm_opensm_destroy +* +* Calling osm_opensm_construct is a prerequisite to calling any other +* method except osm_opensm_init. +* +* SEE ALSO +* SM object, osm_opensm_init, osm_opensm_destroy +*********/ + +/****f* OpenSM: OpenSM/osm_opensm_destroy +* NAME +* osm_opensm_destroy +* +* DESCRIPTION +* The osm_opensm_destroy function destroys an SM, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_opensm_destroy( + IN osm_opensm_t* const p_osm ); +/* +* PARAMETERS +* p_osm +* [in] Pointer to a OpenSM object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified OpenSM object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to osm_opensm_construct or +* osm_opensm_init. +* +* SEE ALSO +* SM object, osm_opensm_construct, osm_opensm_init +*********/ + +/****f* OpenSM: OpenSM/osm_opensm_init +* NAME +* osm_opensm_init +* +* DESCRIPTION +* The osm_opensm_init function initializes a OpenSM object for use. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_opensm_init( + IN osm_opensm_t* const p_osm, + IN const osm_subn_opt_t* const p_opt ); +/* +* PARAMETERS +* p_osm +* [in] Pointer to an osm_opensm_t object to initialize. +* +* p_opt +* [in] Pointer to the subnet options structure. +* +* RETURN VALUES +* IB_SUCCESS if the OpenSM object was initialized successfully. +* +* NOTES +* Allows calling other OpenSM methods. +* +* SEE ALSO +* SM object, osm_opensm_construct, osm_opensm_destroy +*********/ + +/****f* OpenSM: OpenSM/osm_opensm_sweep +* NAME +* osm_opensm_sweep +* +* DESCRIPTION +* Initiates a subnet sweep. +* +* SYNOPSIS +*/ +static inline void +osm_opensm_sweep( + IN osm_opensm_t* const p_osm ) +{ + osm_sm_sweep( &p_osm->sm ); +} +/* +* PARAMETERS +* p_osm +* [in] Pointer to an osm_opensm_t object on which to +* initiate a sweep. +* +* RETURN VALUES +* None +* +* NOTES +* If the OpenSM object is not bound to a port, this function +* does nothing. +* +* SEE ALSO +*********/ + +/****f* OpenSM: OpenSM/osm_opensm_set_log_flags +* NAME +* osm_opensm_set_log_flags +* +* DESCRIPTION +* Sets the log level. +* +* SYNOPSIS +*/ +static inline void +osm_opensm_set_log_flags( + IN osm_opensm_t* const p_osm, + IN const osm_log_level_t log_flags ) +{ + osm_log_set_level( &p_osm->log, log_flags ); +} +/* +* PARAMETERS +* p_osm +* [in] Pointer to an osm_opensm_t object. +* +* log_flags +* [in] Log level flags to set. +* +* RETURN VALUES +* None +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: OpenSM/osm_opensm_bind +* NAME +* osm_opensm_bind +* +* DESCRIPTION +* Binds the opensm object to a port guid. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_opensm_bind( + IN osm_opensm_t* const p_osm, + IN const ib_net64_t guid ); +/* +* PARAMETERS +* p_osm +* [in] Pointer to an osm_opensm_t object to bind. +* +* guid +* [in] Local port GUID with which to bind. +* +* RETURN VALUES +* None +* +* NOTES +* A given opensm object can only be bound to one port at a time. +* +* SEE ALSO +*********/ + +/****f* OpenSM: OpenSM/osm_opensm_wait_for_subnet_up +* NAME +* osm_opensm_wait_for_subnet_up +* +* DESCRIPTION +* Blocks the calling thread until the subnet is up. +* +* SYNOPSIS +*/ +static inline cl_status_t +osm_opensm_wait_for_subnet_up( + IN osm_opensm_t* const p_osm, + IN uint32_t const wait_us, + IN boolean_t const interruptible ) +{ + return( osm_sm_wait_for_subnet_up( &p_osm->sm, wait_us, interruptible ) ); +} +/* +* PARAMETERS +* p_osm +* [in] Pointer to an osm_opensm_t object. +* +* wait_us +* [in] Number of microseconds to wait. +* +* interruptible +* [in] Indicates whether the wait operation can be interrupted +* by external signals. +* +* RETURN VALUES +* CL_SUCCESS if the wait operation succeeded in response to the event +* being set. +* +* CL_TIMEOUT if the specified time period elapses. +* +* CL_NOT_DONE if the wait was interrupted by an external signal. +* +* CL_ERROR if the wait operation failed. +* +* NOTES +* +* SEE ALSO +*********/ + +/****v* OpenSM/osm_exit_flag +*/ +extern volatile unsigned int osm_exit_flag; +/* +* DESCRIPTION +* Set to one to cause all threads to leave +*********/ + +END_C_DECLS + +#endif /* _OSM_OPENSM_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_partition.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_partition.h new file mode 100644 index 00000000..b45d44b8 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_partition.h @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_partition.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_prtn_t. + * This object represents an IBA Partition. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_PARTITION_H_ +#define _OSM_PARTITION_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Partition +* NAME +* Partition +* +* DESCRIPTION +* The Partition object encapsulates the information needed by the +* OpenSM to manage Partitions. The OpenSM allocates one Partition +* object per Partition in the IBA subnet. +* +* The Partition is not thread safe, thus callers must provide +* serialization. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: Partition/osm_prtn_t +* NAME +* osm_prtn_t +* +* DESCRIPTION +* Partition structure. +* +* The osm_prtn_t object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_prtn +{ + cl_map_item_t map_item; + uint16_t pkey; + uint8_t sl; + cl_map_t full_guid_tbl; + cl_map_t part_guid_tbl; + char name[32]; +} osm_prtn_t; +/* +* FIELDS +* map_item +* Linkage structure for cl_qmap. MUST BE FIRST MEMBER! +* +* pkey +* The IBA defined P_KEY of this Partition. +* +* sl +* The Service Level (SL) associated with this Partiton. +* +* full_guid_tbl +* Container of pointers to all Port objects in the Partition +* with full membership, indexed by port GUID. +* +* part_guid_tbl +* Container of pointers to all Port objects in the Partition +* with limited membership, indexed by port GUID. +* +* name +* Name of the Partition as specified in partition +* configuration. +* +* SEE ALSO +* Partition +*********/ + +/****f* OpenSM: Partition/osm_prtn_delete +* NAME +* osm_prtn_delete +* +* DESCRIPTION +* This function destroys and deallocates a Partition object. +* +* SYNOPSIS +*/ +void osm_prtn_delete( + IN OUT osm_prtn_t** const pp_prtn ); +/* +* PARAMETERS +* pp_prtn +* [in][out] Pointer to a pointer to a Partition object to +* delete. On return, this pointer is NULL. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified Partition object. +* +* SEE ALSO +* Partition, osm_prtn_new +*********/ + +/****f* OpenSM: Partition/osm_prtn_new +* NAME +* osm_prtn_new +* +* DESCRIPTION +* This function allocates and initializes a Partition object. +* +* SYNOPSIS +*/ +osm_prtn_t* osm_prtn_new( + IN const char *name, + IN const uint16_t pkey ); +/* +* PARAMETERS +* name +* [in] Partition name string +* +* pkey +* [in] Partition P_Key value +* +* RETURN VALUE +* Pointer to the initialize Partition object. +* +* NOTES +* Allows calling other partition methods. +* +* SEE ALSO +* Partition +*********/ + +/****f* OpenSM: Partition/osm_prtn_is_guid +* NAME +* osm_prtn_is_guid +* +* DESCRIPTION +* Indicates if a port is a member of the partition. +* +* SYNOPSIS +*/ +static inline +boolean_t osm_prtn_is_guid( + IN const osm_prtn_t* const p_prtn, + IN const ib_net64_t guid ) +{ + return (cl_map_get(&p_prtn->full_guid_tbl, guid) != NULL) || + (cl_map_get(&p_prtn->part_guid_tbl, guid) != NULL); +} +/* +* PARAMETERS +* p_prtn +* [in] Pointer to an osm_prtn_t object. +* +* guid +* [in] Port GUID. +* +* RETURN VALUES +* TRUE if the specified port GUID is a member of the partition, +* FALSE otherwise. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Partition/osm_prtn_make_partitions +* NAME +* osm_prtn_make_partitions +* +* DESCRIPTION +* Makes all partitions in subnet. +* +* SYNOPSIS +*/ +ib_api_status_t osm_prtn_make_partitions( + IN osm_log_t * const p_log, + IN osm_subn_t * const p_subn); +/* +* PARAMETERS +* p_log +* [in] Pointer to a log object. +* +* p_subn +* [in] Pointer to subnet object. +* +* RETURN VALUES +* IB_SUCCESS value on success. +* +* NOTES +* +* SEE ALSO +*********/ + +END_C_DECLS + +#endif /* _OSM_PARTITION_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_path.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_path.h new file mode 100644 index 00000000..49ed0402 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_path.h @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_path.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +#ifndef _OSM_PATH_H_ +#define _OSM_PATH_H_ + +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/* + * Abstract: + * Declaration of path related objects. + * These objects are part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +/****h* OpenSM/DR Path +* NAME +* DR Path +* +* DESCRIPTION +* The DR Path structure encapsulates a directed route through the subnet. +* +* This structure allows direct access to member variables. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: DR Path/osm_dr_path_t +* NAME +* osm_dr_path_t +* +* DESCRIPTION +* Directed Route structure. +* +* This structure allows direct access to member variables. +* +* SYNOPSIS +*/ +typedef struct _osm_dr_path +{ + osm_bind_handle_t h_bind; + uint8_t hop_count; + uint8_t path[IB_SUBNET_PATH_HOPS_MAX]; + +} osm_dr_path_t; +/* +* FIELDS +* h_bind +* Bind handle for port to which this path applies. +* +* hop_count +* The number of hops in this path. +* +* path +* The array of port numbers that comprise this path. +* +* SEE ALSO +* DR Path structure +*********/ +/****f* OpenSM: DR Path/osm_dr_path_construct +* NAME +* osm_dr_path_construct +* +* DESCRIPTION +* This function constructs a directed route path object. +* +* SYNOPSIS +*/ +static inline void +osm_dr_path_construct( + IN osm_dr_path_t* const p_path ) +{ + /* The first location in the path array is reserved. */ + memset( p_path, 0, sizeof(*p_path) ); + p_path->h_bind = OSM_BIND_INVALID_HANDLE; +} + +/* +* PARAMETERS +* p_path +* [in] Pointer to a directed route path object to initialize. +* +* h_bind +* [in] Bind handle for the port on which this path applies. +* +* hop_count +* [in] Hop count needed to reach this node. +* +* path +* [in] Directed route path to reach this node. +* +* RETURN VALUE +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: DR Path/osm_dr_path_init +* NAME +* osm_dr_path_init +* +* DESCRIPTION +* This function initializes a directed route path object. +* +* SYNOPSIS +*/ +static inline void +osm_dr_path_init( + IN osm_dr_path_t* const p_path, + IN const osm_bind_handle_t h_bind, + IN const uint8_t hop_count, + IN const uint8_t path[IB_SUBNET_PATH_HOPS_MAX] ) +{ + /* The first location in the path array is reserved. */ + CL_ASSERT( path[0] == 0 ); + CL_ASSERT( hop_count < IB_SUBNET_PATH_HOPS_MAX ); + p_path->h_bind = h_bind; + p_path->hop_count = hop_count; + memcpy( p_path->path, path, IB_SUBNET_PATH_HOPS_MAX ); +} + +/* +* PARAMETERS +* p_path +* [in] Pointer to a directed route path object to initialize. +* +* h_bind +* [in] Bind handle for the port on which this path applies. +* +* hop_count +* [in] Hop count needed to reach this node. +* +* path +* [in] Directed route path to reach this node. +* +* RETURN VALUE +* None. +* +* NOTES +* +* SEE ALSO +*********/ +/****f* OpenSM: DR Path/osm_dr_path_extend +* NAME +* osm_dr_path_extend +* +* DESCRIPTION +* Adds a new hop to a path. +* +* SYNOPSIS +*/ +static inline void +osm_dr_path_extend( + IN osm_dr_path_t* const p_path, + IN const uint8_t port_num ) +{ + p_path->hop_count++; + CL_ASSERT( p_path->hop_count < IB_SUBNET_PATH_HOPS_MAX ); + /* + Location 0 in the path array is reserved per IB spec. + */ + p_path->path[p_path->hop_count] = port_num; +} + +/* +* PARAMETERS +* p_path +* [in] Pointer to a directed route path object to initialize. +* +* port_num +* [in] Additional port to add to the DR path. +* +* RETURN VALUE +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: DR Path/osm_dr_path_get_bind_handle +* NAME +* osm_dr_path_get_bind_handle +* +* DESCRIPTION +* Gets the bind handle from a path. +* +* SYNOPSIS +*/ +static inline osm_bind_handle_t +osm_dr_path_get_bind_handle( + IN const osm_dr_path_t* const p_path ) +{ + return( p_path->h_bind ); +} + +/* +* PARAMETERS +* p_path +* [in] Pointer to a directed route path object to initialize. +* +* port_num +* [in] Additional port to add to the DR path. +* +* RETURN VALUE +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +END_C_DECLS + +#endif /* _OSM_PATH_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_pkey.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_pkey.h new file mode 100644 index 00000000..7f4abbee --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_pkey.h @@ -0,0 +1,755 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_pkey.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +#ifndef _OSM_PKEY_H_ +#define _OSM_PKEY_H_ + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/* + Forward references. +*/ +struct _osm_physp; +struct _osm_port; +struct _osm_subn; +struct _osm_node; +struct _osm_physp; + +/* + * Abstract: + * Declaration of pkey manipulation functions. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.1 $ + */ + +/****s* OpenSM: osm_pkey_tbl_t +* NAME +* osm_pkey_tbl_t +* +* DESCRIPTION +* This object represents a pkey table. The need for a special object +* is required to optimize search performance of a PKey in the IB standard +* non sorted table. +* +* The osm_pkey_tbl_t object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_pkey_tbl +{ + cl_ptr_vector_t blocks; + cl_ptr_vector_t new_blocks; + cl_map_t keys; + cl_qlist_t pending; + uint16_t used_blocks; + uint16_t max_blocks; +} osm_pkey_tbl_t; +/* +* FIELDS +* blocks +* The IBA defined blocks of pkey values, updated from the subnet +* +* new_blocks +* The blocks of pkey values, will be used for updates by SM +* +* keys +* A set holding all keys +* +* pending +* A list of osm_pending_pkey structs that is temporarily set by +* the pkey mgr and used during pkey mgr algorithm only +* +* used_blocks +* Tracks the number of blocks having non-zero pkeys +* +* max_blocks +* The maximal number of blocks this partition table might hold +* this value is based on node_info (for port 0 or CA) or +* switch_info updated on receiving the node_info or switch_info +* GetResp +* +* NOTES +* 'blocks' vector should be used to store pkey values obtained from +* the port and SM pkey manager should not change it directly, for this +* purpose 'new_blocks' should be used. +* +* The only pkey values stored in 'blocks' vector will be mapped with +* 'keys' map +* +*********/ + +/****s* OpenSM: osm_pending_pkey_t +* NAME +* osm_pending_pkey_t +* +* DESCRIPTION +* This objects stores temporary information on pkeys, their target block, +* and index during the pkey manager operation +* +* SYNOPSIS +*/ +typedef struct _osm_pending_pkey { + cl_list_item_t list_item; + uint16_t pkey; + uint16_t block; + uint8_t index; + boolean_t is_new; +} osm_pending_pkey_t; +/* +* FIELDS +* pkey +* The actual P_Key +* +* block +* The block index based on the previous table extracted from the +* device +* +* index +* The index of the pkey within the block +* +* is_new +* TRUE for new P_Keys such that the block and index are invalid +* in that case +* +*********/ + +/****f* OpenSM: osm_pkey_tbl_construct +* NAME +* osm_pkey_tbl_construct +* +* DESCRIPTION +* Constructs the PKey table object +* +* SYNOPSIS +*/ +void osm_pkey_tbl_construct( + IN osm_pkey_tbl_t *p_pkey_tbl); +/* +* p_pkey_tbl +* [in] Pointer to osm_pkey_tbl_t object. +* +* NOTES +* +*********/ + +/****f* OpenSM: osm_pkey_tbl_init +* NAME +* osm_pkey_tbl_init +* +* DESCRIPTION +* Inits the PKey table object +* +* SYNOPSIS +*/ +ib_api_status_t +osm_pkey_tbl_init( + IN osm_pkey_tbl_t *p_pkey_tbl); +/* +* p_pkey_tbl +* [in] Pointer to osm_pkey_tbl_t object. +* +* NOTES +* +*********/ + +/****f* OpenSM: osm_pkey_tbl_destroy +* NAME +* osm_pkey_tbl_destroy +* +* DESCRIPTION +* Destroys the PKey table object +* +* SYNOPSIS +*/ +void osm_pkey_tbl_destroy( + IN osm_pkey_tbl_t *p_pkey_tbl); +/* +* p_pkey_tbl +* [in] Pointer to osm_pkey_tbl_t object. +* +* NOTES +* +*********/ + +/****f* OpenSM: osm_pkey_get_num_blocks +* NAME +* osm_pkey_get_num_blocks +* +* DESCRIPTION +* Obtain the number of blocks in IB PKey table +* +* SYNOPSIS +*/ +static inline uint16_t +osm_pkey_tbl_get_num_blocks( + IN const osm_pkey_tbl_t *p_pkey_tbl ) +{ + return((uint16_t)(cl_ptr_vector_get_size( &p_pkey_tbl->blocks ))); +} +/* +* p_pkey_tbl +* [in] Pointer to osm_pkey_tbl_t object. +* +* RETURN VALUES +* The IB pkey table of that pkey table element +* +* NOTES +* +*********/ + +/****f* OpenSM: osm_pkey_tbl_block_get +* NAME +* osm_pkey_tbl_block_get +* +* DESCRIPTION +* Obtain the pointer to the IB PKey table block stored in the object +* +* SYNOPSIS +*/ +static inline ib_pkey_table_t *osm_pkey_tbl_block_get( + const osm_pkey_tbl_t *p_pkey_tbl, uint16_t block) +{ + return( (block < cl_ptr_vector_get_size(&p_pkey_tbl->blocks)) ? + cl_ptr_vector_get(&p_pkey_tbl->blocks, block) : NULL ); +}; +/* +* p_pkey_tbl +* [in] Pointer to osm_pkey_tbl_t object. +* +* block +* [in] The lock number to get +* +* RETURN VALUES +* The IB pkey table of that pkey table element +* +* NOTES +* +*********/ + +/****f* OpenSM: osm_pkey_tbl_new_block_get +* NAME +* osm_pkey_tbl_new_block_get +* +* DESCRIPTION +* The same as above but for new block +* +* SYNOPSIS +*/ +static inline ib_pkey_table_t *osm_pkey_tbl_new_block_get( + const osm_pkey_tbl_t *p_pkey_tbl, uint16_t block) +{ + return (block < cl_ptr_vector_get_size(&p_pkey_tbl->new_blocks)) ? + cl_ptr_vector_get(&p_pkey_tbl->new_blocks, block) : NULL; +}; + +/****f* OpenSM: osm_pkey_tbl_set_new_entry +* NAME +* osm_pkey_tbl_set_new_entry +* +* DESCRIPTION +* Stores the given pkey in the "new" blocks array and update +* the "map" to show that on the "old" blocks +* +* SYNOPSIS +*/ +ib_api_status_t +osm_pkey_tbl_set_new_entry( + IN osm_pkey_tbl_t *p_pkey_tbl, + IN uint16_t block_idx, + IN uint8_t pkey_idx, + IN uint16_t pkey); +/* +* p_pkey_tbl +* [in] Pointer to the PKey table +* +* block_idx +* [in] The block index to use +* +* pkey_idx +* [in] The index within the block +* +* pkey +* [in] PKey to store +* +* RETURN VALUES +* IB_SUCCESS if OK +* IB_ERROR if failed +* +*********/ + +/****f* OpenSM: osm_pkey_find_next_free_entry +* NAME +* osm_pkey_find_next_free_entry +* +* DESCRIPTION +* Find the next free entry in the PKey table starting at the given +* index and block number. The user should increment pkey_idx before +* next call +* Inspect the "new" blocks array for empty space. +* +* SYNOPSIS +*/ +boolean_t +osm_pkey_find_next_free_entry( + IN osm_pkey_tbl_t *p_pkey_tbl, + OUT uint16_t *p_block_idx, + OUT uint8_t *p_pkey_idx); +/* +* p_pkey_tbl +* [in] Pointer to the PKey table +* +* p_block_idx +* [out] The block index to use +* +* p_pkey_idx +* [out] The index within the block to use +* +* RETURN VALUES +* TRUE if found +* FALSE if did not find +* +*********/ + +/****f* OpenSM: osm_pkey_tbl_init_new_blocks +* NAME +* osm_pkey_tbl_init_new_blocks +* +* DESCRIPTION +* Initializes new_blocks vector content (allocate and clear) +* +* SYNOPSIS +*/ +void osm_pkey_tbl_init_new_blocks( + const osm_pkey_tbl_t *p_pkey_tbl); +/* +* p_pkey_tbl +* [in] Pointer to osm_pkey_tbl_t object. +* +* NOTES +* +*********/ + +/****f* OpenSM: osm_pkey_tbl_get_block_and_idx +* NAME +* osm_pkey_tbl_get_block_and_idx +* +* DESCRIPTION +* Set the block index and pkey index the given +* pkey is found in. Return IB_NOT_FOUND if could +* not find it, IB_SUCCESS if OK +* +* SYNOPSIS +*/ +ib_api_status_t +osm_pkey_tbl_get_block_and_idx( + IN osm_pkey_tbl_t *p_pkey_tbl, + IN uint16_t *p_pkey, + OUT uint16_t *block_idx, + OUT uint8_t *pkey_index); +/* +* p_pkey_tbl +* [in] Pointer to osm_pkey_tbl_t object. +* +* p_pkey +* [in] Pointer to the P_Key entry searched +* +* p_block_idx +* [out] Pointer to the block index to be updated +* +* p_pkey_idx +* [out] Pointer to the pkey index (in the block) to be updated +* +* NOTES +* +*********/ + +/****f* OpenSM: osm_pkey_tbl_set +* NAME +* osm_pkey_tbl_set +* +* DESCRIPTION +* Set the PKey table block provided in the PKey object. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_pkey_tbl_set( + IN osm_pkey_tbl_t *p_pkey_tbl, + IN uint16_t block, + IN ib_pkey_table_t *p_tbl); +/* +* p_pkey_tbl +* [in] Pointer to osm_pkey_tbl_t object. +* +* block +* [in] The block number to set +* +* p_tbl +* [in] The IB PKey block to copy to the object +* +* RETURN VALUES +* IB_SUCCESS or IB_ERROR +* +* NOTES +* +*********/ + +/****f* OpenSM: osm_physp_share_this_pkey +* NAME +* osm_physp_share_this_pkey +* +* DESCRIPTION +* Checks if the given physical ports share the specified pkey. +* +* SYNOPSIS +*/ +boolean_t osm_physp_share_this_pkey( + IN const struct _osm_physp * const p_physp1, + IN const struct _osm_physp * const p_physp2, + IN const ib_net16_t pkey); +/* +* PARAMETERS +* +* p_physp1 +* [in] Pointer to an osm_physp_t object. +* +* p_physp2 +* [in] Pointer to an osm_physp_t object. +* +* pkey +* [in] value of P_Key to check. +* +* RETURN VALUES +* Returns TRUE if the two ports are matching. +* FALSE otherwise. +* +* NOTES +* +*********/ + +/****f* OpenSM: osm_physp_find_common_pkey +* NAME +* osm_physp_find_common_pkey +* +* DESCRIPTION +* Returns first matching P_Key values for specified physical ports. +* +* SYNOPSIS +*/ +ib_net16_t osm_physp_find_common_pkey( + IN const struct _osm_physp * const p_physp1, + IN const struct _osm_physp * const p_physp2 ); +/* +* PARAMETERS +* +* p_physp1 +* [in] Pointer to an osm_physp_t object. +* +* p_physp2 +* [in] Pointer to an osm_physp_t object. +* +* RETURN VALUES +* Returns value of first shared P_Key or INVALID P_Key (0x0) if not +* found. +* +* NOTES +* +*********/ + +/****f* OpenSM: osm_physp_share_pkey +* NAME +* osm_physp_share_pkey +* +* DESCRIPTION +* Checks if the given physical ports share a pkey. +* The meaning P_Key matching: +* 10.9.3 : +* In the following, let M_P_Key(Message P_Key) be the P_Key in the incoming +* packet and E_P_Key(Endnode P_Key) be the P_Key it is being compared against +* in the packet's destination endnode. +* +* If: +* * neither M_P_Key nor E_P_Key are the invalid P_Key +* * and the low-order 15 bits of the M_P_Key match the low order 15 +* bits of the E_P_Key +* * and the high order bit(membership type) of both the M_P_Key and +* E_P_Key are not both 0 (i.e., both are not Limited members of +* the partition) +* +* then the P_Keys are said to match. +* +* SYNOPSIS +*/ +boolean_t osm_physp_share_pkey( + IN osm_log_t* p_log, + IN const struct _osm_physp* const p_physp_1, + IN const struct _osm_physp* const p_physp_2 ); + +/* +* PARAMETERS +* p_log +* [in] Pointer to a log object. +* +* p_physp_1 +* [in] Pointer to an osm_physp_t object. +* +* p_physp_2 +* [in] Pointer to an osm_physp_t object. +* +* RETURN VALUES +* Returns TRUE if the 2 physical ports are matching. +* FALSE otherwise. +* +* NOTES +* +*********/ + +/****f* OpenSM: osm_port_share_pkey +* NAME +* osm_port_share_pkey +* +* DESCRIPTION +* Checks if the given ports (on their default physical port) share a pkey. +* The meaning P_Key matching: +* 10.9.3 : +* In the following, let M_P_Key(Message P_Key) be the P_Key in the incoming +* packet and E_P_Key(Endnode P_Key) be the P_Key it is being compared against +* in the packet's destination endnode. +* +* If: +* * neither M_P_Key nor E_P_Key are the invalid P_Key +* * and the low-order 15 bits of the M_P_Key match the low order 15 +* bits of the E_P_Key +* * and the high order bit(membership type) of both the M_P_Key and +* E_P_Key are not both 0 (i.e., both are not Limited members of +* the partition) +* +* then the P_Keys are said to match. +* +* SYNOPSIS +*/ +boolean_t osm_port_share_pkey( + IN osm_log_t* p_log, + IN const struct _osm_port* const p_port_1, + IN const struct _osm_port* const p_port_2 ); + +/* +* PARAMETERS +* p_log +* [in] Pointer to a log object. +* +* p_port_1 +* [in] Pointer to an osm_port_t object. +* +* p_port_2 +* [in] Pointer to an osm_port_t object. +* +* RETURN VALUES +* Returns TRUE if the 2 ports are matching. +* FALSE otherwise. +* +* NOTES +* +*********/ + +/****f* OpenSM: osm_lid_share_pkey +* NAME +* osm_lid_share_pkey +* +* DESCRIPTION +* Checks if the given lids and port_numbers share a pkey. +* The meaning P_Key matching: +* 10.9.3 : +* In the following, let M_P_Key(Message P_Key) be the P_Key in the incoming +* packet and E_P_Key(Endnode P_Key) be the P_Key it is being compared against +* in the packet's destination endnode. +* +* If: +* * neither M_P_Key nor E_P_Key are the invalid P_Key +* * and the low-order 15 bits of the M_P_Key match the low order 15 +* bits of the E_P_Key +* * and the high order bit(membership type) of both the M_P_Key and +* E_P_Key are not both 0 (i.e., both are not Limited members of +* the partition) +* +* then the P_Keys are said to match. +* +* SYNOPSIS +*/ +boolean_t osm_lid_share_pkey( + IN osm_log_t* p_log, + IN const struct _osm_subn* const p_subn, + IN const ib_net16_t lid1, + IN const uint8_t port_num1, + IN const ib_net16_t lid2, + IN const uint8_t port_num2 ); + +/* +* PARAMETERS +* p_log +* [in] Pointer to a log object. +* +* p_subn +* [in] Pointer to the subnet object for accessing of the options. +* +* lid1 +* [in] lid number of first port. +* +* port_num1 +* [in] port number of first port. +* +* lid2 +* [in] lid number of second port. +* +* port_num2 +* [in] port number of second port. +* +* RETURN VALUES +* Returns TRUE if the 2 physical ports that belong to these lids/port_numbers +* are matching. FALSE otherwise. +* +* NOTES +* +*********/ + +/****f* OpenSM: osm_physp_has_pkey +* NAME +* osm_physp_has_pkey +* +* DESCRIPTION +* Checks if the given lids and port_numbers share a pkey. +* The meaning P_Key matching: +* 10.9.3 : +* In the following, let M_P_Key(Message P_Key) be the P_Key in the incoming +* packet and E_P_Key(Endnode P_Key) be the P_Key it is being compared against +* in the packet's destination endnode. +* +* If: +* * neither M_P_Key nor E_P_Key are the invalid P_Key +* * and the low-order 15 bits of the M_P_Key match the low order 15 +* bits of the E_P_Key +* * and the high order bit(membership type) of both the M_P_Key and +* E_P_Key are not both 0 (i.e., both are not Limited members of +* the partition) +* +* then the P_Keys are said to match. +* +* SYNOPSIS +*/ +boolean_t osm_physp_has_pkey( + IN osm_log_t* p_log, + IN const ib_net16_t pkey, + IN const struct _osm_physp* const p_physp ); + +/* +* PARAMETERS +* p_log +* [in] Pointer to a log object. +* +* pkey +* [in] pkey number to look for. +* +* p_physp +* [in] Pointer to osm_physp_t object. +* +* RETURN VALUES +* Returns TRUE if the p_physp has the pkey given. False otherwise. +* +* NOTES +* +*********/ + +/****f* OpenSM: osm_pkey_get_tables +* NAME +* osm_pkey_get_tables +* +* DESCRIPTION +* Sends a request for getting the pkey tables of the given physp. +* +* SYNOPSIS +*/ +void osm_pkey_get_tables( + IN osm_log_t *p_log, + IN osm_req_t *p_req, + IN osm_subn_t* const p_subn, + IN struct _osm_node* const p_node, + IN struct _osm_physp* const p_physp ); + +/* +* PARAMETERS +* p_log +* [in] Pointer to osm_log object. +* +* p_req +* [in] Pointer to osm_req object. +* +* p_subn +* [in] Pointer to osm_subn object. +* +* p_node +* [in] Pointer to osm_node object. +* +* p_physp +* [in] Pointer to osm_physp_t object. +* +* RETURN VALUES +* None +* +* NOTES +* +*********/ + +END_C_DECLS + +#endif /* _OSM_PKEY_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_pkey_mgr.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_pkey_mgr.h new file mode 100644 index 00000000..42980173 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_pkey_mgr.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_pkey_mgr.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Prototype for osm_pkey_mgr_process() function + * This is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_PKEY_MGR_H_ +#define _OSM_PKEY_MGR_H_ + +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****f* OpenSM: P_Key Manager/osm_pkey_mgr_process +* NAME +* osm_pkey_mgr_process +* +* DESCRIPTION +* This function enforces the pkey rules on the SM DB. +* +* SYNOPSIS +*/ +osm_signal_t +osm_pkey_mgr_process( + IN osm_opensm_t *p_osm ); +/* +* PARAMETERS +* p_osm +* [in] Pointer to an osm_opensm_t object. +* +* RETURN VALUES +* None +* +* NOTES +* +* SEE ALSO +*********/ + +END_C_DECLS + +#endif /* _OSM_PKEY_MGR_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_pkey_rcv.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_pkey_rcv.h new file mode 100644 index 00000000..8e235059 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_pkey_rcv.h @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_pkey_rcv.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +#ifndef _OSM_PKEY_RCV_H_ +#define _OSM_PKEY_RCV_H_ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/P_Key Receiver +* NAME +* P_Key Receiver +* +* DESCRIPTION +* The P_Key Receiver object encapsulates the information +* needed to set or get the vl arbitration attribute from a port. +* +* The P_Key Receiver object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Yael Kalka, Mellanox +* +*********/ + +/****s* OpenSM: P_Key Receiver/osm_pkey_rcv_t +* NAME +* osm_pkey_rcv_t +* +* DESCRIPTION +* P_Key Receiver structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_pkey_rcv +{ + osm_subn_t *p_subn; + osm_req_t *p_req; + osm_log_t *p_log; + cl_plock_t *p_lock; + +} osm_pkey_rcv_t; +/* +* FIELDS +* p_subn +* Pointer to the Subnet object for this subnet. +* +* p_req +* Pointer to the generic attribute request object. +* +* p_log +* Pointer to the log object. +* +* p_lock +* Pointer to the serializing lock. +* +* SEE ALSO +* P_Key Receiver object +*********/ + +/****f* OpenSM: P_Key Receiver/osm_pkey_rcv_construct +* NAME +* osm_pkey_rcv_construct +* +* DESCRIPTION +* This function constructs a P_Key Receiver object. +* +* SYNOPSIS +*/ +void osm_pkey_rcv_construct( + IN osm_pkey_rcv_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a P_Key Receiver object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_pkey_rcv_destroy +* +* Calling osm_pkey_rcv_construct is a prerequisite to calling any other +* method except osm_pkey_rcv_init. +* +* SEE ALSO +* P_Key Receiver object, osm_pkey_rcv_init, +* osm_pkey_rcv_destroy +*********/ + +/****f* OpenSM: P_Key Receiver/osm_pkey_rcv_destroy +* NAME +* osm_pkey_rcv_destroy +* +* DESCRIPTION +* The osm_pkey_rcv_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_pkey_rcv_destroy( + IN osm_pkey_rcv_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* P_Key Receiver object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_pkey_rcv_construct or osm_pkey_rcv_init. +* +* SEE ALSO +* P_Key Receiver object, osm_pkey_rcv_construct, +* osm_pkey_rcv_init +*********/ + +/****f* OpenSM: P_Key Receiver/osm_pkey_rcv_init +* NAME +* osm_pkey_rcv_init +* +* DESCRIPTION +* The osm_pkey_rcv_init function initializes a +* P_Key Receiver object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_pkey_rcv_init( + IN osm_pkey_rcv_t* const p_ctrl, + IN osm_req_t* const p_req, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_pkey_rcv_t object to initialize. +* +* p_req +* [in] Pointer to an osm_req_t object. +* +* p_subn +* [in] Pointer to the Subnet object for this subnet. +* +* p_log +* [in] Pointer to the log object. +* +* p_lock +* [in] Pointer to the OpenSM serializing lock. +* +* RETURN VALUES +* CL_SUCCESS if the P_Key Receiver object was initialized +* successfully. +* +* NOTES +* Allows calling other P_Key Receiver methods. +* +* SEE ALSO +* P_Key Receiver object, osm_pkey_rcv_construct, +* osm_pkey_rcv_destroy +*********/ + +/****f* OpenSM: P_Key Receiver/osm_pkey_rcv_process +* NAME +* osm_pkey_rcv_process +* +* DESCRIPTION +* Process the vl arbitration attribute. +* +* SYNOPSIS +*/ +void osm_pkey_rcv_process( + IN const osm_pkey_rcv_t* const p_ctrl, + IN osm_madw_t* const p_madw ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_pkey_rcv_t object. +* +* p_madw +* [in] Pointer to the MAD Wrapper containing the MAD +* that contains the node's SLtoVL attribute. +* +* RETURN VALUES +* CL_SUCCESS if the SLtoVL processing was successful. +* +* NOTES +* This function processes a SLtoVL attribute. +* +* SEE ALSO +* P_Key Receiver, P_Key Response Controller +*********/ + +END_C_DECLS + +#endif /* _OSM_PKEY_RCV_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_pkey_rcv_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_pkey_rcv_ctrl.h new file mode 100644 index 00000000..dfb7ea0b --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_pkey_rcv_ctrl.h @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_pkey_rcv_ctrl.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +#ifndef _OSM_PKEY_RCV_CTRL_H_ +#define _OSM_PKEY_RCV_CTRL_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/P_Key Table Receive Controller +* NAME +* P_Key Receive Controller +* +* DESCRIPTION +* The P_Key Receive Controller object encapsulates +* the information needed to get or set P_Key table of a port. +* +* The P_Key Receive Controller object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Yael Kalka, Mellanox +* +*********/ + +/****s* OpenSM: P_Key Receive Controller/osm_pkey_rcv_ctrl_t +* NAME +* osm_pkey_rcv_ctrl_t +* +* DESCRIPTION +* P_Key Receive Controller structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_pkey_rcv_ctrl +{ + osm_pkey_rcv_t *p_rcv; + osm_log_t *p_log; + cl_dispatcher_t *p_disp; + cl_disp_reg_handle_t h_disp; + +} osm_pkey_rcv_ctrl_t; +/* +* FIELDS +* p_rcv +* Pointer to the P_Key Receiver object. +* +* p_log +* Pointer to the log object. +* +* p_disp +* Pointer to the Dispatcher. +* +* h_disp +* Handle returned from dispatcher registration. +* +* SEE ALSO +* P_Key Receive Controller object +* P_Key Receiver object +*********/ + +/****f* OpenSM: P_Key Receive Controller/osm_pkey_rcv_ctrl_construct +* NAME +* osm_pkey_rcv_ctrl_construct +* +* DESCRIPTION +* This function constructs a P_Key Receive Controller object. +* +* SYNOPSIS +*/ +void osm_pkey_rcv_ctrl_construct( + IN osm_pkey_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a P_Key Receive Controller +* object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_pkey_rcv_ctrl_init, osm_pkey_rcv_ctrl_destroy, +* and osm_pkey_rcv_ctrl_is_inited. +* +* Calling osm_pkey_rcv_ctrl_construct is a prerequisite to calling any other +* method except osm_pkey_rcv_ctrl_init. +* +* SEE ALSO +* P_Key Receive Controller object, osm_pkey_rcv_ctrl_init, +* osm_pkey_rcv_ctrl_destroy, osm_pkey_rcv_ctrl_is_inited +*********/ + +/****f* OpenSM: P_Key Receive Controller/osm_pkey_rcv_ctrl_destroy +* NAME +* osm_pkey_rcv_ctrl_destroy +* +* DESCRIPTION +* The osm_pkey_rcv_ctrl_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_pkey_rcv_ctrl_destroy( + IN osm_pkey_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* P_Key Receive Controller object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_pkey_rcv_ctrl_construct or osm_pkey_rcv_ctrl_init. +* +* SEE ALSO +* P_Key Receive Controller object, osm_pkey_rcv_ctrl_construct, +* osm_pkey_rcv_ctrl_init +*********/ + +/****f* OpenSM: P_Key Receive Controller/osm_pkey_rcv_ctrl_init +* NAME +* osm_pkey_rcv_ctrl_init +* +* DESCRIPTION +* The osm_pkey_rcv_ctrl_init function initializes a +* P_Key Receive Controller object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_pkey_rcv_ctrl_init( + IN osm_pkey_rcv_ctrl_t* const p_ctrl, + IN osm_pkey_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_pkey_rcv_ctrl_t object to initialize. +* +* p_rcv +* [in] Pointer to an osm_pkey_rcv_t object. +* +* p_log +* [in] Pointer to the log object. +* +* p_disp +* [in] Pointer to the OpenSM central Dispatcher. +* +* RETURN VALUES +* CL_SUCCESS if the P_Key Receive Controller object was initialized +* successfully. +* +* NOTES +* Allows calling other P_Key Receive Controller methods. +* +* SEE ALSO +* P_Key Receive Controller object, osm_pkey_rcv_ctrl_construct, +* osm_pkey_rcv_ctrl_destroy, osm_pkey_rcv_ctrl_is_inited +*********/ + +/****f* OpenSM: P_Key Receive Controller/osm_pkey_rcv_ctrl_is_inited +* NAME +* osm_pkey_rcv_ctrl_is_inited +* +* DESCRIPTION +* Indicates if the object has been initialized with osm_pkey_rcv_ctrl_init. +* +* SYNOPSIS +*/ +boolean_t osm_pkey_rcv_ctrl_is_inited( + IN const osm_pkey_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_pkey_rcv_ctrl_t object. +* +* RETURN VALUES +* TRUE if the object was initialized successfully, +* FALSE otherwise. +* +* NOTES +* The osm_pkey_rcv_ctrl_construct or osm_pkey_rcv_ctrl_init must be +* called before using this function. +* +* SEE ALSO +* P_Key Receive Controller object, osm_pkey_rcv_ctrl_construct, +* osm_pkey_rcv_ctrl_init +*********/ + +END_C_DECLS + +#endif /* _OSM_PKEY_RCV_CTRL_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_port.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_port.h new file mode 100644 index 00000000..5d9ecf42 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_port.h @@ -0,0 +1,2122 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_port.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of port related objects. + * These objects comprise an IBA port. + * These objects are part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.8 $ + */ + +#ifndef _OSM_PORT_H_ +#define _OSM_PORT_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/* + Forward references. +*/ +struct _osm_port; +struct _osm_node; + +/****h* OpenSM/Physical Port +* NAME +* Physical Port +* +* DESCRIPTION +* The Physical Port object encapsulates the information needed by the +* OpenSM to manage physical ports. The OpenSM allocates one Physical Port +* per physical port in the IBA subnet. +* +* In a switch, one multiple Physical Port objects share the same port GUID. +* In an end-point, Physical Ports do not share GUID values. +* +* The Physical Port is not thread safe, thus callers must provide +* serialization. +* +* These objects should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: Physical Port/osm_physp_t +* NAME +* osm_physp_t +* +* DESCRIPTION +* This object represents a physical port on a switch, router or end-point. +* +* The osm_physp_t object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_physp +{ + ib_port_info_t port_info; + ib_net64_t port_guid; + uint8_t port_num; + struct _osm_node *p_node; + struct _osm_physp *p_remote_physp; + boolean_t healthy; + osm_dr_path_t dr_path; + osm_pkey_tbl_t pkeys; + ib_vl_arb_table_t vl_arb[4]; + cl_ptr_vector_t slvl_by_port; + boolean_t got_set_resp; +} osm_physp_t; +/* +* FIELDS +* port_info +* The IBA defined PortInfo data for this port. +* +* port_guid +* Port GUID value of this port. For switches, +* all ports share the same GUID value. +* +* port_num +* The port number of this port. The PortInfo also +* contains a port_number, but that number is not +* the port number of this port, but rather the number +* of the port that received the SMP during discovery. +* Therefore, we must keep a separate record for this +* port's port number. +* +* p_node +* Pointer to the parent Node object of this Physical Port. +* +* p_remote_physp +* Pointer to the Physical Port on the other side of the wire. +* If this pointer is NULL no link exists at this port. +* +* healthy +* Tracks the health of the port. Normally should be TRUE but +* might change as a result of incoming traps indicating the port +* healthy is questionable. +* +* dr_path +* The directed route path to this port. +* +* pkeys +* osm_pkey_tbl_t object holding the port PKeys. +* +* vl_arb[] +* Each Physical Port has 4 sections of VL Arbitration table. +* +* slvl_by_port +* A vector of pointers to the sl2vl tables (ordered by input port). +* On switches have an entry for every other input port (inc SMA=0). +* On CAs only one per port. +* +* got_set_resp +* Marks whether or not we got a PortInfoSetResp from this port or not. +* This is used for minimizing the number of PortInfoSet requests sent. +* If we already got a set response from this port, then we will +* send a PortInfoSet only if the values we are updating are +* different than the ones on the port. If the haven't gotten a set +* response - then we want to send the request anyways - since +* every we need at least one PortInfoSet request for every port +* (by a new SM). +* +* SEE ALSO +* Port +*********/ + +/****f* OpenSM: Physical Port/osm_physp_construct +* NAME +* osm_physp_construct +* +* DESCRIPTION +* Constructs a Physical Port. +* +* SYNOPSIS +*/ +void +osm_physp_construct( + IN osm_physp_t* const p_physp ); +/* +* PARAMETERS +* p_physp +* [in] Pointer to an osm_physp_t object to initialize. +* +* RETURN VALUES +* This function does not return a value. +* +* NOTES +* +* SEE ALSO +* Port, Physical Port +*********/ + +/****f* OpenSM: Physical Port/osm_physp_init +* NAME +* osm_physp_init +* +* DESCRIPTION +* Initializes a Physical Port for use. +* +* SYNOPSIS +*/ +void +osm_physp_init( + IN osm_physp_t* const p_physp, + IN const ib_net64_t port_guid, + IN const uint8_t port_num, + IN const struct _osm_node* const p_node, + IN const osm_bind_handle_t h_bind, + IN const uint8_t hop_count, + IN const uint8_t* const p_initial_path ); +/* +* PARAMETERS +* p_physp +* [in] Pointer to an osm_physp_t object to initialize. +* +* port_guid +* [in] GUID value of this port. Switch ports all share +* the same value. +* Caller should use 0 if the guid is unknown. +* +* port_num +* [in] The port number of this port. +* +* p_node +* [in] Pointer to the parent Node object of this Physical Port. +* +* h_bind +* [in] Bind handle on which this port is accessed. +* Caller should use OSM_INVALID_BIND_HANDLE if the bind +* handle to this port is unknown. +* +* hop_count +* [in] Directed route hop count to reach this port. +* Caller should use 0 if the hop count is unknown. +* +* p_initial_path +* [in] Pointer to the directed route path to reach this node. +* Caller should use NULL if the path is unknown. +* +* RETURN VALUES +* This function does not return a value. +* +* NOTES +* +* SEE ALSO +* Port, Physical Port +*********/ + +/****f* OpenSM: Port/void osm_physp_destroy +* NAME +* osm_physp_destroy +* +* DESCRIPTION +* This function destroys a Port object. +* +* SYNOPSIS +*/ +void +osm_physp_destroy( + IN osm_physp_t* const p_physp ); +/* +* PARAMETERS +* p_port +* [in] Pointer to a PhysPort object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified PhysPort object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to osm_physp_construct or +* osm_physp_init. +* +* SEE ALSO +* Port, osm_port_init, osm_port_destroy +*********/ + +/****f* OpenSM: Physical Port/osm_physp_is_valid +* NAME +* osm_physp_is_valid +* +* DESCRIPTION +* Returns TRUE if the Physical Port has been successfully initialized. +* FALSE otherwise. +* +* SYNOPSIS +*/ +static inline boolean_t +osm_physp_is_valid( + IN const osm_physp_t* const p_physp ) +{ + CL_ASSERT( p_physp ); + return( p_physp->port_guid != 0 ); +} +/* +* PARAMETERS +* p_physp +* [in] Pointer to an osm_physp_t object. +* +* RETURN VALUES +* Returns TRUE if the Physical Port has been successfully initialized. +* FALSE otherwise. +* +* NOTES +* +* SEE ALSO +* Port, Physical Port +*********/ + +/****f* OpenSM: Physical Port/osm_physp_is_healthy +* NAME +* osm_physp_is_healthy +* +* DESCRIPTION +* Returns TRUE if the Physical Port has been maked as healthy +* FALSE otherwise. +* +* SYNOPSIS +*/ +static inline boolean_t +osm_physp_is_healthy( + IN const osm_physp_t* const p_physp ) +{ + CL_ASSERT( p_physp ); + return( p_physp->healthy ); +} +/* +* PARAMETERS +* p_physp +* [in] Pointer to an osm_physp_t object. +* +* RETURN VALUES +* Returns TRUE if the Physical Port has been maked as healthy +* FALSE otherwise. +* All physical ports are initialized as "healthy" but may be marked +* otherwise if a received trap claims otherwise. +* +* NOTES +* +* SEE ALSO +* Port, Physical Port +*********/ + +/****f* OpenSM: Physical Port/osm_link_is_healthy +* NAME +* osm_link_is_healthy +* +* DESCRIPTION +* Returns TRUE if the link given by the physical port is health, +* and FALSE otherwise. Link is healthy if both its physical ports are +* healthy +* +* SYNOPSIS +*/ +boolean_t +osm_link_is_healthy( + IN const osm_physp_t* const p_physp ); +/* +* PARAMETERS +* p_physp +* [in] Pointer to an osm_physp_t object. +* +* RETURN VALUES +* TRUE if both physical ports on the link are healthy, and FALSE otherwise. +* All physical ports are initialized as "healthy" but may be marked +* otherwise if a received trap claiming otherwise. +* +* NOTES +* +* SEE ALSO +* Port, Physical Port +*********/ + +/****f* OpenSM: Physical Port/osm_physp_set_health +* NAME +* osm_physp_set_health +* +* DESCRIPTION +* Sets the port health flag. TRUE means the port is healthy and +* should be used for packet routing. FALSE means it should be avoided. +* +* SYNOPSIS +*/ +static inline void +osm_physp_set_health( + IN osm_physp_t* const p_physp, + IN boolean_t is_healthy ) +{ + CL_ASSERT( p_physp ); + p_physp->healthy = is_healthy; +} +/* +* PARAMETERS +* p_physp +* [in] Pointer to an osm_physp_t object. +* +* is_healthy +* [in] The health value to be assigned to the port. +* TRUE if the Physical Port should been maked as healthy +* FALSE otherwise. +* +* RETURN VALUES +* NONE +* +* NOTES +* +* SEE ALSO +* Port, Physical Port +*********/ + +/****f* OpenSM: Physical Port/osm_physp_set_port_info +* NAME +* osm_physp_set_port_info +* +* DESCRIPTION +* Copies the PortInfo attribute into the Physical Port object +* based on the PortState. +* +* SYNOPSIS +*/ +static inline void +osm_physp_set_port_info( + IN osm_physp_t* const p_physp, + IN const ib_port_info_t* const p_pi ) +{ + CL_ASSERT( p_pi ); + CL_ASSERT( osm_physp_is_valid( p_physp ) ); + + if (ib_port_info_get_port_state(p_pi) == IB_LINK_DOWN) + { + /* If PortState is down, only copy PortState */ + /* and PortPhysicalState per C14-24-2.1 */ + ib_port_info_set_port_state(&p_physp->port_info, IB_LINK_DOWN); + ib_port_info_set_port_phys_state( + ib_port_info_get_port_phys_state(p_pi), &p_physp->port_info); + } + else + { + p_physp->port_info = *p_pi; + } +} +/* +* PARAMETERS +* p_physp +* [in] Pointer to an osm_physp_t object. +* +* p_pi +* [in] Pointer to the IBA defined PortInfo at this port number. +* +* RETURN VALUES +* This function does not return a value. +* +* NOTES +* +* SEE ALSO +* Port, Physical Port +*********/ + +/****f* OpenSM: Physical Port/osm_physp_trim_base_lid_to_valid_range +* NAME +* osm_physp_trim_base_lid_to_valid_range +* +* DESCRIPTION +* Validates the base LID in the Physical Port object +* and resets it if the base LID is invalid. +* +* SYNOPSIS +*/ +static inline ib_net16_t +osm_physp_trim_base_lid_to_valid_range( + IN osm_physp_t* const p_physp ) +{ + ib_net16_t orig_lid = 0; + + CL_ASSERT( osm_physp_is_valid( p_physp ) ); + if ( ( cl_ntoh16( p_physp->port_info.base_lid ) > IB_LID_UCAST_END_HO ) || + ( cl_ntoh16( p_physp->port_info.base_lid ) < IB_LID_UCAST_START_HO ) ) + { + orig_lid = p_physp->port_info.base_lid; + p_physp->port_info.base_lid = 0; + } + return orig_lid; +} +/* +* PARAMETERS +* p_physp +* [in] Pointer to an osm_physp_t object. +* +* RETURN VALUES +* Returns 0 if the base LID in the Physical port object is valid. +* Returns original invalid LID otherwise. +* +* NOTES +* +* SEE ALSO +* Port, Physical Port +*********/ + +/****f* OpenSM: Physical Port/osm_physp_set_pkey_tbl +* NAME +* osm_physp_set_pkey_tbl +* +* DESCRIPTION +* Copies the P_Key table into the Physical Port object. +* +* SYNOPSIS +*/ +void +osm_physp_set_pkey_tbl( IN osm_log_t* p_log, + IN const osm_subn_t* p_subn, + IN osm_physp_t* const p_physp, + IN ib_pkey_table_t *p_pkey_tbl, + IN uint16_t block_num ); +/* +* PARAMETERS +* p_log +* [in] Pointer to a log object. +* +* p_subn +* [in] Pointer to the subnet data structure. +* +* p_physp +* [in] Pointer to an osm_physp_t object. +* +* p_pkey_tbl +* [in] Pointer to the IBA defined P_Key table for this port +* number. +* +* block_num +* [in] The part of the P_Key table as defined in the IBA +* (valid values 0-2047, and is further limited by the +* partitionCap). +* +* RETURN VALUES +* This function does not return a value. +* +* NOTES +* +* SEE ALSO +* Port, Physical Port +*********/ + +/****f* OpenSM: Physical Port/osm_physp_get_pkey_tbl +* NAME +* osm_physp_get_pkey_tbl +* +* DESCRIPTION +* Returns a pointer to the P_Key table object of the Physical Port object. +* +* SYNOPSIS +*/ +static inline const osm_pkey_tbl_t * +osm_physp_get_pkey_tbl( IN const osm_physp_t* const p_physp ) +{ + CL_ASSERT( osm_physp_is_valid( p_physp ) ); + /* + (14.2.5.7) - the block number valid values are 0-2047, and are further + limited by the size of the P_Key table specified by the PartitionCap on the node. + */ + return( &p_physp->pkeys ); +}; +/* +* PARAMETERS +* p_physp +* [in] Pointer to an osm_physp_t object. +* +* RETURN VALUES +* The pointer to the P_Key table object. +* +* NOTES +* +* SEE ALSO +* Port, Physical Port +*********/ + +/****f* OpenSM: Physical Port/osm_physp_get_mod_pkey_tbl +* NAME +* osm_physp_get_mod_pkey_tbl +* +* DESCRIPTION +* Returns a NON CONST pointer to the P_Key table object of the Physical Port object. +* +* SYNOPSIS +*/ +static inline osm_pkey_tbl_t * +osm_physp_get_mod_pkey_tbl( IN osm_physp_t* const p_physp ) +{ + CL_ASSERT( osm_physp_is_valid( p_physp ) ); + /* + (14.2.5.7) - the block number valid values are 0-2047, and are further + limited by the size of the P_Key table specified by the PartitionCap on the node. + */ + return( &p_physp->pkeys ); +}; +/* +* PARAMETERS +* p_physp +* [in] Pointer to an osm_physp_t object. +* +* RETURN VALUES +* The pointer to the P_Key table object. +* +* NOTES +* +* SEE ALSO +* Port, Physical Port +*********/ + +/****f* OpenSM: Physical Port/osm_physp_set_slvl_tbl +* NAME +* osm_physp_set_slvl_tbl +* +* DESCRIPTION +* Copies the SLtoVL attribute into the Physical Port object. +* +* SYNOPSIS +*/ +static inline void +osm_physp_set_slvl_tbl( IN osm_physp_t* const p_physp, + IN ib_slvl_table_t *p_slvl_tbl, + IN uint8_t in_port_num ) +{ + ib_slvl_table_t *p_tbl; + + CL_ASSERT( p_slvl_tbl ); + CL_ASSERT( osm_physp_is_valid( p_physp ) ); + p_tbl = cl_ptr_vector_get(&p_physp->slvl_by_port, in_port_num); + *p_tbl = *p_slvl_tbl; +} +/* +* PARAMETERS +* p_physp +* [in] Pointer to an osm_physp_t object. +* +* p_slvl_tbl +* [in] Pointer to the IBA defined SLtoVL map table for this port number. +* +* in_port_num +* [in] Input Port Number for this SLtoVL. +* +* RETURN VALUES +* This function does not return a value. +* +* NOTES +* +* SEE ALSO +* Port, Physical Port +*********/ + +/****f* OpenSM: Physical Port/osm_physp_get_slvl_tbl +* NAME +* osm_physp_get_slvl_tbl +* +* DESCRIPTION +* Returns a pointer to the SLtoVL attribute of the Physical Port object. +* +* SYNOPSIS +*/ +static inline ib_slvl_table_t * +osm_physp_get_slvl_tbl( IN const osm_physp_t* const p_physp, + IN uint8_t in_port_num ) +{ + ib_slvl_table_t *p_tbl; + + CL_ASSERT( osm_physp_is_valid( p_physp ) ); + p_tbl = cl_ptr_vector_get(&p_physp->slvl_by_port, in_port_num); + return(p_tbl); +} +/* +* PARAMETERS +* p_physp +* [in] Pointer to an osm_physp_t object. +* +* in_port_num +* [in] Input Port Number for this SLtoVL. +* +* RETURN VALUES +* The pointer to the slvl table +* +* NOTES +* +* SEE ALSO +* Port, Physical Port +*********/ + +/****f* OpenSM: Physical Port/osm_physp_set_vla_tbl +* NAME +* osm_physp_set_vla_tbl +* +* DESCRIPTION +* Copies the VL Arbitration attribute into the Physical Port object. +* +* SYNOPSIS +*/ +static inline void +osm_physp_set_vla_tbl( IN osm_physp_t* const p_physp, + IN ib_vl_arb_table_t *p_vla_tbl, + IN uint8_t block_num ) +{ + CL_ASSERT( p_vla_tbl ); + CL_ASSERT( osm_physp_is_valid( p_physp ) ); + CL_ASSERT( (1 <= block_num) && (block_num <= 4)); + p_physp->vl_arb[block_num - 1] = *p_vla_tbl; +} +/* +* PARAMETERS +* p_physp +* [in] Pointer to an osm_physp_t object. +* +* p_vla_tbl +* [in] Pointer to the IBA defined VL Arbitration table for this port number. +* +* block_num +* [in] The part of the VL arbitration as defined in the IBA +* (valid values 1-4) +* +* RETURN VALUES +* This function does not return a value. +* +* NOTES +* +* SEE ALSO +* Port, Physical Port +*********/ + +/****f* OpenSM: Physical Port/osm_physp_get_vla_tbl +* NAME +* osm_physp_get_vla_tbl +* +* DESCRIPTION +* Returns a pointer to the VL Arbitration table of the Physical Port object. +* +* SYNOPSIS +*/ +static inline ib_vl_arb_table_t * +osm_physp_get_vla_tbl( IN osm_physp_t* const p_physp, + IN uint8_t block_num ) +{ + CL_ASSERT( osm_physp_is_valid( p_physp ) ); + CL_ASSERT( (1 <= block_num) && (block_num <= 4)); + return(& (p_physp->vl_arb[block_num - 1])); +} +/* +* PARAMETERS +* p_physp +* [in] Pointer to an osm_physp_t object. +* +* block_num +* [in] The part of the VL arbitration as defined in the IBA +* (valid values 1-4) +* +* RETURN VALUES +* The pointer to the VL Arbitration table +* +* NOTES +* +* SEE ALSO +* Port, Physical Port +*********/ + +/****f* OpenSM: Physical Port/osm_physp_get_remote +* NAME +* osm_physp_get_remote +* +* DESCRIPTION +* Returns a pointer to the Physical Port on the other side the wire. +* +* SYNOPSIS +*/ +static inline osm_physp_t* +osm_physp_get_remote( + IN const osm_physp_t* const p_physp ) +{ + CL_ASSERT( osm_physp_is_valid( p_physp ) ); + return( p_physp->p_remote_physp ); +} +/* +* PARAMETERS +* p_physp +* [in] Pointer to an osm_physp_t object. +* +* RETURN VALUES +* Returns a pointer to the Physical Port on the other side of +* the wire. A return value of NULL means there is no link at this port. +* +* NOTES +* +* SEE ALSO +* Port, Physical Port +*********/ + +/****f* OpenSM: Physical Port/osm_physp_get_port_guid +* NAME +* osm_physp_get_port_guid +* +* DESCRIPTION +* Returns the port guid of this physical port. +* +* SYNOPSIS +*/ +static inline ib_net64_t +osm_physp_get_port_guid( + IN const osm_physp_t* const p_physp ) +{ + CL_ASSERT( osm_physp_is_valid( p_physp ) ); + return( p_physp->port_guid ); +} +/* +* PARAMETERS +* p_physp +* [in] Pointer to an osm_physp_t object. +* +* RETURN VALUES +* Returns the port guid of this physical port. +* +* NOTES +* +* SEE ALSO +* Port, Physical Port +*********/ + +/****f* OpenSM: Physical Port/osm_physp_get_subnet_prefix +* NAME +* osm_physp_get_subnet_prefix +* +* DESCRIPTION +* Returns the subnet prefix for this physical port. +* +* SYNOPSIS +*/ +static inline ib_net64_t +osm_physp_get_subnet_prefix( + IN const osm_physp_t* const p_physp ) +{ + CL_ASSERT( osm_physp_is_valid( p_physp ) ); + return( p_physp->port_info.subnet_prefix ); +} +/* +* PARAMETERS +* p_physp +* [in] Pointer to an osm_physp_t object. +* +* RETURN VALUES +* Returns the subnet prefix for this physical port. +* +* NOTES +* +* SEE ALSO +* Port, Physical Port +*********/ + +/****f* OpenSM: Physical Port/osm_physp_link_exists +* NAME +* osm_physp_link_exists +* +* DESCRIPTION +* Returns TRUE if the Physical Port has a link to the specified port. +* FALSE otherwise. +* +* SYNOPSIS +*/ +static inline boolean_t +osm_physp_link_exists( + IN const osm_physp_t* const p_physp, + IN const osm_physp_t* const p_remote_physp ) +{ + CL_ASSERT( p_physp ); + CL_ASSERT( osm_physp_is_valid( p_physp ) ); + CL_ASSERT( p_remote_physp ); + CL_ASSERT( osm_physp_is_valid( p_remote_physp ) ); + return( (p_physp->p_remote_physp == p_remote_physp ) && + (p_remote_physp->p_remote_physp == p_physp ) ); +} +/* +* PARAMETERS +* p_physp +* [in] Pointer to an osm_physp_t object. +* +* p_remote_physp +* [in] Pointer to an osm_physp_t object. +* +* RETURN VALUES +* Returns TRUE if the Physical Port has a link to another port. +* FALSE otherwise. +* +* NOTES +* +* SEE ALSO +* Port, Physical Port +*********/ + +/****f* OpenSM: Physical Port/osm_physp_link +* NAME +* osm_physp_link +* +* DESCRIPTION +* Sets the pointers to the Physical Ports on the other side the wire. +* +* SYNOPSIS +*/ +static inline void +osm_physp_link( + IN osm_physp_t* const p_physp, + IN osm_physp_t* const p_remote_physp ) +{ + CL_ASSERT( p_physp ); + CL_ASSERT( p_remote_physp ); + p_physp->p_remote_physp = p_remote_physp; + p_remote_physp->p_remote_physp = p_physp; +} +/* +* PARAMETERS +* p_physp +* [in] Pointer to an osm_physp_t object to link. +* +* p_remote_physp +* [in] Pointer to the adjacent osm_physp_t object to link. +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +* Port, Physical Port +*********/ + +/****f* OpenSM: Physical Port/osm_physp_unlink +* NAME +* osm_physp_unlink +* +* DESCRIPTION +* Clears the pointers to the Physical Port on the other side the wire. +* +* SYNOPSIS +*/ +static inline void +osm_physp_unlink( + IN osm_physp_t* const p_physp, + IN osm_physp_t* const p_remote_physp ) +{ + CL_ASSERT( p_physp ); + CL_ASSERT( p_remote_physp ); + CL_ASSERT( osm_physp_link_exists( p_physp, p_remote_physp ) ); + p_physp->p_remote_physp = NULL; + p_remote_physp->p_remote_physp = NULL; +} +/* +* PARAMETERS +* p_physp +* [in] Pointer to an osm_physp_t object to link. +* +* p_remote_physp +* [in] Pointer to the adjacent osm_physp_t object to link. +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +* Port, Physical Port +*********/ + +/****f* OpenSM: Physical Port/osm_physp_has_any_link +* NAME +* osm_physp_has_any_link +* +* DESCRIPTION +* Returns TRUE if the Physical Port has a link to another port. +* FALSE otherwise. +* +* SYNOPSIS +*/ +static inline boolean_t +osm_physp_has_any_link( + IN const osm_physp_t* const p_physp ) +{ + CL_ASSERT( p_physp ); + if( osm_physp_is_valid( p_physp ) ) + return( p_physp->p_remote_physp != NULL ); + else + return( FALSE ); +} +/* +* PARAMETERS +* p_physp +* [in] Pointer to an osm_physp_t object. +* +* RETURN VALUES +* Returns TRUE if the Physical Port has a link to another port. +* FALSE otherwise. +* +* NOTES +* +* SEE ALSO +* Port, Physical Port +*********/ + +/****f* OpenSM: Physical Port/osm_physp_get_port_num +* NAME +* osm_physp_get_port_num +* +* DESCRIPTION +* Returns the local port number of this Physical Port. +* +* SYNOPSIS +*/ +static inline uint8_t +osm_physp_get_port_num( + IN const osm_physp_t* const p_physp ) +{ + CL_ASSERT( p_physp ); + CL_ASSERT( osm_physp_is_valid( p_physp ) ); + return( p_physp->port_num ); +} +/* +* PARAMETERS +* p_physp +* [in] Pointer to an osm_physp_t object. +* +* RETURN VALUES +* Returns the local port number of this Physical Port. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Physical Port/osm_physp_get_port_info_ptr +* NAME +* osm_physp_get_port_info_ptr +* +* DESCRIPTION +* Returns a pointer to the PortInfo attribute for this port. +* +* SYNOPSIS +*/ +static inline ib_port_info_t* +osm_physp_get_port_info_ptr( + IN const osm_physp_t* const p_physp ) +{ + CL_ASSERT( p_physp ); + CL_ASSERT( osm_physp_is_valid( p_physp ) ); + return( (ib_port_info_t*)&p_physp->port_info ); +} +/* +* PARAMETERS +* p_physp +* [in] Pointer to an osm_physp_t object. +* +* RETURN VALUES +* Returns a pointer to the PortInfo attribute for this port. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Physical Port/osm_physp_get_node_ptr +* NAME +* osm_physp_get_node_ptr +* +* DESCRIPTION +* Returns a pointer to the parent Node object for this port. +* +* SYNOPSIS +*/ +static inline struct _osm_node* +osm_physp_get_node_ptr( + IN const osm_physp_t* const p_physp ) +{ + CL_ASSERT( p_physp ); + CL_ASSERT( osm_physp_is_valid( p_physp ) ); + return( (struct _osm_node*)p_physp->p_node ); +} +/* +* PARAMETERS +* p_physp +* [in] Pointer to an osm_physp_t object. +* +* RETURN VALUES +* Returns a pointer to the parent Node object for this port. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Physical Port/osm_physp_get_port_state +* NAME +* osm_physp_get_port_state +* +* DESCRIPTION +* Returns the port state of this Physical Port. +* +* SYNOPSIS +*/ +static inline uint8_t +osm_physp_get_port_state( + IN const osm_physp_t* const p_physp ) +{ + CL_ASSERT( p_physp ); + CL_ASSERT( osm_physp_is_valid( p_physp ) ); + return( ib_port_info_get_port_state( &p_physp->port_info )); +} +/* +* PARAMETERS +* p_physp +* [in] Pointer to an osm_physp_t object. +* +* RETURN VALUES +* Returns the local port number of this Physical Port. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Physical Port/osm_physp_get_base_lid +* NAME +* osm_physp_get_base_lid +* +* DESCRIPTION +* Returns the base lid of this Physical Port. +* +* SYNOPSIS +*/ +static inline ib_net16_t +osm_physp_get_base_lid( + IN const osm_physp_t* const p_physp ) +{ + CL_ASSERT( p_physp ); + CL_ASSERT( osm_physp_is_valid( p_physp ) ); + return( p_physp->port_info.base_lid ); +} +/* +* PARAMETERS +* p_physp +* [in] Pointer to an osm_physp_t object. +* +* RETURN VALUES +* Returns the base lid of this Physical Port. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Physical Port/osm_physp_get_lmc +* NAME +* osm_physp_get_lmc +* +* DESCRIPTION +* Returns the LMC value of this Physical Port. +* +* SYNOPSIS +*/ +static inline uint8_t +osm_physp_get_lmc( + IN const osm_physp_t* const p_physp ) +{ + CL_ASSERT( p_physp ); + CL_ASSERT( osm_physp_is_valid( p_physp ) ); + return( ib_port_info_get_lmc( &p_physp->port_info ) ); +} +/* +* PARAMETERS +* p_physp +* [in] Pointer to an osm_physp_t object. +* +* RETURN VALUES +* Returns the LMC value of this Physical Port. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Physical Port/osm_physp_get_dr_path_ptr +* NAME +* osm_physp_get_dr_path_ptr +* +* DESCRIPTION +* Returns a pointer to the directed route path for this port. +* +* SYNOPSIS +*/ +static inline osm_dr_path_t* +osm_physp_get_dr_path_ptr( + IN const osm_physp_t* const p_physp ) +{ + CL_ASSERT( p_physp ); + CL_ASSERT( osm_physp_is_valid( p_physp ) ); + return( (osm_dr_path_t*)&p_physp->dr_path ); +} +/* +* PARAMETERS +* p_physp +* [in] Pointer to a Physical Port object. +* +* RETURN VALUES +* Returns a pointer to the directed route path for this port. +* +* NOTES +* +* SEE ALSO +* Physical Port object +*********/ + +/****h* OpenSM/Port +* NAME +* Port +* +* DESCRIPTION +* The Port object encapsulates the information needed by the +* OpenSM to manage ports. The OpenSM allocates one Port object +* per port in the IBA subnet. +* +* Each Port object is associated with a single port GUID. A Port object +* contains 1 or more Physical Port objects. An end point node has +* one Physical Port per Port. A switch node has more than +* one Physical Port per Port. +* +* The Port object is not thread safe, thus callers must provide +* serialization. +* +* These objects should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****d* OpenSM: Port/osm_port_lid_category_t +* NAME +* osm_port_lid_category_t +* +* DESCRIPTION +* Enumerated values for LID disposition. +* +* SYNOPSIS +*/ +typedef enum _osm_port_lid_category +{ + OSM_PORT_LID_ASSIGNED = 0, + OSM_PORT_LID_UNASSIGNED, + OSM_PORT_LID_CONFLICT, + OSM_PORT_LID_FOREIGN, + +} osm_port_lid_category_t; +/* +* FIELDS +* OSM_PORT_LID_ASSIGNED +* Indicates the Port has a known LID value. +* +* OSM_PORT_LID_UNASSIGNED +* Indicates the Port does not have a LID value. +* +* OSM_PORT_LID_CONFLICT +* Indicates the Port's LID conflicts with an assigned LID. +* +* OSM_PORT_LID_FOREIGN +* Indicates the Port has a LID value not currently known in +* in the OpenSM LID database. +* +* SEE ALSO +* Port +*********/ + +/****s* OpenSM: Port/osm_port_t +* NAME +* osm_port_t +* +* DESCRIPTION +* This object represents a logical port on a switch, router or end-point. +* +* The osm_port_t object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_port +{ + cl_map_item_t map_item; + struct _osm_node *p_node; + ib_net64_t guid; + uint32_t discovery_count; + uint8_t default_port_num; + uint8_t physp_tbl_size; + cl_qlist_t mcm_list; + osm_physp_t *tbl[1]; +} osm_port_t; +/* +* FIELDS +* map_item +* Linkage structure for cl_qmap. MUST BE FIRST MEMBER! +* +* p_node +* Points to the Node object that owns this port. +* +* guid +* Manufacturer assigned GUID for this port. +* +* discovery_count +* The number of times this port has been discovered +* during the current fabric sweep. This number is reset +* to zero at the start of a sweep. +* +* default_port_num +* Index of the physical port used when physical characteristics +* contained in the Physical Port are needed. +* +* physp_tbl_size +* Number of physical ports associated with this logical port. +* +* mcm_list +* Multicast member list +* +* tbl +* Array of pointers to Physical Port objects contained by this node. +* MUST BE LAST ELEMENT SINCE IT CAN GROW !!! +* +* SEE ALSO +* Port, Physical Port, Physical Port Table +*********/ + +/****f* OpenSM: Port/osm_port_construct +* NAME +* osm_port_construct +* +* DESCRIPTION +* This function constructs a Port object. +* +* SYNOPSIS +*/ +static inline void +osm_port_construct( + IN osm_port_t* const p_port ) +{ + memset( p_port, 0, sizeof(*p_port) ); + cl_qlist_init( &p_port->mcm_list ); +} +/* +* PARAMETERS +* p_port +* [in] Pointer to a Port object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_port_init, and osm_port_destroy. +* +* Calling osm_port_construct is a prerequisite to calling any other +* method except osm_port_init. +* +* SEE ALSO +* Port, osm_port_init, osm_port_destroy +*********/ + +/****f* OpenSM: Port/osm_port_destroy +* NAME +* osm_port_destroy +* +* DESCRIPTION +* This function destroys a Port object. +* +* SYNOPSIS +*/ +void +osm_port_destroy( + IN osm_port_t* const p_port ); +/* +* PARAMETERS +* p_port +* [in] Pointer to a Port object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified Port object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to osm_port_construct +* or osm_port_init. +* +* SEE ALSO +* Port, osm_port_init, osm_port_destroy +*********/ + +/****f* OpenSM: Port/osm_port_delete +* NAME +* osm_port_delete +* +* DESCRIPTION +* This function destroys and deallocates a Port object. +* +* SYNOPSIS +*/ +inline static void +osm_port_delete( + IN OUT osm_port_t** const pp_port ) +{ + osm_port_destroy( *pp_port ); + free( *pp_port ); + *pp_port = NULL; +} +/* +* PARAMETERS +* pp_port +* [in][out] Pointer to a pointer to a Port object to delete. +* On return, this pointer is NULL. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified Port object. +* +* SEE ALSO +* Port, osm_port_init, osm_port_destroy +*********/ + +/****f* OpenSM: Port/osm_port_init +* NAME +* osm_port_init +* +* DESCRIPTION +* This function initializes a Port object. +* +* SYNOPSIS +*/ +void +osm_port_init( + IN osm_port_t* const p_port, + IN const ib_node_info_t* p_ni, + IN const struct _osm_node* const p_parent_node ); +/* +* PARAMETERS +* p_port +* [in] Pointer to a Port object to initialize. +* +* p_ni +* [in] Pointer to the NodeInfo attribute relavent for this port. +* +* p_parent_node +* [in] Pointer to the initialized parent osm_node_t object +* that owns this port. +* +* RETURN VALUE +* None. +* +* NOTES +* Allows calling other port methods. +* +* SEE ALSO +* Port +*********/ + +/****f* OpenSM: Port/osm_port_new +* NAME +* osm_port_new +* +* DESCRIPTION +* This function allocates and initializes a Port object. +* +* SYNOPSIS +*/ +osm_port_t* +osm_port_new( + IN const ib_node_info_t* p_ni, + IN const struct _osm_node* const p_parent_node ); +/* +* PARAMETERS +* p_ni +* [in] Pointer to the NodeInfo attribute relavent for this port. +* +* p_parent_node +* [in] Pointer to the initialized parent osm_node_t object +* that owns this port. +* +* RETURN VALUE +* Pointer to the initialize Port object. +* +* NOTES +* Allows calling other port methods. +* +* SEE ALSO +* Port +*********/ + +/****f* OpenSM: Port/osm_port_get_base_lid +* NAME +* osm_port_get_base_lid +* +* DESCRIPTION +* Gets the base LID of a port. +* +* SYNOPSIS +*/ +static inline ib_net16_t +osm_port_get_base_lid( + IN const osm_port_t* const p_port ) +{ + const osm_physp_t* const p_physp = p_port->tbl[p_port->default_port_num]; + CL_ASSERT( p_physp ); + CL_ASSERT( osm_physp_is_valid( p_physp ) ); + return( osm_physp_get_base_lid( p_physp )); +} +/* +* PARAMETERS +* p_port +* [in] Pointer to a Port object. +* +* RETURN VALUE +* Base LID of the port. +* If the return value is 0, then this port has no assigned LID. +* +* NOTES +* +* SEE ALSO +* Port +*********/ + +/****f* OpenSM: Port/osm_port_get_lmc +* NAME +* osm_port_get_lmc +* +* DESCRIPTION +* Gets the LMC value of a port. +* +* SYNOPSIS +*/ +static inline uint8_t +osm_port_get_lmc( + IN const osm_port_t* const p_port ) +{ + const osm_physp_t* const p_physp = p_port->tbl[p_port->default_port_num]; + CL_ASSERT( p_physp ); + CL_ASSERT( osm_physp_is_valid( p_physp ) ); + return( osm_physp_get_lmc( p_physp )); +} +/* +* PARAMETERS +* p_port +* [in] Pointer to a Port object. +* +* RETURN VALUE +* Gets the LMC value of a port. +* +* NOTES +* +* SEE ALSO +* Port +*********/ + +/****f* OpenSM: Port/osm_port_get_guid +* NAME +* osm_port_get_guid +* +* DESCRIPTION +* Gets the GUID of a port. +* +* SYNOPSIS +*/ +static inline ib_net64_t +osm_port_get_guid( + IN const osm_port_t* const p_port ) +{ + return( p_port->guid ); +} +/* +* PARAMETERS +* p_port +* [in] Pointer to a Port object. +* +* RETURN VALUE +* Manufacturer assigned GUID of the port. +* +* NOTES +* +* SEE ALSO +* Port +*********/ + +/****f* OpenSM: Port/osm_port_get_num_physp +* NAME +* osm_port_get_num_physp +* +* DESCRIPTION +* Returns the number of Physical Port objects associated with this port. +* +* SYNOPSIS +*/ +static inline uint8_t +osm_port_get_num_physp( + IN const osm_port_t* const p_port ) +{ + return( p_port->physp_tbl_size ); +} +/* +* PARAMETERS +* p_port +* [in] Pointer to a Port object. +* +* RETURN VALUE +* Returns the number of Physical Port objects associated with this port. +* +* NOTES +* +* SEE ALSO +* Port +*********/ + +/****f* OpenSM: Port/osm_port_get_phys_ptr +* NAME +* osm_port_get_phys_ptr +* +* DESCRIPTION +* Gets the pointer to the specified Physical Port object. +* +* SYNOPSIS +*/ +static inline osm_physp_t* +osm_port_get_phys_ptr( + IN const osm_port_t* const p_port, + IN const uint8_t port_num ) +{ + CL_ASSERT( port_num < p_port->physp_tbl_size ); + return( p_port->tbl[port_num] ); +} +/* +* PARAMETERS +* p_port +* [in] Pointer to a Port object. +* +* port_num +* [in] Number of physical port for which to return the +* osm_physp_t object. If this port is on an HCA, then +* this value is ignored. +* +* RETURN VALUE +* Pointer to the Physical Port object. +* +* NOTES +* +* SEE ALSO +* Port +*********/ + +/****f* OpenSM: Port/osm_port_get_default_phys_ptr +* NAME +* osm_port_get_default_phys_ptr +* +* DESCRIPTION +* Gets the pointer to the default Physical Port object. +* This call should only be used for non-switch ports in which there +* is a one-for-one mapping of port to physp. +* +* SYNOPSIS +*/ +static inline +osm_physp_t* +osm_port_get_default_phys_ptr( + IN const osm_port_t* const p_port ) +{ + CL_ASSERT( p_port->tbl[p_port->default_port_num] ); + CL_ASSERT( osm_physp_is_valid( p_port->tbl[p_port->default_port_num] ) ); + return( p_port->tbl[p_port->default_port_num] ); +} +/* +* PARAMETERS +* p_port +* [in] Pointer to a Port object. +* +* RETURN VALUE +* Pointer to the Physical Port object. +* +* NOTES +* +* SEE ALSO +* Port +*********/ + +/****f* OpenSM: Port/osm_port_get_parent_node +* NAME +* osm_port_get_parent_node +* +* DESCRIPTION +* Gets the pointer to the this port's Node object. +* +* SYNOPSIS +*/ +static inline struct _osm_node* +osm_port_get_parent_node( + IN const osm_port_t* const p_port ) +{ + return( p_port->p_node ); +} +/* +* PARAMETERS +* p_port +* [in] Pointer to a Port object. +* +* port_num +* [in] Number of physical port for which to return the +* osm_physp_t object. +* +* RETURN VALUE +* Pointer to the Physical Port object. +* +* NOTES +* +* SEE ALSO +* Port +*********/ + +/****f* OpenSM: Port/osm_port_get_lid_range_ho +* NAME +* osm_port_get_lid_range_ho +* +* DESCRIPTION +* Returns the HOST ORDER lid min and max values for this port, +* based on the lmc value. +* +* SYNOPSIS +*/ +void +osm_port_get_lid_range_ho( + IN const osm_port_t* const p_port, + OUT uint16_t* const p_min_lid, + OUT uint16_t* const p_max_lid ); +/* +* PARAMETERS +* p_port +* [in] Pointer to a Port object. +* +* p_min_lid +* [out] Pointer to the minimum LID value occupied by this port. +* +* p_max_lid +* [out] Pointer to the maximum LID value occupied by this port. +* +* RETURN VALUE +* None. +* +* NOTES +* +* SEE ALSO +* Port +*********/ + +/****f* OpenSM: Port/osm_get_port_by_base_lid +* NAME +* osm_get_port_by_base_lid +* +* DESCRIPTION +* Returns a status on whether a Port was able to be +* determined based on the LID supplied and if so, return the Port. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_get_port_by_base_lid( + IN const osm_subn_t* const p_subn, + IN const ib_net16_t lid, + IN OUT const osm_port_t** const pp_port ); +/* +* PARAMETERS +* p_subn +* [in] Pointer to the subnet data structure. +* +* lid +* [in] LID requested. +* +* pp_port +* [in][out] Pointer to pointer to Port object. +* +* RETURN VALUES +* IB_SUCCESS +* IB_NOT_FOUND +* +* NOTES +* +* SEE ALSO +* Port +*********/ + +/****f* OpenSM: Port/osm_port_add_new_physp +* NAME +* osm_port_add_new_physp +* +* DESCRIPTION +* Adds a new physical port to the logical collection owned by the Port. +* Physical Ports added here must share the same GUID as the Port. +* +* SYNOPSIS +*/ +void +osm_port_add_new_physp( + IN osm_port_t* const p_port, + IN const uint8_t port_num ); +/* +* PARAMETERS +* p_port +* [in] Pointer to a Port object. +* +* port_num +* [in] Port number to add. +* +* RETURN VALUE +* None. +* +* NOTES +* +* SEE ALSO +* Port +*********/ + +/****f* OpenSM: Port/osm_port_discovery_count_reset +* NAME +* osm_port_discovery_count_reset +* +* DESCRIPTION +* Resets the discovery count for this Port to zero. +* This operation should be performed at the start of a sweep. +* +* SYNOPSIS +*/ +static inline void +osm_port_discovery_count_reset( + IN osm_port_t* const p_port ) +{ + p_port->discovery_count = 0; +} +/* +* PARAMETERS +* p_port +* [in] Pointer to an osm_port_t object. +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +* Port object +*********/ + +/****f* OpenSM: Port/osm_port_discovery_count_get +* NAME +* osm_port_discovery_count_get +* +* DESCRIPTION +* Returns the number of times this port has been discovered +* since the last time the discovery count was reset. +* +* SYNOPSIS +*/ +static inline uint32_t +osm_port_discovery_count_get( + IN const osm_port_t* const p_port ) +{ + return( p_port->discovery_count ); +} +/* +* PARAMETERS +* p_port +* [in] Pointer to an osm_port_t object. +* +* RETURN VALUES +* Returns the number of times this port has been discovered +* since the last time the discovery count was reset. +* +* NOTES +* +* SEE ALSO +* Port object +*********/ + +/****f* OpenSM: Port/osm_port_discovery_count_inc +* NAME +* osm_port_discovery_count_inc +* +* DESCRIPTION +* Increments the discovery count for this Port. +* +* SYNOPSIS +*/ +static inline void +osm_port_discovery_count_inc( + IN osm_port_t* const p_port ) +{ + p_port->discovery_count++; +} +/* +* PARAMETERS +* p_port +* [in] Pointer to an osm_port_t object. +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +* Port object +*********/ + +/****f* OpenSM: Port/osm_port_add_mgrp +* NAME +* osm_port_add_mgrp +* +* DESCRIPTION +* Logically connects a port to a multicast group. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_port_add_mgrp( + IN osm_port_t* const p_port, + IN const ib_net16_t mlid ); +/* +* PARAMETERS +* p_port +* [in] Pointer to an osm_port_t object. +* +* mlid +* [in] MLID of the multicast group. +* +* RETURN VALUES +* IB_SUCCESS +* IB_INSUFFICIENT_MEMORY +* +* NOTES +* +* SEE ALSO +* Port object +*********/ + +/****f* OpenSM: Port/osm_port_remove_mgrp +* NAME +* osm_port_remove_mgrp +* +* DESCRIPTION +* Logically disconnects a port from a multicast group. +* +* SYNOPSIS +*/ +void +osm_port_remove_mgrp( + IN osm_port_t* const p_port, + IN const ib_net16_t mlid ); +/* +* PARAMETERS +* p_port +* [in] Pointer to an osm_port_t object. +* +* mlid +* [in] MLID of the multicast group. +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +* Port object +*********/ + +/****f* OpenSM: Port/osm_port_remove_all_mgrp +* NAME +* osm_port_remove_all_mgrp +* +* DESCRIPTION +* Logically disconnects a port from all its multicast groups. +* +* SYNOPSIS +*/ +void +osm_port_remove_all_mgrp( + IN osm_port_t* const p_port ); +/* +* PARAMETERS +* p_port +* [in] Pointer to an osm_port_t object. +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +* Port object +*********/ + +/****f* OpenSM: Physical Port/osm_physp_calc_link_mtu +* NAME +* osm_physp_calc_link_mtu +* +* DESCRIPTION +* Calculate the Port MTU based on current and remote +* physical ports MTU CAP values. +* +* SYNOPSIS +*/ +uint8_t +osm_physp_calc_link_mtu( + IN osm_log_t* p_log, + IN const osm_physp_t* p_physp ); +/* +* PARAMETERS +* p_log +* [in] Pointer to a log object. +* +* p_physp +* [in] Pointer to an osm_physp_t object. +* +* RETURN VALUES +* The MTU of the link to be used. +* +* NOTES +* +* SEE ALSO +* PhysPort object +*********/ + +/****f* OpenSM: Physical Port/osm_physp_calc_link_op_vls +* NAME +* osm_physp_calc_link_op_vls +* +* DESCRIPTION +* Calculate the Port OP_VLS based on current and remote +* physical ports VL CAP values. Allowing user option for a max limit. +* +* SYNOPSIS +*/ +uint8_t +osm_physp_calc_link_op_vls( + IN osm_log_t* p_log, + IN const osm_subn_t * p_subn, + IN const osm_physp_t* p_physp ); +/* +* PARAMETERS +* p_log +* [in] Pointer to a log object. +* +* p_subn +* [in] Pointer to the subnet object for accessing of the options. +* +* p_physp +* [in] Pointer to an osm_physp_t object. +* +* RETURN VALUES +* The OP_VLS of the link to be used. +* +* NOTES +* +* SEE ALSO +* PhysPort object +*********/ + +/****f* OpenSM: Physical Port/osm_physp_replace_dr_path_with_alternate_dr_path +* NAME +* osm_physp_replace_dr_path_with_alternate_dr_path +* +* DESCRIPTION +* Replace the direct route path for the given phys port with an +* alternate path going through forien set of phys port. +* +* SYNOPSIS +*/void +osm_physp_replace_dr_path_with_alternate_dr_path( + IN osm_log_t *p_log, + IN osm_subn_t const *p_subn, + IN osm_physp_t const *p_physp, + IN osm_bind_handle_t *h_bind ); +/* +* PARAMETERS +* p_log +* [in] Pointer to a log object. +* +* p_subn +* [in] Pointer to the subnet object for accessing of the options. +* +* p_physp +* [in] Pointer to an osm_physp_t object. +* +* h_bind +* [in] Pointer to osm_bind_handle_t object. +* +* RETURN VALUES +* NONE +* +* NOTES +* +* SEE ALSO +* PhysPort object +*********/ + +END_C_DECLS + +#endif /* _OSM_PORT_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_port_info_rcv.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_port_info_rcv.h new file mode 100644 index 00000000..85a8078f --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_port_info_rcv.h @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_port_info_rcv.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_pi_rcv_t. + * This object represents the PortInfo Receiver object. + * attribute from a node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_PI_RCV_H_ +#define _OSM_PI_RCV_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Port Info Receiver +* NAME +* Port Info Receiver +* +* DESCRIPTION +* The Port Info Receiver object encapsulates the information +* needed to receive the PortInfo attribute from a node. +* +* The Port Info Receiver object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: Port Info Receiver/osm_pi_rcv_t +* NAME +* osm_pi_rcv_t +* +* DESCRIPTION +* Port Info Receiver structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_pi_rcv +{ + osm_subn_t *p_subn; + osm_req_t *p_req; + osm_log_t *p_log; + osm_state_mgr_t *p_state_mgr; + cl_plock_t *p_lock; +} osm_pi_rcv_t; +/* +* FIELDS +* p_subn +* Pointer to the Subnet object for this subnet. +* +* p_req +* Pointer to the generic attribute request object. +* +* p_log +* Pointer to the log object. +* +* p_state_mgr +* Pointer to the State Manager object. +* +* p_lock +* Pointer to the serializing lock. +* +* SEE ALSO +* Port Info Receiver object +*********/ + +/****f* OpenSM: Port Info Receiver/osm_pi_rcv_construct +* NAME +* osm_pi_rcv_construct +* +* DESCRIPTION +* This function constructs a Port Info Receiver object. +* +* SYNOPSIS +*/ +void osm_pi_rcv_construct( + IN osm_pi_rcv_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a Port Info Receiver object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_pi_rcv_destroy +* +* Calling osm_pi_rcv_construct is a prerequisite to calling any other +* method except osm_pi_rcv_init. +* +* SEE ALSO +* Port Info Receiver object, osm_pi_rcv_init, +* osm_pi_rcv_destroy +*********/ + +/****f* OpenSM: Port Info Receiver/osm_pi_rcv_destroy +* NAME +* osm_pi_rcv_destroy +* +* DESCRIPTION +* The osm_pi_rcv_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_pi_rcv_destroy( + IN osm_pi_rcv_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* Port Info Receiver object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_pi_rcv_construct or osm_pi_rcv_init. +* +* SEE ALSO +* Port Info Receiver object, osm_pi_rcv_construct, +* osm_pi_rcv_init +*********/ + +/****f* OpenSM: Port Info Receiver/osm_pi_rcv_init +* NAME +* osm_pi_rcv_init +* +* DESCRIPTION +* The osm_pi_rcv_init function initializes a +* Port Info Receiver object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_pi_rcv_init( + IN osm_pi_rcv_t* const p_ctrl, + IN osm_req_t* const p_req, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN osm_state_mgr_t* const p_state_mgr, + IN cl_plock_t* const p_lock ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_pi_rcv_t object to initialize. +* +* p_req +* [in] Pointer to an osm_req_t object. +* +* p_subn +* [in] Pointer to the Subnet object for this subnet. +* +* p_log +* [in] Pointer to the log object. +* +* p_state_mgr +* [in] Pointer to the state manager object. +* +* p_lock +* [in] Pointer to the OpenSM serializing lock. +* +* RETURN VALUES +* CL_SUCCESS if the Port Info Receiver object was initialized +* successfully. +* +* NOTES +* Allows calling other Port Info Receiver methods. +* +* SEE ALSO +* Port Info Receiver object, osm_pi_rcv_construct, +* osm_pi_rcv_destroy +*********/ + +/****f* OpenSM: Port Info Receiver/osm_pi_rcv_process +* NAME +* osm_pi_rcv_process +* +* DESCRIPTION +* Process the PortInfo attribute. +* +* SYNOPSIS +*/ +void osm_pi_rcv_process( + IN const osm_pi_rcv_t* const p_ctrl, + IN osm_madw_t* const p_madw ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_pi_rcv_t object. +* +* p_madw +* [in] Pointer to the MAD Wrapper containing the MAD +* that contains the node's PortInfo attribute. +* +* RETURN VALUES +* None. +* +* NOTES +* This function processes a PortInfo attribute. +* +* SEE ALSO +* Port Info Receiver, Port Info Response Controller +*********/ + +END_C_DECLS + +#endif /* _OSM_PI_RCV_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_port_info_rcv_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_port_info_rcv_ctrl.h new file mode 100644 index 00000000..644005c0 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_port_info_rcv_ctrl.h @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_port_info_rcv_ctrl.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_pi_rcv_ctrl_t. + * This object represents a controller that receives the IBA NodeInfo + * attribute from a node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_PI_RCV_CTRL_H_ +#define _OSM_PI_RCV_CTRL_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Port Info Receive Controller +* NAME +* Port Info Receive Controller +* +* DESCRIPTION +* The Port Info Receive Controller object encapsulates +* the information needed to receive the NodeInfo attribute from a node. +* +* The Port Info Receive Controller object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: Port Info Receive Controller/osm_pi_rcv_ctrl_t +* NAME +* osm_pi_rcv_ctrl_t +* +* DESCRIPTION +* Port Info Receive Controller structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_pi_rcv_ctrl +{ + osm_pi_rcv_t *p_rcv; + osm_log_t *p_log; + cl_dispatcher_t *p_disp; + cl_disp_reg_handle_t h_disp; + +} osm_pi_rcv_ctrl_t; +/* +* FIELDS +* p_rcv +* Pointer to the Port Info Receiver object. +* +* p_log +* Pointer to the log object. +* +* p_disp +* Pointer to the Dispatcher. +* +* h_disp +* Handle returned from dispatcher registration. +* +* SEE ALSO +* Port Info Receive Controller object +* Port Info Receiver object +*********/ + +/****f* OpenSM: Port Info Receive Controller/osm_pi_rcv_ctrl_construct +* NAME +* osm_pi_rcv_ctrl_construct +* +* DESCRIPTION +* This function constructs a Port Info Receive Controller object. +* +* SYNOPSIS +*/ +void osm_pi_rcv_ctrl_construct( + IN osm_pi_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a Port Info Receive Controller +* object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_pi_rcv_ctrl_init, osm_pi_rcv_ctrl_destroy, +* and osm_pi_rcv_ctrl_is_inited. +* +* Calling osm_pi_rcv_ctrl_construct is a prerequisite to calling any other +* method except osm_pi_rcv_ctrl_init. +* +* SEE ALSO +* Port Info Receive Controller object, osm_pi_rcv_ctrl_init, +* osm_pi_rcv_ctrl_destroy, osm_pi_rcv_ctrl_is_inited +*********/ + +/****f* OpenSM: Port Info Receive Controller/osm_pi_rcv_ctrl_destroy +* NAME +* osm_pi_rcv_ctrl_destroy +* +* DESCRIPTION +* The osm_pi_rcv_ctrl_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_pi_rcv_ctrl_destroy( + IN osm_pi_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* Port Info Receive Controller object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_pi_rcv_ctrl_construct or osm_pi_rcv_ctrl_init. +* +* SEE ALSO +* Port Info Receive Controller object, osm_pi_rcv_ctrl_construct, +* osm_pi_rcv_ctrl_init +*********/ + +/****f* OpenSM: Port Info Receive Controller/osm_pi_rcv_ctrl_init +* NAME +* osm_pi_rcv_ctrl_init +* +* DESCRIPTION +* The osm_pi_rcv_ctrl_init function initializes a +* Port Info Receive Controller object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_pi_rcv_ctrl_init( + IN osm_pi_rcv_ctrl_t* const p_ctrl, + IN osm_pi_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_pi_rcv_ctrl_t object to initialize. +* +* p_rcv +* [in] Pointer to an osm_pi_rcv_t object. +* +* p_log +* [in] Pointer to the log object. +* +* p_disp +* [in] Pointer to the OpenSM central Dispatcher. +* +* RETURN VALUES +* CL_SUCCESS if the Port Info Receive Controller object was initialized +* successfully. +* +* NOTES +* Allows calling other Port Info Receive Controller methods. +* +* SEE ALSO +* Port Info Receive Controller object, osm_pi_rcv_ctrl_construct, +* osm_pi_rcv_ctrl_destroy, osm_pi_rcv_ctrl_is_inited +*********/ + +/****f* OpenSM: Port Info Receive Controller/osm_pi_rcv_ctrl_is_inited +* NAME +* osm_pi_rcv_ctrl_is_inited +* +* DESCRIPTION +* Indicates if the object has been initialized with osm_pi_rcv_ctrl_init. +* +* SYNOPSIS +*/ +boolean_t osm_pi_rcv_ctrl_is_inited( + IN const osm_pi_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_pi_rcv_ctrl_t object. +* +* RETURN VALUES +* TRUE if the object was initialized successfully, +* FALSE otherwise. +* +* NOTES +* The osm_pi_rcv_ctrl_construct or osm_pi_rcv_ctrl_init must be +* called before using this function. +* +* SEE ALSO +* Port Info Receive Controller object, osm_pi_rcv_ctrl_construct, +* osm_pi_rcv_ctrl_init +*********/ + +END_C_DECLS + +#endif /* _OSM_PI_RCV_CTRL_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_port_profile.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_port_profile.h new file mode 100644 index 00000000..88c004ea --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_port_profile.h @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_port_profile.h 1091 2008-04-30 07:01:35Z tzachid $ + */ + + +/* + * Abstract: + * Declaration of Switch/osm_port_profile_t. + * This object represents a port profile for an IBA switch. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.7 $ + */ + +#ifndef _OSM_PORT_PROFILE_H_ +#define _OSM_PORT_PROFILE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Port Profile +* NAME +* Port Profile +* +* DESCRIPTION +* The Port Profile object contains profiling information for +* each Physical Port on a switch. The profile information +* may be used to optimize path selection. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: Switch/osm_port_profile_t +* NAME +* osm_port_profile_t +* +* DESCRIPTION +* The Port Profile object contains profiling information for +* each Physical Port on the switch. The profile information +* may be used to optimize path selection. +* +* This object should be treated as opaque and should be +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_port_profile +{ + uint32_t num_paths; +} osm_port_profile_t; +/* +* FIELDS +* num_paths +* The number of paths using this port. +* +* SEE ALSO +*********/ + +/****f* OpenSM: Port Profile/osm_port_prof_construct +* NAME +* osm_port_prof_construct +* +* DESCRIPTION +* +* +* SYNOPSIS +*/ +static inline void +osm_port_prof_construct( + IN osm_port_profile_t* const p_prof ) +{ + CL_ASSERT( p_prof ); + memset( p_prof, 0, sizeof(*p_prof) ); +} +/* +* PARAMETERS +* p_prof +* [in] Pointer to the Port Profile object to construct. +* +* RETURN VALUE +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Port Profile/osm_port_prof_path_count_inc +* NAME +* osm_port_prof_path_count_inc +* +* DESCRIPTION +* Increments the count of the number of paths going through this port. +* +* +* SYNOPSIS +*/ +static inline void +osm_port_prof_path_count_inc( + IN osm_port_profile_t* const p_prof ) +{ + CL_ASSERT( p_prof ); + p_prof->num_paths++; +} +/* +* PARAMETERS +* p_pro +* [in] Pointer to the Port Profile object. +* +* RETURN VALUE +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Port Profile/osm_port_prof_path_count_get +* NAME +* osm_port_prof_path_count_get +* +* DESCRIPTION +* Returns the count of the number of paths going through this port. +* +* SYNOPSIS +*/ +static inline uint32_t +osm_port_prof_path_count_get( + IN const osm_port_profile_t* const p_prof ) +{ + return( p_prof->num_paths ); +} +/* +* PARAMETERS +* p_pro +* [in] Pointer to the Port Profile object. +* +* RETURN VALUE +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Port Profile Opt/osm_port_prof_is_ignored_port +* NAME +* osm_port_prof_is_ignored_port +* +* DESCRIPTION +* Check to see if this port is to be ignored in path counting. +* This is done by examining the optional list of port_prof_ignore_guids. +* +* SYNOPSIS +*/ +static inline boolean_t +osm_port_prof_is_ignored_port( + IN const osm_subn_t *p_subn, + IN uint64_t port_guid, + IN uint8_t port_num ) +{ + const cl_map_t *p_map = &(p_subn->opt.port_prof_ignore_guids); + const void *p_obj = cl_map_get(p_map, port_guid); + size_t res; + + // HACK: we currently support ignoring ports 0 - 31 + if (p_obj != NULL) { + res = (size_t)p_obj & (size_t)(1 << port_num); + return (res != 0); + } + return FALSE; +} +/* +* PARAMETERS +* p_subn +* [in] Pointer to the OSM Subnet object. +* +* port_guid +* [in] The port guid +* +* RETURN VALUE +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Port Profile Opt/osm_port_prof_set_ignored_port +* NAME +* osm_port_prof_set_ignored_port +* +* DESCRIPTION +* Set the ignored property of the port. +* +* SYNOPSIS +*/ +static inline void +osm_port_prof_set_ignored_port( + IN osm_subn_t *p_subn, + IN uint64_t port_guid, + IN uint8_t port_num ) +{ + cl_map_t *p_map = &(p_subn->opt.port_prof_ignore_guids); + const void *p_obj = cl_map_get(p_map, port_guid); + size_t value = 0; + + // HACK: we currently support ignoring ports 0 - 31 + CL_ASSERT(port_num < 32); + + if (p_obj != NULL) { + value = (size_t)p_obj; + } + + value = value | ((size_t)1 << port_num); //size_t will be 64 bit length in Win2003_64 + cl_map_insert(&(p_subn->opt.port_prof_ignore_guids), + port_guid, + (void *)value); +} +/* +* PARAMETERS +* p_subn +* [in] Pointer to the OSM Subnet object. +* +* port_guid +* [in] The port guid +* +* RETURN VALUE +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +END_C_DECLS + +#endif /* _OSM_PORT_PROFILE_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_rand_fwd_tbl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_rand_fwd_tbl.h new file mode 100644 index 00000000..a8db882a --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_rand_fwd_tbl.h @@ -0,0 +1,354 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_rand_fwd_tbl.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_switch_t. + * This object represents an IBA switch. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_RAND_FWD_TBL_H_ +#define _OSM_RAND_FWD_TBL_H_ + +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Random Forwarding Table +* NAME +* Random Forwarding Table +* +* DESCRIPTION +* The Random Forwarding Table objects encapsulate the information +* needed by the OpenSM to manage random forwarding tables. The OpenSM +* allocates one Random Forwarding Table object per switch in the +* IBA subnet, if that switch uses a random forwarding table. +* +* The Random Forwarding Table objects are not thread safe, thus +* callers must provide serialization. +* +* ** RANDOM FORWARDING TABLES ARE NOT SUPPORTED IN THE CURRENT VERSION ** +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: Forwarding Table/osm_rand_fwd_tbl_t +* NAME +* osm_rand_fwd_tbl_t +* +* DESCRIPTION +* Random Forwarding Table structure. +* +* THIS OBJECT IS PLACE HOLDER. SUPPORT FOR SWITCHES WITH +* RANDOM FORWARDING TABLES HAS NOT BEEN IMPLEMENTED YET. +* +* SYNOPSIS +*/ +typedef struct _osm_rand_fwd_tbl +{ + /* PLACE HOLDER STRUCTURE ONLY!! */ + uint32_t size; +} osm_rand_fwd_tbl_t; +/* +* FIELDS +* RANDOM FORWARDING TABLES ARE NOT SUPPORTED YET!! +* +* SEE ALSO +* Forwarding Table object, Random Forwarding Table object. +*********/ + +/****f* OpenSM: Forwarding Table/osm_rand_tbl_delete +* NAME +* osm_rand_tbl_delete +* +* DESCRIPTION +* This destroys and deallocates a Random Forwarding Table object. +* +* SYNOPSIS +*/ +static inline void +osm_rand_tbl_delete( + IN osm_rand_fwd_tbl_t** const pp_tbl ) +{ + /* + TO DO - This is a place holder function only! + */ + free( *pp_tbl ); + *pp_tbl = NULL; +} +/* +* PARAMETERS +* pp_tbl +* [in] Pointer a Pointer to the Random Forwarding Table object. +* +* RETURN VALUE +* On success, returns a pointer to a new Linear Forwarding Table object +* of the specified size. +* NULL otherwise. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Forwarding Table/osm_rand_fwd_tbl_set +* NAME +* osm_rand_fwd_tbl_set +* +* DESCRIPTION +* Sets the port to route the specified LID. +* +* SYNOPSIS +*/ +static inline void +osm_rand_fwd_tbl_set( + IN osm_rand_fwd_tbl_t* const p_tbl, + IN const uint16_t lid_ho, + IN const uint8_t port ) +{ + /* Random forwarding tables not supported yet. */ + UNUSED_PARAM( p_tbl ); + UNUSED_PARAM( lid_ho ); + UNUSED_PARAM( port ); + CL_ASSERT( FALSE ); +} +/* +* PARAMETERS +* p_tbl +* [in] Pointer to the Random Forwarding Table object. +* +* lid_ho +* [in] LID value (host order) for which to set the route. +* +* port +* [in] Port to route the specified LID value. +* +* RETURN VALUE +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Forwarding Table/osm_rand_fwd_tbl_set_block +* NAME +* osm_rand_fwd_tbl_set_block +* +* DESCRIPTION +* Copies the specified block into the Random Forwarding Table. +* +* SYNOPSIS +*/ +static inline ib_api_status_t +osm_rand_fwd_tbl_set_block( + IN osm_rand_fwd_tbl_t* const p_tbl, + IN const uint8_t* const p_block, + IN const uint32_t block_num ) +{ + /* Random forwarding tables not supported yet. */ + UNUSED_PARAM( p_tbl ); + UNUSED_PARAM( p_block ); + UNUSED_PARAM( block_num ); + CL_ASSERT( FALSE ); + return( IB_ERROR ); +} +/* +* PARAMETERS +* p_tbl +* [in] Pointer to the Random Forwarding Table object. +* +* p_block +* [in] Pointer to the Forwarding Table block. +* +* block_num +* [in] Block number of this block. +* +* RETURN VALUE +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Forwarding Table/osm_rand_fwd_tbl_get +* NAME +* osm_rand_fwd_tbl_get +* +* DESCRIPTION +* Returns the port that routes the specified LID. +* +* SYNOPSIS +*/ +static inline uint8_t +osm_rand_fwd_tbl_get( + IN const osm_rand_fwd_tbl_t* const p_tbl, + IN const uint16_t lid_ho ) +{ + CL_ASSERT( FALSE ); + UNUSED_PARAM( p_tbl ); + UNUSED_PARAM( lid_ho ); + + return( OSM_NO_PATH ); +} +/* +* PARAMETERS +* p_tbl +* [in] Pointer to the Linear Forwarding Table object. +* +* lid_ho +* [in] LID value (host order) for which to get the route. +* +* RETURN VALUE +* Returns the port that routes the specified LID. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Forwarding Table/osm_rand_fwd_tbl_get_lids_per_block +* NAME +* osm_rand_fwd_tbl_get_lids_per_block +* +* DESCRIPTION +* Returns the number of LIDs per LID block. +* +* SYNOPSIS +*/ +static inline uint16_t +osm_rand_fwd_tbl_get_lids_per_block( + IN const osm_rand_fwd_tbl_t* const p_tbl ) +{ + UNUSED_PARAM( p_tbl ); + return( 16 ); +} +/* +* PARAMETERS +* p_tbl +* [in] Pointer to the Forwarding Table object. +* +* RETURN VALUE +* Returns the number of LIDs per LID block. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Forwarding Table/osm_rand_fwd_tbl_get_max_block_id_in_use +* NAME +* osm_rand_fwd_tbl_get_max_block_id_in_use +* +* DESCRIPTION +* Returns the maximum block ID in actual use by the forwarding table. +* +* SYNOPSIS +*/ +static inline uint16_t +osm_rand_fwd_tbl_get_max_block_id_in_use( + IN const osm_rand_fwd_tbl_t* const p_tbl, + IN const uint16_t lid_top_ho ) +{ + UNUSED_PARAM( p_tbl ); + UNUSED_PARAM( lid_top_ho ); + CL_ASSERT( FALSE ); + return( 0 ); +} +/* +* PARAMETERS +* p_tbl +* [in] Pointer to the Forwarding Table object. +* +* RETURN VALUE +* Returns the maximum block ID in actual use by the forwarding table. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Forwarding Table/osm_rand_fwd_tbl_get_size +* NAME +* osm_rand_fwd_tbl_get_size +* +* DESCRIPTION +* Returns the number of entries available in the forwarding table. +* +* SYNOPSIS +*/ +static inline uint16_t +osm_rand_fwd_tbl_get_size( + IN const osm_rand_fwd_tbl_t* const p_tbl ) +{ + UNUSED_PARAM( p_tbl ); + CL_ASSERT( FALSE ); + return( 0 ); +} +/* +* PARAMETERS +* p_tbl +* [in] Pointer to the Forwarding Table object. +* +* RETURN VALUE +* Returns the number of entries available in the forwarding table. +* +* NOTES +* +* SEE ALSO +*********/ + +END_C_DECLS + +#endif /* _OSM_RAND_FWD_TBL_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_remote_sm.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_remote_sm.h new file mode 100644 index 00000000..6f393a4c --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_remote_sm.h @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_remote_sm.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_sm_t, osm_remote_sm_t. + * This object represents an IBA subnet. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_REMOTE_SM_H_ +#define _OSM_REMOTE_SM_H_ + +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Remote SM +* NAME +* Remote SM +* +* DESCRIPTION +* The Remote SM object encapsulates the information tracked for +* other SM ports on the subnet. +* +* The Remote SM object is thread safe. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: Remote SM/osm_remote_sm_t +* NAME +* osm_remote_sm_t +* +* DESCRIPTION +* Remote Subnet Manager structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_remote_sm +{ + cl_map_item_t map_item; + const osm_port_t *p_port; + ib_sm_info_t smi; +} osm_remote_sm_t; +/* +* FIELDS +* map_item +* Linkage for the cl_qmap container. MUST BE FIRST ELEMENT!! +* p_port +* Pointer to the port object for this SM. +* +* smi +* The SMInfo attribute for this SM. +* +* SEE ALSO +*********/ + +/****f* OpenSM: SM/osm_remote_sm_construct +* NAME +* osm_remote_sm_construct +* +* DESCRIPTION +* This function constructs an Remote SM object. +* +* SYNOPSIS +*/ +void +osm_remote_sm_construct( + IN osm_remote_sm_t* const p_sm ); +/* +* PARAMETERS +* p_sm +* [in] Pointer to an Remote SM object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_remote_sm_init, osm_remote_sm_destroy +* +* Calling osm_remote_sm_construct is a prerequisite to calling any other +* method except osm_remote_sm_init. +* +* SEE ALSO +* SM object, osm_remote_sm_init, osm_remote_sm_destroy +*********/ + +/****f* OpenSM: SM/osm_remote_sm_destroy +* NAME +* osm_remote_sm_destroy +* +* DESCRIPTION +* The osm_remote_sm_destroy function destroys an SM, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_remote_sm_destroy( + IN osm_remote_sm_t* const p_sm ); +/* +* PARAMETERS +* p_sm +* [in] Pointer to an Remote SM object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified Remote SM object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_remote_sm_construct or osm_remote_sm_init. +* +* SEE ALSO +* Remote SM object, osm_remote_sm_construct, osm_remote_sm_init +*********/ + +/****f* OpenSM: SM/osm_remote_sm_init +* NAME +* osm_remote_sm_init +* +* DESCRIPTION +* The osm_remote_sm_init function initializes an Remote SM object for use. +* +* SYNOPSIS +*/ +void +osm_remote_sm_init( + IN osm_remote_sm_t* const p_sm, + IN const osm_port_t* const p_port, + IN const ib_sm_info_t* const p_smi ); +/* +* PARAMETERS +* p_sm +* [in] Pointer to an osm_remote_sm_t object to initialize. +* +* p_port +* [in] Pointer to the Remote SM's port object. +* +* p_smi +* [in] Pointer to the SMInfo attribute for this SM. +* +* RETURN VALUES +* This function does not return a value. +* +* NOTES +* Allows calling other Remote SM methods. +* +* SEE ALSO +* Remote SM object, osm_remote_sm_construct, osm_remote_sm_destroy +*********/ + +END_C_DECLS + +#endif /* _OSM_REMOTE_SM_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_req.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_req.h new file mode 100644 index 00000000..cbcb409f --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_req.h @@ -0,0 +1,354 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_req.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_req_t. + * This object represents an object that genericly requests + * attributes from a node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_REQ_H_ +#define _OSM_REQ_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Generic Requester +* NAME +* Generic Requester +* +* DESCRIPTION +* The Generic Requester object encapsulates the information +* needed to request an attribute from a node. +* +* The Generic Requester object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: Generic Requester/osm_req_t +* NAME +* osm_req_t +* +* DESCRIPTION +* Generic Requester structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_req +{ + osm_mad_pool_t *p_pool; + osm_vl15_t *p_vl15; + osm_log_t *p_log; + osm_subn_t *p_subn; + atomic32_t *p_sm_trans_id; + +} osm_req_t; +/* +* FIELDS +* p_pool +* Pointer to the MAD pool. +* +* p_vl15 +* Pointer to the VL15 interface. +* +* p_log +* Pointer to the log object. +* +* p_subn +* Pointer to the subnet object. +* +* SEE ALSO +* Generic Requester object +*********/ + +/****f* OpenSM: Generic Requester/osm_req_construct +* NAME +* osm_req_construct +* +* DESCRIPTION +* This function constructs a Generic Requester object. +* +* SYNOPSIS +*/ +void +osm_req_construct( + IN osm_req_t* const p_req ); +/* +* PARAMETERS +* p_req +* [in] Pointer to a Generic Requester object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_req_init, and osm_req_destroy. +* +* Calling osm_req_construct is a prerequisite to calling any other +* method except osm_req_init. +* +* SEE ALSO +* Generic Requester object, osm_req_init, +* osm_req_destroy +*********/ + +/****f* OpenSM: Generic Requester/osm_req_destroy +* NAME +* osm_req_destroy +* +* DESCRIPTION +* The osm_req_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_req_destroy( + IN osm_req_t* const p_req ); +/* +* PARAMETERS +* p_req +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* Generic Requester object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_req_construct or osm_req_init. +* +* SEE ALSO +* Generic Requester object, osm_req_construct, +* osm_req_init +*********/ + +/****f* OpenSM: Generic Requester/osm_req_init +* NAME +* osm_req_init +* +* DESCRIPTION +* The osm_req_init function initializes a +* Generic Requester object for use. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_req_init( + IN osm_req_t* const p_req, + IN osm_mad_pool_t* const p_pool, + IN osm_vl15_t* const p_vl15, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN atomic32_t* const p_sm_trans_id ); +/* +* PARAMETERS +* p_req +* [in] Pointer to an osm_req_t object to initialize. +* +* p_mad_pool +* [in] Pointer to the MAD pool. +* +* p_vl15 +* [in] Pointer to the VL15 interface. +* +* p_subn +* [in] Pointer to the subnet object. +* +* p_log +* [in] Pointer to the log object. +* +* p_sm_trans_id +* [in] Pointer to the atomic SM transaction ID. +* +* RETURN VALUES +* IB_SUCCESS if the Generic Requester object was initialized +* successfully. +* +* NOTES +* Allows calling other Generic Requester methods. +* +* SEE ALSO +* Generic Requester object, osm_req_construct, +* osm_req_destroy +*********/ + +/****f* OpenSM: Generic Requester/osm_req_get +* NAME +* osm_req_get +* +* DESCRIPTION +* Starts the process to transmit a directed route request for +* the attribute. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_req_get( + IN const osm_req_t* const p_req, + IN const osm_dr_path_t* const p_path, + IN const uint16_t attr_id, + IN const uint32_t attr_mod, + IN const cl_disp_msgid_t err_msg, + IN const osm_madw_context_t* const p_context ); +/* +* PARAMETERS +* p_req +* [in] Pointer to an osm_req_t object. +* +* p_path +* [in] Pointer to the directed route path to the node +* from which to retrieve the attribute. +* +* attr_id +* [in] Attribute ID to request. +* +* attr_mod +* [in] Attribute modifier for this request. +* +* err_msg +* [in] Message id with which to post this MAD if an error occurs. +* +* p_context +* [in] Mad wrapper context structure to be copied into the wrapper +* context, and thus visible to the recipient of the response. +* +* RETURN VALUES +* IB_SUCCESS if the request was successful. +* +* NOTES +* This function asynchronously requests the specified attribute. +* The response from the node will be routed through the Dispatcher +* to the appropriate receive controller object. +* +* SEE ALSO +* Generic Requester +*********/ +/****f* OpenSM: Generic Requester/osm_req_set +* NAME +* osm_req_set +* +* DESCRIPTION +* Starts the process to transmit a directed route Set() request. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_req_set( + IN const osm_req_t* const p_req, + IN const osm_dr_path_t* const p_path, + IN const uint8_t* const p_payload, + IN const size_t payload_size, + IN const uint16_t attr_id, + IN const uint32_t attr_mod, + IN const cl_disp_msgid_t err_msg, + IN const osm_madw_context_t* const p_context ); +/* +* PARAMETERS +* p_req +* [in] Pointer to an osm_req_t object. +* +* p_path +* [in] Pointer to the directed route path of the recipient. +* +* p_payload +* [in] Pointer to the SMP payload to send. +* +* payload_size +* [in] The size of the payload to be copied to the SMP data field. +* +* attr_id +* [in] Attribute ID to request. +* +* attr_mod +* [in] Attribute modifier for this request. +* +* err_msg +* [in] Message id with which to post this MAD if an error occurs. +* +* p_context +* [in] Mad wrapper context structure to be copied into the wrapper +* context, and thus visible to the recipient of the response. +* +* RETURN VALUES +* IB_SUCCESS if the request was successful. +* +* NOTES +* This function asynchronously requests the specified attribute. +* The response from the node will be routed through the Dispatcher +* to the appropriate receive controller object. +* +* SEE ALSO +* Generic Requester +*********/ + +END_C_DECLS + +#endif /* _OSM_REQ_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_req_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_req_ctrl.h new file mode 100644 index 00000000..f8bbc40c --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_req_ctrl.h @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_req_ctrl.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_req_ctrl_t. + * This object represents a controller that calls the + * generic requester object to retrieve attributes from a node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_REQ_CTRL_H_ +#define _OSM_REQ_CTRL_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Generic Request Controller +* NAME +* Generic Request Controller +* +* DESCRIPTION +* The Generic Request Controller object encapsulates the information +* needed to request an attribute from a node. +* +* The Generic Request Controller object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: Generic Request Controller/osm_req_ctrl_t +* NAME +* osm_req_ctrl_t +* +* DESCRIPTION +* Generic Request Controller structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_req_ctrl +{ + osm_req_t *p_req; + osm_log_t *p_log; + cl_dispatcher_t *p_disp; + cl_disp_reg_handle_t h_disp; + +} osm_req_ctrl_t; +/* +* FIELDS +* p_log +* Pointer to the log object. +* +* p_disp +* Pointer to the Dispatcher. +* +* h_disp +* Handle returned from dispatcher registration. +* +* SEE ALSO +* Generic Request Controller object +*********/ + +/****f* OpenSM: Generic Request Controller/osm_req_ctrl_construct +* NAME +* osm_req_ctrl_construct +* +* DESCRIPTION +* This function constructs a Generic Request Controller object. +* +* SYNOPSIS +*/ +void +osm_req_ctrl_construct( + IN osm_req_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a Generic Request Controller object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_req_ctrl_init, and osm_req_ctrl_destroy. +* +* Calling osm_req_ctrl_construct is a prerequisite to calling any other +* method except osm_req_ctrl_init. +* +* SEE ALSO +* Generic Request Controller object, osm_req_ctrl_init, +* osm_req_ctrl_destroy +*********/ + +/****f* OpenSM: Generic Request Controller/osm_req_ctrl_destroy +* NAME +* osm_req_ctrl_destroy +* +* DESCRIPTION +* The osm_req_ctrl_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_req_ctrl_destroy( + IN osm_req_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* Generic Request Controller object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_req_ctrl_construct or osm_req_ctrl_init. +* +* SEE ALSO +* Generic Request Controller object, osm_req_ctrl_construct, +* osm_req_ctrl_init +*********/ + +/****f* OpenSM: Generic Request Controller/osm_req_ctrl_init +* NAME +* osm_req_ctrl_init +* +* DESCRIPTION +* The osm_req_ctrl_init function initializes a +* Generic Request Controller object for use. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_req_ctrl_init( + IN osm_req_ctrl_t* const p_ctrl, + IN osm_req_t* const p_req, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_req_ctrl_t object to initialize. +* +* p_req +* [in] Pointer to a Generic Requester object. +* +* p_log +* [in] Pointer to the log object. +* +* p_disp +* [in] Pointer to the OpenSM central Dispatcher. +* +* RETURN VALUES +* CL_SUCCESS if the Generic Request Controller object was initialized +* successfully. +* +* NOTES +* Allows calling other Generic Request Controller methods. +* +* SEE ALSO +* Generic Request Controller object, osm_req_ctrl_construct, +* Generic Requester object, osm_req_ctrl_destroy +*********/ + +END_C_DECLS + +#endif /* _OSM_REQ_CTRL_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_resp.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_resp.h new file mode 100644 index 00000000..2909e2ad --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_resp.h @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_resp.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_resp_t. + * This object represents an object that genericly requests + * attributes from a node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_RESP_H_ +#define _OSM_RESP_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Generic Responder +* NAME +* Generic Responder +* +* DESCRIPTION +* The Generic Responder object encapsulates the information +* needed to respond to an attribute from a node. +* +* The Generic Responder object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: Generic Responder/osm_resp_t +* NAME +* osm_resp_t +* +* DESCRIPTION +* Generic Responder structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_resp +{ + osm_mad_pool_t *p_pool; + osm_vl15_t *p_vl15; + osm_log_t *p_log; + osm_subn_t *p_subn; + +} osm_resp_t; +/* +* FIELDS +* p_pool +* Pointer to the MAD pool. +* +* p_vl15 +* Pointer to the VL15 interface. +* +* p_log +* Pointer to the log object. +* +* p_subn +* Pointer to the subnet object. +* +* SEE ALSO +* Generic Responder object +*********/ + +/****f* OpenSM: Generic Responder/osm_resp_construct +* NAME +* osm_resp_construct +* +* DESCRIPTION +* This function constructs a Generic Responder object. +* +* SYNOPSIS +*/ +void +osm_resp_construct( + IN osm_resp_t* const p_resp ); +/* +* PARAMETERS +* p_resp +* [in] Pointer to a Generic Responder object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_resp_init, osm_resp_destroy +* +* Calling osm_resp_construct is a prerequisite to calling any other +* method except osm_resp_init. +* +* SEE ALSO +* Generic Responder object, osm_resp_init, +* osm_resp_destroy +*********/ + +/****f* OpenSM: Generic Responder/osm_resp_destroy +* NAME +* osm_resp_destroy +* +* DESCRIPTION +* The osm_resp_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_resp_destroy( + IN osm_resp_t* const p_resp ); +/* +* PARAMETERS +* p_resp +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* Generic Responder object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_resp_construct or osm_resp_init. +* +* SEE ALSO +* Generic Responder object, osm_resp_construct, +* osm_resp_init +*********/ + +/****f* OpenSM: Generic Responder/osm_resp_init +* NAME +* osm_resp_init +* +* DESCRIPTION +* The osm_resp_init function initializes a +* Generic Responder object for use. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_resp_init( + IN osm_resp_t* const p_resp, + IN osm_mad_pool_t* const p_pool, + IN osm_vl15_t* const p_vl15, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log ); +/* +* PARAMETERS +* p_resp +* [in] Pointer to an osm_resp_t object to initialize. +* +* p_mad_pool +* [in] Pointer to the MAD pool. +* +* p_vl15 +* [in] Pointer to the VL15 interface. +* +* p_subn +* [in] Pointer to the subnet object. +* +* p_log +* [in] Pointer to the log object. +* +* RETURN VALUES +* IB_SUCCESS if the Generic Responder object was initialized +* successfully. +* +* NOTES +* Allows calling other Generic Responder methods. +* +* SEE ALSO +* Generic Responder object, osm_resp_construct, +* osm_resp_destroy +*********/ + +/****f* OpenSM: Generic Responder/osm_resp_send +* NAME +* osm_resp_send +* +* DESCRIPTION +* Starts the process to transmit a directed route response. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_resp_send( + IN const osm_resp_t* const p_resp, + IN const osm_madw_t* const p_req_madw, + IN const ib_net16_t status, + IN const uint8_t* const p_payload ); +/* +* PARAMETERS +* p_resp +* [in] Pointer to an osm_resp_t object. +* +* p_madw +* [in] Pointer to the MAD Wrapper object for the requesting MAD +* to which this response is generated. +* +* status +* [in] Status for this response. +* +* p_payload +* [in] Pointer to the payload of the response MAD. +* +* RETURN VALUES +* IB_SUCCESS if the response was successful. +* +* NOTES +* +* SEE ALSO +* Generic Responder +*********/ + +END_C_DECLS + +#endif /* _OSM_RESP_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_router.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_router.h new file mode 100644 index 00000000..91b04166 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_router.h @@ -0,0 +1,323 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ + + +/* + * Abstract: + * Declaration of osm_router_t. + * This object represents an IBA router. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + */ + +#ifndef _OSM_ROUTER_H_ +#define _OSM_ROUTER_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Router +* NAME +* Router +* +* DESCRIPTION +* The Router object encapsulates the information needed by the +* OpenSM to manage routers. The OpenSM allocates one router object +* per router in the IBA subnet. +* +* The Router object is not thread safe, thus callers must provide +* serialization. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Hal Rosenstock, Voltaire +* +*********/ + +/****s* OpenSM: Router/osm_router_t +* NAME +* osm_router_t +* +* DESCRIPTION +* Router structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_router +{ + cl_map_item_t map_item; + osm_port_t *p_port; +} osm_router_t; +/* +* FIELDS +* map_item +* Linkage structure for cl_qmap. MUST BE FIRST MEMBER! +* +* p_port +* Pointer to the Port object for this router. +* +* SEE ALSO +* Router object +*********/ + +/****f* OpenSM: Router/osm_router_construct +* NAME +* osm_router_construct +* +* DESCRIPTION +* This function constructs a Router object. +* +* SYNOPSIS +*/ +void +osm_router_construct( + IN osm_router_t* const p_rtr ); +/* +* PARAMETERS +* p_rtr +* [in] Pointer to a Router object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_router_init, and osm_router_destroy. +* +* Calling osm_router_construct is a prerequisite to calling any other +* method except osm_router_init. +* +* SEE ALSO +* Router object, osm_router_init, osm_router_destroy +*********/ + +/****f* OpenSM: Router/osm_router_destroy +* NAME +* osm_router_destroy +* +* DESCRIPTION +* The osm_router_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_router_destroy( + IN osm_router_t* const p_rtr ); +/* +* PARAMETERS +* p_rtr +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* None. +* +* NOTES +* Performs any necessary cleanup of the specified object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to osm_router_construct +* or osm_router_init. +* +* SEE ALSO +* Router object, osm_router_construct, osm_router_init +*********/ + +/****f* OpenSM: Router/osm_router_destroy +* NAME +* osm_router_destroy +* +* DESCRIPTION +* Destroys and deallocates the object. +* +* SYNOPSIS +*/ +void +osm_router_delete( + IN OUT osm_router_t** const pp_rtr ); +/* +* PARAMETERS +* p_rtr +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* None. +* +* NOTES +* +* SEE ALSO +* Router object, osm_router_construct, osm_router_init +*********/ + +/****f* OpenSM: Router/osm_router_init +* NAME +* osm_router_init +* +* DESCRIPTION +* The osm_router_init function initializes a Router object for use. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_router_init( + IN osm_router_t* const p_rtr, + IN osm_port_t* const p_port ); +/* +* PARAMETERS +* p_rtr +* [in] Pointer to an osm_router_t object to initialize. +* +* p_port +* [in] Pointer to the port object of this router +* +* RETURN VALUES +* IB_SUCCESS if the Router object was initialized successfully. +* +* NOTES +* Allows calling other node methods. +* +* SEE ALSO +* Router object, osm_router_construct, osm_router_destroy +*********/ + +/****f* OpenSM: Router/osm_router_new +* NAME +* osm_router_new +* +* DESCRIPTION +* The osm_router_init function initializes a Router object for use. +* +* SYNOPSIS +*/ +osm_router_t* +osm_router_new( + IN osm_port_t* const p_port ); +/* +* PARAMETERS +* p_node +* [in] Pointer to the node object of this router +* +* RETURN VALUES +* Pointer to the new initialized router object. +* +* NOTES +* +* SEE ALSO +* Router object, osm_router_construct, osm_router_destroy, +*********/ + +/****f* OpenSM: Router/osm_router_get_port_ptr +* NAME +* osm_router_get_port_ptr +* +* DESCRIPTION +* Returns a pointer to the Port object for this router. +* +* SYNOPSIS +*/ +static inline osm_port_t* +osm_router_get_port_ptr( + IN const osm_router_t* const p_rtr ) +{ + return( p_rtr->p_port ); +} +/* +* PARAMETERS +* p_rtr +* [in] Pointer to an osm_router_t object. +* +* RETURN VALUES +* Returns a pointer to the Port object for this router. +* +* NOTES +* +* SEE ALSO +* Router object +*********/ + +/****f* OpenSM: Router/osm_router_get_node_ptr +* NAME +* osm_router_get_node_ptr +* +* DESCRIPTION +* Returns a pointer to the Node object for this router. +* +* SYNOPSIS +*/ +static inline osm_node_t* +osm_router_get_node_ptr( + IN const osm_router_t* const p_rtr ) +{ + return( p_rtr->p_port->p_node ); +} +/* +* PARAMETERS +* p_rtr +* [in] Pointer to an osm_router_t object. +* +* RETURN VALUES +* Returns a pointer to the Node object for this router. +* +* NOTES +* +* SEE ALSO +* Router object +*********/ + +END_C_DECLS + +#endif /* _OSM_ROUTER_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa.h new file mode 100644 index 00000000..0c493b9f --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa.h @@ -0,0 +1,500 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_sa_t. + * This object represents an IBA subnet. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.6 $ + */ + +#ifndef _OSM_SA_H_ +#define _OSM_SA_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/SA +* NAME +* SA +* +* DESCRIPTION +* The SA object encapsulates the information needed by the +* OpenSM to instantiate a subnet administrator. The OpenSM allocates +* one SA object per subnet manager. +* +* The SA object is thread safe. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* AUTHOR +* Ranjit Pandit, Intel +* Anil Keshavamurthy, Intel +* +*********/ + +/****d* OpenSM: SA/osm_sa_state_t +* NAME +* osm_sa_state_t +* +* DESCRIPTION +* Enumerates the possible states of SA object. +* +* SYNOPSIS +*/ +typedef enum _osm_sa_state +{ + OSM_SA_STATE_INIT = 0, + OSM_SA_STATE_READY + +} osm_sa_state_t; +/***********/ + +/****s* OpenSM: SM/osm_sa_t +* NAME +* osm_sa_t +* +* DESCRIPTION +* Subnet Administration structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_sa +{ + osm_sa_state_t state; + osm_subn_t *p_subn; + osm_vendor_t *p_vendor; + osm_log_t *p_log; + osm_mad_pool_t *p_mad_pool; + cl_dispatcher_t *p_disp; + cl_plock_t *p_lock; + atomic32_t sa_trans_id; + osm_sa_mad_ctrl_t mad_ctrl; + osm_sa_resp_t resp; + osm_cpi_rcv_t cpi_rcv; + osm_cpi_rcv_ctrl_t cpi_rcv_ctrl; + osm_nr_rcv_t nr_rcv; + osm_nr_rcv_ctrl_t nr_rcv_ctrl; + osm_pir_rcv_t pir_rcv; + osm_pir_rcv_ctrl_t pir_rcv_ctrl; + osm_gir_rcv_t gir_rcv; + osm_gir_rcv_ctrl_t gir_rcv_ctrl; + osm_lr_rcv_t lr_rcv; + osm_lr_rcv_ctrl_t lr_rcv_ctrl; + osm_pr_rcv_t pr_rcv; + osm_pr_rcv_ctrl_t pr_rcv_ctrl; + osm_smir_rcv_t smir_rcv; + osm_smir_ctrl_t smir_ctrl; + osm_mcmr_recv_t mcmr_rcv; + osm_mcmr_rcv_ctrl_t mcmr_rcv_ctlr; + osm_sr_rcv_t sr_rcv; + osm_sr_rcv_ctrl_t sr_rcv_ctrl; +#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP) + osm_mpr_rcv_t mpr_rcv; + osm_mpr_rcv_ctrl_t mpr_rcv_ctrl; +#endif + + /* InformInfo Receiver */ + osm_infr_rcv_t infr_rcv; + osm_infr_rcv_ctrl_t infr_rcv_ctrl; + + /* VL Arbitrartion Query */ + osm_vlarb_rec_rcv_t vlarb_rec_rcv; + osm_vlarb_rec_rcv_ctrl_t vlarb_rec_rcv_ctrl; + + /* SLtoVL Map Query */ + osm_slvl_rec_rcv_t slvl_rec_rcv; + osm_slvl_rec_rcv_ctrl_t slvl_rec_rcv_ctrl; + + /* P_Key table Query */ + osm_pkey_rec_rcv_t pkey_rec_rcv; + osm_pkey_rec_rcv_ctrl_t pkey_rec_rcv_ctrl; + + /* LinearForwardingTable Query */ + osm_lftr_rcv_t lftr_rcv; + osm_lftr_rcv_ctrl_t lftr_rcv_ctrl; + + /* SwitchInfo Query */ + osm_sir_rcv_t sir_rcv; + osm_sir_rcv_ctrl_t sir_rcv_ctrl; + + /* MulticastForwardingTable Query */ + osm_mftr_rcv_t mftr_rcv; + osm_mftr_rcv_ctrl_t mftr_rcv_ctrl; +} osm_sa_t; +/* +* FIELDS +* state +* State of this SA object +* p_subn +* Pointer to the Subnet object for this subnet. +* +* p_vendor +* Pointer to the vendor specific interfaces object. +* +* p_log +* Pointer to the log object. +* +* p_mad_pool +* Pointer to the MAD pool. +* +* p_disp +* Pointer to dispatcher +* +* p_lock +* Pointer to Lock for serialization +* +* sa_trans_id +* Transaction ID +* +* mad_ctrl +* Mad Controller +* +* resp +* Response object +* +* nr +* +* nr_ctrl +* +* pir_rcv +* +* pir_rcv_ctrl +* +* lr +* +* lr_ctrl +* +* pr +* +* pr_ctrl +* +* smir +* +* smir_ctrl +* +* SEE ALSO +* SM object +*********/ + +/****f* OpenSM: SA/osm_sa_construct +* NAME +* osm_sa_construct +* +* DESCRIPTION +* This function constructs an SA object. +* +* SYNOPSIS +*/ +void osm_sa_construct( + IN osm_sa_t* const p_sa ); +/* +* PARAMETERS +* p_sa +* [in] Pointer to a SA object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_sa_init, osm_sa_destroy, and osm_sa_is_inited. +* +* Calling osm_sa_construct is a prerequisite to calling any other +* method except osm_sa_init. +* +* SEE ALSO +* SA object, osm_sa_init, osm_sa_destroy, osm_sa_is_inited +*********/ + +/****f* OpenSM: SA/osm_sa_shutdown +* NAME +* osm_sa_shutdown +* +* DESCRIPTION +* The osm_sa_shutdown function shutdowns an SA, unregistering from all +* dispatcher messages and unbinding the QP1 mad service +* +* SYNOPSIS +*/ +void osm_sa_shutdown( + IN osm_sa_t* const p_sa ); +/* +* PARAMETERS +* p_sa +* [in] Pointer to a SA object to shutdown. +* +* RETURN VALUE +* This function does not return a value. +* +* SEE ALSO +* SA object, osm_sa_construct, osm_sa_init +*********/ + +/****f* OpenSM: SA/osm_sa_destroy +* NAME +* osm_sa_destroy +* +* DESCRIPTION +* The osm_sa_destroy function destroys an SA, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_sa_destroy( + IN osm_sa_t* const p_sa ); +/* +* PARAMETERS +* p_sa +* [in] Pointer to a SA object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified SA object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to osm_sa_construct or +* osm_sa_init. +* +* SEE ALSO +* SA object, osm_sa_construct, osm_sa_init +*********/ + +/****f* OpenSM: SA/osm_sa_init +* NAME +* osm_sa_init +* +* DESCRIPTION +* The osm_sa_init function initializes a SA object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_sa_init( + IN osm_sm_t* const p_sm, + IN osm_sa_t* const p_sa, + IN osm_subn_t* const p_subn, + IN osm_vendor_t* const p_vendor, + IN osm_mad_pool_t* const p_mad_pool, + IN osm_log_t* const p_log, + IN osm_stats_t* const p_stats, + IN cl_dispatcher_t* const p_disp, + IN cl_plock_t* const p_lock ); +/* +* PARAMETERS +* p_sa +* [in] Pointer to an osm_sa_t object to initialize. +* +* p_subn +* [in] Pointer to the Subnet object for this subnet. +* +* p_vendor +* [in] Pointer to the vendor specific interfaces object. +* +* p_mad_pool +* [in] Pointer to the MAD pool. +* +* p_log +* [in] Pointer to the log object. +* +* p_stats +* [in] Pointer to the statistics object. +* +* p_disp +* [in] Pointer to the OpenSM central Dispatcher. +* +* p_lock +* [in] Pointer to the OpenSM serializing lock. +* +* RETURN VALUES +* CL_SUCCESS if the SA object was initialized successfully. +* +* NOTES +* Allows calling other SA methods. +* +* SEE ALSO +* SA object, osm_sa_construct, osm_sa_destroy, +* osm_sa_is_inited +*********/ + +/****f* OpenSM: SA/osm_sa_is_inited +* NAME +* osm_sa_is_inited +* +* DESCRIPTION +* Indicates if the object has been initialized with osm_sa_init. +* +* SYNOPSIS +*/ +boolean_t osm_sa_is_inited( + IN const osm_sa_t* const p_sa ); +/* +* PARAMETERS +* p_sa +* [in] Pointer to an osm_sa_t object. +* +* RETURN VALUES +* TRUE if the object was initialized successfully, +* FALSE otherwise. +* +* NOTES +* The osm_sa_construct or osm_sa_init must be called before using +* this function. +* +* SEE ALSO +* SA object, osm_sa_construct, osm_sa_init +*********/ + +/****f* OpenSM: SA/osm_sa_bind +* NAME +* osm_sa_bind +* +* DESCRIPTION +* Binds the SA object to a port guid. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_sa_bind( + IN osm_sa_t* const p_sa, + IN const ib_net64_t port_guid ); +/* +* PARAMETERS +* p_sa +* [in] Pointer to an osm_sa_t object to bind. +* +* port_guid +* [in] Local port GUID with which to bind. +* +* +* RETURN VALUES +* None +* +* NOTES +* A given SA object can only be bound to one port at a time. +* +* SEE ALSO +*********/ + +struct _osm_opensm_t; +/****f* OpenSM: SA/osm_sa_db_file_dump +* NAME +* osm_sa_db_file_dump +* +* DESCRIPTION +* Dumps the SA DB to the dump file. +* +* SYNOPSIS +*/ +int osm_sa_db_file_dump(struct _osm_opensm_t *p_osm); +/* +* PARAMETERS +* p_osm +* [in] Pointer to an osm_opensm_t object. +* +* RETURN VALUES +* None +* +*********/ + +/****f* OpenSM: SA/osm_sa_db_file_load +* NAME +* osm_sa_db_file_load +* +* DESCRIPTION +* Loads SA DB from the file. +* +* SYNOPSIS +*/ +int osm_sa_db_file_load(struct _osm_opensm_t *p_osm); +/* +* PARAMETERS +* p_osm +* [in] Pointer to an osm_opensm_t object. +* +* RETURN VALUES +* 0 on success, other value on failure. +* +*********/ + +END_C_DECLS + +#endif /* _OSM_SA_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_class_port_info.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_class_port_info.h new file mode 100644 index 00000000..ea64fbed --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_class_port_info.h @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_class_port_info.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_cpi_rcv_t. + * This object represents the ClassPortInfo Receiver object. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.2 $ + */ + +#ifndef _OSM_CPI_H_ +#define _OSM_CPI_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/ClassPort Info Receiver +* NAME +* ClassPort Info Receiver +* +* DESCRIPTION +* The ClassPort Info Receiver object encapsulates the information +* needed to receive the ClassPortInfo request from a node. +* +* The ClassPort Info Receiver object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Eitan Zahavi, Mellanox +* +*********/ + +/****s* OpenSM: ClassPort Info Receiver/osm_cpi_rcv_t +* NAME +* osm_cpi_rcv_t +* +* DESCRIPTION +* ClassPort Info Receiver structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_cpi_rcv +{ + osm_subn_t *p_subn; + osm_sa_resp_t *p_resp; + osm_mad_pool_t *p_mad_pool; + osm_log_t *p_log; + cl_plock_t *p_lock; + +} osm_cpi_rcv_t; +/* +* FIELDS +* p_subn +* Pointer to the Subnet object for this subnet. +* +* p_gen_req_ctrl +* Pointer to the generic request controller. +* +* p_log +* Pointer to the log object. +* +* p_lock +* Pointer to the serializing lock. +* +* SEE ALSO +* ClassPort Info Receiver object +*********/ + +/****f* OpenSM: ClassPort Info Receiver/osm_cpi_rcv_construct +* NAME +* osm_cpi_rcv_construct +* +* DESCRIPTION +* This function constructs a ClassPort Info Receiver object. +* +* SYNOPSIS +*/ +void +osm_cpi_rcv_construct( + IN osm_cpi_rcv_t* const p_rcv ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to a ClassPort Info Receiver object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_cpi_rcv_init, osm_cpi_rcv_destroy +* +* Calling osm_cpi_rcv_construct is a prerequisite to calling any other +* method except osm_cpi_rcv_init. +* +* SEE ALSO +* ClassPort Info Receiver object, osm_cpi_rcv_init, osm_cpi_rcv_destroy +*********/ + +/****f* OpenSM: ClassPort Info Receiver/osm_cpi_rcv_destroy +* NAME +* osm_cpi_rcv_destroy +* +* DESCRIPTION +* The osm_cpi_rcv_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_cpi_rcv_destroy( + IN osm_cpi_rcv_t* const p_rcv ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* ClassPort Info Receiver object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_cpi_rcv_construct or osm_cpi_rcv_init. +* +* SEE ALSO +* ClassPort Info Receiver object, osm_cpi_rcv_construct, +* osm_cpi_rcv_init +*********/ + +/****f* OpenSM: ClassPort Info Receiver/osm_cpi_rcv_init +* NAME +* osm_cpi_rcv_init +* +* DESCRIPTION +* The osm_cpi_rcv_init function initializes a +* ClassPort Info Receiver object for use. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_cpi_rcv_init( + IN osm_cpi_rcv_t* const p_rcv, + IN osm_sa_resp_t* const p_resp, + IN osm_mad_pool_t* const p_mad_pool, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to an osm_cpi_rcv_t object to initialize. +* +* p_subn +* [in] Pointer to the Subnet object for this subnet. +* +* p_log +* [in] Pointer to the log object. +* +* p_lock +* [in] Pointer to the OpenSM serializing lock. +* +* RETURN VALUES +* IB_SUCCESS if the ClassPort Info Receiver object was initialized +* successfully. +* +* NOTES +* Allows calling other ClassPort Info Receiver methods. +* +* SEE ALSO +* ClassPort Info Receiver object, osm_cpi_rcv_construct, +* osm_cpi_rcv_destroy +*********/ + +/****f* OpenSM: ClassPort Info Receiver/osm_cpi_rcv_process +* NAME +* osm_cpi_rcv_process +* +* DESCRIPTION +* Process the ClassPortInfo request. +* +* SYNOPSIS +*/ +void +osm_cpi_rcv_process( + IN osm_cpi_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to an osm_cpi_rcv_t object. +* +* p_madw +* [in] Pointer to the MAD Wrapper containing the MAD +* that contains the ClassPortInfo attribute. +* +* RETURN VALUES +* IB_SUCCESS if the ClassPortInfo processing was successful. +* +* NOTES +* This function processes a ClassPortInfo attribute. +* +* SEE ALSO +* ClassPort Info Receiver, ClassPort Info Response Controller +*********/ + +END_C_DECLS + +#endif /* _OSM_CPI_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_class_port_info_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_class_port_info_ctrl.h new file mode 100644 index 00000000..79f13b45 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_class_port_info_ctrl.h @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_class_port_info_ctrl.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_cpi_rcv_ctrl_t. + * This object represents a controller that receives the IBA ClassPortInfo + * attribute from a node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.2 $ + */ + +#ifndef _OSM_CPICTRL_H_ +#define _OSM_CPICTRL_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Class Port Info Receive Controller +* NAME +* Class Port Info Receive Controller +* +* DESCRIPTION +* The Class Port Info Receive Controller object encapsulates +* the information requested by the ClassPortInfo attribute. +* +* The ClassPortInfo Receive Controller object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Eitan Zahavi, Mellanox +* +*********/ + +/****s* OpenSM: ClassPort Info Receive Controller/osm_cpi_rcv_ctrl_t +* NAME +* osm_cpi_rcv_ctrl_t +* +* DESCRIPTION +* ClassPort Info Receive Controller structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_cpi_rcv_ctrl +{ + osm_cpi_rcv_t *p_rcv; + osm_log_t *p_log; + cl_dispatcher_t *p_disp; + cl_disp_reg_handle_t h_disp; + +} osm_cpi_rcv_ctrl_t; +/* +* FIELDS +* p_rcv +* Pointer to the ClassPort Info Receiver object. +* +* p_log +* Pointer to the log object. +* +* p_disp +* Pointer to the Dispatcher. +* +* h_disp +* Handle returned from dispatcher registration. +* +* SEE ALSO +* Class Port Info Receive Controller object +* Class Port Info Receiver object +*********/ + +/****f* OpenSM: Class Port Info Receive Controller/osm_cpi_rcv_ctrl_construct +* NAME +* osm_cpi_rcv_ctrl_construct +* +* DESCRIPTION +* This function constructs a Class Port Info Receive Controller object. +* +* SYNOPSIS +*/ +void osm_cpi_rcv_ctrl_construct( + IN osm_cpi_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a Class Port Info Receive Controller +* object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_cpi_rcv_ctrl_init, osm_cpi_rcv_ctrl_destroy, +* and osm_cpi_rcv_ctrl_is_inited. +* +* Calling osm_cpi_rcv_ctrl_construct is a prerequisite to calling any other +* method except osm_cpi_rcv_ctrl_init. +* +* SEE ALSO +* Class Port Info Receive Controller object, osm_cpi_rcv_ctrl_init, +* osm_cpi_rcv_ctrl_destroy, osm_cpi_rcv_ctrl_is_inited +*********/ + +/****f* OpenSM: Class Port Info Receive Controller/osm_cpi_rcv_ctrl_destroy +* NAME +* osm_cpi_rcv_ctrl_destroy +* +* DESCRIPTION +* The osm_cpi_rcv_ctrl_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_cpi_rcv_ctrl_destroy( + IN osm_cpi_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* Class Port Info Receive Controller object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_cpi_rcv_ctrl_construct or osm_cpi_rcv_ctrl_init. +* +* SEE ALSO +* Class Port Info Receive Controller object, osm_cpi_rcv_ctrl_construct, +* osm_cpi_rcv_ctrl_init +*********/ + +/****f* OpenSM: Class Port Info Receive Controller/osm_cpi_rcv_ctrl_init +* NAME +* osm_cpi_rcv_ctrl_init +* +* DESCRIPTION +* The osm_cpi_rcv_ctrl_init function initializes a +* Class Port Info Receive Controller object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_cpi_rcv_ctrl_init( + IN osm_cpi_rcv_ctrl_t* const p_ctrl, + IN osm_cpi_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_cpi_rcv_ctrl_t object to initialize. +* +* p_rcv +* [in] Pointer to an osm_cpi_rcv_t object. +* +* p_log +* [in] Pointer to the log object. +* +* p_disp +* [in] Pointer to the OpenSM central Dispatcher. +* +* RETURN VALUES +* CL_SUCCESS if the Class Port Info Receive Controller object was initialized +* successfully. +* +* NOTES +* Allows calling other Class Port Info Receive Controller methods. +* +* SEE ALSO +* Class Port Info Receive Controller object, osm_cpi_rcv_ctrl_construct, +* osm_cpi_rcv_ctrl_destroy, osm_cpi_rcv_ctrl_is_inited +*********/ + +/****f* OpenSM: Class Port Info Receive Controller/osm_cpi_rcv_ctrl_is_inited +* NAME +* osm_cpi_rcv_ctrl_is_inited +* +* DESCRIPTION +* Indicates if the object has been initialized with osm_cpi_rcv_ctrl_init. +* +* SYNOPSIS +*/ +boolean_t osm_cpi_rcv_ctrl_is_inited( + IN const osm_cpi_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_cpi_rcv_ctrl_t object. +* +* RETURN VALUES +* TRUE if the object was initialized successfully, +* FALSE otherwise. +* +* NOTES +* The osm_cpi_rcv_ctrl_construct or osm_cpi_rcv_ctrl_init must be +* called before using this function. +* +* SEE ALSO +* Class Port Info Receive Controller object, osm_cpi_rcv_ctrl_construct, +* osm_cpi_rcv_ctrl_init +*********/ + +END_C_DECLS + +#endif /* _OSM_CPICTRL_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_guidinfo_record.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_guidinfo_record.h new file mode 100644 index 00000000..216b5200 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_guidinfo_record.h @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_guidinfo_record.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_gir_rcv_t. + * This object represents the GUIDInfo Record Receiver object. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + */ + +#ifndef _OSM_GIR_RCV_H_ +#define _OSM_GIR_RCV_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/GUIDInfo Record Receiver +* NAME +* GUIDInfo Record Receiver +* +* DESCRIPTION +* The GUIDInfo Record Receiver object encapsulates the information +* needed to receive the GUIDInfoRecord attribute from a node. +* +* The GUIDInfo Record Receiver object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Hal Rosenstock, Voltaire +* +*********/ + +/****s* OpenSM: GUIDInfo Record Receiver/osm_gir_rcv_t +* NAME +* osm_gir_rcv_t +* +* DESCRIPTION +* GUIDInfo Record Receiver structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_gir_rcv +{ + const osm_subn_t *p_subn; + osm_sa_resp_t *p_resp; + osm_mad_pool_t *p_mad_pool; + osm_log_t *p_log; + cl_plock_t *p_lock; + cl_qlock_pool_t pool; + +} osm_gir_rcv_t; +/* +* FIELDS +* p_subn +* Pointer to the Subnet object for this subnet. +* +* p_resp +* Pointer to the SA responder. +* +* p_mad_pool +* Pointer to the mad pool. +* +* p_log +* Pointer to the log object. +* +* p_lock +* Pointer to the serializing lock. +* +* pool +* Pool of linkable GUIDInfo Record objects used to generate +* the query response. +* +* SEE ALSO +* +*********/ + +/****f* OpenSM: GUIDInfo Record Receiver/osm_gir_rcv_construct +* NAME +* osm_gir_rcv_construct +* +* DESCRIPTION +* This function constructs a GUIDInfo Record Receiver object. +* +* SYNOPSIS +*/ +void +osm_gir_rcv_construct( + IN osm_gir_rcv_t* const p_rcv ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to a GUIDInfo Record Receiver object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_gir_rcv_init, osm_gir_rcv_destroy +* +* Calling osm_gir_rcv_construct is a prerequisite to calling any other +* method except osm_gir_rcv_init. +* +* SEE ALSO +* GUIDInfo Record Receiver object, osm_gir_rcv_init, +* osm_gir_rcv_destroy +*********/ + +/****f* OpenSM: GUIDInfo Record Receiver/osm_gir_rcv_destroy +* NAME +* osm_gir_rcv_destroy +* +* DESCRIPTION +* The osm_gir_rcv_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_gir_rcv_destroy( + IN osm_gir_rcv_t* const p_rcv ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* GUIDInfo Record Receiver object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_gir_rcv_construct or osm_gir_rcv_init. +* +* SEE ALSO +* GUIDInfo Record Receiver object, osm_gir_rcv_construct, +* osm_gir_rcv_init +*********/ + +/****f* OpenSM: GUIDInfo Record Receiver/osm_gir_rcv_init +* NAME +* osm_gir_rcv_init +* +* DESCRIPTION +* The osm_gir_rcv_init function initializes a +* GUIDInfo Record Receiver object for use. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_gir_rcv_init( + IN osm_gir_rcv_t* const p_rcv, + IN osm_sa_resp_t* const p_resp, + IN osm_mad_pool_t* const p_mad_pool, + IN const osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to an osm_gir_rcv_t object to initialize. +* +* p_req +* [in] Pointer to an osm_req_t object. +* +* p_subn +* [in] Pointer to the Subnet object for this subnet. +* +* p_log +* [in] Pointer to the log object. +* +* p_lock +* [in] Pointer to the OpenSM serializing lock. +* +* RETURN VALUES +* CL_SUCCESS if the GUIDInfo Record Receiver object was initialized +* successfully. +* +* NOTES +* Allows calling other GUIDInfo Record Receiver methods. +* +* SEE ALSO +* GUIDInfo Record Receiver object, osm_gir_rcv_construct, +* osm_gir_rcv_destroy +*********/ + +/****f* OpenSM: GUIDInfo Record Receiver/osm_gir_rcv_process +* NAME +* osm_gir_rcv_process +* +* DESCRIPTION +* Process the GUIDInfoRecord attribute. +* +* SYNOPSIS +*/ +void +osm_gir_rcv_process( + IN osm_gir_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to an osm_gir_rcv_t object. +* +* p_madw +* [in] Pointer to the MAD Wrapper containing the MAD +* that contains the node's GUIDInfoRecord attribute. +* +* RETURN VALUES +* CL_SUCCESS if the GUIDInfoRecord processing was successful. +* +* NOTES +* This function processes a GUIDInfoRecord attribute. +* +* SEE ALSO +* GUIDInfo Record Receiver, GUIDInfo Record Response Controller +*********/ + +END_C_DECLS + +#endif /* _OSM_GIR_RCV_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_guidinfo_record_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_guidinfo_record_ctrl.h new file mode 100644 index 00000000..07e776e7 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_guidinfo_record_ctrl.h @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_guidinfo_record_ctrl.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_sa_gir_rec_rcv_ctrl_t. + * This object represents a controller that receives the IBA GUID Info + * record query from SA client. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + */ + +#ifndef _OSM_GIR_CTRL_H_ +#define _OSM_GIR_CTRL_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/GUID Info Record Receive Controller +* NAME +* GUID Info Record Receive Controller +* +* DESCRIPTION +* The GUID Info Record Receive Controller object encapsulates +* the information needed to handle GUID Info record query from SA client. +* +* The GUID Info Record Receive Controller object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Hal Rosenstock, Voltaire +* +*********/ + +/****s* OpenSM: GUID Info Record Receive Controller/osm_gir_rcv_ctrl_t +* NAME +* osm_gir_rcv_ctrl_t +* +* DESCRIPTION +* GUID Info Record Receive Controller structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_gir_rcv_ctrl +{ + osm_gir_rcv_t *p_rcv; + osm_log_t *p_log; + cl_dispatcher_t *p_disp; + cl_disp_reg_handle_t h_disp; + +} osm_gir_rcv_ctrl_t; +/* +* FIELDS +* p_rcv +* Pointer to the GUID Info Record Receiver object. +* +* p_log +* Pointer to the log object. +* +* p_disp +* Pointer to the Dispatcher. +* +* h_disp +* Handle returned from dispatcher registration. +* +* SEE ALSO +* GUID Info Record Receive Controller object +* GUID Info Record Receiver object +*********/ + +/****f* OpenSM: GUID Info Record Receive Controller/osm_gir_rec_rcv_ctrl_construct +* NAME +* osm_gir_rcv_ctrl_construct +* +* DESCRIPTION +* This function constructs a GUID Info Record Receive Controller object. +* +* SYNOPSIS +*/ +void osm_gir_rcv_ctrl_construct( + IN osm_gir_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a GUID Info Record Receive Controller +* object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_gir_rcv_ctrl_init, osm_gir_rcv_ctrl_destroy +* +* Calling osm_gir_rcv_ctrl_construct is a prerequisite to calling any other +* method except osm_gir_rcv_ctrl_init. +* +* SEE ALSO +* GUID Info Record Receive Controller object, osm_gir_rcv_ctrl_init, +* osm_gir_rcv_ctrl_destroy +*********/ + +/****f* OpenSM: GUID Info Record Receive Controller/osm_gir_rcv_ctrl_destroy +* NAME +* osm_gir_rcv_ctrl_destroy +* +* DESCRIPTION +* The osm_gir_rcv_ctrl_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_gir_rcv_ctrl_destroy( + IN osm_gir_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* GUIDInfo Record Receive Controller object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_gir_rcv_ctrl_construct or osm_gir_rcv_ctrl_init. +* +* SEE ALSO +* GUIDInfo Record Receive Controller object, osm_gir_rcv_ctrl_construct, +* osm_gir_rcv_ctrl_init +*********/ + +/****f* OpenSM: GUID Info Record Receive Controller/osm_gir_rcv_ctrl_init +* NAME +* osm_gir_rcv_ctrl_init +* +* DESCRIPTION +* The osm_gir_rcv_ctrl_init function initializes a +* GUID Info Record Receive Controller object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_gir_rcv_ctrl_init( + IN osm_gir_rcv_ctrl_t* const p_ctrl, + IN osm_gir_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_gir_rcv_ctrl_t object to initialize. +* +* p_rcv +* [in] Pointer to an osm_gir_rcv_t object. +* +* p_log +* [in] Pointer to the log object. +* +* p_disp +* [in] Pointer to the OpenSM central Dispatcher. +* +* RETURN VALUES +* CL_SUCCESS if the GUID Info Record Receive Controller object was initialized +* successfully. +* +* NOTES +* Allows calling other GUID Info Record Receive Controller methods. +* +* SEE ALSO +* GUID Info Record Receive Controller object, osm_gir_rcv_ctrl_construct, +* osm_gir_rcv_ctrl_destroy +*********/ + +END_C_DECLS + +#endif /* _OSM_GIR_CTRL_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_informinfo.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_informinfo.h new file mode 100644 index 00000000..7bedf647 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_informinfo.h @@ -0,0 +1,299 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_informinfo.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_infr_rcv_t. + * This object represents the InformInfoRecord Receiver object. + * attribute from a node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.3 $ + */ + +#ifndef _OSM_SA_INFR_H_ +#define _OSM_SA_INFR_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/InformInfo Receiver +* NAME +* InformInfo Receiver +* +* DESCRIPTION +* The InformInfo Receiver object encapsulates the information +* needed to receive the InformInfo request from a node. +* +* The InformInfo Receiver object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Eitan Zahavi, Mellanox +* +*********/ + +/****s* OpenSM: InformInfo Receiver/osm_infr_rcv_t +* NAME +* osm_infr_rcv_t +* +* DESCRIPTION +* InformInfo Receiver structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_infr_rcv +{ + osm_subn_t *p_subn; + osm_sa_resp_t *p_resp; + osm_mad_pool_t *p_mad_pool; + osm_log_t *p_log; + cl_plock_t *p_lock; + cl_qlock_pool_t pool; +} osm_infr_rcv_t; +/* +* FIELDS +* p_subn +* Pointer to the Subnet object for this subnet. +* +* p_resp +* Pointer to the osm_sa_resp_t object. +* +* p_log +* Pointer to the log object. +* +* p_lock +* Pointer to the serializing lock. +* +* pool +* Pool of linkable InformInfo Record objects used to +* generate the query response. +* +* SEE ALSO +* InformInfo Receiver object +*********/ + +/****f* OpenSM: InformInfo Receiver/osm_infr_rcv_construct +* NAME +* osm_infr_rcv_construct +* +* DESCRIPTION +* This function constructs a InformInfo Receiver object. +* +* SYNOPSIS +*/ +void +osm_infr_rcv_construct( + IN osm_infr_rcv_t* const p_rcv ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to a InformInfo Receiver object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_infr_rcv_init, osm_infr_rcv_destroy +* +* Calling osm_infr_rcv_construct is a prerequisite to calling any other +* method except osm_infr_rcv_init. +* +* SEE ALSO +* InformInfo Receiver object, osm_infr_rcv_init, osm_infr_rcv_destroy +*********/ + +/****f* OpenSM: InformInfo Receiver/osm_infr_rcv_destroy +* NAME +* osm_infr_rcv_destroy +* +* DESCRIPTION +* The osm_infr_rcv_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_infr_rcv_destroy( + IN osm_infr_rcv_t* const p_rcv ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* InformInfo Receiver object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_infr_rcv_construct or osm_infr_rcv_init. +* +* SEE ALSO +* InformInfo Receiver object, osm_infr_rcv_construct, +* osm_infr_rcv_init +*********/ + +/****f* OpenSM: InformInfo Receiver/osm_infr_rcv_init +* NAME +* osm_infr_rcv_init +* +* DESCRIPTION +* The osm_infr_rcv_init function initializes a +* InformInfo Receiver object for use. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_infr_rcv_init( + IN osm_infr_rcv_t* const p_rcv, + IN osm_sa_resp_t* const p_resp, + IN osm_mad_pool_t* const p_mad_pool, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to an osm_infr_rcv_t object to initialize. +* +* p_subn +* [in] Pointer to the Subnet object for this subnet. +* +* p_log +* [in] Pointer to the log object. +* +* p_lock +* [in] Pointer to the OpenSM serializing lock. +* +* RETURN VALUES +* IB_SUCCESS if the InformInfo Receiver object was initialized +* successfully. +* +* NOTES +* Allows calling other InformInfo Receiver methods. +* +* SEE ALSO +* InformInfo Receiver object, osm_infr_rcv_construct, +* osm_infr_rcv_destroy +*********/ + +/****f* OpenSM: InformInfo Receiver/osm_infr_rcv_process +* NAME +* osm_infr_rcv_process +* +* DESCRIPTION +* Process the InformInfo request. +* +* SYNOPSIS +*/ +void +osm_infr_rcv_process( + IN osm_infr_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to an osm_infr_rcv_t object. +* +* p_madw +* [in] Pointer to the MAD Wrapper containing the MAD +* that contains the node's InformInfo attribute. +* NOTES +* This function processes a InformInfo attribute. +* +* SEE ALSO +* InformInfo Receiver +*********/ + +/****f* OpenSM: InformInfo Record Receiver/osm_infir_rcv_process +* NAME +* osm_infir_rcv_process +* +* DESCRIPTION +* Process the InformInfo Record request. +* +* SYNOPSIS +*/ +void +osm_infir_rcv_process( + IN osm_infr_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to an osm_infr_rcv_t object. +* +* p_madw +* [in] Pointer to the MAD Wrapper containing the MAD +* that contains the node's InformInfo Record attribute. +* NOTES +* This function processes a InformInfo Record attribute. +* +* SEE ALSO +* InformInfo Receiver +*********/ + +END_C_DECLS + +#endif /* _OSM_SA_INFR_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_informinfo_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_informinfo_ctrl.h new file mode 100644 index 00000000..42113cf9 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_informinfo_ctrl.h @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_informinfo_ctrl.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_infr_rcv_ctrl_t. + * This object represents a controller that receives the IBA InfromInfo + * Set method attribute from a node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.3 $ + */ + +#ifndef _OSM_INFR_RCV_CTRL_H_ +#define _OSM_INFR_RCV_CTRL_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/InformInfo Receive Controller +* NAME +* InformInfo Receive Controller +* +* DESCRIPTION +* The InformInfo Receive Controller object encapsulates +* the information needed to receive the InformInfo attribute from a node. +* +* The InformInfo Receive Controller object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Eitan Zahavi, Mellanox +* +*********/ + +/****s* OpenSM: InformInfo Receive Controller/osm_infr_rcv_ctrl_t +* NAME +* osm_infr_rcv_ctrl_t +* +* DESCRIPTION +* InformInfo Receive Controller structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_infr_rcv_ctrl +{ + osm_infr_rcv_t *p_rcv; + osm_log_t *p_log; + cl_dispatcher_t *p_disp; + cl_disp_reg_handle_t h_disp; + cl_disp_reg_handle_t h_disp2; +} osm_infr_rcv_ctrl_t; +/* +* FIELDS +* p_rcv +* Pointer to the InformInfo Receiver object. +* +* p_log +* Pointer to the log object. +* +* p_disp +* Pointer to the Dispatcher. +* +* h_disp +* Handle returned from dispatcher registration. +* +* SEE ALSO +* InformInfo Receive Controller object +* InformInfo Receiver object +*********/ + +/****f* OpenSM: InformInfo Receive Controller/osm_infr_rcv_ctrl_construct +* NAME +* osm_infr_rcv_ctrl_construct +* +* DESCRIPTION +* This function constructs a InformInfo Receive Controller object. +* +* SYNOPSIS +*/ +void osm_infr_rcv_ctrl_construct( + IN osm_infr_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a InformInfo Receive Controller +* object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_infr_rcv_ctrl_init, osm_infr_rcv_ctrl_destroy, +* and osm_infr_rcv_ctrl_is_inited. +* +* Calling osm_infr_rcv_ctrl_construct is a prerequisite to calling any +* other method except osm_infr_rcv_ctrl_init. +* +* SEE ALSO +* InformInfo Receive Controller object, osm_infr_rcv_ctrl_init, +* osm_infr_rcv_ctrl_destroy, osm_infr_rcv_ctrl_is_inited +*********/ + +/****f* OpenSM: InformInfo Receive Controller/osm_infr_rcv_ctrl_destroy +* NAME +* osm_infr_rcv_ctrl_destroy +* +* DESCRIPTION +* The osm_infr_rcv_ctrl_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_infr_rcv_ctrl_destroy( + IN osm_infr_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* InformInfo Receive Controller object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_infr_rcv_ctrl_construct or osm_infr_rcv_ctrl_init. +* +* SEE ALSO +* InformInfo Receive Controller object, osm_infr_rcv_ctrl_construct, +* osm_infr_rcv_ctrl_init +*********/ + +/****f* OpenSM: InformInfo Receive Controller/osm_infr_rcv_ctrl_init +* NAME +* osm_infr_rcv_ctrl_init +* +* DESCRIPTION +* The osm_infr_rcv_ctrl_init function initializes a +* InformInfo Receive Controller object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_infr_rcv_ctrl_init( + IN osm_infr_rcv_ctrl_t* const p_ctrl, + IN osm_infr_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_infr_rcv_ctrl_t object to initialize. +* +* p_rcv +* [in] Pointer to an osm_infr_rcv_t object. +* +* p_log +* [in] Pointer to the log object. +* +* p_disp +* [in] Pointer to the OpenSM central Dispatcher. +* +* RETURN VALUES +* CL_SUCCESS if the InformInfo Receive Controller object was initialized +* successfully. +* +* NOTES +* Allows calling other InformInfo Receive Controller methods. +* +* SEE ALSO +* InformInfo Receive Controller object, osm_infr_rcv_ctrl_construct, +* osm_infr_rcv_ctrl_destroy, osm_infr_rcv_ctrl_is_inited +*********/ + +/****f* OpenSM: InformInfo Receive Controller/osm_infr_rcv_ctrl_is_inited +* NAME +* osm_infr_rcv_ctrl_is_inited +* +* DESCRIPTION +* Indicates if the object has been initialized with osm_infr_rcv_ctrl_init. +* +* SYNOPSIS +*/ +boolean_t osm_infr_rcv_ctrl_is_inited( + IN const osm_infr_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_infr_rcv_ctrl_t object. +* +* RETURN VALUES +* TRUE if the object was initialized successfully, +* FALSE otherwise. +* +* NOTES +* The osm_infr_rcv_ctrl_construct or osm_infr_rcv_ctrl_init must be +* called before using this function. +* +* SEE ALSO +* InformInfo Receive Controller object, osm_infr_rcv_ctrl_construct, +* osm_infr_rcv_ctrl_init +*********/ + +END_C_DECLS + +#endif /* _OSM_INFR_RCV_CTRL_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_lft_record.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_lft_record.h new file mode 100644 index 00000000..514e5c8e --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_lft_record.h @@ -0,0 +1,281 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_lft_record.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_lftr_rcv_t. + * This object represents the LinearForwardingTable Receiver object. + * attribute from a switch node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_LFTR_H_ +#define _OSM_LFTR_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Linear Forwarding Table Receiver +* NAME +* Linear Forwarding Table Receiver +* +* DESCRIPTION +* The Linear Forwarding Table Receiver object encapsulates the information +* needed to receive the LinearForwardingTable attribute from a switch node. +* +* The Linear Forwarding Table Receiver object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Eitan Zahavi, Mellanox Technologies LTD +* +*********/ + +/****s* OpenSM: Linear Forwarding Table Receiver/osm_lftr_rcv_t +* NAME +* osm_lftr_rcv_t +* +* DESCRIPTION +* Linear Forwarding Table Receiver structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_lft +{ + osm_subn_t* p_subn; + osm_stats_t* p_stats; + osm_sa_resp_t* p_resp; + osm_mad_pool_t* p_mad_pool; + osm_log_t* p_log; + cl_plock_t* p_lock; + cl_qlock_pool_t pool; +} osm_lftr_rcv_t; +/* +* FIELDS +* p_subn +* Pointer to the Subnet object for this subnet. +* +* p_stats +* Pointer to the statistics. +* +* p_resp +* Pointer to the SA responder. +* +* p_mad_pool +* Pointer to the mad pool. +* +* p_log +* Pointer to the log object. +* +* p_lock +* Pointer to the serializing lock. +* +* pool +* Pool of linkable Linear Forwarding Table Record objects used to +* generate the query response. +* +* SEE ALSO +* Linear Forwarding Table Receiver object +*********/ + +/****f* OpenSM: Linear Forwarding Table Receiver/osm_lftr_rcv_construct +* NAME +* osm_lftr_rcv_construct +* +* DESCRIPTION +* This function constructs a Linear Forwarding Table Receiver object. +* +* SYNOPSIS +*/ +void osm_lftr_rcv_construct( + IN osm_lftr_rcv_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a Linear Forwarding Table Receiver object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_lftr_rcv_init, osm_lftr_rcv_destroy +* +* Calling osm_lftr_rcv_construct is a prerequisite to calling any other +* method except osm_lftr_rcv_init. +* +* SEE ALSO +* Linear Forwarding Table Receiver object, osm_lftr_rcv_init, +* osm_lftr_rcv_destroy +*********/ + +/****f* OpenSM: Linear Forwarding Table Receiver/osm_lftr_rcv_destroy +* NAME +* osm_lftr_rcv_destroy +* +* DESCRIPTION +* The osm_lftr_rcv_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_lftr_rcv_destroy( + IN osm_lftr_rcv_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* Linear Forwarding Table Receiver object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_lftr_rcv_construct or osm_lftr_rcv_init. +* +* SEE ALSO +* Linear Forwarding Table Receiver object, osm_lftr_rcv_construct, +* osm_lftr_rcv_init +*********/ + +/****f* OpenSM: Linear Forwarding Table Receiver/osm_lftr_rcv_init +* NAME +* osm_lftr_rcv_init +* +* DESCRIPTION +* The osm_lftr_rcv_init function initializes a +* Linear Forwarding Table Receiver object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_lftr_rcv_init( + IN osm_lftr_rcv_t* const p_rcv, + IN osm_sa_resp_t* const p_resp, + IN osm_mad_pool_t* const p_mad_pool, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to an osm_lftr_rcv_t object to initialize. +* +* p_req +* [in] Pointer to an osm_req_t object. +* +* p_subn +* [in] Pointer to the Subnet object for this subnet. +* +* p_log +* [in] Pointer to the log object. +* +* p_lock +* [in] Pointer to the OpenSM serializing lock. +* +* RETURN VALUES +* CL_SUCCESS if the Linear Forwarding Table Receiver object was initialized +* successfully. +* +* NOTES +* Allows calling other Linear Forwarding Table Receiver methods. +* +* SEE ALSO +* Linear Forwarding Table Receiver object, osm_lftr_rcv_construct, +* osm_lftr_rcv_destroy +*********/ + +/****f* OpenSM: Linear Forwarding Table Receiver/osm_lftr_rcv_process +* NAME +* osm_lftr_rcv_process +* +* DESCRIPTION +* Process the LinearForwardingTable attribute. +* +* SYNOPSIS +*/ +void osm_lftr_rcv_process( + IN osm_lftr_rcv_t* const p_ctrl, + IN const osm_madw_t* const p_madw ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_lftr_rcv_t object. +* +* p_madw +* [in] Pointer to the MAD Wrapper containing the MAD +* that contains the switch node's LinearForwardingTable attribute. +* +* RETURN VALUES +* CL_SUCCESS if the LinearForwardingTable processing was successful. +* +* NOTES +* This function processes a LinearForwardingTable attribute. +* +* SEE ALSO +* Linear Forwarding Table Receiver, Linear Forwarding Table Response +* Controller +*********/ + +END_C_DECLS + +#endif /* _OSM_LFTR_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_lft_record_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_lft_record_ctrl.h new file mode 100644 index 00000000..ca6b98dd --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_lft_record_ctrl.h @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_lft_record_ctrl.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_lftr_rcv_ctrl_t. + * This object represents a controller that receives the IBA + * LinearForwardingTable attribute from a switch. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_LFTR_RCV_CTRL_H_ +#define _OSM_LFTR_RCV_CTRL_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Linear Forwarding Table Receive Controller +* NAME +* Linear Forwarding Table Record Receive Controller +* +* DESCRIPTION +* The Linear Forwarding Table Receive Controller object encapsulates +* the information needed to receive the LinearFowardingTable attribute +* from a switch node. +* +* The Linear Forwarding Table Receive Controller object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Eitan Zahavi, Mellanox Technologies LTD +* +*********/ + +/****s* OpenSM: Linear Forwarding Table Receive Controller/osm_lftr_rcv_ctrl_t +* NAME +* osm_lftr_rcv_ctrl_t +* +* DESCRIPTION +* Linear Forwarding Table Receive Controller structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_lftr_rcv_ctrl +{ + osm_lftr_rcv_t *p_rcv; + osm_log_t *p_log; + cl_dispatcher_t *p_disp; + cl_disp_reg_handle_t h_disp; + +} osm_lftr_rcv_ctrl_t; +/* +* FIELDS +* p_rcv +* Pointer to the Linear Forwarding Table Receiver object. +* +* p_log +* Pointer to the log object. +* +* p_disp +* Pointer to the Dispatcher. +* +* h_disp +* Handle returned from dispatcher registration. +* +* SEE ALSO +* Linear Forwarding Table Receive Controller object +* Linear Forwarding Table Receiver object +*********/ + +/****f* OpenSM: Linear Forwarding Table Receive Controller/osm_lftr_rcv_ctrl_construct +* NAME +* osm_lftr_rcv_ctrl_construct +* +* DESCRIPTION +* This function constructs a Linear Forwarding Table Receive +* Controller object. +* +* SYNOPSIS +*/ +void osm_lftr_rcv_ctrl_construct( + IN osm_lftr_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a Linear Forwarding Table Receive Controller +* object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_lftr_rcv_ctrl_init, osm_lftr_rcv_ctrl_destroy +* +* Calling osm_lftr_rcv_ctrl_construct is a prerequisite to calling any other +* method except osm_lftr_rcv_ctrl_init. +* +* SEE ALSO +* Linear Forwarding Table Receive Controller object, osm_lftr_rcv_ctrl_init, +* osm_lftr_rcv_ctrl_destroy +*********/ + +/****f* OpenSM: Linear Forwarding Table Receive Controller/osm_lftr_rcv_ctrl_destroy +* NAME +* osm_lftr_rcv_ctrl_destroy +* +* DESCRIPTION +* The osm_lftr_rcv_ctrl_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_lftr_rcv_ctrl_destroy( + IN osm_lftr_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* Linear Forwarding Table Receive Controller object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_lftr_rcv_ctrl_construct or osm_lftr_rcv_ctrl_init. +* +* SEE ALSO +* Linear Forwarding Table Receive Controller object, osm_lftr_rcv_ctrl_construct, +* osm_lftr_rcv_ctrl_init +*********/ + +/****f* OpenSM: Linear Forwarding Table Receive Controller/osm_lftr_rcv_ctrl_init +* NAME +* osm_lftr_rcv_ctrl_init +* +* DESCRIPTION +* The osm_lftr_rcv_ctrl_init function initializes a +* Linear Forwarding Table Receive Controller object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_lftr_rcv_ctrl_init( + IN osm_lftr_rcv_ctrl_t* const p_ctrl, + IN osm_lftr_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_lftr_rcv_ctrl_t object to initialize. +* +* p_rcv +* [in] Pointer to an osm_lftr_t object. +* +* p_log +* [in] Pointer to the log object. +* +* p_disp +* [in] Pointer to the OpenSM central Dispatcher. +* +* RETURN VALUES +* CL_SUCCESS if the Linear Forwarding Table Receive Controller object +* was initialized successfully. +* +* NOTES +* Allows calling other Linear Forwarding Table Receive Controller methods. +* +* SEE ALSO +* Linear Forwarding Table Receive Controller object, +* osm_lftr_rcv_ctrl_construct, osm_lftr_rcv_ctrl_destroy +*********/ + +END_C_DECLS + +#endif /* _OSM_LFTR_RCV_CTRL_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_link_record.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_link_record.h new file mode 100644 index 00000000..fbab6e3e --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_link_record.h @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_link_record.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_lr_rcv_t. + * This object represents the Link Record Receiver object. + * attribute from a node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_LR_RCV_H_ +#define _OSM_LR_RCV_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Link Record Receiver +* NAME +* Link Record Receiver +* +* DESCRIPTION +* The Link Record Receiver object encapsulates the information +* needed to receive the Link Record attribute from a node. +* +* The Link Record Receiver object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Ranjit Pandit, Intel +* +*********/ + +/****s* OpenSM: Link Record Receiver/osm_lr_rcv_t +* NAME +* osm_lr_rcv_t +* +* DESCRIPTION +* Link Record Receiver structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_lr_rcv +{ + osm_subn_t *p_subn; + osm_sa_resp_t *p_resp; + osm_mad_pool_t *p_mad_pool; + osm_log_t *p_log; + cl_plock_t *p_lock; + cl_qlock_pool_t lr_pool; + +} osm_lr_rcv_t; +/* +* FIELDS +* p_subn +* Pointer to the Subnet object for this subnet. +* +* p_resp +* Pointer to the SA responder. +* +* p_mad_pool +* Pointer to the mad pool. +* +* p_log +* Pointer to the log object. +* +* p_lock +* Pointer to the serializing lock. +* +* lr_pool +* Pool of link record objects used to generate the query response. +* +* SEE ALSO +*********/ + +/****f* OpenSM: Link Record Receiver/osm_lr_rcv_construct +* NAME +* osm_lr_rcv_construct +* +* DESCRIPTION +* This function constructs a Link Record Receiver object. +* +* SYNOPSIS +*/ +void +osm_lr_rcv_construct( + IN osm_lr_rcv_t* const p_rcv ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to a Link Record Receiver object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_lr_rcv_init, osm_lr_rcv_destroy +* +* Calling osm_lr_rcv_construct is a prerequisite to calling any other +* method except osm_lr_rcv_init. +* +* SEE ALSO +* Link Record Receiver object, osm_lr_rcv_init, osm_lr_rcv_destroy +*********/ + +/****f* OpenSM: Link Record Receiver/osm_lr_rcv_destroy +* NAME +* osm_lr_rcv_destroy +* +* DESCRIPTION +* The osm_lr_rcv_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_lr_rcv_destroy( + IN osm_lr_rcv_t* const p_rcv ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* Link Record Receiver object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_lr_rcv_construct or osm_lr_rcv_init. +* +* SEE ALSO +* Link Record Receiver object, osm_lr_rcv_construct, +* osm_lr_rcv_init +*********/ + +/****f* OpenSM: Link Record Receiver/osm_lr_rcv_init +* NAME +* osm_lr_rcv_init +* +* DESCRIPTION +* The osm_lr_rcv_init function initializes a +* Link Record Receiver object for use. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_lr_rcv_init( + IN osm_lr_rcv_t* const p_rcv, + IN osm_sa_resp_t* const p_resp, + IN osm_mad_pool_t* const p_mad_pool, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to an osm_lr_rcv_t object to initialize. +* +* p_resp +* [in] Pointer to the SA Responder object. +* +* p_mad_pool +* [in] Pointer to the mad pool. +* +* p_subn +* [in] Pointer to the Subnet object for this subnet. +* +* p_log +* [in] Pointer to the log object. +* +* p_lock +* [in] Pointer to the OpenSM serializing lock. +* +* RETURN VALUES +* IB_SUCCESS if the Link Record Receiver object was initialized +* successfully. +* +* NOTES +* Allows calling other Link Record Receiver methods. +* +* SEE ALSO +* Link Record Receiver object, osm_lr_rcv_construct, osm_lr_rcv_destroy +*********/ + +/****f* OpenSM: Link Record Receiver/osm_lr_rcv_process +* NAME +* osm_lr_rcv_process +* +* DESCRIPTION +* Process the Link Record attribute. +* +* SYNOPSIS +*/ +void osm_lr_rcv_process( + IN osm_lr_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to an osm_lr_rcv_t object. +* +* p_madw +* [in] Pointer to the MAD Wrapper containing the MAD +* that contains the node's Link Record attribute. +* +* NOTES +* This function processes a Link Record attribute. +* +* SEE ALSO +* Link Record Receiver, Link Record Response Controller +*********/ + +END_C_DECLS + +#endif /* _OSM_LR_RCV_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_link_record_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_link_record_ctrl.h new file mode 100644 index 00000000..d4a740a8 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_link_record_ctrl.h @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_link_record_ctrl.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_lr_rcv_ctrl_t. + * This object represents a controller that receives the IBA Link Record + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_LR_CTRL_H_ +#define _OSM_LR_CTRL_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Link Record Receive Controller +* NAME +* Link Record Receive Controller +* +* DESCRIPTION +* The Link Record Receive Controller object encapsulates +* the information needed to receive the LinkRecord attribute from a node. +* +* The Link Record Receive Controller object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Ranjit Pandit, Intel +* +*********/ + +/****s* OpenSM: Link Record Receive Controller/osm_lr_rcv_ctrl_t +* NAME +* osm_lr_rcv_ctrl_t +* +* DESCRIPTION +* Link Record Receive Controller structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_lr_rcv_ctrl +{ + osm_lr_rcv_t *p_rcv; + osm_log_t *p_log; + cl_dispatcher_t *p_disp; + cl_disp_reg_handle_t h_disp; + +} osm_lr_rcv_ctrl_t; +/* +* FIELDS +* p_rcv +* Pointer to the Link Record Receiver object. +* +* p_log +* Pointer to the log object. +* +* p_disp +* Pointer to the Dispatcher. +* +* h_disp +* Handle returned from dispatcher registration. +* +* SEE ALSO +* Link Record Receive Controller object +* Link Record Receiver object +*********/ + +/****f* OpenSM: Link Record Receive Controller/osm_lr_rcv_ctrl_construct +* NAME +* osm_lr_rcv_ctrl_construct +* +* DESCRIPTION +* This function constructs a Link Record Receive Controller object. +* +* SYNOPSIS +*/ +void osm_lr_rcv_ctrl_construct( + IN osm_lr_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a Link Record Receive Controller +* object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_lr_rcv_ctrl_init, osm_lr_rcv_ctrl_destroy, +* and osm_lr_rcv_ctrl_is_inited. +* +* Calling osm_lr_rcv_ctrl_construct is a prerequisite to calling any other +* method except osm_lr_rcv_ctrl_init. +* +* SEE ALSO +* Link Record Receive Controller object, osm_lr_rcv_ctrl_init, +* osm_lr_rcv_ctrl_destroy, osm_lr_rcv_ctrl_is_inited +*********/ + +/****f* OpenSM: Link Record Receive Controller/osm_lr_rcv_ctrl_destroy +* NAME +* osm_lr_rcv_ctrl_destroy +* +* DESCRIPTION +* The osm_lr_rcv_ctrl_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_lr_rcv_ctrl_destroy( + IN osm_lr_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* Link Record Receive Controller object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_lr_rcv_ctrl_construct or osm_lr_rcv_ctrl_init. +* +* SEE ALSO +* Link Record Receive Controller object, osm_lr_rcv_ctrl_construct, +* osm_lr_rcv_ctrl_init +*********/ + +/****f* OpenSM: Link Record Receive Controller/osm_lr_rcv_ctrl_init +* NAME +* osm_lr_rcv_ctrl_init +* +* DESCRIPTION +* The osm_lr_rcv_ctrl_init function initializes a +* Link Record Receive Controller object for use. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_lr_rcv_ctrl_init( + IN osm_lr_rcv_ctrl_t* const p_ctrl, + IN osm_lr_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_lr_rcv_ctrl_t object to initialize. +* +* p_rcv +* [in] Pointer to an osm_lr_t object. +* +* p_log +* [in] Pointer to the log object. +* +* p_disp +* [in] Pointer to the OpenSM central Dispatcher. +* +* RETURN VALUES +* CL_SUCCESS if the Link Record Receive Controller object was initialized +* successfully. +* +* NOTES +* Allows calling other Link Record Receive Controller methods. +* +* SEE ALSO +* Link Record Receive Controller object, osm_lr_rcv_ctrl_construct, +* osm_lr_rcv_ctrl_destroy, osm_lr_rcv_ctrl_is_inited +*********/ + +/****f* OpenSM: Link Record Receive Controller/osm_lr_rcv_ctrl_is_inited +* NAME +* osm_lr_rcv_ctrl_is_inited +* +* DESCRIPTION +* Indicates if the object has been initialized with osm_lr_rcv_ctrl_init. +* +* SYNOPSIS +*/ +boolean_t osm_lr_rcv_ctrl_is_inited( + IN const osm_lr_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_lr_rcv_ctrl_t object. +* +* RETURN VALUES +* TRUE if the object was initialized successfully, +* FALSE otherwise. +* +* NOTES +* The osm_lr_rcv_ctrl_construct or osm_lr_rcv_ctrl_init must be +* called before using this function. +* +* SEE ALSO +* Link Record Receive Controller object, osm_lr_rcv_ctrl_construct, +* osm_lr_rcv_ctrl_init +*********/ + +END_C_DECLS + +#endif /* _OSM_LR_CTRL_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_mad_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_mad_ctrl.h new file mode 100644 index 00000000..085eab7d --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_mad_ctrl.h @@ -0,0 +1,352 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_mad_ctrl.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_sa_mad_ctrl_t. + * This object represents a controller that receives the IBA SA + * attributes from a node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_SA_MAD_CTRL_H_ +#define _OSM_SA_MAD_CTRL_H_ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/SA MAD Controller +* NAME +* SA MAD Controller +* +* DESCRIPTION +* The SA MAD Controller object encapsulates +* the information needed to receive MADs from the transport layer. +* +* The SA MAD Controller object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Ranjit Pandit, Intel +* +*********/ + +/****s* OpenSM: SA MAD Controller/osm_sa_mad_ctrl_t +* NAME +* osm_sa_mad_ctrl_t +* +* DESCRIPTION +* SA MAD Controller structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_sa_mad_ctrl +{ + osm_log_t *p_log; + osm_mad_pool_t *p_mad_pool; + osm_vendor_t *p_vendor; + osm_bind_handle_t h_bind; + cl_dispatcher_t *p_disp; + cl_disp_reg_handle_t h_disp; + osm_stats_t *p_stats; + osm_subn_t *p_subn; + osm_sa_resp_t *p_resp; +} osm_sa_mad_ctrl_t; +/* +* FIELDS +* p_log +* Pointer to the log object. +* +* p_mad_pool +* Pointer to the MAD pool. +* +* p_vendor +* Pointer to the vendor specific interfaces object. +* +* h_bind +* Bind handle returned by the transport layer. +* +* p_disp +* Pointer to the Dispatcher. +* +* h_disp +* Handle returned from dispatcher registration. +* +* p_stats +* Pointer to the OpenSM statistics block. +* +* p_resp +* Pointer to the SA response manager +* +* SEE ALSO +* SA MAD Controller object +* SA MADr object +*********/ + +/****f* OpenSM: SA MAD Controller/osm_sa_mad_ctrl_construct +* NAME +* osm_sa_mad_ctrl_construct +* +* DESCRIPTION +* This function constructs a SA MAD Controller object. +* +* SYNOPSIS +*/ +void osm_sa_mad_ctrl_construct( + IN osm_sa_mad_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a SA MAD Controller +* object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_sa_mad_ctrl_init, and osm_sa_mad_ctrl_destroy. +* +* Calling osm_sa_mad_ctrl_construct is a prerequisite to calling any other +* method except osm_sa_mad_ctrl_init. +* +* SEE ALSO +* SA MAD Controller object, osm_sa_mad_ctrl_init, +* osm_sa_mad_ctrl_destroy +*********/ + +/****f* OpenSM: SA MAD Controller/osm_sa_mad_ctrl_destroy +* NAME +* osm_sa_mad_ctrl_destroy +* +* DESCRIPTION +* The osm_sa_mad_ctrl_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_sa_mad_ctrl_destroy( + IN osm_sa_mad_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* SA MAD Controller object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_sa_mad_ctrl_construct or osm_sa_mad_ctrl_init. +* +* SEE ALSO +* SA MAD Controller object, osm_sa_mad_ctrl_construct, +* osm_sa_mad_ctrl_init +*********/ + +/****f* OpenSM: SA MAD Controller/osm_sa_mad_ctrl_init +* NAME +* osm_sa_mad_ctrl_init +* +* DESCRIPTION +* The osm_sa_mad_ctrl_init function initializes a +* SA MAD Controller object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_sa_mad_ctrl_init( + IN osm_sa_mad_ctrl_t* const p_ctrl, + IN osm_sa_resp_t* const p_resp, + IN osm_mad_pool_t* const p_mad_pool, + IN osm_vendor_t* const p_vendor, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN osm_stats_t* const p_stats, + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_sa_mad_ctrl_t object to initialize. +* +* p_resp +* [in] Pointer to the response SA manager object +* +* p_mad_pool +* [in] Pointer to the MAD pool. +* +* p_vendor +* [in] Pointer to the vendor specific interfaces object. +* +* p_log +* [in] Pointer to the log object. +* +* p_stats +* [in] Pointer to the OpenSM stastics block. +* +* p_disp +* [in] Pointer to the OpenSM central Dispatcher. +* +* RETURN VALUES +* IB_SUCCESS if the SA MAD Controller object was initialized +* successfully. +* +* NOTES +* Allows calling other SA MAD Controller methods. +* +* SEE ALSO +* SA MAD Controller object, osm_sa_mad_ctrl_construct, +* osm_sa_mad_ctrl_destroy +*********/ + +/****f* OpenSM: SA/osm_sa_mad_ctrl_bind +* NAME +* osm_sa_mad_ctrl_bind +* +* DESCRIPTION +* Binds the SA MAD Controller object to a port guid. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_sa_mad_ctrl_bind( + IN osm_sa_mad_ctrl_t* const p_ctrl, + IN const ib_net64_t port_guid ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_sa_mad_ctrl_t object to initialize. +* +* port_guid +* [in] Local port GUID with which to bind. +* +* +* RETURN VALUES +* None +* +* NOTES +* A given SA MAD Controller object can only be bound to one +* port at a time. +* +* SEE ALSO +*********/ + +/****f* OpenSM: SA/osm_sa_mad_ctrl_unbind +* NAME +* osm_sa_mad_ctrl_unbind +* +* DESCRIPTION +* Un-Binds the SA MAD Controller object from the IB port +* +* SYNOPSIS +*/ +ib_api_status_t +osm_sa_mad_ctrl_unbind( + IN osm_sa_mad_ctrl_t* const p_ctrl); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_sa_mad_ctrl_t object to initialize. +* +* RETURN VALUES +* None +* +* NOTES +* A given SA MAD Controller should be previously bound to IB +* port. +* +* SEE ALSO +*********/ + +/****f* OpenSM: SA/osm_sa_mad_ctrl_get_bind_handle +* NAME +* osm_sa_mad_ctrl_get_bind_handle +* +* DESCRIPTION +* Returns the bind handle. +* +* SYNOPSIS +*/ +static inline osm_bind_handle_t +osm_sa_mad_ctrl_get_bind_handle( + IN const osm_sa_mad_ctrl_t* const p_ctrl ) +{ + return( p_ctrl->h_bind ); +} +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_sa_mad_ctrl_t object. +* +* RETURN VALUES +* Returns the bind handle, which may be OSM_BIND_INVALID_HANDLE +* if no port has been bound. +* +* NOTES +* A given SA MAD Controller object can only be bound to one +* port at a time. +* +* SEE ALSO +*********/ + +END_C_DECLS + +#endif /* _OSM_SA_MAD_CTRL_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_mcmember_record.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_mcmember_record.h new file mode 100644 index 00000000..0ee1f28e --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_mcmember_record.h @@ -0,0 +1,420 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_mcmember_record.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_mcmr_recv_t. + * This object represents the MCMemberRecord Receiver object. + * attribute from a node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.7 $ + */ + +#ifndef _OSM_MCMR_H_ +#define _OSM_MCMR_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/MCMember Receiver +* NAME +* MCMember Receiver +* +* DESCRIPTION +* The MCMember Receiver object encapsulates the information +* needed to receive the MCMemberRecord attribute from a node. +* +* The MCMember Receiver object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Anil Keshavamurthy, Intel +* +*********/ + +/****s* OpenSM: MCMember Receiver/osm_mcmr_recv_t +* NAME +* osm_mcmr_recv_t +* +* DESCRIPTION +* MCMember Receiver structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ + + +typedef struct _osm_mcmr +{ + osm_subn_t *p_subn; + osm_sm_t *p_sm; + osm_sa_resp_t *p_resp; + osm_mad_pool_t *p_mad_pool; + osm_log_t *p_log; + cl_plock_t *p_lock; + uint16_t mlid_ho; + cl_qlock_pool_t pool; +} osm_mcmr_recv_t; + + +/* +* FIELDS +* p_subn +* Pointer to the Subnet object for this subnet. +* +* p_gen_req_ctrl +* Pointer to the generic request controller. +* +* p_log +* Pointer to the log object. +* +* p_lock +* Pointer to the serializing lock. +* +* SEE ALSO +* MCMember Receiver object +*********/ + +/****f* OpenSM: MCMember Receiver/osm_mcmr_rcv_construct +* NAME +* osm_mcmr_rcv_construct +* +* DESCRIPTION +* This function constructs a MCMember Receiver object. +* +* SYNOPSIS +*/ +void osm_mcmr_rcv_construct( + IN osm_mcmr_recv_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a MCMember Receiver object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_mcmr_rcv_init, osm_mcmr_rcv_destroy +* +* Calling osm_mcmr_rcv_construct is a prerequisite to calling any other +* method except osm_mcmr_init. +* +* SEE ALSO +* MCMember Receiver object, osm_mcmr_init, +* osm_mcmr_rcv_destroy +*********/ + +/****f* OpenSM: MCMember Receiver/osm_mcmr_rcv_destroy +* NAME +* osm_mcmr_rcv_destroy +* +* DESCRIPTION +* The osm_mcmr_rcv_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_mcmr_rcv_destroy( + IN osm_mcmr_recv_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* MCMember Receiver object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_mcmr_rcv_construct or osm_mcmr_init. +* +* SEE ALSO +* MCMember Receiver object, osm_mcmr_rcv_construct, +* osm_mcmr_init +*********/ + +/****f* OpenSM: MCMember Receiver/osm_mcmr_rcv_init +* NAME +* osm_mcmr_init +* +* DESCRIPTION +* The osm_mcmr_init function initializes a +* MCMember Receiver object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_mcmr_rcv_init( + IN osm_sm_t * const p_sm, + IN osm_mcmr_recv_t* const p_ctrl, + IN osm_sa_resp_t* const p_resp, + IN osm_mad_pool_t* const p_mad_pool, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ); +/* +* PARAMETERS +* p_sm +* [in] pointer to osm_sm_t object +* p_ctrl +* [in] Pointer to an osm_mcmr_recv_t object to initialize. +* +* p_req +* [in] Pointer to an osm_req_t object. +* +* p_subn +* [in] Pointer to the Subnet object for this subnet. +* +* p_log +* [in] Pointer to the log object. +* +* p_lock +* [in] Pointer to the OpenSM serializing lock. +* +* RETURN VALUES +* CL_SUCCESS if the MCMember Receiver object was initialized +* successfully. +* +* NOTES +* Allows calling other MCMember Receiver methods. +* +* SEE ALSO +* MCMember Receiver object, osm_mcmr_rcv_construct, +* osm_mcmr_rcv_destroy +*********/ + +/****f* OpenSM: MCMember Receiver/osm_mcmr_rcv_process +* NAME +* osm_mcmr_rcv_process +* +* DESCRIPTION +* Process the MCMemberRecord attribute. +* +* SYNOPSIS +*/ +void osm_mcmr_rcv_process( + IN osm_mcmr_recv_t* const p_ctrl, + IN const osm_madw_t* const p_madw ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_mcmr_recv_t object. +* +* p_madw +* [in] Pointer to the MAD Wrapper containing the MAD +* that contains the node's MCMemberRecord attribute. +* +* RETURN VALUES +* CL_SUCCESS if the MCMemberRecord processing was successful. +* +* NOTES +* This function processes a MCMemberRecord attribute. +* +* SEE ALSO +* MCMember Receiver, MCMember Response Controller +*********/ + + + +/****f* OpenSM: MC Member Record Receiver/osm_mcmr_rcv_create_new_mgrp +* NAME +* osm_mcmr_rcv_create_new_mgrp +* +* DESCRIPTION +* Create new Multicast group +* +* SYNOPSIS +*/ + +ib_api_status_t +osm_mcmr_rcv_create_new_mgrp( + IN osm_mcmr_recv_t* const p_mcmr, + IN uint64_t comp_mask, + IN const ib_member_rec_t* const p_recvd_mcmember_rec, + IN const osm_physp_t* const p_req_physp, + OUT osm_mgrp_t **pp_mgrp); +/* +* PARAMETERS +* p_mcmr +* [in] Pointer to an osm_mcmr_recv_t object. +* p_recvd_mcmember_rec +* [in] Received Multicast member record +* +* p_req_physp +* [in] The requesting osm_physp_t object. +* NULL if the creation is without a requesting port (e.g - ipoib known mcgroups) +* +* pp_mgrp +* [out] pointer the osm_mgrp_t object +* +* RETURN VALUES +* IB_SUCCESS, IB_ERROR +* +* NOTES +* +* +* SEE ALSO +* +*********/ + +/****f* OpenSM: MC Member Record Receiver/osm_mcmr_rcv_find_or_create_new_mgrp +* NAME +* osm_mcmr_rcv_find_or_create_new_mgrp +* +* DESCRIPTION +* Create new Multicast group +* +* SYNOPSIS +*/ + +ib_api_status_t +osm_mcmr_rcv_find_or_create_new_mgrp( + IN osm_mcmr_recv_t* const p_mcmr, + IN uint64_t comp_mask, + IN ib_member_rec_t* const p_recvd_mcmember_rec, + OUT osm_mgrp_t **pp_mgrp); +/* +* PARAMETERS +* p_mcmr +* [in] Pointer to an osm_mcmr_recv_t object. +* p_recvd_mcmember_rec +* [in] Received Multicast member record +* +* pp_mgrp +* [out] pointer the osm_mgrp_t object +* +* RETURN VALUES +* IB_SUCCESS, IB_ERROR +* +* NOTES +* +* +* SEE ALSO +* +*********/ + +#define JOIN_MC_COMP_MASK (IB_MCR_COMPMASK_MGID | \ + IB_MCR_COMPMASK_PORT_GID | \ + IB_MCR_COMPMASK_JOIN_STATE) + +#define REQUIRED_MC_CREATE_COMP_MASK (IB_MCR_COMPMASK_MGID | \ + IB_MCR_COMPMASK_PORT_GID | \ + IB_MCR_COMPMASK_JOIN_STATE | \ + IB_MCR_COMPMASK_QKEY | \ + IB_MCR_COMPMASK_TCLASS | \ + IB_MCR_COMPMASK_PKEY | \ + IB_MCR_COMPMASK_FLOW | \ + IB_MCR_COMPMASK_SL) + +/****d* OpenSM: MC Member Record Receiver/OSM_DEFAULT_MGRP_MTU +* Name +* OSM_DEFAULT_MGRP_MTU +* +* DESCRIPTION +* Default MTU used for new MGRP creation (2048 bytes) +* Note it includes the MTUSelector which is set to "Greater Than" +* +* SYNOPSIS +*/ +#define OSM_DEFAULT_MGRP_MTU 0x04 +/***********/ + +/****d* OpenSM: MC Member Record Receiver/OSM_DEFAULT_MGRP_RATE +* Name +* OSM_DEFAULT_MGRP_RATE +* +* DESCRIPTION +* Default RATE used for new MGRP creation (10Gb/sec) +* Note it includes the RateSelector which is set to "Greater Than" +* +* SYNOPSIS +*/ +#define OSM_DEFAULT_MGRP_RATE 0x03 +/***********/ + +/* Scope component definitions from IBA 1.2 (Table 3 p. 146) */ +#define MC_SCOPE_LINK_LOCAL 0x2 +#define MC_SCOPE_SITE_LOCAL 0x5 +#define MC_SCOPE_ORG_LOCAL 0x8 +#define MC_SCOPE_GLOBAL 0xE + +/****d* OpenSM: MC Member Record Receiver/OSM_DEFAULT_MGRP_SCOPE +* Name +* OSM_DEFAULT_MGRP_SCOPE +* +* DESCRIPTION +* Default SCOPE used for new MGRP creation (link local) +* +* SYNOPSIS +*/ +#define OSM_DEFAULT_MGRP_SCOPE MC_SCOPE_LINK_LOCAL +/***********/ + +/* JoinState definitions from IBA 1.2 */ +#define MC_FULL_MEMBER 0x1 +#define MC_NON_MEMBER 0x2 +#define MC_SENDONLY_NON_MEMBER 0x4 + +END_C_DECLS + +#endif /* _OSM_MCMR_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_mcmember_record_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_mcmember_record_ctrl.h new file mode 100644 index 00000000..3adc02d9 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_mcmember_record_ctrl.h @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_mcmember_record_ctrl.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_mcmr_rcv_ctrl_t. + * This object represents a controller that receives the IBA MCMemberRecord + * attribute from a node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + + +#ifndef _OSM_MCMRCTRL_H +#define _OSM_MCMRCTRL_H + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/MCMember Receive Controller +* NAME +* MCMember Receive Controller +* +* DESCRIPTION +* The MCMember Receive Controller object encapsulates +* the information needed to receive the MCMemberRecord attribute from a node. +* +* The MCMember Receive Controller object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Ranjit Pandit, Intel +* +*********/ + +/****s* OpenSM: MCMember Receive Controller/osm_mcmr_rcv_ctrl_t +* NAME +* osm_mcmr_rcv_ctrl_t +* +* DESCRIPTION +* MCMember Receive Controller structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_mcmr_rcv_ctrl +{ + osm_mcmr_recv_t *p_rcv; + osm_log_t *p_log; + cl_dispatcher_t *p_disp; + cl_disp_reg_handle_t h_disp; + +} osm_mcmr_rcv_ctrl_t; +/* +* FIELDS +* p_rcv +* Pointer to the MCMember Receiver object. +* +* p_log +* Pointer to the log object. +* +* p_disp +* Pointer to the Dispatcher. +* +* h_disp +* Handle returned from dispatcher registration. +* +* SEE ALSO +* MCMember Receive Controller object +* MCMember Receiver object +*********/ + +/****f* OpenSM: MCMember Receive Controller/osm_mcmr_rcv_ctrl_construct +* NAME +* osm_mcmr_rcv_ctrl_construct +* +* DESCRIPTION +* This function constructs a MCMember Receive Controller object. +* +* SYNOPSIS +*/ +void osm_mcmr_rcv_ctrl_construct( + IN osm_mcmr_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a MCMember Receive Controller +* object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_mcmr_rcv_ctrl_init, osm_mcmr_rcv_ctrl_destroy, +* and osm_mcmr_ctrl_is_inited. +* +* Calling osm_mcmr_rcv_ctrl_construct is a prerequisite to calling any other +* method except osm_mcmr_rcv_ctrl_init. +* +* SEE ALSO +* MCMember Receive Controller object, osm_mcmr_rcv_ctrl_init, +* osm_mcmr_rcv_ctrl_destroy, osm_mcmr_ctrl_is_inited +*********/ + +/****f* OpenSM: MCMember Receive Controller/osm_mcmr_rcv_ctrl_destroy +* NAME +* osm_mcmr_rcv_ctrl_destroy +* +* DESCRIPTION +* The osm_mcmr_rcv_ctrl_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_mcmr_rcv_ctrl_destroy( + IN osm_mcmr_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* MCMember Receive Controller object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_mcmr_rcv_ctrl_construct or osm_mcmr_rcv_ctrl_init. +* +* SEE ALSO +* MCMember Receive Controller object, osm_mcmr_rcv_ctrl_construct, +* osm_mcmr_rcv_ctrl_init +*********/ + +/****f* OpenSM: MCMember Receive Controller/osm_mcmr_rcv_ctrl_init +* NAME +* osm_mcmr_rcv_ctrl_init +* +* DESCRIPTION +* The osm_mcmr_rcv_ctrl_init function initializes a +* MCMember Receive Controller object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_mcmr_rcv_ctrl_init( + IN osm_mcmr_rcv_ctrl_t* const p_ctrl, + IN osm_mcmr_recv_t* const p_mcmr, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_mcmr_rcv_ctrl_t object to initialize. +* +* p_rcv +* [in] Pointer to an osm_mcmr_recv_t object. +* +* p_log +* [in] Pointer to the log object. +* +* p_disp +* [in] Pointer to the OpenSM central Dispatcher. +* +* RETURN VALUES +* CL_SUCCESS if the MCMember Receive Controller object was initialized +* successfully. +* +* NOTES +* Allows calling other MCMember Receive Controller methods. +* +* SEE ALSO +* MCMember Receive Controller object, osm_mcmr_rcv_ctrl_construct, +* osm_mcmr_rcv_ctrl_destroy, osm_mcmr_ctrl_is_inited +*********/ + +/****f* OpenSM: MCMember Receive Controller/osm_mcmr_ctrl_is_inited +* NAME +* osm_mcmr_ctrl_is_inited +* +* DESCRIPTION +* Indicates if the object has been initialized with osm_mcmr_rcv_ctrl_init. +* +* SYNOPSIS +*/ +boolean_t osm_mcmr_ctrl_is_inited( + IN const osm_mcmr_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_mcmr_rcv_ctrl_t object. +* +* RETURN VALUES +* TRUE if the object was initialized successfully, +* FALSE otherwise. +* +* NOTES +* The osm_mcmr_rcv_ctrl_construct or osm_mcmr_rcv_ctrl_init must be +* called before using this function. +* +* SEE ALSO +* MCMember Receive Controller object, osm_mcmr_rcv_ctrl_construct, +* osm_mcmr_rcv_ctrl_init +*********/ + +END_C_DECLS + +#endif /* _OSM_MCMRCTRL_H */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_mft_record.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_mft_record.h new file mode 100644 index 00000000..a4e42483 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_mft_record.h @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ + + +/* + * Abstract: + * Declaration of osm_mftr_rcv_t. + * This object represents the MulticastForwardingTable Receiver object. + * attribute from a switch node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + */ + +#ifndef _OSM_MFTR_H_ +#define _OSM_MFTR_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Multicast Forwarding Table Receiver +* NAME +* Multicast Forwarding Table Receiver +* +* DESCRIPTION +* The Multicast Forwarding Table Receiver object encapsulates the information +* needed to receive the MulticastForwardingTable attribute from a switch node. +* +* The Multicast Forwarding Table Receiver object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Hal Rosenstock, Voltaire +* +*********/ + +/****s* OpenSM: Multicast Forwarding Table Receiver/osm_mftr_rcv_t +* NAME +* osm_mftr_rcv_t +* +* DESCRIPTION +* Multicast Forwarding Table Receiver structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_mft +{ + osm_subn_t* p_subn; + osm_stats_t* p_stats; + osm_sa_resp_t* p_resp; + osm_mad_pool_t* p_mad_pool; + osm_log_t* p_log; + cl_plock_t* p_lock; + cl_qlock_pool_t pool; +} osm_mftr_rcv_t; +/* +* FIELDS +* p_subn +* Pointer to the Subnet object for this subnet. +* +* p_stats +* Pointer to the statistics. +* +* p_resp +* Pointer to the SA responder. +* +* p_mad_pool +* Pointer to the mad pool. +* +* p_log +* Pointer to the log object. +* +* p_lock +* Pointer to the serializing lock. +* +* pool +* Pool of linkable Multicast Forwarding Table Record objects used to +* generate the query response. +* +* SEE ALSO +* Multicast Forwarding Table Receiver object +*********/ + +/****f* OpenSM: Multicast Forwarding Table Receiver/osm_mftr_rcv_construct +* NAME +* osm_mftr_rcv_construct +* +* DESCRIPTION +* This function constructs a Multicast Forwarding Table Receiver object. +* +* SYNOPSIS +*/ +void osm_mftr_rcv_construct( + IN osm_mftr_rcv_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a Multicast Forwarding Table Receiver object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_mftr_rcv_init, osm_mftr_rcv_destroy +* +* Calling osm_mftr_rcv_construct is a prerequisite to calling any other +* method except osm_mftr_rcv_init. +* +* SEE ALSO +* Multicast Forwarding Table Receiver object, osm_mftr_rcv_init, +* osm_mftr_rcv_destroy +*********/ + +/****f* OpenSM: Multicast Forwarding Table Receiver/osm_mftr_rcv_destroy +* NAME +* osm_mftr_rcv_destroy +* +* DESCRIPTION +* The osm_mftr_rcv_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_mftr_rcv_destroy( + IN osm_mftr_rcv_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* Multicast Forwarding Table Receiver object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_mftr_rcv_construct or osm_mftr_rcv_init. +* +* SEE ALSO +* Multicast Forwarding Table Receiver object, osm_mftr_rcv_construct, +* osm_mftr_rcv_init +*********/ + +/****f* OpenSM: Multicast Forwarding Table Receiver/osm_mftr_rcv_init +* NAME +* osm_mftr_rcv_init +* +* DESCRIPTION +* The osm_mftr_rcv_init function initializes a +* Multicast Forwarding Table Receiver object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_mftr_rcv_init( + IN osm_mftr_rcv_t* const p_rcv, + IN osm_sa_resp_t* const p_resp, + IN osm_mad_pool_t* const p_mad_pool, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to an osm_mftr_rcv_t object to initialize. +* +* p_req +* [in] Pointer to an osm_req_t object. +* +* p_subn +* [in] Pointer to the Subnet object for this subnet. +* +* p_log +* [in] Pointer to the log object. +* +* p_lock +* [in] Pointer to the OpenSM serializing lock. +* +* RETURN VALUES +* CL_SUCCESS if the Multicast Forwarding Table Receiver object was initialized +* successfully. +* +* NOTES +* Allows calling other Multicast Forwarding Table Receiver methods. +* +* SEE ALSO +* Multicast Forwarding Table Receiver object, osm_mftr_rcv_construct, +* osm_mftr_rcv_destroy +*********/ + +/****f* OpenSM: Multicast Forwarding Table Receiver/osm_mftr_rcv_process +* NAME +* osm_mftr_rcv_process +* +* DESCRIPTION +* Process the MulticastForwardingTable attribute. +* +* SYNOPSIS +*/ +void osm_mftr_rcv_process( + IN osm_mftr_rcv_t* const p_ctrl, + IN const osm_madw_t* const p_madw ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_mftr_rcv_t object. +* +* p_madw +* [in] Pointer to the MAD Wrapper containing the MAD +* that contains the switch node's MulticastForwardingTable attribute. +* +* RETURN VALUES +* CL_SUCCESS if the MulticastForwardingTable processing was successful. +* +* NOTES +* This function processes a MulticastForwardingTable attribute. +* +* SEE ALSO +* Multicast Forwarding Table Receiver, Multicast Forwarding Table Response +* Controller +*********/ + +END_C_DECLS + +#endif /* _OSM_MFTR_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_mft_record_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_mft_record_ctrl.h new file mode 100644 index 00000000..8f815ff5 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_mft_record_ctrl.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ + + +/* + * Abstract: + * Declaration of osm_mftr_rcv_ctrl_t. + * This object represents a controller that receives the IBA + * MulticastForwardingTable attribute from a switch. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + */ + +#ifndef _OSM_MFTR_RCV_CTRL_H_ +#define _OSM_MFTR_RCV_CTRL_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Multicast Forwarding Table Receive Controller +* NAME +* Multicast Forwarding Table Record Receive Controller +* +* DESCRIPTION +* The Multicast Forwarding Table Receive Controller object encapsulates +* the information needed to receive the MulticastFowardingTable attribute +* from a switch node. +* +* The Multicast Forwarding Table Receive Controller object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Hal Rosenstock, Voltaire +* +*********/ + +/****s* OpenSM: Multicast Forwarding Table Receive Controller/osm_mftr_rcv_ctrl_t +* NAME +* osm_mftr_rcv_ctrl_t +* +* DESCRIPTION +* Multicast Forwarding Table Receive Controller structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_mftr_rcv_ctrl +{ + osm_mftr_rcv_t *p_rcv; + osm_log_t *p_log; + cl_dispatcher_t *p_disp; + cl_disp_reg_handle_t h_disp; +} osm_mftr_rcv_ctrl_t; +/* +* FIELDS +* p_rcv +* Pointer to the Multicast Forwarding Table Receiver object. +* +* p_log +* Pointer to the log object. +* +* p_disp +* Pointer to the Dispatcher. +* +* h_disp +* Handle returned from dispatcher registration. +* +* SEE ALSO +* Multicast Forwarding Table Receive Controller object +* Multicast Forwarding Table Receiver object +*********/ + +/****f* OpenSM: Multicast Forwarding Table Receive Controller/osm_mftr_rcv_ctrl_construct +* NAME +* osm_mftr_rcv_ctrl_construct +* +* DESCRIPTION +* This function constructs a Multicast Forwarding Table Receive +* Controller object. +* +* SYNOPSIS +*/ +void osm_mftr_rcv_ctrl_construct( + IN osm_mftr_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a Multicast Forwarding Table Receive Controller +* object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_mftr_rcv_ctrl_init, osm_mftr_rcv_ctrl_destroy +* +* Calling osm_mftr_rcv_ctrl_construct is a prerequisite to calling any other +* method except osm_mftr_rcv_ctrl_init. +* +* SEE ALSO +* Multicast Forwarding Table Receive Controller object, osm_mftr_rcv_ctrl_init, +* osm_mftr_rcv_ctrl_destroy +*********/ + +/****f* OpenSM: Multicast Forwarding Table Receive Controller/osm_mftr_rcv_ctrl_destroy +* NAME +* osm_mftr_rcv_ctrl_destroy +* +* DESCRIPTION +* The osm_mftr_rcv_ctrl_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_mftr_rcv_ctrl_destroy( + IN osm_mftr_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* Multicast Forwarding Table Receive Controller object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_mftr_rcv_ctrl_construct or osm_mftr_rcv_ctrl_init. +* +* SEE ALSO +* Multicast Forwarding Table Receive Controller object, osm_mftr_rcv_ctrl_construct, +* osm_mftr_rcv_ctrl_init +*********/ + +/****f* OpenSM: Multicast Forwarding Table Receive Controller/osm_mftr_rcv_ctrl_init +* NAME +* osm_mftr_rcv_ctrl_init +* +* DESCRIPTION +* The osm_mftr_rcv_ctrl_init function initializes a +* Multicast Forwarding Table Receive Controller object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_mftr_rcv_ctrl_init( + IN osm_mftr_rcv_ctrl_t* const p_ctrl, + IN osm_mftr_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_mftr_rcv_ctrl_t object to initialize. +* +* p_rcv +* [in] Pointer to an osm_mftr_t object. +* +* p_log +* [in] Pointer to the log object. +* +* p_disp +* [in] Pointer to the OpenSM central Dispatcher. +* +* RETURN VALUES +* CL_SUCCESS if the Multicast Forwarding Table Receive Controller object +* was initialized successfully. +* +* NOTES +* Allows calling other Multicast Forwarding Table Receive Controller methods. +* +* SEE ALSO +* Multicast Forwarding Table Receive Controller object, +* osm_mftr_rcv_ctrl_construct, osm_mftr_rcv_ctrl_destroy +*********/ + +END_C_DECLS + +#endif /* _OSM_MFTR_RCV_CTRL_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_multipath_record.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_multipath_record.h new file mode 100644 index 00000000..b55cfb09 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_multipath_record.h @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ + + +/* + * Abstract: + * Declaration of osm_mpr_rcv_t. + * This object represents the MultiPathRecord Receiver object. + * attribute from a node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + */ + +#ifndef _OSM_MPR_RCV_H_ +#define _OSM_MPR_RCV_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/MultiPath Record Receiver +* NAME +* MultiPath Record Receiver +* +* DESCRIPTION +* The MultiPath Record Receiver object encapsulates the information +* needed to receive the PathRecord request from a node. +* +* The MultiPath Record Receiver object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Hal Rosenstock, Voltaire +* +*********/ + +/****s* OpenSM: MultiPath Record Receiver/osm_mpr_rcv_t +* NAME +* osm_mpr_rcv_t +* +* DESCRIPTION +* MultiPath Record Receiver structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_mpr_rcv +{ + osm_subn_t *p_subn; + osm_sa_resp_t *p_resp; + osm_mad_pool_t *p_mad_pool; + osm_log_t *p_log; + cl_plock_t *p_lock; + cl_qlock_pool_t pr_pool; +} osm_mpr_rcv_t; +/* +* FIELDS +* p_subn +* Pointer to the Subnet object for this subnet. +* +* p_gen_req_ctrl +* Pointer to the generic request controller. +* +* p_log +* Pointer to the log object. +* +* p_lock +* Pointer to the serializing lock. +* +* pr_pool +* Pool of multipath record objects used to generate query responses. +* +* SEE ALSO +* MultiPath Record Receiver object +*********/ + +/****f* OpenSM: MultiPath Record Receiver/osm_mpr_rcv_construct +* NAME +* osm_mpr_rcv_construct +* +* DESCRIPTION +* This function constructs a MultiPath Record Receiver object. +* +* SYNOPSIS +*/ +void +osm_mpr_rcv_construct( + IN osm_mpr_rcv_t* const p_rcv ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to a MultiPath Record Receiver object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_mpr_rcv_init, osm_mpr_rcv_destroy +* +* Calling osm_mpr_rcv_construct is a prerequisite to calling any other +* method except osm_mpr_rcv_init. +* +* SEE ALSO +* MultiPath Record Receiver object, osm_mpr_rcv_init, osm_mpr_rcv_destroy +*********/ + +/****f* OpenSM: MultiPath Record Receiver/osm_mpr_rcv_destroy +* NAME +* osm_mpr_rcv_destroy +* +* DESCRIPTION +* The osm_mpr_rcv_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_mpr_rcv_destroy( + IN osm_mpr_rcv_t* const p_rcv ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* MultiPath Record Receiver object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_mpr_rcv_construct or osm_mpr_rcv_init. +* +* SEE ALSO +* MultiPath Record Receiver object, osm_mpr_rcv_construct, +* osm_mpr_rcv_init +*********/ + +/****f* OpenSM: MultiPath Record Receiver/osm_mpr_rcv_init +* NAME +* osm_mpr_rcv_init +* +* DESCRIPTION +* The osm_mpr_rcv_init function initializes a +* MultiPath Record Receiver object for use. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_mpr_rcv_init( + IN osm_mpr_rcv_t* const p_rcv, + IN osm_sa_resp_t* const p_resp, + IN osm_mad_pool_t* const p_mad_pool, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to an osm_mpr_rcv_t object to initialize. +* +* p_subn +* [in] Pointer to the Subnet object for this subnet. +* +* p_log +* [in] Pointer to the log object. +* +* p_lock +* [in] Pointer to the OpenSM serializing lock. +* +* RETURN VALUES +* IB_SUCCESS if the MultiPath Record Receiver object was initialized +* successfully. +* +* NOTES +* Allows calling other MultiPath Record Receiver methods. +* +* SEE ALSO +* MultiPath Record Receiver object, osm_mpr_rcv_construct, +* osm_mpr_rcv_destroy +*********/ + +/****f* OpenSM: MultiPath Record Receiver/osm_mpr_rcv_process +* NAME +* osm_mpr_rcv_process +* +* DESCRIPTION +* Process the MultiPathRecord request. +* +* SYNOPSIS +*/ +void +osm_mpr_rcv_process( + IN osm_mpr_rcv_t* const p_rcv, + IN osm_madw_t* const p_madw ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to an osm_mpr_rcv_t object. +* +* p_madw +* [in] Pointer to the MAD Wrapper containing the MAD +* that contains the node's MultiPathRecord attribute. +* +* RETURN VALUES +* IB_SUCCESS if the MultiPathRecord processing was successful. +* +* NOTES +* This function processes a MultiPathRecord attribute. +* +* SEE ALSO +* MultiPath Record Receiver, Node Info Response Controller +*********/ + +END_C_DECLS + +#endif /* _OSM_MPR_RCV_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_multipath_record_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_multipath_record_ctrl.h new file mode 100644 index 00000000..090dc9e8 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_multipath_record_ctrl.h @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ + + +/* + * Abstract: + * Declaration of osm_mpr_rcv_ctrl_t. + * This object represents a controller that receives the IBA + * MultiPathRecord attribute from a node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + */ + +#ifndef _OSM_MPRCTRL_H_ +#define _OSM_MPRCTRL_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/MultiPath Record Receive Controller +* NAME +* MultiPath Record Receive Controller +* +* DESCRIPTION +* The MultiPath Record Receive Controller object encapsulates +* the information needed to receive the MultiPathRecord attribute from a node. +* +* The MultiPath record Receive Controller object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Hal Rosenstock, Voltaire +* +*********/ + +/****s* OpenSM: MultiPath Record Receive Controller/osm_mpr_rcv_ctrl_t +* NAME +* osm_mpr_rcv_ctrl_t +* +* DESCRIPTION +* MultiPath Record Receive Controller structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_mpr_rcv_ctrl +{ + osm_mpr_rcv_t *p_rcv; + osm_log_t *p_log; + cl_dispatcher_t *p_disp; + cl_disp_reg_handle_t h_disp; + +} osm_mpr_rcv_ctrl_t; +/* +* FIELDS +* p_rcv +* Pointer to the MultiPath Record Receiver object. +* +* p_log +* Pointer to the log object. +* +* p_disp +* Pointer to the Dispatcher. +* +* h_disp +* Handle returned from dispatcher registration. +* +* SEE ALSO +* MultiPath Record Receive Controller object +* MultiPath Record Receiver object +*********/ + +/****f* OpenSM: MultiPath Record Receive Controller/osm_pr_rcv_ctrl_construct +* NAME +* osm_mpr_rcv_ctrl_construct +* +* DESCRIPTION +* This function constructs a MultiPath Record Receive Controller object. +* +* SYNOPSIS +*/ +void osm_mpr_rcv_ctrl_construct( + IN osm_mpr_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a MultiPath Record Receive Controller +* object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_mpr_rcv_ctrl_init, osm_mpr_rcv_ctrl_destroy, +* and osm_mpr_rcv_ctrl_is_inited. +* +* Calling osm_mpr_rcv_ctrl_construct is a prerequisite to calling any +* other method except osm_mpr_rcv_ctrl_init. +* +* SEE ALSO +* MultiPath Record Receive Controller object, osm_mpr_rcv_ctrl_init, +* osm_mpr_rcv_ctrl_destroy, osm_mpr_rcv_ctrl_is_inited +*********/ + +/****f* OpenSM: MultiPath Record Receive Controller/osm_mpr_rcv_ctrl_destroy +* NAME +* osm_mpr_rcv_ctrl_destroy +* +* DESCRIPTION +* The osm_mpr_rcv_ctrl_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_mpr_rcv_ctrl_destroy( + IN osm_mpr_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* MultiPath Record Receive Controller object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_mpr_rcv_ctrl_construct or osm_mpr_rcv_ctrl_init. +* +* SEE ALSO +* MultiPath Record Receive Controller object, osm_mpr_rcv_ctrl_construct, +* osm_mpr_rcv_ctrl_init +*********/ + +/****f* OpenSM: MultiPath Record Receive Controller/osm_mpr_rcv_ctrl_init +* NAME +* osm_mpr_rcv_ctrl_init +* +* DESCRIPTION +* The osm_mpr_rcv_ctrl_init function initializes a +* MultiPath Record Receive Controller object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_mpr_rcv_ctrl_init( + IN osm_mpr_rcv_ctrl_t* const p_ctrl, + IN osm_mpr_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_mpr_rcv_ctrl_t object to initialize. +* +* p_rcv +* [in] Pointer to an osm_mpr_t object. +* +* p_log +* [in] Pointer to the log object. +* +* p_disp +* [in] Pointer to the OpenSM central Dispatcher. +* +* RETURN VALUES +* CL_SUCCESS if the MultiPath Record Receive Controller object was +* initialized successfully. +* +* NOTES +* Allows calling other MultiPath Record Receive Controller methods. +* +* SEE ALSO +* MultiPath Record Receive Controller object, osm_pr_rcv_ctrl_construct, +* osm_mpr_rcv_ctrl_destroy, osm_mpr_rcv_ctrl_is_inited +*********/ + +/****f* OpenSM: MultiPath Record Receive Controller/osm_mpr_rcv_ctrl_is_inited +* NAME +* osm_mpr_rcv_ctrl_is_inited +* +* DESCRIPTION +* Indicates if the object has been initialized with osm_mpr_rcv_ctrl_init. +* +* SYNOPSIS +*/ +boolean_t osm_mpr_rcv_ctrl_is_inited( + IN const osm_mpr_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_mpr_rcv_ctrl_t object. +* +* RETURN VALUES +* TRUE if the object was initialized successfully, +* FALSE otherwise. +* +* NOTES +* The osm_mpr_rcv_ctrl_construct or osm_mpr_rcv_ctrl_init must be +* called before using this function. +* +* SEE ALSO +* MultiPath Record Receive Controller object, osm_mpr_rcv_ctrl_construct, +* osm_mpr_rcv_ctrl_init +*********/ + +END_C_DECLS + +#endif /* _OSM_MPRCTRL_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_node_record.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_node_record.h new file mode 100644 index 00000000..a3a1f9ae --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_node_record.h @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_node_record.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_nr_rcv_t. + * This object represents the NodeRecord Receiver object. + * attribute from a node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_NR_H_ +#define _OSM_NR_H_ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Node Record Receiver +* NAME +* Node Record Receiver +* +* DESCRIPTION +* The Node Record Receiver object encapsulates the information +* needed to receive the NodeRecord attribute from a node. +* +* The Node record Receiver object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Anil S Keshavamurthy, Intel +* +*********/ + +/****s* OpenSM: Node Record Receiver/osm_nr_rcv_t +* NAME +* osm_nr_rcv_t +* +* DESCRIPTION +* Node Record Receiver structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_nr_recv +{ + const osm_subn_t *p_subn; + osm_sa_resp_t *p_resp; + osm_mad_pool_t *p_mad_pool; + osm_log_t *p_log; + cl_plock_t *p_lock; + cl_qlock_pool_t pool; + +} osm_nr_rcv_t; +/* +* FIELDS +* p_subn +* Pointer to the Subnet object for this subnet. +* +* p_resp +* Pointer to the SA responder. +* +* p_mad_pool +* Pointer to the mad pool. +* +* p_log +* Pointer to the log object. +* +* p_lock +* Pointer to the serializing lock. +* +* pool +* Pool of linkable node record objects used to generate +* the query response. +* +* SEE ALSO +* +*********/ + +/****f* OpenSM: Node Record Receiver/osm_nr_rcv_construct +* NAME +* osm_nr_rcv_construct +* +* DESCRIPTION +* This function constructs a Node Record Receiver object. +* +* SYNOPSIS +*/ +void osm_nr_rcv_construct( + IN osm_nr_rcv_t* const p_rcv ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to a Node Record Receiver object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_nr_rcv_init, osm_nr_rcv_destroy +* +* Calling osm_nr_rcv_construct is a prerequisite to calling any other +* method except osm_nr_rcv_init. +* +* SEE ALSO +* Node Record Receiver object, osm_nr_rcv_init, osm_lr_rcv_destroy +*********/ + +/****f* OpenSM: Node Record Receiver/osm_nr_rcv_destroy +* NAME +* osm_nr_rcv_destroy +* +* DESCRIPTION +* The osm_nr_rcv_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_nr_rcv_destroy( + IN osm_nr_rcv_t* const p_rcv ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* Node Record Receiver object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_nr_rcv_construct or osm_nr_rcv_init. +* +* SEE ALSO +* Node Record Receiver object, osm_nr_rcv_construct, +* osm_nr_rcv_init +*********/ + +/****f* OpenSM: Node Record Receiver/osm_nr_rcv_init +* NAME +* osm_nr_rcv_init +* +* DESCRIPTION +* The osm_nr_rcv_init function initializes a +* Node Record Receiver object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_nr_rcv_init( + IN osm_nr_rcv_t* const p_rcv, + IN osm_sa_resp_t* const p_resp, + IN osm_mad_pool_t* const p_mad_pool, + IN const osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to an osm_nr_rcv_t object to initialize. +* +* p_resp +* [in] Pointer to the SA Responder object. +* +* p_mad_pool +* [in] Pointer to the mad pool. +* +* p_subn +* [in] Pointer to the Subnet object for this subnet. +* +* p_log +* [in] Pointer to the log object. +* +* p_lock +* [in] Pointer to the OpenSM serializing lock. +* +* RETURN VALUES +* IB_SUCCESS if the Node Record Receiver object was initialized +* successfully. +* +* NOTES +* Allows calling other Link Record Receiver methods. +* +* SEE ALSO +* Node Record Receiver object, osm_nr_rcv_construct, osm_nr_rcv_destroy +*********/ + + +/****f* OpenSM: Node Record Receiver/osm_nr_rcv_process +* NAME +* osm_nr_rcv_process +* +* DESCRIPTION +* Process the NodeRecord attribute. +* +* SYNOPSIS +*/ +void osm_nr_rcv_process( + IN osm_nr_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to an osm_nr_rcv_t object. +* +* p_madw +* [in] Pointer to the MAD Wrapper containing the MAD +* that contains the node's NodeRecord attribute. +* +* NOTES +* This function processes a NodeRecord attribute. +* +* SEE ALSO +* Node Record Receiver, Node Record Response Controller +*********/ + +END_C_DECLS + +#endif /* _OSM_NR_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_node_record_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_node_record_ctrl.h new file mode 100644 index 00000000..8dd5c58d --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_node_record_ctrl.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_node_record_ctrl.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_nr_rcv_ctrl_t. + * This object represents a controller that receives the IBA NodeInfo + * record from a node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_NR_CTRL_H_ +#define _OSM_NR_CTRL_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Node Record Receive Controller +* NAME +* Node Record Receive Controller +* +* DESCRIPTION +* The Node Record Receive Controller object encapsulates +* the information needed to receive the NodeInfo attribute from a node. +* +* The Node Record Receive Controller object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Anil S Keshavamurthy, Intel +* +*********/ + +/****s* OpenSM: Node Record Receive Controller/osm_nr_rcv_ctrl_t +* NAME +* osm_nr_rcv_ctrl_t +* +* DESCRIPTION +* Node Record Receive Controller structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_nr_ctrl +{ + osm_nr_rcv_t *p_rcv; + osm_log_t *p_log; + cl_dispatcher_t *p_disp; + cl_disp_reg_handle_t h_disp; + +} osm_nr_rcv_ctrl_t; +/* +* FIELDS +* p_rcv +* Pointer to the Node Record Receiver object. +* +* p_log +* Pointer to the log object. +* +* p_disp +* Pointer to the Dispatcher. +* +* h_disp +* Handle returned from dispatcher registration. +* +* SEE ALSO +* Node Record Receive Controller object +* Node Record Receiver object +*********/ + +/****f* OpenSM: Node Record Receive Controller/osm_nr_rcv_ctrl_construct +* NAME +* osm_nr_rcv_ctrl_construct +* +* DESCRIPTION +* This function constructs a Node Record Receive Controller object. +* +* SYNOPSIS +*/ +void osm_nr_rcv_ctrl_construct( + IN osm_nr_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a Node Record Receive Controller +* object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_nr_rcv_ctrl_init, osm_nr_rcv_ctrl_destroy, +* +* Calling osm_nr_rcv_ctrl_construct is a prerequisite to calling any other +* method except osm_nr_rcv_ctrl_init. +* +* SEE ALSO +* Node Record Receive Controller object, osm_nr_rcv_ctrl_init, +* osm_nr_rcv_ctrl_destroy +*********/ + +/****f* OpenSM: Node Record Receive Controller/osm_nr_rcv_ctrl_destroy +* NAME +* osm_nr_rcv_ctrl_destroy +* +* DESCRIPTION +* The osm_nr_rcv_ctrl_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_nr_rcv_ctrl_destroy( + IN osm_nr_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* Node Record Receive Controller object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_nr_rcv_ctrl_construct or osm_nr_rcv_ctrl_init. +* +* SEE ALSO +* Node Record Receive Controller object, osm_nr_rcv_ctrl_construct, +* osm_nr_rcv_ctrl_init +*********/ + +/****f* OpenSM: Node Record Receive Controller/osm_nr_rcv_ctrl_init +* NAME +* osm_nr_rcv_ctrl_init +* +* DESCRIPTION +* The osm_nr_rcv_ctrl_init function initializes a +* Node Record Receive Controller object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_nr_rcv_ctrl_init( + IN osm_nr_rcv_ctrl_t* const p_ctrl, + IN osm_nr_rcv_t* const p_nr, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_nr_rcv_ctrl_t object to initialize. +* +* p_rcv +* [in] Pointer to an osm_nr_rcv_t object. +* +* p_log +* [in] Pointer to the log object. +* +* p_disp +* [in] Pointer to the OpenSM central Dispatcher. +* +* RETURN VALUES +* CL_SUCCESS if the Node Record Receive Controller object was initialized +* successfully. +* +* NOTES +* Allows calling other Node Record Receive Controller methods. +* +* SEE ALSO +* Node Record Receive Controller object, osm_nr_rcv_ctrl_construct, +* osm_nr_rcv_ctrl_destroy +*********/ + +END_C_DECLS + +#endif /* _OSM_NR_CTRL_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_path_record.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_path_record.h new file mode 100644 index 00000000..c7acd3b4 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_path_record.h @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_path_record.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_pr_rcv_t. + * This object represents the PathRecord Receiver object. + * attribute from a node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_PR_H_ +#define _OSM_PR_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Path Record Receiver +* NAME +* Path Record Receiver +* +* DESCRIPTION +* The Path Record Receiver object encapsulates the information +* needed to receive the PathRecord request from a node. +* +* The Path Record Receiver object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Ranjit Pandit, Intel +* Steve King, Intel +* +*********/ + +/****s* OpenSM: Path Record Receiver/osm_pr_rcv_t +* NAME +* osm_pr_rcv_t +* +* DESCRIPTION +* Path Record Receiver structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_pr_rcv +{ + osm_subn_t *p_subn; + osm_sa_resp_t *p_resp; + osm_mad_pool_t *p_mad_pool; + osm_log_t *p_log; + cl_plock_t *p_lock; + cl_qlock_pool_t pr_pool; +} osm_pr_rcv_t; +/* +* FIELDS +* p_subn +* Pointer to the Subnet object for this subnet. +* +* p_gen_req_ctrl +* Pointer to the generic request controller. +* +* p_log +* Pointer to the log object. +* +* p_lock +* Pointer to the serializing lock. +* +* pr_pool +* Pool of path record objects used to generate query responses. +* +* SEE ALSO +* Path Record Receiver object +*********/ + +/****f* OpenSM: Path Record Receiver/osm_pr_rcv_construct +* NAME +* osm_pr_rcv_construct +* +* DESCRIPTION +* This function constructs a Path Record Receiver object. +* +* SYNOPSIS +*/ +void +osm_pr_rcv_construct( + IN osm_pr_rcv_t* const p_rcv ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to a Path Record Receiver object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_pr_rcv_init, osm_pr_rcv_destroy +* +* Calling osm_pr_rcv_construct is a prerequisite to calling any other +* method except osm_pr_rcv_init. +* +* SEE ALSO +* Path Record Receiver object, osm_pr_rcv_init, osm_pr_rcv_destroy +*********/ + +/****f* OpenSM: Path Record Receiver/osm_pr_rcv_destroy +* NAME +* osm_pr_rcv_destroy +* +* DESCRIPTION +* The osm_pr_rcv_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_pr_rcv_destroy( + IN osm_pr_rcv_t* const p_rcv ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* Path Record Receiver object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_pr_rcv_construct or osm_pr_rcv_init. +* +* SEE ALSO +* Path Record Receiver object, osm_pr_rcv_construct, +* osm_pr_rcv_init +*********/ + +/****f* OpenSM: Path Record Receiver/osm_pr_rcv_init +* NAME +* osm_pr_rcv_init +* +* DESCRIPTION +* The osm_pr_rcv_init function initializes a +* Path Record Receiver object for use. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_pr_rcv_init( + IN osm_pr_rcv_t* const p_rcv, + IN osm_sa_resp_t* const p_resp, + IN osm_mad_pool_t* const p_mad_pool, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to an osm_pr_rcv_t object to initialize. +* +* p_subn +* [in] Pointer to the Subnet object for this subnet. +* +* p_log +* [in] Pointer to the log object. +* +* p_lock +* [in] Pointer to the OpenSM serializing lock. +* +* RETURN VALUES +* IB_SUCCESS if the Path Record Receiver object was initialized +* successfully. +* +* NOTES +* Allows calling other Path Record Receiver methods. +* +* SEE ALSO +* Path Record Receiver object, osm_pr_rcv_construct, +* osm_pr_rcv_destroy +*********/ + +/****f* OpenSM: Path Record Receiver/osm_pr_rcv_process +* NAME +* osm_pr_rcv_process +* +* DESCRIPTION +* Process the PathRecord request. +* +* SYNOPSIS +*/ +void +osm_pr_rcv_process( + IN osm_pr_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to an osm_pr_rcv_t object. +* +* p_madw +* [in] Pointer to the MAD Wrapper containing the MAD +* that contains the node's PathRecord attribute. +* +* RETURN VALUES +* IB_SUCCESS if the PathRecord processing was successful. +* +* NOTES +* This function processes a PathRecord attribute. +* +* SEE ALSO +* Path Record Receiver, Path Record Response Controller +*********/ + +END_C_DECLS + +#endif /* _OSM_PR_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_path_record_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_path_record_ctrl.h new file mode 100644 index 00000000..245ab44f --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_path_record_ctrl.h @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_path_record_ctrl.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_pr_rcv_ctrl_t. + * This object represents a controller that receives the IBA PathRecord + * attribute from a node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_PRCTRL_H_ +#define _OSM_PRCTRL_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Path Record Receive Controller +* NAME +* Path Record Receive Controller +* +* DESCRIPTION +* The Path Record Receive Controller object encapsulates +* the information needed to receive the PathRecord attribute from a node. +* +* The Path record Receive Controller object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Ranjit Pandit, Intel +* +*********/ + +/****s* OpenSM: Path Record Receive Controller/osm_pr_rcv_ctrl_t +* NAME +* osm_pr_rcv_ctrl_t +* +* DESCRIPTION +* Path Record Receive Controller structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_pr_rcv_ctrl +{ + osm_pr_rcv_t *p_rcv; + osm_log_t *p_log; + cl_dispatcher_t *p_disp; + cl_disp_reg_handle_t h_disp; + +} osm_pr_rcv_ctrl_t; +/* +* FIELDS +* p_rcv +* Pointer to the Path Record Receiver object. +* +* p_log +* Pointer to the log object. +* +* p_disp +* Pointer to the Dispatcher. +* +* h_disp +* Handle returned from dispatcher registration. +* +* SEE ALSO +* Path Record Receive Controller object +* Path Record Receiver object +*********/ + +/****f* OpenSM: Path Record Receive Controller/osm_pr_rcv_ctrl_construct +* NAME +* osm_pr_rcv_ctrl_construct +* +* DESCRIPTION +* This function constructs a Path Record Receive Controller object. +* +* SYNOPSIS +*/ +void osm_pr_rcv_ctrl_construct( + IN osm_pr_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a Path Record Receive Controller +* object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_pr_rcv_ctrl_init, osm_pr_rcv_ctrl_destroy, +* and osm_pr_rcv_ctrl_is_inited. +* +* Calling osm_pr_rcv_ctrl_construct is a prerequisite to calling any other +* method except osm_pr_rcv_ctrl_init. +* +* SEE ALSO +* Path Record Receive Controller object, osm_pr_rcv_ctrl_init, +* osm_pr_rcv_ctrl_destroy, osm_pr_rcv_ctrl_is_inited +*********/ + +/****f* OpenSM: Path Record Receive Controller/osm_pr_rcv_ctrl_destroy +* NAME +* osm_pr_rcv_ctrl_destroy +* +* DESCRIPTION +* The osm_pr_rcv_ctrl_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_pr_rcv_ctrl_destroy( + IN osm_pr_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* Path Record Receive Controller object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_pr_rcv_ctrl_construct or osm_pr_rcv_ctrl_init. +* +* SEE ALSO +* Path Record Receive Controller object, osm_pr_rcv_ctrl_construct, +* osm_pr_rcv_ctrl_init +*********/ + +/****f* OpenSM: Path Record Receive Controller/osm_pr_rcv_ctrl_init +* NAME +* osm_pr_rcv_ctrl_init +* +* DESCRIPTION +* The osm_pr_rcv_ctrl_init function initializes a +* Path Record Receive Controller object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_pr_rcv_ctrl_init( + IN osm_pr_rcv_ctrl_t* const p_ctrl, + IN osm_pr_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_pr_rcv_ctrl_t object to initialize. +* +* p_rcv +* [in] Pointer to an osm_pr_t object. +* +* p_log +* [in] Pointer to the log object. +* +* p_disp +* [in] Pointer to the OpenSM central Dispatcher. +* +* RETURN VALUES +* CL_SUCCESS if the Path Record Receive Controller object was initialized +* successfully. +* +* NOTES +* Allows calling other Path Record Receive Controller methods. +* +* SEE ALSO +* Path Record Receive Controller object, osm_pr_rcv_ctrl_construct, +* osm_pr_rcv_ctrl_destroy, osm_pr_rcv_ctrl_is_inited +*********/ + +/****f* OpenSM: Path Record Receive Controller/osm_pr_rcv_ctrl_is_inited +* NAME +* osm_pr_rcv_ctrl_is_inited +* +* DESCRIPTION +* Indicates if the object has been initialized with osm_pr_rcv_ctrl_init. +* +* SYNOPSIS +*/ +boolean_t osm_pr_rcv_ctrl_is_inited( + IN const osm_pr_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_pr_rcv_ctrl_t object. +* +* RETURN VALUES +* TRUE if the object was initialized successfully, +* FALSE otherwise. +* +* NOTES +* The osm_pr_rcv_ctrl_construct or osm_pr_rcv_ctrl_init must be +* called before using this function. +* +* SEE ALSO +* Path Record Receive Controller object, osm_pr_rcv_ctrl_construct, +* osm_pr_rcv_ctrl_init +*********/ + +END_C_DECLS + +#endif /* _OSM_PRCTRL_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_pkey_record.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_pkey_record.h new file mode 100644 index 00000000..eb52037b --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_pkey_record.h @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_pkey_record.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +#ifndef _OSM_PKEY_REC_RCV_H_ +#define _OSM_PKEY_REC_RCV_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/P_Key Record Receiver +* NAME +* P_Key Record Receiver +* +* DESCRIPTION +* The P_Key Record Receiver object encapsulates the information +* needed to handle P_Key Record query from a SA. +* +* The P_Key Record Receiver object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Yael Kalka, Mellanox +* +*********/ + +/****s* OpenSM: P_Key Record Receiver/osm_pkey_rec_rcv_t +* NAME +* osm_pkey_rec_rcv_t +* +* DESCRIPTION +* P_Key Record Receiver structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_pkey_rec_rcv +{ + const osm_subn_t *p_subn; + osm_sa_resp_t *p_resp; + osm_mad_pool_t *p_mad_pool; + osm_log_t *p_log; + cl_plock_t *p_lock; + cl_qlock_pool_t pool; + +} osm_pkey_rec_rcv_t; +/* +* FIELDS +* p_subn +* Pointer to the Subnet object for this subnet. +* +* p_resp +* Pointer to the SA responder. +* +* p_mad_pool +* Pointer to the mad pool. +* +* p_log +* Pointer to the log object. +* +* p_lock +* Pointer to the serializing lock. +* +* pool +* Pool of linkable P_Key Record objects used to generate +* the query response. +* +* SEE ALSO +* +*********/ + +/****f* OpenSM: P_Key Record Receiver/osm_vlarb_rec_rcv_construct +* NAME +* osm_pkey_rec_rcv_construct +* +* DESCRIPTION +* This function constructs a P_Key Record Receiver object. +* +* SYNOPSIS +*/ +void +osm_pkey_rec_rcv_construct( + IN osm_pkey_rec_rcv_t* const p_rcv ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to a P_Key Record Receiver object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_pkey_rec_rcv_init, osm_pkey_rec_rcv_destroy +* +* Calling osm_pkey_rec_rcv_construct is a prerequisite to calling any other +* method except osm_pkey_rec_rcv_init. +* +* SEE ALSO +* P_Key Record Receiver object, osm_pkey_rec_rcv_init, +* osm_pkey_rec_rcv_destroy +*********/ + +/****f* OpenSM: P_Key Record Receiver/osm_pkey_rec_rcv_destroy +* NAME +* osm_pkey_rec_rcv_destroy +* +* DESCRIPTION +* The osm_pkey_rec_rcv_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_pkey_rec_rcv_destroy( + IN osm_pkey_rec_rcv_t* const p_rcv ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* P_Key Record Receiver object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_pkey_rec_rcv_construct or osm_pkey_rec_rcv_init. +* +* SEE ALSO +* P_Key Record Receiver object, osm_pkey_rec_rcv_construct, +* osm_pkey_rec_rcv_init +*********/ + +/****f* OpenSM: P_Key Record Receiver/osm_pkey_rec_rcv_init +* NAME +* osm_pkey_rec_rcv_init +* +* DESCRIPTION +* The osm_pkey_rec_rcv_init function initializes a +* P_Key Record Receiver object for use. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_pkey_rec_rcv_init( + IN osm_pkey_rec_rcv_t* const p_rcv, + IN osm_sa_resp_t* const p_resp, + IN osm_mad_pool_t* const p_mad_pool, + IN const osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to an osm_pkey_rec_rcv_t object to initialize. +* +* p_req +* [in] Pointer to an osm_req_t object. +* +* p_subn +* [in] Pointer to the Subnet object for this subnet. +* +* p_log +* [in] Pointer to the log object. +* +* p_lock +* [in] Pointer to the OpenSM serializing lock. +* +* RETURN VALUES +* CL_SUCCESS if the P_Key Record Receiver object was initialized +* successfully. +* +* NOTES +* Allows calling other P_Key Record Receiver methods. +* +* SEE ALSO +* P_Key Record Receiver object, osm_pkey_rec_rcv_construct, +* osm_pkey_rec_rcv_destroy +*********/ + +/****f* OpenSM: P_Key Record Receiver/osm_pkey_rec_rcv_process +* NAME +* osm_pkey_rec_rcv_process +* +* DESCRIPTION +* Process the P_Key Table Query . +* +* SYNOPSIS +*/ +void +osm_pkey_rec_rcv_process( + IN osm_pkey_rec_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to an osm_pkey_rec_rcv_t object. +* +* p_madw +* [in] Pointer to the MAD Wrapper containing the MAD +* that contains the P_Key Record Query attribute. +* +* RETURN VALUES +* CL_SUCCESS if the Query processing was successful. +* +* NOTES +* This function processes a SA P_Key Record attribute. +* +* SEE ALSO +* P_Key Record Receiver, P_Key Record Response Controller +*********/ + +END_C_DECLS + +#endif /* _OSM_PKEY_REC_RCV_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_pkey_record_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_pkey_record_ctrl.h new file mode 100644 index 00000000..8c2d9a85 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_pkey_record_ctrl.h @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_pkey_record_ctrl.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +#ifndef _OSM_PKEY_REC_CTRL_H_ +#define _OSM_PKEY_REC_CTRL_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/P_Key Record Receive Controller +* NAME +* P_Key Record Receive Controller +* +* DESCRIPTION +* The P_Key Record Receive Controller object encapsulates +* the information needed to handle P_Key record query from SA client. +* +* The P_Key Record Receive Controller object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Yael Kalka, Mellanox +* +*********/ + +/****s* OpenSM: P_Key Record Receive Controller/osm_pkey_rec_rcv_ctrl_t +* NAME +* osm_pkey_rec_rcv_ctrl_t +* +* DESCRIPTION +* P_Key Record Receive Controller structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_pkey_rec_rcv_ctrl +{ + osm_pkey_rec_rcv_t *p_rcv; + osm_log_t *p_log; + cl_dispatcher_t *p_disp; + cl_disp_reg_handle_t h_disp; + +} osm_pkey_rec_rcv_ctrl_t; +/* +* FIELDS +* p_rcv +* Pointer to the P_Key Record Receiver object. +* +* p_log +* Pointer to the log object. +* +* p_disp +* Pointer to the Dispatcher. +* +* h_disp +* Handle returned from dispatcher registration. +* +* SEE ALSO +* P_Key Record Receive Controller object +* P_Key Record Receiver object +*********/ + +/****f* OpenSM: P_Key Record Receive Controller/osm_pkey_rec_rcv_ctrl_construct +* NAME +* osm_pkey_rec_rcv_ctrl_construct +* +* DESCRIPTION +* This function constructs a P_Key Record Receive Controller object. +* +* SYNOPSIS +*/ +void osm_pkey_rec_rcv_ctrl_construct( + IN osm_pkey_rec_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a P_Key Record Receive Controller +* object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_pkey_rec_rcv_ctrl_init, osm_pkey_rec_rcv_ctrl_destroy +* +* Calling osm_pkey_rec_rcv_ctrl_construct is a prerequisite to calling any other +* method except osm_pkey_rec_rcv_ctrl_init. +* +* SEE ALSO +* P_Key Record Receive Controller object, osm_pkey_rec_rcv_ctrl_init, +* osm_pkey_rec_rcv_ctrl_destroy +*********/ + +/****f* OpenSM: P_Key Record Receive Controller/osm_pkey_rec_rcv_ctrl_destroy +* NAME +* osm_pkey_rec_rcv_ctrl_destroy +* +* DESCRIPTION +* The osm_pkey_rec_rcv_ctrl_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_pkey_rec_rcv_ctrl_destroy( + IN osm_pkey_rec_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* P_Key Record Receive Controller object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_pkey_rec_rcv_ctrl_construct or osm_pkey_rec_rcv_ctrl_init. +* +* SEE ALSO +* P_Key Record Receive Controller object, osm_pkey_rec_rcv_ctrl_construct, +* osm_pkey_rec_rcv_ctrl_init +*********/ + +/****f* OpenSM: P_Key Record Receive Controller/osm_pkey_rec_rcv_ctrl_init +* NAME +* osm_pkey_rec_rcv_ctrl_init +* +* DESCRIPTION +* The osm_pkey_rec_rcv_ctrl_init function initializes a +* P_Key Record Receive Controller object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_pkey_rec_rcv_ctrl_init( + IN osm_pkey_rec_rcv_ctrl_t* const p_ctrl, + IN osm_pkey_rec_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_pkey_rec_rcv_ctrl_t object to initialize. +* +* p_rcv +* [in] Pointer to an osm_pkey_rec_rcv_t object. +* +* p_log +* [in] Pointer to the log object. +* +* p_disp +* [in] Pointer to the OpenSM central Dispatcher. +* +* RETURN VALUES +* CL_SUCCESS if the P_Key Record Receive Controller object was initialized +* successfully. +* +* NOTES +* Allows calling other P_Key Record Receive Controller methods. +* +* SEE ALSO +* P_Key Record Receive Controller object, osm_pkey_rec_rcv_ctrl_construct, +* osm_pkey_rec_rcv_ctrl_destroy +*********/ + +END_C_DECLS + +#endif /* _OSM_PKEY_REC_CTRL_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_portinfo_record.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_portinfo_record.h new file mode 100644 index 00000000..acd42af2 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_portinfo_record.h @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_portinfo_record.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_pir_rcv_t. + * This object represents the PortInfo Record Receiver object. + * attribute from a node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_PIR_RCV_H_ +#define _OSM_PIR_RCV_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/PortInfo Record Receiver +* NAME +* PortInfo Record Receiver +* +* DESCRIPTION +* The PortInfo Record Receiver object encapsulates the information +* needed to receive the PortInfoRecord attribute from a node. +* +* The PortInfo Record Receiver object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Ranjit Pandit, Intel +* +*********/ + +/****s* OpenSM: PortInfo Record Receiver/osm_pir_rcv_t +* NAME +* osm_pir_rcv_t +* +* DESCRIPTION +* PortInfo Record Receiver structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_pir_rcv +{ + osm_subn_t *p_subn; + osm_sa_resp_t *p_resp; + osm_mad_pool_t *p_mad_pool; + osm_log_t *p_log; + cl_plock_t *p_lock; + cl_qlock_pool_t pool; +} osm_pir_rcv_t; +/* +* FIELDS +* p_subn +* Pointer to the Subnet object for this subnet. +* +* p_resp +* Pointer to the SA responder. +* +* p_mad_pool +* Pointer to the mad pool. +* +* p_log +* Pointer to the log object. +* +* p_lock +* Pointer to the serializing lock. +* +* pool +* Pool of linkable PortInfo Record objects used to generate +* the query response. +* +* SEE ALSO +* +*********/ + +/****f* OpenSM: PortInfo Record Receiver/osm_pir_rcv_construct +* NAME +* osm_pir_rcv_construct +* +* DESCRIPTION +* This function constructs a PortInfo Record Receiver object. +* +* SYNOPSIS +*/ +void +osm_pir_rcv_construct( + IN osm_pir_rcv_t* const p_rcv ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to a PortInfo Record Receiver object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_pir_rcv_init, osm_pir_rcv_destroy +* +* Calling osm_pir_rcv_construct is a prerequisite to calling any other +* method except osm_pir_rcv_init. +* +* SEE ALSO +* PortInfo Record Receiver object, osm_pir_rcv_init, +* osm_pir_rcv_destroy +*********/ + +/****f* OpenSM: PortInfo Record Receiver/osm_pir_rcv_destroy +* NAME +* osm_pir_rcv_destroy +* +* DESCRIPTION +* The osm_pir_rcv_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_pir_rcv_destroy( + IN osm_pir_rcv_t* const p_rcv ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* PortInfo Record Receiver object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_pir_rcv_construct or osm_pir_rcv_init. +* +* SEE ALSO +* PortInfo Record Receiver object, osm_pir_rcv_construct, +* osm_pir_rcv_init +*********/ + +/****f* OpenSM: PortInfo Record Receiver/osm_pir_rcv_init +* NAME +* osm_pir_rcv_init +* +* DESCRIPTION +* The osm_pir_rcv_init function initializes a +* PortInfo Record Receiver object for use. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_pir_rcv_init( + IN osm_pir_rcv_t* const p_rcv, + IN osm_sa_resp_t* const p_resp, + IN osm_mad_pool_t* const p_mad_pool, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to an osm_pir_rcv_t object to initialize. +* +* p_req +* [in] Pointer to an osm_req_t object. +* +* p_subn +* [in] Pointer to the Subnet object for this subnet. +* +* p_log +* [in] Pointer to the log object. +* +* p_lock +* [in] Pointer to the OpenSM serializing lock. +* +* RETURN VALUES +* CL_SUCCESS if the PortInfo Record Receiver object was initialized +* successfully. +* +* NOTES +* Allows calling other PortInfo Record Receiver methods. +* +* SEE ALSO +* PortInfo Record Receiver object, osm_pir_rcv_construct, +* osm_pir_rcv_destroy +*********/ + +/****f* OpenSM: PortInfo Record Receiver/osm_pir_rcv_process +* NAME +* osm_pir_rcv_process +* +* DESCRIPTION +* Process the PortInfoRecord attribute. +* +* SYNOPSIS +*/ +void +osm_pir_rcv_process( + IN osm_pir_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to an osm_pir_rcv_t object. +* +* p_madw +* [in] Pointer to the MAD Wrapper containing the MAD +* that contains the node's PortInfoRecord attribute. +* +* RETURN VALUES +* CL_SUCCESS if the PortInfoRecord processing was successful. +* +* NOTES +* This function processes a PortInfoRecord attribute. +* +* SEE ALSO +* PortInfo Record Receiver, PortInfo Record Response Controller +*********/ + +END_C_DECLS + +#endif /* _OSM_PIR_RCV_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_portinfo_record_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_portinfo_record_ctrl.h new file mode 100644 index 00000000..8e9bed3a --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_portinfo_record_ctrl.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_portinfo_record_ctrl.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_pir_rcv_ctrl_t. + * This object represents a controller that receives the IBA PortInfo + * attribute from a node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_PIR_CTRL_H_ +#define _OSM_PIR_CTRL_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/PortInfo Record Receive Controller +* NAME +* PortInfo Record Receive Controller +* +* DESCRIPTION +* The PortInfo Record Receive Controller object encapsulates +* the information needed to receive the PortInfo attribute from a node. +* +* The PortInfo Record Receive Controller object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Ranjit Pandit, Intel +* +*********/ + +/****s* OpenSM: PortInfo Record Receive Controller/osm_pir_rcv_ctrl_t +* NAME +* osm_pir_rcv_ctrl_t +* +* DESCRIPTION +* PortInfo Record Receive Controller structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_pir_rcv_ctrl +{ + osm_pir_rcv_t *p_rcv; + osm_log_t *p_log; + cl_dispatcher_t *p_disp; + cl_disp_reg_handle_t h_disp; + +} osm_pir_rcv_ctrl_t; +/* +* FIELDS +* p_rcv +* Pointer to the PortInfo Record Receiver object. +* +* p_log +* Pointer to the log object. +* +* p_disp +* Pointer to the Dispatcher. +* +* h_disp +* Handle returned from dispatcher registration. +* +* SEE ALSO +* PortInfo Record Receive Controller object +* PortInfo Record Receiver object +*********/ + +/****f* OpenSM: PortInfo Record Receive Controller/osm_pir_rcv_ctrl_construct +* NAME +* osm_pir_rcv_ctrl_construct +* +* DESCRIPTION +* This function constructs a PortInfo Record Receive Controller object. +* +* SYNOPSIS +*/ +void osm_pir_rcv_ctrl_construct( + IN osm_pir_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a PortInfo Record Receive Controller +* object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_pir_rcv_ctrl_init, osm_pir_rcv_ctrl_destroy +* +* Calling osm_pir_rcv_ctrl_construct is a prerequisite to calling any other +* method except osm_pir_rcv_ctrl_init. +* +* SEE ALSO +* PortInfo Record Receive Controller object, osm_pir_rcv_ctrl_init, +* osm_pir_rcv_ctrl_destroy +*********/ + +/****f* OpenSM: PortInfo Record Receive Controller/osm_pir_rcv_ctrl_destroy +* NAME +* osm_pir_rcv_ctrl_destroy +* +* DESCRIPTION +* The osm_pir_rcv_ctrl_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_pir_rcv_ctrl_destroy( + IN osm_pir_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* PortInfo Record Receive Controller object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_pir_rcv_ctrl_construct or osm_pir_rcv_ctrl_init. +* +* SEE ALSO +* PortInfo Record Receive Controller object, osm_pir_rcv_ctrl_construct, +* osm_pir_rcv_ctrl_init +*********/ + +/****f* OpenSM: PortInfo Record Receive Controller/osm_pir_rcv_ctrl_init +* NAME +* osm_pir_rcv_ctrl_init +* +* DESCRIPTION +* The osm_pir_rcv_ctrl_init function initializes a +* PortInfo Record Receive Controller object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_pir_rcv_ctrl_init( + IN osm_pir_rcv_ctrl_t* const p_ctrl, + IN osm_pir_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_pir_rcv_ctrl_t object to initialize. +* +* p_rcv +* [in] Pointer to an osm_pir_rcv_t object. +* +* p_log +* [in] Pointer to the log object. +* +* p_disp +* [in] Pointer to the OpenSM central Dispatcher. +* +* RETURN VALUES +* CL_SUCCESS if the PortInfo Record Receive Controller object was initialized +* successfully. +* +* NOTES +* Allows calling other PortInfo Record Receive Controller methods. +* +* SEE ALSO +* PortInfo Record Receive Controller object, osm_pir_rcv_ctrl_construct, +* osm_pir_rcv_ctrl_destroy +*********/ + +END_C_DECLS + +#endif /* _OSM_PIR_CTRL_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_response.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_response.h new file mode 100644 index 00000000..8fa97af9 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_response.h @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_response.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_sa_resp_t. + * This object represents an object that responds to SA queries. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_SA_RESP_H_ +#define _OSM_SA_RESP_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/SA Response +* NAME +* SA Response +* +* DESCRIPTION +* The SA Response object encapsulates the information +* needed to respond to an SA query. +* +* The SA Response object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Ranjit Pandit, Intel +* Steve King, Intel +* +*********/ + +/****s* OpenSM: SA Response/osm_sa_resp_t +* NAME +* osm_sa_resp_t +* +* DESCRIPTION +* SA Response structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_sa_resp +{ + osm_mad_pool_t *p_pool; + osm_log_t *p_log; +} osm_sa_resp_t; +/* +* FIELDS +* p_pool +* Pointer to the MAD pool. +* +* SEE ALSO +* SA Response object +*********/ + +/****f* OpenSM: SA Response/osm_sa_resp_construct +* NAME +* osm_sa_resp_construct +* +* DESCRIPTION +* This function constructs a SA Response object. +* +* SYNOPSIS +*/ +void +osm_sa_resp_construct( + IN osm_sa_resp_t* const p_resp ); +/* +* PARAMETERS +* p_resp +* [in] Pointer to a SA Response object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_sa_resp_init, and osm_sa_resp_destroy. +* +* Calling osm_sa_resp_construct is a prerequisite to calling any other +* method except osm_sa_resp_init. +* +* SEE ALSO +* SA Response object, osm_sa_resp_init, +* osm_sa_resp_destroy +*********/ + +/****f* OpenSM: SA Response/osm_sa_resp_destroy +* NAME +* osm_sa_resp_destroy +* +* DESCRIPTION +* The osm_sa_resp_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_sa_resp_destroy( + IN osm_sa_resp_t* const p_resp ); +/* +* PARAMETERS +* p_resp +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* SA Response object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_sa_resp_construct or osm_sa_resp_init. +* +* SEE ALSO +* SA Response object, osm_sa_resp_construct, +* osm_sa_resp_init +*********/ + +/****f* OpenSM: SA Response/osm_sa_resp_init +* NAME +* osm_sa_resp_init +* +* DESCRIPTION +* The osm_sa_resp_init function initializes a +* SA Response object for use. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_sa_resp_init( + IN osm_sa_resp_t* const p_resp, + IN osm_mad_pool_t* const p_pool, + IN osm_log_t* const p_log ); +/* +* PARAMETERS +* p_resp +* [in] Pointer to an osm_sa_resp_t object to initialize. +* +* p_mad_pool +* [in] Pointer to the MAD pool. +* +* p_vl15 +* [in] Pointer to the VL15 interface. +* +* p_log +* [in] Pointer to the log object. +* +* RETURN VALUES +* IB_SUCCESS if the SA Response object was initialized +* successfully. +* +* NOTES +* Allows calling other SA Response methods. +* +* SEE ALSO +* SA Response object, osm_sa_resp_construct, +* osm_sa_resp_destroy +*********/ + +/****f* IBA Base: Types/osm_sa_send_error +* NAME +* osm_sa_send_error +* +* DESCRIPTION +* Sends a generic SA response with the specified error status. +* The payload is simply replicated from the request MAD. +* +* SYNOPSIS +*/ +void +osm_sa_send_error( + IN osm_sa_resp_t* const p_resp, + IN const osm_madw_t* const p_madw, + IN const ib_net16_t sa_status ); +/* +* PARAMETERS +* p_resp +* [in] Pointer to an osm_sa_resp_t object. +* +* p_madw +* [in] Original MAD to which the response must be sent. +* +* sa_status +* [in] Status to send in the response. +* +* RETURN VALUES +* None. +* +* NOTES +* Allows calling other SA Response methods. +* +* SEE ALSO +* SA Response object, osm_sa_resp_construct, +* osm_sa_resp_destroy +*********/ + +END_C_DECLS + +#endif /* _OSM_SA_RESP_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_service_record.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_service_record.h new file mode 100644 index 00000000..549706b8 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_service_record.h @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_service_record.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_sr_rcv_t. + * This object represents the ServiceRecord Receiver object. + * attribute from a node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_SR_H_ +#define _OSM_SR_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Service Record Receiver +* NAME +* Service Record Receiver +* +* DESCRIPTION +* The Service Record Receiver object encapsulates the information +* needed to receive the ServiceRecord request from a node. +* +* The Service Record Receiver object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Anil S Keshavamurthy +* +*********/ + +/****s* OpenSM: Service Record Receiver/osm_sr_rcv_t +* NAME +* osm_sr_rcv_t +* +* DESCRIPTION +* Service Record Receiver structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_sr_rcv +{ + osm_subn_t *p_subn; + osm_sa_resp_t *p_resp; + osm_mad_pool_t *p_mad_pool; + osm_log_t *p_log; + cl_plock_t *p_lock; + cl_qlock_pool_t sr_pool; + cl_timer_t sr_timer; + +} osm_sr_rcv_t; +/* +* FIELDS +* p_subn +* Pointer to the Subnet object for this subnet. +* +* p_resp +* Pointer to the osm_sa_resp_t object. +* +* p_log +* Pointer to the log object. +* +* p_lock +* Pointer to the serializing lock. +* +* sr_pool +* Pool of Service Record objects used to generate query responses. +* +* SEE ALSO +* Service Record Receiver object +*********/ + +/****f* OpenSM: Service Record Receiver/osm_sr_rcv_construct +* NAME +* osm_sr_rcv_construct +* +* DESCRIPTION +* This function constructs a Service Record Receiver object. +* +* SYNOPSIS +*/ +void +osm_sr_rcv_construct( + IN osm_sr_rcv_t* const p_rcv ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to a Service Record Receiver object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_sr_rcv_init, osm_sr_rcv_destroy +* +* Calling osm_sr_rcv_construct is a prerequisite to calling any other +* method except osm_sr_rcv_init. +* +* SEE ALSO +* Service Record Receiver object, osm_sr_rcv_init, osm_sr_rcv_destroy +*********/ + +/****f* OpenSM: Service Record Receiver/osm_sr_rcv_destroy +* NAME +* osm_sr_rcv_destroy +* +* DESCRIPTION +* The osm_sr_rcv_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_sr_rcv_destroy( + IN osm_sr_rcv_t* const p_rcv ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* Service Record Receiver object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_sr_rcv_construct or osm_sr_rcv_init. +* +* SEE ALSO +* Service Record Receiver object, osm_sr_rcv_construct, +* osm_sr_rcv_init +*********/ + +/****f* OpenSM: Service Record Receiver/osm_sr_rcv_init +* NAME +* osm_sr_rcv_init +* +* DESCRIPTION +* The osm_sr_rcv_init function initializes a +* Service Record Receiver object for use. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_sr_rcv_init( + IN osm_sr_rcv_t* const p_rcv, + IN osm_sa_resp_t* const p_resp, + IN osm_mad_pool_t* const p_mad_pool, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to an osm_sr_rcv_t object to initialize. +* +* p_subn +* [in] Pointer to the Subnet object for this subnet. +* +* p_log +* [in] Pointer to the log object. +* +* p_lock +* [in] Pointer to the OpenSM serializing lock. +* +* RETURN VALUES +* IB_SUCCESS if the Service Record Receiver object was initialized +* successfully. +* +* NOTES +* Allows calling other Service Record Receiver methods. +* +* SEE ALSO +* Service Record Receiver object, osm_sr_rcv_construct, +* osm_sr_rcv_destroy +*********/ + +/****f* OpenSM: Service Record Receiver/osm_sr_rcv_process +* NAME +* osm_sr_rcv_process +* +* DESCRIPTION +* Process the ServiceRecord request. +* +* SYNOPSIS +*/ +void +osm_sr_rcv_process( + IN osm_sr_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to an osm_sr_rcv_t object. +* +* p_madw +* [in] Pointer to the MAD Wrapper containing the MAD +* that contains the node's ServiceRecord attribute. +* NOTES +* This function processes a ServiceRecord attribute. +* +* SEE ALSO +* Service Record Receiver +*********/ + +/****f* OpenSM: Service Record Receiver/osm_sr_rcv_lease_cb +* NAME +* osm_sr_rcv_lease_cb +* +* DESCRIPTION +* Timer Callback function which is executed to check the lease period +* expiration +* +* SYNOPSIS +*/ + +void +osm_sr_rcv_lease_cb( + IN void* context ); +/* +* PARAMETERS +* context +* [in] Pointer to osm_sa_db_t object. +* +* NOTES +* This function processes a ServiceRecord attribute. +* +* SEE ALSO +* Service Record Receiver +*********/ + +END_C_DECLS + +#endif /* _OSM_SR_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_service_record_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_service_record_ctrl.h new file mode 100644 index 00000000..f542c362 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_service_record_ctrl.h @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_service_record_ctrl.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_sr_rcv_ctrl_t. + * This object represents a controller that receives the IBA Service + * record attribute from a node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_SRCTRL_H_ +#define _OSM_SRCTRL_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Service Record Receive Controller +* NAME +* Service Record Receive Controller +* +* DESCRIPTION +* The Service Record Receive Controller object encapsulates +* the information needed to receive the Service Record attribute from a node. +* +* The Service Record Receive Controller object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Anil S Keshavamurthy, Intel +* +*********/ + +/****s* OpenSM: Service Record Receive Controller/osm_sr_rcv_ctrl_t +* NAME +* osm_sr_rcv_ctrl_t +* +* DESCRIPTION +* Service Record Receive Controller structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_sr_rcv_ctrl +{ + osm_sr_rcv_t *p_rcv; + osm_log_t *p_log; + cl_dispatcher_t *p_disp; + cl_disp_reg_handle_t h_disp; + +} osm_sr_rcv_ctrl_t; +/* +* FIELDS +* p_rcv +* Pointer to the Service Record Receiver object. +* +* p_log +* Pointer to the log object. +* +* p_disp +* Pointer to the Dispatcher. +* +* h_disp +* Handle returned from dispatcher registration. +* +* SEE ALSO +* Service Record Receiver object +*********/ + +/****f* OpenSM: Service Record Receive Controller/osm_sr_rcv_ctrl_construct +* NAME +* osm_sr_rcv_ctrl_construct +* +* DESCRIPTION +* This function constructs a Service Record Receive Controller object. +* +* SYNOPSIS +*/ +void osm_sr_rcv_ctrl_construct( + IN osm_sr_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a Service Record Receive Controller +* object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_sr_rcv_ctrl_init, osm_sr_rcv_ctrl_destroy, +* +* Calling osm_sr_rcv_ctrl_construct is a prerequisite to calling any other +* method except osm_psr_rcv_ctrl_init. +* +* SEE ALSO +* Service Record Receive Controller object, osm_sr_rcv_ctrl_init, +* osm_sr_rcv_ctrl_destroy +*********/ + +/****f* OpenSM: Service Record Receive Controller/osm_sr_rcv_ctrl_destroy +* NAME +* osm_sr_rcv_ctrl_destroy +* +* DESCRIPTION +* The osm_sr_rcv_ctrl_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_sr_rcv_ctrl_destroy( + IN osm_sr_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* Service Record Receive Controller object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_sr_rcv_ctrl_construct or osm_sr_rcv_ctrl_init. +* +* SEE ALSO +* Service Record Receive Controller object, osm_sr_rcv_ctrl_construct, +* osm_sr_rcv_ctrl_init +*********/ + +/****f* OpenSM: Service Record Receive Controller/osm_sr_rcv_ctrl_init +* NAME +* osm_sr_rcv_ctrl_init +* +* DESCRIPTION +* The osm_sr_rcv_ctrl_init function initializes a +* Service Record Receive Controller object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_sr_rcv_ctrl_init( + IN osm_sr_rcv_ctrl_t* const p_ctrl, + IN osm_sr_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_sr_rcv_ctrl_t object to initialize. +* +* p_rcv +* [in] Pointer to an osm_sr_rcv_t object. +* +* p_log +* [in] Pointer to the log object. +* +* p_disp +* [in] Pointer to the OpenSM central Dispatcher. +* +* RETURN VALUES +* IB_SUCCESS if the osm_sr_rcv_t Receive Controller object was initialized +* successfully. +* +* NOTES +* Allows calling other Service Record Receive Controller methods. +* +* SEE ALSO +* Service Record Receive Controller object, osm_sr_rcv_ctrl_construct, +* osm_sr_rcv_ctrl_destroy +*********/ + +END_C_DECLS + +#endif /* _OSM_SRCTRL_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_slvl_record.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_slvl_record.h new file mode 100644 index 00000000..29dce36c --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_slvl_record.h @@ -0,0 +1,281 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_slvl_record.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_slvl_rec_rcv_t. + * This object represents the SLtoVL Mapping Table Receiver object. + * attribute from a SA query. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.3 $ + */ + +#ifndef _OSM_SLVL_REC_RCV_H_ +#define _OSM_SLVL_REC_RCV_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/SLtoVL Mapping Record Receiver +* NAME +* SLtoVL Mapping Record Receiver +* +* DESCRIPTION +* The SLtoVL Mapping Record Receiver object encapsulates the information +* needed to handle SLtoVL Mapping Record query from a SA. +* +* The SLtoVL Mapping Record Receiver object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Eitan Zahavi, Mellanox +* +*********/ + +/****s* OpenSM: SLtoVL Mapping Record Receiver/osm_slvl_rec_rcv_t +* NAME +* osm_slvl_rec_rcv_t +* +* DESCRIPTION +* SLtoVL Mapping Record Receiver structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_slvl_rec_rcv +{ + const osm_subn_t *p_subn; + osm_sa_resp_t *p_resp; + osm_mad_pool_t *p_mad_pool; + osm_log_t *p_log; + cl_plock_t *p_lock; + cl_qlock_pool_t pool; + +} osm_slvl_rec_rcv_t; +/* +* FIELDS +* p_subn +* Pointer to the Subnet object for this subnet. +* +* p_resp +* Pointer to the SA responder. +* +* p_mad_pool +* Pointer to the mad pool. +* +* p_log +* Pointer to the log object. +* +* p_lock +* Pointer to the serializing lock. +* +* pool +* Pool of linkable SLtoVL Mapping Record objects used to generate +* the query response. +* +* SEE ALSO +* +*********/ + +/****f* OpenSM: SLtoVL Mapping Record Receiver/osm_slvl_rec_rcv_construct +* NAME +* osm_slvl_rec_rcv_construct +* +* DESCRIPTION +* This function constructs a SLtoVL Mapping Record Receiver object. +* +* SYNOPSIS +*/ +void +osm_slvl_rec_rcv_construct( + IN osm_slvl_rec_rcv_t* const p_rcv ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to a SLtoVL Mapping Record Receiver object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_slvl_rec_rcv_init, osm_slvl_rec_rcv_destroy +* +* Calling osm_slvl_rec_rcv_construct is a prerequisite to calling any other +* method except osm_slvl_rec_rcv_init. +* +* SEE ALSO +* SLtoVL Mapping Record Receiver object, osm_slvl_rec_rcv_init, +* osm_slvl_rec_rcv_destroy +*********/ + +/****f* OpenSM: SLtoVL Mapping Record Receiver/osm_slvl_rec_rcv_destroy +* NAME +* osm_slvl_rec_rcv_destroy +* +* DESCRIPTION +* The osm_slvl_rec_rcv_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_slvl_rec_rcv_destroy( + IN osm_slvl_rec_rcv_t* const p_rcv ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* SLtoVL Mapping Record Receiver object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_slvl_rec_rcv_construct or osm_slvl_rec_rcv_init. +* +* SEE ALSO +* SLtoVL Mapping Record Receiver object, osm_slvl_rec_rcv_construct, +* osm_slvl_rec_rcv_init +*********/ + +/****f* OpenSM: SLtoVL Mapping Record Receiver/osm_slvl_rec_rcv_init +* NAME +* osm_slvl_rec_rcv_init +* +* DESCRIPTION +* The osm_slvl_rec_rcv_init function initializes a +* SLtoVL Mapping Record Receiver object for use. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_slvl_rec_rcv_init( + IN osm_slvl_rec_rcv_t* const p_rcv, + IN osm_sa_resp_t* const p_resp, + IN osm_mad_pool_t* const p_mad_pool, + IN const osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to an osm_slvl_rec_rcv_t object to initialize. +* +* p_req +* [in] Pointer to an osm_req_t object. +* +* p_subn +* [in] Pointer to the Subnet object for this subnet. +* +* p_log +* [in] Pointer to the log object. +* +* p_lock +* [in] Pointer to the OpenSM serializing lock. +* +* RETURN VALUES +* CL_SUCCESS if the SLtoVL Mapping Record Receiver object was initialized +* successfully. +* +* NOTES +* Allows calling other SLtoVL Mapping Record Receiver methods. +* +* SEE ALSO +* SLtoVL Mapping Record Receiver object, osm_slvl_rec_rcv_construct, +* osm_slvl_rec_rcv_destroy +*********/ + +/****f* OpenSM: SLtoVL Mapping Record Receiver/osm_slvl_rec_rcv_process +* NAME +* osm_slvl_rec_rcv_process +* +* DESCRIPTION +* Process the SLtoVL Map Table Query . +* +* SYNOPSIS +*/ +void +osm_slvl_rec_rcv_process( + IN osm_slvl_rec_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to an osm_slvl_rec_rcv_t object. +* +* p_madw +* [in] Pointer to the MAD Wrapper containing the MAD +* that contains the SLtoVL Map Record Query attribute. +* +* RETURN VALUES +* CL_SUCCESS if the Query processing was successful. +* +* NOTES +* This function processes a SA SLtoVL Map Record attribute. +* +* SEE ALSO +* SLtoVL Mapping Record Receiver, SLtoVL Mapping Record Response Controller +*********/ + +END_C_DECLS + +#endif /* _OSM_SLVL_REC_RCV_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_slvl_record_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_slvl_record_ctrl.h new file mode 100644 index 00000000..8e8108c6 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_slvl_record_ctrl.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_slvl_record_ctrl.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_sa_slvl_rec_rcv_ctrl_t. + * This object represents a controller that receives the IBA VL Arbitration + * record query from SA client. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.3 $ + */ + +#ifndef _OSM_SLVL_REC_CTRL_H_ +#define _OSM_SLVL_REC_CTRL_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/SLtoVL Record Receive Controller +* NAME +* SLtoVL Record Receive Controller +* +* DESCRIPTION +* The SLtoVL Mapping Record Receive Controller object encapsulates +* the information needed to handle SLtoVL Mapping record query from SA client. +* +* The SLtoVL Mapping Record Receive Controller object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Eitan Zahavi, Mellanox +* +*********/ + +/****s* OpenSM: SLtoVL Mapping Record Receive Controller/osm_slvl_rec_rcv_ctrl_t +* NAME +* osm_slvl_rec_rcv_ctrl_t +* +* DESCRIPTION +* SLtoVL Mapping Record Receive Controller structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_slvl_rec_rcv_ctrl +{ + osm_slvl_rec_rcv_t *p_rcv; + osm_log_t *p_log; + cl_dispatcher_t *p_disp; + cl_disp_reg_handle_t h_disp; + +} osm_slvl_rec_rcv_ctrl_t; +/* +* FIELDS +* p_rcv +* Pointer to the SLtoVL Mapping Record Receiver object. +* +* p_log +* Pointer to the log object. +* +* p_disp +* Pointer to the Dispatcher. +* +* h_disp +* Handle returned from dispatcher registration. +* +* SEE ALSO +* SLtoVL Mapping Record Receive Controller object +* SLtoVL Mapping Record Receiver object +*********/ + +/****f* OpenSM: SLtoVL Mapping Record Receive Controller/osm_slvl_rec_rcv_ctrl_construct +* NAME +* osm_slvl_rec_rcv_ctrl_construct +* +* DESCRIPTION +* This function constructs a SLtoVL Mapping Record Receive Controller object. +* +* SYNOPSIS +*/ +void osm_slvl_rec_rcv_ctrl_construct( + IN osm_slvl_rec_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a SLtoVL Mapping Record Receive Controller +* object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_slvl_rec_rcv_ctrl_init, osm_slvl_rec_rcv_ctrl_destroy +* +* Calling osm_slvl_rec_rcv_ctrl_construct is a prerequisite to calling any other +* method except osm_slvl_rec_rcv_ctrl_init. +* +* SEE ALSO +* SLtoVL Mapping Record Receive Controller object, osm_slvl_rec_rcv_ctrl_init, +* osm_slvl_rec_rcv_ctrl_destroy +*********/ + +/****f* OpenSM: SLtoVL Mapping Record Receive Controller/osm_slvl_rec_rcv_ctrl_destroy +* NAME +* osm_slvl_rec_rcv_ctrl_destroy +* +* DESCRIPTION +* The osm_slvl_rec_rcv_ctrl_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_slvl_rec_rcv_ctrl_destroy( + IN osm_slvl_rec_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* SLtoVL Mapping Record Receive Controller object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_slvl_rec_rcv_ctrl_construct or osm_slvl_rec_rcv_ctrl_init. +* +* SEE ALSO +* SLtoVL Mapping Record Receive Controller object, osm_slvl_rec_rcv_ctrl_construct, +* osm_slvl_rec_rcv_ctrl_init +*********/ + +/****f* OpenSM: SLtoVL Mapping Record Receive Controller/osm_slvl_rec_rcv_ctrl_init +* NAME +* osm_slvl_rec_rcv_ctrl_init +* +* DESCRIPTION +* The osm_slvl_rec_rcv_ctrl_init function initializes a +* SLtoVL Mapping Record Receive Controller object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_slvl_rec_rcv_ctrl_init( + IN osm_slvl_rec_rcv_ctrl_t* const p_ctrl, + IN osm_slvl_rec_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_slvl_rec_rcv_ctrl_t object to initialize. +* +* p_rcv +* [in] Pointer to an osm_slvl_rec_rcv_t object. +* +* p_log +* [in] Pointer to the log object. +* +* p_disp +* [in] Pointer to the OpenSM central Dispatcher. +* +* RETURN VALUES +* CL_SUCCESS if the SLtoVL Mapping Record Receive Controller object was initialized +* successfully. +* +* NOTES +* Allows calling other SLtoVL Mapping Record Receive Controller methods. +* +* SEE ALSO +* SLtoVL Mapping Record Receive Controller object, osm_slvl_rec_rcv_ctrl_construct, +* osm_slvl_rec_rcv_ctrl_destroy +*********/ + +END_C_DECLS + +#endif /* _OSM_SLVL_REC_CTRL_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_sminfo_record.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_sminfo_record.h new file mode 100644 index 00000000..5b4c8ead --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_sminfo_record.h @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_sminfo_record.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_smir_rcv_t. + * This object represents the SMInfo Receiver object. + * attribute from a node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_SMIR_H_ +#define _OSM_SMIR_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/SM Info Receiver +* NAME +* SM Info Receiver +* +* DESCRIPTION +* The SM Info Receiver object encapsulates the information +* needed to receive the SMInfoRecord attribute from a node. +* +* The SM Info Receiver object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Ranjit Pandit, Intel +* +*********/ +/****s* OpenSM: SM Info Receiver/osm_smir_rcv_t +* NAME +* osm_smir_rcv_t +* +* DESCRIPTION +* SM Info Receiver structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_smir +{ + osm_subn_t* p_subn; + osm_stats_t* p_stats; + osm_sa_resp_t* p_resp; + osm_mad_pool_t* p_mad_pool; + osm_log_t* p_log; + cl_plock_t* p_lock; + cl_qlock_pool_t pool; +} osm_smir_rcv_t; +/* +* FIELDS +* p_subn +* Pointer to the Subnet object for this subnet. +* +* SEE ALSO +* SM Info Receiver object +*********/ + +/****f* OpenSM: SM Info Receiver/osm_smir_rcv_construct +* NAME +* osm_smir_rcv_construct +* +* DESCRIPTION +* This function constructs a SM Info Receiver object. +* +* SYNOPSIS +*/ +void osm_smir_rcv_construct( + IN osm_smir_rcv_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a SM Info Receiver object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_smir_rcv_init, osm_smir_rcv_destroy +* +* Calling osm_smir_rcv_construct is a prerequisite to calling any other +* method except osm_smir_rcv_init. +* +* SEE ALSO +* SM Info Receiver object, osm_smir_rcv_init, osm_smir_rcv_destroy +*********/ + +/****f* OpenSM: SM Info Receiver/osm_smir_rcv_destroy +* NAME +* osm_smir_rcv_destroy +* +* DESCRIPTION +* The osm_smir_rcv_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_smir_rcv_destroy( + IN osm_smir_rcv_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* SM Info Receiver object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_smir_rcv_construct or osm_smir_rcv_init. +* +* SEE ALSO +* SM Info Receiver object, osm_smir_rcv_construct, +* osm_smir_rcv_init +*********/ + +/****f* OpenSM: SM Info Receiver/osm_smir_rcv_init +* NAME +* osm_smir_rcv_init +* +* DESCRIPTION +* The osm_smir_rcv_init function initializes a +* SM Info Receiver object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_smir_rcv_init( + IN osm_smir_rcv_t* const p_ctrl, + IN osm_sa_resp_t* const p_resp, + IN osm_mad_pool_t* const p_mad_pool, + IN osm_subn_t* const p_subn, + IN osm_stats_t* const p_stats, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_smir_rcv_t object to initialize. +* +* p_req +* [in] Pointer to an osm_req_t object. +* +* p_subn +* [in] Pointer to the Subnet object for this subnet. +* +* p_stats +* [in] Pointer to the Statistics object for this subnet. +* +* p_log +* [in] Pointer to the log object. +* +* p_lock +* [in] Pointer to the OpenSM serializing lock. +* +* RETURN VALUES +* CL_SUCCESS if the SM Info Receiver object was initialized +* successfully. +* +* NOTES +* Allows calling other SM Info Receiver methods. +* +* SEE ALSO +* SM Info Receiver object, osm_smir_rcv_construct, osm_smir_rcv_destroy +*********/ + +/****f* OpenSM: SM Info Receiver/osm_smir_rcv_process +* NAME +* osm_smir_rcv_process +* +* DESCRIPTION +* Process the SMInfoRecord attribute. +* +* SYNOPSIS +*/ +void osm_smir_rcv_process( + IN osm_smir_rcv_t* const p_ctrl, + IN const osm_madw_t* const p_madw ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_smir_rcv_t object. +* +* p_madw +* [in] Pointer to the MAD Wrapper containing the MAD +* that contains the node's SMInfoRecord attribute. +* +* RETURN VALUES +* CL_SUCCESS if the SMInfoRecord processing was successful. +* +* NOTES +* This function processes a SMInfoRecord attribute. +* +* SEE ALSO +* SM Info Receiver, SM Info Response Controller +*********/ + +END_C_DECLS + +#endif /* _OSM_SMIR_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_sminfo_record_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_sminfo_record_ctrl.h new file mode 100644 index 00000000..861c1482 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_sminfo_record_ctrl.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_sminfo_record_ctrl.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_smir_ctrl_t. + * This object represents a controller that receives the IBA SMInfo + * attribute from a node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_SMIR_CTRL_H_ +#define _OSM_SMIR_CTRL_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/SM Info Receive Controller +* NAME +* SM Info Receive Controller +* +* DESCRIPTION +* The SM Info Receive Controller object encapsulates +* the information needed to receive the SMInfo attribute from a node. +* +* The SM Info Receive Controller object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Ranjit Pandit, Intel +* +*********/ + +/****s* OpenSM: SM Info Receive Controller/osm_smir_ctrl_t +* NAME +* osm_smir_ctrl_t +* +* DESCRIPTION +* SM Info Receive Controller structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_smir_ctrl +{ + osm_smir_rcv_t *p_rcv; + osm_log_t *p_log; + cl_dispatcher_t *p_disp; + cl_disp_reg_handle_t h_disp; + +} osm_smir_ctrl_t; +/* +* FIELDS +* p_rcv +* Pointer to the SM Info Receiver object. +* +* p_log +* Pointer to the log object. +* +* p_disp +* Pointer to the Dispatcher. +* +* h_disp +* Handle returned from dispatcher registration. +* +* SEE ALSO +* SM Info Receive Controller object +* SM Info Receiver object +*********/ + +/****f* OpenSM: SM Info Receive Controller/osm_smir_ctrl_construct +* NAME +* osm_smir_ctrl_construct +* +* DESCRIPTION +* This function constructs a SM Info Receive Controller object. +* +* SYNOPSIS +*/ +void osm_smir_ctrl_construct( + IN osm_smir_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a SM Info Receive Controller +* object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_smir_ctrl_init, osm_smir_ctrl_destroy +* +* Calling osm_smir_ctrl_construct is a prerequisite to calling any other +* method except osm_smir_ctrl_init. +* +* SEE ALSO +* SM Info Receive Controller object, osm_smir_ctrl_init, +* osm_smir_ctrl_destroy +*********/ + +/****f* OpenSM: SM Info Receive Controller/osm_smir_ctrl_destroy +* NAME +* osm_smir_ctrl_destroy +* +* DESCRIPTION +* The osm_smir_ctrl_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_smir_ctrl_destroy( + IN osm_smir_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* SM Info Receive Controller object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_smir_ctrl_construct or osm_smir_ctrl_init. +* +* SEE ALSO +* SM Info Receive Controller object, osm_smir_ctrl_construct, +* osm_smir_ctrl_init +*********/ + +/****f* OpenSM: SM Info Receive Controller/osm_smir_ctrl_init +* NAME +* osm_smir_ctrl_init +* +* DESCRIPTION +* The osm_smir_ctrl_init function initializes a +* SM Info Receive Controller object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_smir_ctrl_init( + IN osm_smir_ctrl_t* const p_ctrl, + IN osm_smir_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_smir_ctrl_t object to initialize. +* +* p_rcv +* [in] Pointer to an osm_smir_t object. +* +* p_log +* [in] Pointer to the log object. +* +* p_disp +* [in] Pointer to the OpenSM central Dispatcher. +* +* RETURN VALUES +* CL_SUCCESS if the SM Info Receive Controller object was initialized +* successfully. +* +* NOTES +* Allows calling other SM Info Receive Controller methods. +* +* SEE ALSO +* SM Info Receive Controller object, osm_smir_ctrl_construct, +* osm_smir_ctrl_destroy +*********/ + +END_C_DECLS + +#endif /* _OSM_SMIR_CTRL_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_sw_info_record.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_sw_info_record.h new file mode 100644 index 00000000..e8cf0bb0 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_sw_info_record.h @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ + + +/* + * Abstract: + * Declaration of osm_sir_rcv_t. + * This object represents the SwitchInfo Receiver object. + * attribute from a switch node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + */ + +#ifndef _OSM_SIR_RCV_H_ +#define _OSM_SIR_RCV_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Switch Info Receiver +* NAME +* Switch Info Receiver +* +* DESCRIPTION +* The Switch Info Receiver object encapsulates the information +* needed to receive the SwitchInfo attribute from a switch node. +* +* The Switch Info Receiver object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Hal Rosenstock, Voltaire +* +*********/ + +/****s* OpenSM: Switch Info Receiver/osm_sir_rcv_t +* NAME +* osm_sir_rcv_t +* +* DESCRIPTION +* Switch Info Receiver structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_sir_rcv +{ + osm_subn_t *p_subn; + osm_sa_resp_t *p_resp; + osm_mad_pool_t *p_mad_pool; + osm_log_t *p_log; + osm_req_t *p_req; + osm_state_mgr_t *p_state_mgr; + cl_plock_t *p_lock; + cl_qlock_pool_t pool; +} osm_sir_rcv_t; +/* +* FIELDS +* p_subn +* Pointer to the Subnet object for this subnet. +* +* p_log +* Pointer to the log object. +* +* p_req +* Pointer to the Request object. +* +* p_state_mgr +* Pointer to the State Manager object. +* +* p_lock +* Pointer to the serializing lock. +* +* SEE ALSO +* Switch Info Receiver object +*********/ + +/****f* OpenSM: Switch Info Receiver/osm_sir_rcv_construct +* NAME +* osm_sir_rcv_construct +* +* DESCRIPTION +* This function constructs a Switch Info Receiver object. +* +* SYNOPSIS +*/ +void osm_sir_rcv_construct( + IN osm_sir_rcv_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a Switch Info Receiver object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_sir_rcv_init, osm_sir_rcv_destroy, +* and osm_sir_rcv_is_inited. +* +* Calling osm_sir_rcv_construct is a prerequisite to calling any other +* method except osm_sir_rcv_init. +* +* SEE ALSO +* Switch Info Receiver object, osm_sir_rcv_init, +* osm_sir_rcv_destroy, osm_sir_rcv_is_inited +*********/ + +/****f* OpenSM: Switch Info Receiver/osm_sir_rcv_destroy +* NAME +* osm_sir_rcv_destroy +* +* DESCRIPTION +* The osm_sir_rcv_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_sir_rcv_destroy( + IN osm_sir_rcv_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* Switch Info Receiver object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_sir_rcv_construct or osm_sir_rcv_init. +* +* SEE ALSO +* Switch Info Receiver object, osm_sir_rcv_construct, +* osm_sir_rcv_init +*********/ + +/****f* OpenSM: Switch Info Receiver/osm_sir_rcv_init +* NAME +* osm_sir_rcv_init +* +* DESCRIPTION +* The osm_sir_rcv_init function initializes a +* Switch Info Receiver object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_sir_rcv_init( + IN osm_sir_rcv_t* const p_rcv, + IN osm_sa_resp_t* const p_resp, + IN osm_mad_pool_t* const p_mad_pool, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to an osm_sir_rcv_t object to initialize. +* +* p_resp +* [in] Pointer to the SA Responder object. +* +* p_mad_pool +* [in] Pointer to the mad pool. +* +* p_subn +* [in] Pointer to the Subnet object for this subnet. +* +* p_log +* [in] Pointer to the log object. +* +* p_lock +* [in] Pointer to the OpenSM serializing lock. +* +* RETURN VALUES +* IB_SUCCESS if the Switch Info Receiver object was initialized +* successfully. +* +* NOTES +* Allows calling other Switch Info Receiver methods. +* +* SEE ALSO +* Switch Info Receiver object, osm_sir_rcv_construct, +* osm_sir_rcv_destroy, osm_sir_rcv_is_inited +*********/ + +/****f* OpenSM: Switch Info Receiver/osm_sir_rcv_is_inited +* NAME +* osm_sir_rcv_is_inited +* +* DESCRIPTION +* Indicates if the object has been initialized with osm_sir_rcv_init. +* +* SYNOPSIS +*/ +boolean_t osm_sir_rcv_is_inited( + IN const osm_sir_rcv_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_sir_rcv_t object. +* +* RETURN VALUES +* TRUE if the object was initialized successfully, +* FALSE otherwise. +* +* NOTES +* The osm_sir_rcv_construct or osm_sir_rcv_init must be +* called before using this function. +* +* SEE ALSO +* Switch Info Receiver object, osm_sir_rcv_construct, +* osm_sir_rcv_init +*********/ + +/****f* OpenSM: Switch Info Receiver/osm_sir_rcv_process +* NAME +* osm_sir_rcv_process +* +* DESCRIPTION +* Process the SwitchInfo attribute. +* +* SYNOPSIS +*/ +void osm_sir_rcv_process( + IN osm_sir_rcv_t* const p_ctrl, + IN const osm_madw_t* const p_madw ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_sir_rcv_t object. +* +* p_madw +* [in] Pointer to the MAD Wrapper containing the MAD +* that contains the node's SwitchInfo attribute. +* +* RETURN VALUES +* CL_SUCCESS if the SwitchInfo processing was successful. +* +* NOTES +* This function processes a SwitchInfo attribute. +* +* SEE ALSO +* Switch Info Receiver, Switch Info Response Controller +*********/ + +END_C_DECLS + +#endif /* _OSM_SIR_RCV_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_sw_info_record_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_sw_info_record_ctrl.h new file mode 100644 index 00000000..86b9674f --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_sw_info_record_ctrl.h @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ + + +/* + * Abstract: + * Declaration of osm_sir_rcv_ctrl_t. + * This object represents a controller that receives the IBA SwitchInfo + * attribute from a switch node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + */ + +#ifndef _OSM_SIR_RCV_CTRL_H_ +#define _OSM_SIR_RCV_CTRL_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Switch Info Receive Controller +* NAME +* Switch Info Receive Controller +* +* DESCRIPTION +* The Switch Info Receive Controller object encapsulates the information +* needed to receive the SwitchInfo attribute from a switch node. +* +* The Switch Info Receive Controller object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Hal Rosenstock, Voltaire +* +*********/ + +/****s* OpenSM: Switch Info Receive Controller/osm_sir_rcv_ctrl_t +* NAME +* osm_sir_rcv_ctrl_t +* +* DESCRIPTION +* Switch Info Receive Controller structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_sir_rcv_ctrl +{ + osm_sir_rcv_t *p_rcv; + osm_log_t *p_log; + cl_dispatcher_t *p_disp; + cl_disp_reg_handle_t h_disp; +} osm_sir_rcv_ctrl_t; +/* +* FIELDS +* p_rcv +* Pointer to the Switch Info Receiver object. +* +* p_log +* Pointer to the log object. +* +* p_disp +* Pointer to the Dispatcher. +* +* h_disp +* Handle returned from dispatcher registration. +* +* SEE ALSO +* Switch Info Receive Controller object +* Switch Info Receiver object +*********/ + +/****f* OpenSM: Switch Info Receive Controller/osm_sir_rcv_ctrl_construct +* NAME +* osm_sir_rcv_ctrl_construct +* +* DESCRIPTION +* This function constructs a Switch Info Receive Controller object. +* +* SYNOPSIS +*/ +void osm_sir_rcv_ctrl_construct( + IN osm_sir_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a Switch Info Receive Controller +* object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_sir_rcv_ctrl_init, osm_sir_rcv_ctrl_destroy, +* and osm_sir_rcv_ctrl_is_inited. +* +* Calling osm_sir_rcv_ctrl_construct is a prerequisite to calling any +* other method except osm_sir_rcv_ctrl_init. +* +* SEE ALSO +* Switch Info Receive Controller object, osm_sir_rcv_ctrl_init, +* osm_sir_rcv_ctrl_destroy, osm_sir_rcv_ctrl_is_inited +*********/ + +/****f* OpenSM: Switch Info Receive Controller/osm_sir_rcv_ctrl_destroy +* NAME +* osm_sir_rcv_ctrl_destroy +* +* DESCRIPTION +* The osm_sir_rcv_ctrl_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_sir_rcv_ctrl_destroy( + IN osm_sir_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* Switch Info Receive Controller object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_sir_rcv_ctrl_construct or osm_sir_rcv_ctrl_init. +* +* SEE ALSO +* Switch Info Receive Controller object, osm_sir_rcv_ctrl_construct, +* osm_sir_rcv_ctrl_init +*********/ + +/****f* OpenSM: Switch Info Receive Controller/osm_sir_rcv_ctrl_init +* NAME +* osm_sir_rcv_ctrl_init +* +* DESCRIPTION +* The osm_sir_rcv_ctrl_init function initializes a +* Switch Info Receive Controller object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_sir_rcv_ctrl_init( + IN osm_sir_rcv_ctrl_t* const p_ctrl, + IN osm_sir_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_sir_rcv_ctrl_t object to initialize. +* +* p_rcv +* [in] Pointer to an osm_sir_rcv_t object. +* +* p_log +* [in] Pointer to the log object. +* +* p_disp +* [in] Pointer to the OpenSM central Dispatcher. +* +* RETURN VALUES +* CL_SUCCESS if the Switch Info Receive Controller object was initialized +* successfully. +* +* NOTES +* Allows calling other Switch Info Receive Controller methods. +* +* SEE ALSO +* Switch Info Receive Controller object, osm_sir_rcv_ctrl_construct, +* osm_sir_rcv_ctrl_destroy, osm_sir_rcv_ctrl_is_inited +*********/ + +/****f* OpenSM: Switch Info Receive Controller/osm_sir_rcv_ctrl_is_inited +* NAME +* osm_sir_rcv_ctrl_is_inited +* +* DESCRIPTION +* Indicates if the object has been initialized with osm_sir_rcv_ctrl_init. +* +* SYNOPSIS +*/ +boolean_t osm_sir_rcv_ctrl_is_inited( + IN const osm_sir_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_sir_rcv_ctrl_t object. +* +* RETURN VALUES +* TRUE if the object was initialized successfully, +* FALSE otherwise. +* +* NOTES +* The osm_sir_rcv_ctrl_construct or osm_sir_rcv_ctrl_init must be +* called before using this function. +* +* SEE ALSO +* Switch Info Receive Controller object, osm_sir_rcv_ctrl_construct, +* osm_sir_rcv_ctrl_init +*********/ + +END_C_DECLS + +#endif /* _OSM_SIR_RCV_CTRL_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_vlarb_record.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_vlarb_record.h new file mode 100644 index 00000000..b3295007 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_vlarb_record.h @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_vlarb_record.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_vlarb_rec_rcv_t. + * This object represents the VLArbitration Record Receiver object. + * attribute from a node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.3 $ + */ + +#ifndef _OSM_VLARB_REC_RCV_H_ +#define _OSM_VLARB_REC_RCV_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/VLArbitration Record Receiver +* NAME +* VLArbitration Record Receiver +* +* DESCRIPTION +* The VLArbitration Record Receiver object encapsulates the information +* needed to handle VL Arbitration Record query from a SA. +* +* The VLArbitration Record Receiver object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Eitan Zahavi, Mellanox +* +*********/ + +/****s* OpenSM: VLArbitration Record Receiver/osm_vlarb_rec_rcv_t +* NAME +* osm_vlarb_rec_rcv_t +* +* DESCRIPTION +* VLArbitration Record Receiver structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_vlarb_rec_rcv +{ + const osm_subn_t *p_subn; + osm_sa_resp_t *p_resp; + osm_mad_pool_t *p_mad_pool; + osm_log_t *p_log; + cl_plock_t *p_lock; + cl_qlock_pool_t pool; +} osm_vlarb_rec_rcv_t; +/* +* FIELDS +* p_subn +* Pointer to the Subnet object for this subnet. +* +* p_resp +* Pointer to the SA responder. +* +* p_mad_pool +* Pointer to the mad pool. +* +* p_log +* Pointer to the log object. +* +* p_lock +* Pointer to the serializing lock. +* +* pool +* Pool of linkable VLArbitration Record objects used to generate +* the query response. +* +* SEE ALSO +* +*********/ + +/****f* OpenSM: VLArbitration Record Receiver/osm_vlarb_rec_rcv_construct +* NAME +* osm_vlarb_rec_rcv_construct +* +* DESCRIPTION +* This function constructs a VLArbitration Record Receiver object. +* +* SYNOPSIS +*/ +void +osm_vlarb_rec_rcv_construct( + IN osm_vlarb_rec_rcv_t* const p_rcv ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to a VLArbitration Record Receiver object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_vlarb_rec_rcv_init, osm_vlarb_rec_rcv_destroy +* +* Calling osm_vlarb_rec_rcv_construct is a prerequisite to calling any other +* method except osm_vlarb_rec_rcv_init. +* +* SEE ALSO +* VLArbitration Record Receiver object, osm_vlarb_rec_rcv_init, +* osm_vlarb_rec_rcv_destroy +*********/ + +/****f* OpenSM: VLArbitration Record Receiver/osm_vlarb_rec_rcv_destroy +* NAME +* osm_vlarb_rec_rcv_destroy +* +* DESCRIPTION +* The osm_vlarb_rec_rcv_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_vlarb_rec_rcv_destroy( + IN osm_vlarb_rec_rcv_t* const p_rcv ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* VLArbitration Record Receiver object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_vlarb_rec_rcv_construct or osm_vlarb_rec_rcv_init. +* +* SEE ALSO +* VLArbitration Record Receiver object, osm_vlarb_rec_rcv_construct, +* osm_vlarb_rec_rcv_init +*********/ + +/****f* OpenSM: VLArbitration Record Receiver/osm_vlarb_rec_rcv_init +* NAME +* osm_vlarb_rec_rcv_init +* +* DESCRIPTION +* The osm_vlarb_rec_rcv_init function initializes a +* VLArbitration Record Receiver object for use. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_vlarb_rec_rcv_init( + IN osm_vlarb_rec_rcv_t* const p_rcv, + IN osm_sa_resp_t* const p_resp, + IN osm_mad_pool_t* const p_mad_pool, + IN const osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to an osm_vlarb_rec_rcv_t object to initialize. +* +* p_req +* [in] Pointer to an osm_req_t object. +* +* p_subn +* [in] Pointer to the Subnet object for this subnet. +* +* p_log +* [in] Pointer to the log object. +* +* p_lock +* [in] Pointer to the OpenSM serializing lock. +* +* RETURN VALUES +* CL_SUCCESS if the VLArbitration Record Receiver object was initialized +* successfully. +* +* NOTES +* Allows calling other VLArbitration Record Receiver methods. +* +* SEE ALSO +* VLArbitration Record Receiver object, osm_vlarb_rec_rcv_construct, +* osm_vlarb_rec_rcv_destroy +*********/ + +/****f* OpenSM: VLArbitration Record Receiver/osm_vlarb_rec_rcv_process +* NAME +* osm_vlarb_rec_rcv_process +* +* DESCRIPTION +* Process the VL Arbitration Table Query . +* +* SYNOPSIS +*/ +void +osm_vlarb_rec_rcv_process( + IN osm_vlarb_rec_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to an osm_vlarb_rec_rcv_t object. +* +* p_madw +* [in] Pointer to the MAD Wrapper containing the MAD +* that contains the VL Arbitration Record Query attribute. +* +* RETURN VALUES +* CL_SUCCESS if the Query processing was successful. +* +* NOTES +* This function processes a SA VL Arbitration Record attribute. +* +* SEE ALSO +* VLArbitration Record Receiver, VLArbitration Record Response Controller +*********/ + +END_C_DECLS + +#endif /* _OSM_VLARB_REC_RCV_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_vlarb_record_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_vlarb_record_ctrl.h new file mode 100644 index 00000000..9f476831 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_vlarb_record_ctrl.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_vlarb_record_ctrl.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_sa_vlarb_rec_rcv_ctrl_t. + * This object represents a controller that receives the IBA VL Arbitration + * record query from SA client. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.3 $ + */ + +#ifndef _OSM_VLARB_REC_CTRL_H_ +#define _OSM_VLARB_REC_CTRL_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/VLArbitration Record Receive Controller +* NAME +* VLArbitration Record Receive Controller +* +* DESCRIPTION +* The VLArbitration Record Receive Controller object encapsulates +* the information needed to handle VLArbitration record query from SA client. +* +* The VLArbitration Record Receive Controller object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Eitan Zahavi, Mellanox +* +*********/ + +/****s* OpenSM: VLArbitration Record Receive Controller/osm_vlarb_rec_rcv_ctrl_t +* NAME +* osm_vlarb_rec_rcv_ctrl_t +* +* DESCRIPTION +* VLArbitration Record Receive Controller structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_vlarb_rec_rcv_ctrl +{ + osm_vlarb_rec_rcv_t *p_rcv; + osm_log_t *p_log; + cl_dispatcher_t *p_disp; + cl_disp_reg_handle_t h_disp; + +} osm_vlarb_rec_rcv_ctrl_t; +/* +* FIELDS +* p_rcv +* Pointer to the VLArbitration Record Receiver object. +* +* p_log +* Pointer to the log object. +* +* p_disp +* Pointer to the Dispatcher. +* +* h_disp +* Handle returned from dispatcher registration. +* +* SEE ALSO +* VLArbitration Record Receive Controller object +* VLArbitration Record Receiver object +*********/ + +/****f* OpenSM: VLArbitration Record Receive Controller/osm_vlarb_rec_rcv_ctrl_construct +* NAME +* osm_vlarb_rec_rcv_ctrl_construct +* +* DESCRIPTION +* This function constructs a VLArbitration Record Receive Controller object. +* +* SYNOPSIS +*/ +void osm_vlarb_rec_rcv_ctrl_construct( + IN osm_vlarb_rec_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a VLArbitration Record Receive Controller +* object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_vlarb_rec_rcv_ctrl_init, osm_vlarb_rec_rcv_ctrl_destroy +* +* Calling osm_vlarb_rec_rcv_ctrl_construct is a prerequisite to calling any other +* method except osm_vlarb_rec_rcv_ctrl_init. +* +* SEE ALSO +* VLArbitration Record Receive Controller object, osm_vlarb_rec_rcv_ctrl_init, +* osm_vlarb_rec_rcv_ctrl_destroy +*********/ + +/****f* OpenSM: VLArbitration Record Receive Controller/osm_vlarb_rec_rcv_ctrl_destroy +* NAME +* osm_vlarb_rec_rcv_ctrl_destroy +* +* DESCRIPTION +* The osm_vlarb_rec_rcv_ctrl_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_vlarb_rec_rcv_ctrl_destroy( + IN osm_vlarb_rec_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* VLArbitration Record Receive Controller object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_vlarb_rec_rcv_ctrl_construct or osm_vlarb_rec_rcv_ctrl_init. +* +* SEE ALSO +* VLArbitration Record Receive Controller object, osm_vlarb_rec_rcv_ctrl_construct, +* osm_vlarb_rec_rcv_ctrl_init +*********/ + +/****f* OpenSM: VLArbitration Record Receive Controller/osm_vlarb_rec_rcv_ctrl_init +* NAME +* osm_vlarb_rec_rcv_ctrl_init +* +* DESCRIPTION +* The osm_vlarb_rec_rcv_ctrl_init function initializes a +* VLArbitration Record Receive Controller object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_vlarb_rec_rcv_ctrl_init( + IN osm_vlarb_rec_rcv_ctrl_t* const p_ctrl, + IN osm_vlarb_rec_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_vlarb_rec_rcv_ctrl_t object to initialize. +* +* p_rcv +* [in] Pointer to an osm_vlarb_rec_rcv_t object. +* +* p_log +* [in] Pointer to the log object. +* +* p_disp +* [in] Pointer to the OpenSM central Dispatcher. +* +* RETURN VALUES +* CL_SUCCESS if the VLArbitration Record Receive Controller object was initialized +* successfully. +* +* NOTES +* Allows calling other VLArbitration Record Receive Controller methods. +* +* SEE ALSO +* VLArbitration Record Receive Controller object, osm_vlarb_rec_rcv_ctrl_construct, +* osm_vlarb_rec_rcv_ctrl_destroy +*********/ + +END_C_DECLS + +#endif /* _OSM_VLARB_REC_CTRL_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_service.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_service.h new file mode 100644 index 00000000..f5f48a3f --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_service.h @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_service.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +#ifndef _OSM_SVCR_H_ +#define _OSM_SVCR_H_ + +/* + * Abstract: + * Declaration of osm_service_rec_t. + * This object represents an IBA Service Record. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Service Record +* NAME +* Service Record +* +* DESCRIPTION +* The service record encapsulates the information needed by the +* SA to manage service registrations. +* +* The service records is not thread safe, thus callers must provide +* serialization. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Anil S Keshavamurthy, Intel +* +*********/ + +/****s* OpenSM: Service Record/osm_svcr_t +* NAME +* osm_svcr_t +* +* DESCRIPTION +* Service Record structure. +* +* The osm_svcr_t object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ + +typedef struct _osm_svcr_t +{ + cl_list_item_t list_item; + ib_service_record_t service_record; + uint32_t modified_time; + uint32_t lease_period; +} osm_svcr_t; +/* +* FIELDS +* map_item +* Map Item for qmap linkage. Must be first element!! +* +* svc_rec +* IB Service record structure +* +* modified_time +* Last modified time of this record in milliseconds +* +* lease_period +* Remaining lease period for this record +* +* +* SEE ALSO +*********/ + + +/****f* OpenSM: Service Record/osm_svcr_new +* NAME +* osm_svcr_new +* +* DESCRIPTION +* Allocates and initializes a Service Record for use. +* +* SYNOPSIS +*/ +osm_svcr_t* +osm_svcr_new( + IN const ib_service_record_t *p_svc_rec ); +/* +* PARAMETERS +* p_svc_rec +* [in] Pointer to IB Service Record +* +* RETURN VALUES +* pointer to osm_svcr_t structure. +* +* NOTES +* Allows calling other service record methods. +* +* SEE ALSO +* Service Record, osm_svcr_construct, osm_svcr_destroy +*********/ + + +/****f* OpenSM: Service Record/osm_svcr_init +* NAME +* osm_svcr_new +* +* DESCRIPTION +* Initializes the osm_svcr_t structure. +* +* SYNOPSIS +*/ +void +osm_svcr_init( + IN osm_svcr_t* const p_svcr, + IN const ib_service_record_t *p_svc_rec ); +/* +* PARAMETERS +* p_svc_rec +* [in] Pointer to osm_svcr_t structure +* p_svc_rec +* [in] Pointer to the ib_service_record_t +* +* SEE ALSO +* Service Record, osm_svcr_construct, osm_svcr_destroy +*********/ + +/****f* OpenSM: Service Record/osm_svcr_construct +* NAME +* osm_svcr_construct +* +* DESCRIPTION +* Constructs the osm_svcr_t structure. +* +* SYNOPSIS +*/ +void +osm_svcr_construct( + IN osm_svcr_t* const p_svcr ); +/* +* PARAMETERS +* p_svc_rec +* [in] Pointer to osm_svcr_t structure +* +* SEE ALSO +* Service Record, osm_svcr_construct, osm_svcr_destroy +*********/ + +/****f* OpenSM: Service Record/osm_svcr_destroy +* NAME +* osm_svcr_destroy +* +* DESCRIPTION +* Constructs the osm_svcr_t structure. +* +* SYNOPSIS +*/ +void +osm_svcr_destroy( + IN osm_svcr_t* const p_svcr ); +/* +* PARAMETERS +* p_svc_rec +* [in] Pointer to osm_svcr_t structure +* +* SEE ALSO +* Service Record, osm_svcr_construct, osm_svcr_destroy +*********/ + + + +osm_svcr_t* +osm_svcr_get_by_rid( + IN osm_subn_t const *p_subn, + IN osm_log_t *p_log, + IN ib_service_record_t* const p_svc_rec ); + +void +osm_svcr_insert_to_db( + IN osm_subn_t *p_subn, + IN osm_log_t *p_log, + IN osm_svcr_t *p_svcr); +void +osm_svcr_remove_from_db( + IN osm_subn_t *p_subn, + IN osm_log_t *p_log, + IN osm_svcr_t *p_svcr); + + +END_C_DECLS + +#endif /* _OSM_SVCR_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_slvl_map_rcv.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_slvl_map_rcv.h new file mode 100644 index 00000000..f96bbe9f --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_slvl_map_rcv.h @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_slvl_map_rcv.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_slvl_rcv_t. + * This object represents the SLtoVL Map Receiver object. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.3 $ + */ + +#ifndef _OSM_SLVL_RCV_H_ +#define _OSM_SLVL_RCV_H_ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Slvl Map Receiver +* NAME +* Slvl Map Receiver +* +* DESCRIPTION +* The Slvl Map Receiver object encapsulates the information +* needed to set or get the SLtoVL map attribute from a port. +* +* The Slvl Map Receiver object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Eitan Zahavi, Mellanox +* +*********/ + +/****s* OpenSM: Slvl Map Receiver/osm_slvl_rcv_t +* NAME +* osm_slvl_rcv_t +* +* DESCRIPTION +* Slvl Map Receiver structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_slvl_rcv +{ + osm_subn_t *p_subn; + osm_req_t *p_req; + osm_log_t *p_log; + cl_plock_t *p_lock; + +} osm_slvl_rcv_t; +/* +* FIELDS +* p_subn +* Pointer to the Subnet object for this subnet. +* +* p_req +* Pointer to the generic attribute request object. +* +* p_log +* Pointer to the log object. +* +* p_lock +* Pointer to the serializing lock. +* +* SEE ALSO +* Slvl Map Receiver object +*********/ + +/****f* OpenSM: Slvl Map Receiver/osm_slvl_rcv_construct +* NAME +* osm_slvl_rcv_construct +* +* DESCRIPTION +* This function constructs a Slvl Map Receiver object. +* +* SYNOPSIS +*/ +void osm_slvl_rcv_construct( + IN osm_slvl_rcv_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a Slvl Map Receiver object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_slvl_rcv_destroy +* +* Calling osm_slvl_rcv_construct is a prerequisite to calling any other +* method except osm_slvl_rcv_init. +* +* SEE ALSO +* Slvl Map Receiver object, osm_slvl_rcv_init, +* osm_slvl_rcv_destroy +*********/ + +/****f* OpenSM: Slvl Map Receiver/osm_slvl_rcv_destroy +* NAME +* osm_slvl_rcv_destroy +* +* DESCRIPTION +* The osm_slvl_rcv_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_slvl_rcv_destroy( + IN osm_slvl_rcv_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* Slvl Map Receiver object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_slvl_rcv_construct or osm_slvl_rcv_init. +* +* SEE ALSO +* Slvl Map Receiver object, osm_slvl_rcv_construct, +* osm_slvl_rcv_init +*********/ + +/****f* OpenSM: Slvl Map Receiver/osm_slvl_rcv_init +* NAME +* osm_slvl_rcv_init +* +* DESCRIPTION +* The osm_slvl_rcv_init function initializes a +* Slvl Map Receiver object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_slvl_rcv_init( + IN osm_slvl_rcv_t* const p_ctrl, + IN osm_req_t* const p_req, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_slvl_rcv_t object to initialize. +* +* p_req +* [in] Pointer to an osm_req_t object. +* +* p_subn +* [in] Pointer to the Subnet object for this subnet. +* +* p_log +* [in] Pointer to the log object. +* +* p_lock +* [in] Pointer to the OpenSM serializing lock. +* +* RETURN VALUES +* CL_SUCCESS if the Slvl Map Receiver object was initialized +* successfully. +* +* NOTES +* Allows calling other Slvl Map Receiver methods. +* +* SEE ALSO +* Slvl Map Receiver object, osm_slvl_rcv_construct, +* osm_slvl_rcv_destroy +*********/ + +/****f* OpenSM: Slvl Map Receiver/osm_slvl_rcv_process +* NAME +* osm_slvl_rcv_process +* +* DESCRIPTION +* Process the SLtoVL map attribute. +* +* SYNOPSIS +*/ +void osm_slvl_rcv_process( + IN const osm_slvl_rcv_t* const p_ctrl, + IN osm_madw_t* const p_madw ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_slvl_rcv_t object. +* +* p_madw +* [in] Pointer to the MAD Wrapper containing the MAD +* that contains the node's SLtoVL attribute. +* +* RETURN VALUES +* CL_SUCCESS if the SLtoVL processing was successful. +* +* NOTES +* This function processes a SLtoVL attribute. +* +* SEE ALSO +* Slvl Map Receiver, Slvl Map Response Controller +*********/ + +END_C_DECLS + +#endif /* _OSM_SLVL_RCV_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_slvl_map_rcv_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_slvl_map_rcv_ctrl.h new file mode 100644 index 00000000..c62e44c9 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_slvl_map_rcv_ctrl.h @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_slvl_map_rcv_ctrl.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_pi_rcv_ctrl_t. + * This object represents a controller that receives the IBA NodeInfo + * attribute from a node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.3 $ + */ + +#ifndef _OSM_SLVL_RCV_CTRL_H_ +#define _OSM_SLVL_RCV_CTRL_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/SltoVL Map Table Receive Controller +* NAME +* Slvl Map Receive Controller +* +* DESCRIPTION +* The Slvl Map Receive Controller object encapsulates +* the information needed to get or set SLtoVL Map of a port. +* +* The Slvl Map Receive Controller object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Eitan Zahavi, Mellanox +* +*********/ + +/****s* OpenSM: Slvl Map Receive Controller/osm_slvl_rcv_ctrl_t +* NAME +* osm_slvl_rcv_ctrl_t +* +* DESCRIPTION +* Slvl Map Receive Controller structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_slvl_rcv_ctrl +{ + osm_slvl_rcv_t *p_rcv; + osm_log_t *p_log; + cl_dispatcher_t *p_disp; + cl_disp_reg_handle_t h_disp; + +} osm_slvl_rcv_ctrl_t; +/* +* FIELDS +* p_rcv +* Pointer to the Slvl Map Receiver object. +* +* p_log +* Pointer to the log object. +* +* p_disp +* Pointer to the Dispatcher. +* +* h_disp +* Handle returned from dispatcher registration. +* +* SEE ALSO +* Slvl Map Receive Controller object +* Slvl Map Receiver object +*********/ + +/****f* OpenSM: Slvl Map Receive Controller/osm_slvl_rcv_ctrl_construct +* NAME +* osm_slvl_rcv_ctrl_construct +* +* DESCRIPTION +* This function constructs a Slvl Map Receive Controller object. +* +* SYNOPSIS +*/ +void osm_slvl_rcv_ctrl_construct( + IN osm_slvl_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a Slvl Map Receive Controller +* object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_slvl_rcv_ctrl_init, osm_slvl_rcv_ctrl_destroy, +* and osm_slvl_rcv_ctrl_is_inited. +* +* Calling osm_slvl_rcv_ctrl_construct is a prerequisite to calling any other +* method except osm_slvl_rcv_ctrl_init. +* +* SEE ALSO +* Slvl Map Receive Controller object, osm_slvl_rcv_ctrl_init, +* osm_slvl_rcv_ctrl_destroy, osm_slvl_rcv_ctrl_is_inited +*********/ + +/****f* OpenSM: Slvl Map Receive Controller/osm_slvl_rcv_ctrl_destroy +* NAME +* osm_slvl_rcv_ctrl_destroy +* +* DESCRIPTION +* The osm_slvl_rcv_ctrl_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_slvl_rcv_ctrl_destroy( + IN osm_slvl_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* Slvl Map Receive Controller object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_slvl_rcv_ctrl_construct or osm_slvl_rcv_ctrl_init. +* +* SEE ALSO +* Slvl Map Receive Controller object, osm_slvl_rcv_ctrl_construct, +* osm_slvl_rcv_ctrl_init +*********/ + +/****f* OpenSM: Slvl Map Receive Controller/osm_slvl_rcv_ctrl_init +* NAME +* osm_slvl_rcv_ctrl_init +* +* DESCRIPTION +* The osm_slvl_rcv_ctrl_init function initializes a +* Slvl Map Receive Controller object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_slvl_rcv_ctrl_init( + IN osm_slvl_rcv_ctrl_t* const p_ctrl, + IN osm_slvl_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_slvl_rcv_ctrl_t object to initialize. +* +* p_rcv +* [in] Pointer to an osm_slvl_rcv_t object. +* +* p_log +* [in] Pointer to the log object. +* +* p_disp +* [in] Pointer to the OpenSM central Dispatcher. +* +* RETURN VALUES +* CL_SUCCESS if the Slvl Map Receive Controller object was initialized +* successfully. +* +* NOTES +* Allows calling other Slvl Map Receive Controller methods. +* +* SEE ALSO +* Slvl Map Receive Controller object, osm_slvl_rcv_ctrl_construct, +* osm_slvl_rcv_ctrl_destroy, osm_slvl_rcv_ctrl_is_inited +*********/ + +/****f* OpenSM: Slvl Map Receive Controller/osm_slvl_rcv_ctrl_is_inited +* NAME +* osm_slvl_rcv_ctrl_is_inited +* +* DESCRIPTION +* Indicates if the object has been initialized with osm_slvl_rcv_ctrl_init. +* +* SYNOPSIS +*/ +boolean_t osm_slvl_rcv_ctrl_is_inited( + IN const osm_slvl_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_slvl_rcv_ctrl_t object. +* +* RETURN VALUES +* TRUE if the object was initialized successfully, +* FALSE otherwise. +* +* NOTES +* The osm_slvl_rcv_ctrl_construct or osm_slvl_rcv_ctrl_init must be +* called before using this function. +* +* SEE ALSO +* Slvl Map Receive Controller object, osm_slvl_rcv_ctrl_construct, +* osm_slvl_rcv_ctrl_init +*********/ + +END_C_DECLS + +#endif /* _OSM_SLVL_RCV_CTRL_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sm.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sm.h new file mode 100644 index 00000000..6c260bd8 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sm.h @@ -0,0 +1,566 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sm.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_sm_t, osm_other_sm_t. + * This object represents an IBA subnet. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + +#ifndef _OSM_SM_H_ +#define _OSM_SM_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/SM +* NAME +* SM +* +* DESCRIPTION +* The SM object encapsulates the information needed by the +* OpenSM to instantiate a subnet manager. The OpenSM allocates +* one SM object per subnet manager. +* +* The SM object is thread safe. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: SM/osm_sm_t +* NAME +* osm_sm_t +* +* DESCRIPTION +* Subnet Manager structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_sm +{ + osm_thread_state_t thread_state; + cl_event_t signal; + cl_event_t subnet_up_event; + cl_thread_t sweeper; + osm_subn_t *p_subn; + osm_db_t *p_db; + osm_vendor_t *p_vendor; + osm_log_t *p_log; + osm_mad_pool_t *p_mad_pool; + osm_vl15_t *p_vl15; + cl_dispatcher_t *p_disp; + cl_plock_t *p_lock; + atomic32_t sm_trans_id; + osm_req_t req; + osm_req_ctrl_t req_ctrl; + osm_resp_t resp; + osm_ni_rcv_t ni_rcv; + osm_ni_rcv_ctrl_t ni_rcv_ctrl; + osm_pi_rcv_t pi_rcv; + osm_pi_rcv_ctrl_t pi_rcv_ctrl; + osm_nd_rcv_t nd_rcv; + osm_nd_rcv_ctrl_t nd_rcv_ctrl; + osm_sm_mad_ctrl_t mad_ctrl; + osm_si_rcv_t si_rcv; + osm_si_rcv_ctrl_t si_rcv_ctrl; + osm_state_mgr_ctrl_t state_mgr_ctrl; + osm_lid_mgr_t lid_mgr; + osm_ucast_mgr_t ucast_mgr; + osm_link_mgr_t link_mgr; + osm_state_mgr_t state_mgr; + osm_drop_mgr_t drop_mgr; + osm_lft_rcv_t lft_rcv; + osm_lft_rcv_ctrl_t lft_rcv_ctrl; + osm_mft_rcv_t mft_rcv; + osm_mft_rcv_ctrl_t mft_rcv_ctrl; + osm_sweep_fail_ctrl_t sweep_fail_ctrl; + osm_sminfo_rcv_t sm_info_rcv; + osm_sminfo_rcv_ctrl_t sm_info_rcv_ctrl; + osm_trap_rcv_t trap_rcv; + osm_trap_rcv_ctrl_t trap_rcv_ctrl; + osm_sm_state_mgr_t sm_state_mgr; + osm_mcast_mgr_t mcast_mgr; + osm_slvl_rcv_t slvl_rcv; + osm_slvl_rcv_ctrl_t slvl_rcv_ctrl; + osm_vla_rcv_t vla_rcv; + osm_vla_rcv_ctrl_t vla_rcv_ctrl; + osm_pkey_rcv_t pkey_rcv; + osm_pkey_rcv_ctrl_t pkey_rcv_ctrl; +} osm_sm_t; +/* +* FIELDS +* p_subn +* Pointer to the Subnet object for this subnet. +* +* p_db +* Pointer to the database (persistency) object +* +* p_vendor +* Pointer to the vendor specific interfaces object. +* +* p_log +* Pointer to the log object. +* +* p_mad_pool +* Pointer to the MAD pool. +* +* p_vl15 +* Pointer to the VL15 interface. +* +* req +* Generic MAD attribute requester. +* +* req_ctrl +* Controller for the generic requester. +* +* resp +* MAD attribute responder. +* +* nd_rcv_ctrl +* Node Description Receive Controller. +* +* ni_rcv_ctrl +* Node Info Receive Controller. +* +* pi_rcv_ctrl +* Port Info Receive Controller. +* +* si_rcv_ctrl +* Switch Info Receive Controller. +* +* nd_rcv_ctrl +* Node Description Receive Controller. +* +* mad_ctrl +* MAD Controller. +* +* smi_get_ctrl +* SM Info Get Controller. +* +* p_disp +* Pointer to the Dispatcher. +* +* p_lock +* Pointer to the serializing lock. +* +* SEE ALSO +* SM object +*********/ + +/****f* OpenSM: SM/osm_sm_construct +* NAME +* osm_sm_construct +* +* DESCRIPTION +* This function constructs an SM object. +* +* SYNOPSIS +*/ +void +osm_sm_construct( + IN osm_sm_t* const p_sm ); +/* +* PARAMETERS +* p_sm +* [in] Pointer to a SM object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_sm_init, osm_sm_destroy +* +* Calling osm_sm_construct is a prerequisite to calling any other +* method except osm_sm_init. +* +* SEE ALSO +* SM object, osm_sm_init, osm_sm_destroy +*********/ + +/****f* OpenSM: SM/osm_sm_shutdown +* NAME +* osm_sm_shutdown +* +* DESCRIPTION +* The osm_sm_shutdown function shutdowns an SM, stopping the sweeper +* and unregistering all messages from the dispatcher +* +* SYNOPSIS +*/ +void +osm_sm_shutdown( + IN osm_sm_t* const p_sm ); +/* +* PARAMETERS +* p_sm +* [in] Pointer to a SM object to shutdown. +* +* RETURN VALUE +* This function does not return a value. +* +* SEE ALSO +* SM object, osm_sm_construct, osm_sm_init +*********/ + +/****f* OpenSM: SM/osm_sm_destroy +* NAME +* osm_sm_destroy +* +* DESCRIPTION +* The osm_sm_destroy function destroys an SM, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_sm_destroy( + IN osm_sm_t* const p_sm ); +/* +* PARAMETERS +* p_sm +* [in] Pointer to a SM object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified SM object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to osm_sm_construct or +* osm_sm_init. +* +* SEE ALSO +* SM object, osm_sm_construct, osm_sm_init +*********/ + +/****f* OpenSM: SM/osm_sm_init +* NAME +* osm_sm_init +* +* DESCRIPTION +* The osm_sm_init function initializes a SM object for use. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_sm_init( + IN osm_sm_t* const p_sm, + IN osm_subn_t* const p_subn, + IN osm_db_t* const p_db, + IN osm_vendor_t* const p_vendor, + IN osm_mad_pool_t* const p_mad_pool, + IN osm_vl15_t* const p_vl15, + IN osm_log_t* const p_log, + IN osm_stats_t* const p_stats, + IN cl_dispatcher_t* const p_disp, + IN cl_plock_t* const p_lock ); +/* +* PARAMETERS +* p_sm +* [in] Pointer to an osm_sm_t object to initialize. +* +* p_subn +* [in] Pointer to the Subnet object for this subnet. +* +* p_vendor +* [in] Pointer to the vendor specific interfaces object. +* +* p_mad_pool +* [in] Pointer to the MAD pool. +* +* p_vl15 +* [in] Pointer to the VL15 interface. +* +* p_log +* [in] Pointer to the log object. +* +* p_stats +* [in] Pointer to the statistics object. +* +* p_disp +* [in] Pointer to the OpenSM central Dispatcher. +* +* p_lock +* [in] Pointer to the OpenSM serializing lock. +* +* RETURN VALUES +* IB_SUCCESS if the SM object was initialized successfully. +* +* NOTES +* Allows calling other SM methods. +* +* SEE ALSO +* SM object, osm_sm_construct, osm_sm_destroy +*********/ + +/****f* OpenSM: SM/osm_sm_sweep +* NAME +* osm_sm_sweep +* +* DESCRIPTION +* Initiates a subnet sweep. +* +* SYNOPSIS +*/ +void +osm_sm_sweep( + IN osm_sm_t* const p_sm ); +/* +* PARAMETERS +* p_sm +* [in] Pointer to an osm_sm_t object. +* +* RETURN VALUES +* IB_SUCCESS if the sweep completed successfully. +* +* NOTES +* +* SEE ALSO +* SM object +*********/ + +/****f* OpenSM: SM/osm_sm_bind +* NAME +* osm_sm_bind +* +* DESCRIPTION +* Binds the sm object to a port guid. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_sm_bind( + IN osm_sm_t* const p_sm, + IN const ib_net64_t port_guid ); +/* +* PARAMETERS +* p_sm +* [in] Pointer to an osm_sm_t object to bind. +* +* port_guid +* [in] Local port GUID with which to bind. +* +* +* RETURN VALUES +* None +* +* NOTES +* A given SM object can only be bound to one port at a time. +* +* SEE ALSO +*********/ + +/****f* OpenSM: SM/osm_sm_mcgrp_join +* NAME +* osm_sm_mcgrp_join +* +* DESCRIPTION +* Adds a port to the multicast group. Creates the multicast group +* if necessary. +* +* This function is called by the SA. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_sm_mcgrp_join( + IN osm_sm_t* const p_sm, + IN const ib_net16_t mlid, + IN const ib_net64_t port_guid, + IN osm_mcast_req_type_t req_type ); +/* +* PARAMETERS +* p_sm +* [in] Pointer to an osm_sm_t object. +* +* mlid +* [in] Multicast LID +* +* port_guid +* [in] Port GUID to add to the group. +* +* req_type +* [in] Type of the MC request that caused this join +* (MC create/join). +* +* RETURN VALUES +* None +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: SM/osm_sm_mcgrp_leave +* NAME +* osm_sm_mcgrp_leave +* +* DESCRIPTION +* Removes a port from the multicast group. +* +* This function is called by the SA. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_sm_mcgrp_leave( + IN osm_sm_t* const p_sm, + IN const ib_net16_t mlid, + IN const ib_net64_t port_guid ); +/* +* PARAMETERS +* p_sm +* [in] Pointer to an osm_sm_t object. +* +* mlid +* [in] Multicast LID +* +* port_guid +* [in] Port GUID to remove from the group. +* +* RETURN VALUES +* None +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: OpenSM/osm_sm_wait_for_subnet_up +* NAME +* osm_sm_wait_for_subnet_up +* +* DESCRIPTION +* Blocks the calling thread until the subnet is up. +* +* SYNOPSIS +*/ +static inline cl_status_t +osm_sm_wait_for_subnet_up( + IN osm_sm_t* const p_sm, + IN uint32_t const wait_us, + IN boolean_t const interruptible ) +{ + return( cl_event_wait_on( &p_sm->subnet_up_event, + wait_us, interruptible ) ); +} +/* +* PARAMETERS +* p_sm +* [in] Pointer to an osm_sm_t object. +* +* wait_us +* [in] Number of microseconds to wait. +* +* interruptible +* [in] Indicates whether the wait operation can be interrupted +* by external signals. +* +* RETURN VALUES +* CL_SUCCESS if the wait operation succeeded in response to the event +* being set. +* +* CL_TIMEOUT if the specified time period elapses. +* +* CL_NOT_DONE if the wait was interrupted by an external signal. +* +* CL_ERROR if the wait operation failed. +* +* NOTES +* +* SEE ALSO +*********/ + +END_C_DECLS + +#endif /* _OSM_SM_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sm_mad_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sm_mad_ctrl.h new file mode 100644 index 00000000..b5d5fced --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sm_mad_ctrl.h @@ -0,0 +1,339 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sm_mad_ctrl.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_sm_mad_ctrl_t. + * This object represents a controller that receives the IBA NodeInfo + * attribute from a node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_SM_MAD_CTRL_H_ +#define _OSM_SM_MAD_CTRL_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/SM MAD Controller +* NAME +* SM MAD Controller +* +* DESCRIPTION +* The SM MAD Controller object encapsulates +* the information needed to receive MADs from the transport layer. +* +* The SM MAD Controller object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: SM MAD Controller/osm_sm_mad_ctrl_t +* NAME +* osm_sm_mad_ctrl_t +* +* DESCRIPTION +* SM MAD Controller structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_sm_mad_ctrl +{ + osm_log_t *p_log; + osm_subn_t *p_subn; + osm_mad_pool_t *p_mad_pool; + osm_vl15_t *p_vl15; + osm_vendor_t *p_vendor; + osm_bind_handle_t h_bind; + cl_plock_t *p_lock; + cl_dispatcher_t *p_disp; + cl_disp_reg_handle_t h_disp; + osm_stats_t *p_stats; + +} osm_sm_mad_ctrl_t; +/* +* FIELDS +* p_log +* Pointer to the log object. +* +* p_subn +* Pointer to the subnet object. +* +* p_mad_pool +* Pointer to the MAD pool. +* +* p_vendor +* Pointer to the vendor specific interfaces object. +* +* h_bind +* Bind handle returned by the transport layer. +* +* p_lock +* Pointer to the serializing lock. +* +* p_disp +* Pointer to the Dispatcher. +* +* h_disp +* Handle returned from dispatcher registration. +* +* p_stats +* Pointer to the OpenSM statistics block. +* +* SEE ALSO +* SM MAD Controller object +* SM MADr object +*********/ + +/****f* OpenSM: SM MAD Controller/osm_sm_mad_ctrl_construct +* NAME +* osm_sm_mad_ctrl_construct +* +* DESCRIPTION +* This function constructs a SM MAD Controller object. +* +* SYNOPSIS +*/ +void +osm_sm_mad_ctrl_construct( + IN osm_sm_mad_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a SM MAD Controller +* object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_sm_mad_ctrl_init, and osm_sm_mad_ctrl_destroy. +* +* Calling osm_sm_mad_ctrl_construct is a prerequisite to calling any other +* method except osm_sm_mad_ctrl_init. +* +* SEE ALSO +* SM MAD Controller object, osm_sm_mad_ctrl_init, +* osm_sm_mad_ctrl_destroy +*********/ + +/****f* OpenSM: SM MAD Controller/osm_sm_mad_ctrl_destroy +* NAME +* osm_sm_mad_ctrl_destroy +* +* DESCRIPTION +* The osm_sm_mad_ctrl_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_sm_mad_ctrl_destroy( + IN osm_sm_mad_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* SM MAD Controller object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_sm_mad_ctrl_construct or osm_sm_mad_ctrl_init. +* +* SEE ALSO +* SM MAD Controller object, osm_sm_mad_ctrl_construct, +* osm_sm_mad_ctrl_init +*********/ + +/****f* OpenSM: SM MAD Controller/osm_sm_mad_ctrl_init +* NAME +* osm_sm_mad_ctrl_init +* +* DESCRIPTION +* The osm_sm_mad_ctrl_init function initializes a +* SM MAD Controller object for use. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_sm_mad_ctrl_init( + IN osm_sm_mad_ctrl_t* const p_ctrl, + IN osm_subn_t* const p_subn, + IN osm_mad_pool_t* const p_mad_pool, + IN osm_vl15_t* const p_vl15, + IN osm_vendor_t* const p_vendor, + IN osm_log_t* const p_log, + IN osm_stats_t* const p_stats, + IN cl_plock_t* const p_lock, + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_sm_mad_ctrl_t object to initialize. +* +* p_mad_pool +* [in] Pointer to the MAD pool. +* +* p_vl15 +* [in] Pointer to the VL15 interface object. +* +* p_vendor +* [in] Pointer to the vendor specific interfaces object. +* +* p_log +* [in] Pointer to the log object. +* +* p_stats +* [in] Pointer to the OpenSM stastics block. +* +* p_lock +* [in] Pointer to the OpenSM serializing lock. +* +* p_disp +* [in] Pointer to the OpenSM central Dispatcher. +* +* RETURN VALUES +* IB_SUCCESS if the SM MAD Controller object was initialized +* successfully. +* +* NOTES +* Allows calling other SM MAD Controller methods. +* +* SEE ALSO +* SM MAD Controller object, osm_sm_mad_ctrl_construct, +* osm_sm_mad_ctrl_destroy +*********/ + +/****f* OpenSM: SM/osm_sm_mad_ctrl_bind +* NAME +* osm_sm_mad_ctrl_bind +* +* DESCRIPTION +* Binds the SM MAD Controller object to a port guid. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_sm_mad_ctrl_bind( + IN osm_sm_mad_ctrl_t* const p_ctrl, + IN const ib_net64_t port_guid ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_sm_mad_ctrl_t object to initialize. +* +* port_guid +* [in] Local port GUID with which to bind. +* +* +* RETURN VALUES +* None +* +* NOTES +* A given SM MAD Controller object can only be bound to one +* port at a time. +* +* SEE ALSO +*********/ + +/****f* OpenSM: SM/osm_sm_mad_ctrl_get_bind_handle +* NAME +* osm_sm_mad_ctrl_get_bind_handle +* +* DESCRIPTION +* Returns the bind handle. +* +* SYNOPSIS +*/ +static inline osm_bind_handle_t +osm_sm_mad_ctrl_get_bind_handle( + IN const osm_sm_mad_ctrl_t* const p_ctrl ) +{ + return( p_ctrl->h_bind ); +} +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_sm_mad_ctrl_t object. +* +* RETURN VALUES +* Returns the bind handle, which may be OSM_BIND_INVALID_HANDLE +* if no port has been bound. +* +* NOTES +* A given SM MAD Controller object can only be bound to one +* port at a time. +* +* SEE ALSO +*********/ + +END_C_DECLS + +#endif /* _OSM_SM_MAD_CTRL_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sm_state_mgr.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sm_state_mgr.h new file mode 100644 index 00000000..0b703f9b --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sm_state_mgr.h @@ -0,0 +1,353 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sm_state_mgr.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_sm_state_mgr_t. + * This object represents the SM State Manager object. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.2 $ + */ + +#ifndef _OSM_SM_STATE_MGR_H_ +#define _OSM_SM_STATE_MGR_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/SM State Manager +* NAME +* SM State Manager +* +* DESCRIPTION +* The SM State Manager object encapsulates the information +* needed to control the state of the SM. +* +* The SM State Manager object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Yael Kalka, Mellanox +* +*********/ + +/****s* OpenSM: SM State Manager/osm_sm_state_mgr_t +* NAME +* osm_sm_state_mgr_t +* +* DESCRIPTION +* SM State Manager structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_sm_state_mgr +{ + cl_spinlock_t state_lock; + cl_timer_t polling_timer; + uint32_t retry_number; + ib_net64_t master_guid; + osm_state_mgr_t* p_state_mgr; + osm_subn_t* p_subn; + osm_req_t* p_req; + osm_log_t* p_log; + osm_remote_sm_t* p_polling_sm; +} osm_sm_state_mgr_t; + +/* +* FIELDS +* state_lock +* Spinlock guarding the state and processes. +* +* retry_number +* Used on Standby state - to count the number of retries +* of queries to the master SM. +* +* polling_timer +* Timer for polling +* +* p_state_mgr +* Point to the state manager object +* +* p_subn +* Pointer to the Subnet object for this subnet. +* +* p_req +* Pointer to the generic attribute request object. +* +* p_log +* Pointer to the log object. +* +* p_polling_sm +* Pointer to a osm_remote_sm_t object. When our SM needs +* to poll on a remote sm, this will be the pointer of the +* polled SM. +* +* SEE ALSO +* SM State Manager object +*********/ + + +/****f* OpenSM: SM State Manager/osm_sm_state_mgr_construct +* NAME +* osm_sm_state_mgr_construct +* +* DESCRIPTION +* This function constructs a SM State Manager object. +* +* SYNOPSIS +*/ +void +osm_sm_state_mgr_construct( + IN osm_sm_state_mgr_t* const p_sm_mgr ); +/* +* PARAMETERS +* p_sm_mgr +* [in] Pointer to a SM State Manager object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows osm_sm_state_mgr_destroy +* +* Calling osm_sm_state_mgr_construct is a prerequisite to calling any other +* method except osm_sm_state_mgr_init. +* +* SEE ALSO +* SM State Manager object, osm_sm_state_mgr_init, +* osm_sm_state_mgr_destroy +*********/ + +/****f* OpenSM: SM State Manager/osm_sm_state_mgr_destroy +* NAME +* osm_sm_state_mgr_destroy +* +* DESCRIPTION +* The osm_sm_state_mgr_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_sm_state_mgr_destroy( + IN osm_sm_state_mgr_t* const p_sm_mgr ); +/* +* PARAMETERS +* p_sm_mgr +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* SM State Manager object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_sm_state_mgr_construct or osm_sm_state_mgr_init. +* +* SEE ALSO +* SM State Manager object, osm_sm_state_mgr_construct, +* osm_sm_state_mgr_init +*********/ + +/****f* OpenSM: SM State Manager/osm_sm_state_mgr_init +* NAME +* osm_sm_state_mgr_init +* +* DESCRIPTION +* The osm_sm_state_mgr_init function initializes a +* SM State Manager object for use. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_sm_state_mgr_init( + IN osm_sm_state_mgr_t* const p_sm_mgr, + IN osm_state_mgr_t* const p_state_mgr, + IN osm_subn_t* const p_subn, + IN osm_req_t* const p_req, + IN osm_log_t* const p_log ); +/* +* PARAMETERS +* p_sm_mgr +* [in] Pointer to an osm_sm_state_mgr_t object to initialize. +* +* +* p_state_mgr +* [in] Pointer to the State Manager object. +* +* p_subn +* [in] Pointer to the Subnet object for this subnet. +* +* p_req +* [in] Pointer to an osm_req_t object. +* +* p_log +* [in] Pointer to the log object. +* +* RETURN VALUES +* IB_SUCCESS if the SM State Manager object was initialized +* successfully. +* +* NOTES +* Allows calling other SM State Manager methods. +* +* SEE ALSO +* SM State Manager object, osm_sm_state_mgr_construct, +* osm_sm_state_mgr_destroy +*********/ + +/****f* OpenSM: SM State Manager/osm_sm_state_mgr_process +* NAME +* osm_sm_state_mgr_process +* +* DESCRIPTION +* Processes and maintains the states of the SM. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_sm_state_mgr_process( + IN osm_sm_state_mgr_t* const p_sm_mgr, + IN osm_sm_signal_t signal ); +/* +* PARAMETERS +* p_sm_mgr +* [in] Pointer to an osm_sm_state_mgr_t object. +* +* signal +* [in] Signal to the state SM engine. +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +* State Manager +*********/ + + +/****f* OpenSM: SM State Manager/osm_sm_state_mgr_signal_master_is_alive +* NAME +* osm_sm_state_mgr_signal_master_is_alive +* +* DESCRIPTION +* Signals that the remote Master SM is alive. +* Need to clear the retry_number variable. +* +* SYNOPSIS +*/ +void +osm_sm_state_mgr_signal_master_is_alive( + IN osm_sm_state_mgr_t* const p_sm_mgr ); +/* +* PARAMETERS +* p_sm_mgr +* [in] Pointer to an osm_sm_state_mgr_t object. +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +* State Manager +*********/ + +/****f* OpenSM: SM State Manager/osm_sm_state_mgr_check_legality +* NAME +* osm_sm_state_mgr_check_legality +* +* DESCRIPTION +* Checks the legality of the signal received, according to the +* current state of the SM state machine. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_sm_state_mgr_check_legality( + IN osm_sm_state_mgr_t* const p_sm_mgr, + IN osm_sm_signal_t signal ); +/* +* PARAMETERS +* p_sm_mgr +* [in] Pointer to an osm_sm_state_mgr_t object. +* +* signal +* [in] Signal to the state SM engine. +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +* State Manager +*********/ + +END_C_DECLS + +#endif /* _OSM_SM_STATE_MGR_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sminfo_rcv.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sminfo_rcv.h new file mode 100644 index 00000000..c55a6234 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sminfo_rcv.h @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sminfo_rcv.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_sminfo_rcv_t. + * This object represents the SMInfo Receiver object. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_SMINFO_RCV_H_ +#define _OSM_SMINFO_RCV_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/SMInfo Receiver +* NAME +* SMInfo Receiver +* +* DESCRIPTION +* The SMInfo Receiver object encapsulates the information +* needed to receive the SMInfo attribute from a node. +* +* The SMInfo Receiver object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: SMInfo Receiver/osm_sminfo_rcv_t +* NAME +* osm_sminfo_rcv_t +* +* DESCRIPTION +* SMInfo Receiver structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_sminfo_rcv +{ + osm_subn_t *p_subn; + osm_stats_t *p_stats; + osm_log_t *p_log; + osm_resp_t *p_resp; + osm_state_mgr_t *p_state_mgr; + struct _osm_sm_state_mgr *p_sm_state_mgr; + cl_plock_t *p_lock; + +} osm_sminfo_rcv_t; +/* +* FIELDS +* p_subn +* Pointer to the Subnet object for this subnet. +* +* p_stats +* Pointer to the OpenSM statistics block. +* +* p_log +* Pointer to the log object. +* +* p_resp +* Pointer to the generic MAD responder object. +* +* p_state_mgr +* Pointer to the State Manager object. +* +* p_sm_state_mgr +* Pointer to the SM State Manager object. +* +* p_lock +* Pointer to the serializing lock. +* +* SEE ALSO +* SMInfo Receiver object +*********/ + +/****f* OpenSM: SMInfo Receiver/osm_sminfo_rcv_construct +* NAME +* osm_sminfo_rcv_construct +* +* DESCRIPTION +* This function constructs a SMInfo Receiver object. +* +* SYNOPSIS +*/ +void osm_sminfo_rcv_construct( + IN osm_sminfo_rcv_t* const p_rcv ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to a SMInfo Receiver object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_sminfo_rcv_init, osm_sminfo_rcv_destroy +* +* Calling osm_sminfo_rcv_construct is a prerequisite to calling any other +* method except osm_sminfo_rcv_init. +* +* SEE ALSO +* SMInfo Receiver object, osm_sminfo_rcv_init, +* osm_sminfo_rcv_destroy +*********/ + +/****f* OpenSM: SMInfo Receiver/osm_sminfo_rcv_destroy +* NAME +* osm_sminfo_rcv_destroy +* +* DESCRIPTION +* The osm_sminfo_rcv_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_sminfo_rcv_destroy( + IN osm_sminfo_rcv_t* const p_rcv ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* SMInfo Receiver object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_sminfo_rcv_construct or osm_sminfo_rcv_init. +* +* SEE ALSO +* SMInfo Receiver object, osm_sminfo_rcv_construct, +* osm_sminfo_rcv_init +*********/ + +/****f* OpenSM: SMInfo Receiver/osm_sminfo_rcv_init +* NAME +* osm_sminfo_rcv_init +* +* DESCRIPTION +* The osm_sminfo_rcv_init function initializes a +* SMInfo Receiver object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_sminfo_rcv_init( + IN osm_sminfo_rcv_t* const p_rcv, + IN osm_subn_t* const p_subn, + IN osm_stats_t* const p_stats, + IN osm_resp_t* const p_resp, + IN osm_log_t* const p_log, + IN osm_state_mgr_t* const p_state_mgr, + IN struct _osm_sm_state_mgr* const p_sm_state_mgr, + IN cl_plock_t* const p_lock ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to an osm_sminfo_rcv_t object to initialize. +* +* p_subn +* [in] Pointer to the Subnet object for this subnet. +* +* p_stats +* [in] Pointer to the OpenSM statistics block. +* +* p_resp +* [in] Pointer to the generic MAD Responder object. +* +* p_log +* [in] Pointer to the log object. +* +* p_state_mgr +* [in] Pointer to the State Manager object. +* +* p_sm_state_mgr +* [in] Pointer to the SM State Manager object. +* +* p_lock +* [in] Pointer to the OpenSM serializing lock. +* +* RETURN VALUES +* IB_SUCCESS if the SMInfo Receiver object was initialized +* successfully. +* +* NOTES +* Allows calling other SMInfo Receiver methods. +* +* SEE ALSO +* SMInfo Receiver object, osm_sminfo_rcv_construct, +* osm_sminfo_rcv_destroy +*********/ + +/****f* OpenSM: SMInfo Receiver/osm_sminfo_rcv_process +* NAME +* osm_sminfo_rcv_process +* +* DESCRIPTION +* Process the SMInfo attribute. +* +* SYNOPSIS +*/ +void osm_sminfo_rcv_process( + IN const osm_sminfo_rcv_t* const p_rcv, + IN osm_madw_t* const p_madw ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to an osm_sminfo_rcv_t object. +* +* p_madw +* [in] Pointer to the MAD Wrapper containing the MAD +* that contains the node's SMInfo attribute. +* +* RETURN VALUES +* IB_SUCCESS if the SMInfo processing was successful. +* +* NOTES +* This function processes a SMInfo attribute. +* +* SEE ALSO +* SMInfo Receiver, SMInfo Response Controller +*********/ + +END_C_DECLS + +#endif /* _OSM_SMINFO_RCV_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sminfo_rcv_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sminfo_rcv_ctrl.h new file mode 100644 index 00000000..f34bb204 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sminfo_rcv_ctrl.h @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sminfo_rcv_ctrl.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_sminfo_rcv_ctrl_t. + * This object represents a controller that receives the IBA SMInfo + * attribute from a node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_SMINFO_RCV_CTRL_H_ +#define _OSM_SMINFO_RCV_CTRL_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/SMInfo Receive Controller +* NAME +* SMInfo Receive Controller +* +* DESCRIPTION +* The SMInfo Receive Controller object encapsulates the information +* needed to receive the SMInfo attribute from a node. +* +* The SMInfo Receive Controller object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: SMInfo Receive Controller/osm_sminfo_rcv_ctrl_t +* NAME +* osm_sminfo_rcv_ctrl_t +* +* DESCRIPTION +* SMInfo Receive Controller structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_sminfo_rcv_ctrl +{ + osm_sminfo_rcv_t *p_rcv; + osm_log_t *p_log; + cl_dispatcher_t *p_disp; + cl_disp_reg_handle_t h_disp; + +} osm_sminfo_rcv_ctrl_t; +/* +* FIELDS +* p_rcv +* Pointer to the SMInfo Receiver object. +* +* p_log +* Pointer to the log object. +* +* p_disp +* Pointer to the Dispatcher. +* +* h_disp +* Handle returned from dispatcher registration. +* +* SEE ALSO +* SMInfo Receive Controller object +*********/ + +/****f* OpenSM: SMInfo Receive Controller/osm_sminfo_rcv_ctrl_construct +* NAME +* osm_sminfo_rcv_ctrl_construct +* +* DESCRIPTION +* This function constructs a SMInfo Receive Controller object. +* +* SYNOPSIS +*/ +void +osm_sminfo_rcv_ctrl_construct( + IN osm_sminfo_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a SMInfo Receive Controller object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_sminfo_rcv_ctrl_init, osm_sminfo_rcv_ctrl_destroy +* +* Calling osm_sminfo_rcv_ctrl_construct is a prerequisite to calling any other +* method except osm_sminfo_rcv_ctrl_init. +* +* SEE ALSO +* SMInfo Receive Controller object, osm_sminfo_rcv_ctrl_init, +* osm_sminfo_rcv_ctrl_destroy +*********/ + +/****f* OpenSM: SMInfo Receive Controller/osm_sminfo_rcv_ctrl_destroy +* NAME +* osm_sminfo_rcv_ctrl_destroy +* +* DESCRIPTION +* The osm_sminfo_rcv_ctrl_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_sminfo_rcv_ctrl_destroy( + IN osm_sminfo_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* SMInfo Receive Controller object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_sminfo_rcv_ctrl_construct or osm_sminfo_rcv_ctrl_init. +* +* SEE ALSO +* SMInfo Receive Controller object, osm_sminfo_rcv_ctrl_construct, +* osm_sminfo_rcv_ctrl_init +*********/ + +/****f* OpenSM: SMInfo Receive Controller/osm_sminfo_rcv_ctrl_init +* NAME +* osm_sminfo_rcv_ctrl_init +* +* DESCRIPTION +* The osm_sminfo_rcv_ctrl_init function initializes a +* SMInfo Receive Controller object for use. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_sminfo_rcv_ctrl_init( + IN osm_sminfo_rcv_ctrl_t* const p_ctrl, + IN osm_sminfo_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_sminfo_rcv_ctrl_t object to initialize. +* +* p_rcv +* [in] Pointer to an osm_sminfo_rcv_t object. +* +* p_log +* [in] Pointer to the log object. +* +* p_disp +* [in] Pointer to the OpenSM central Dispatcher. +* +* RETURN VALUES +* IB_SUCCESS if the SMInfo Receive Controller object was initialized +* successfully. +* +* NOTES +* Allows calling other SMInfo Receive Controller methods. +* +* SEE ALSO +* SMInfo Receive Controller object, osm_sminfo_rcv_ctrl_construct, +* osm_sminfo_rcv_ctrl_destroy +*********/ + +END_C_DECLS + +#endif /* OSM_SMINFO_RCV_CTRL_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_state_mgr.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_state_mgr.h new file mode 100644 index 00000000..e82d3941 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_state_mgr.h @@ -0,0 +1,518 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_state_mgr.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_state_mgr_t. + * This object represents the State Manager object. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + +#ifndef _OSM_STATE_MGR_H_ +#define _OSM_STATE_MGR_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/State Manager +* NAME +* State Manager +* +* DESCRIPTION +* The State Manager object encapsulates the information +* needed to control subnet sweeps and configuration. +* +* The State Manager object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: State Manager/osm_state_mgr_t +* NAME +* osm_state_mgr_t +* +* DESCRIPTION +* State Manager structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_state_mgr +{ + osm_subn_t *p_subn; + osm_log_t *p_log; + osm_lid_mgr_t *p_lid_mgr; + osm_ucast_mgr_t *p_ucast_mgr; + osm_mcast_mgr_t *p_mcast_mgr; + osm_link_mgr_t *p_link_mgr; + osm_drop_mgr_t *p_drop_mgr; + osm_req_t *p_req; + osm_stats_t *p_stats; + struct _osm_sm_state_mgr *p_sm_state_mgr; + const osm_sm_mad_ctrl_t *p_mad_ctrl; + cl_spinlock_t state_lock; + cl_spinlock_t idle_lock; + cl_qlist_t idle_time_list; + cl_plock_t *p_lock; + cl_event_t *p_subnet_up_event; + osm_sm_state_t state; + osm_state_mgr_mode_t state_step_mode; + osm_signal_t next_stage_signal; +} osm_state_mgr_t; +/* +* FIELDS +* p_subn +* Pointer to the Subnet object for this subnet. +* +* p_log +* Pointer to the log object. +* +* p_lid_mgr +* Pointer to the LID Manager object. +* +* p_ucast_mgr +* Pointer to the Unicast Manager object. +* +* p_mcast_mgr +* Pointer to the Multicast Manager object. +* +* p_link_mgr +* Pointer to the Link Manager object. +* +* p_drop_mgr +* Pointer to the Drop Manager object. +* +* p_req +* Pointer to the Requester object sending SMPs. +* +* p_stats +* Pointer to the OpenSM statistics block. +* +* p_sm_state_mgr +* Pointer to the SM state mgr object. +* +* p_mad_ctrl +* Pointer to the SM's MAD Controller object. +* +* state_lock +* Spinlock guarding the state and processes. +* +* p_lock +* lock guarding the subnet object. +* +* p_subnet_up_event +* Pointer to the event to set if/when the subnet comes up. +* +* state +* State of the SM. +* +* state_step_mode +* Controls the mode of progressing to next stage: +* OSM_STATE_STEP_CONTINUOUS - normal automatic progress mode +* OSM_STATE_STEP_TAKE_ONE - do one step and stop +* OSM_STATE_STEP_BREAK - stop before taking next step +* +* next_stage_signal +* Stores the signal to be provided when running the next stage. +* +* SEE ALSO +* State Manager object +*********/ + +/****s* OpenSM: State Manager/_osm_idle_item +* NAME +* _osm_idle_item +* +* DESCRIPTION +* Idle item. +* +* SYNOPSIS +*/ + +typedef osm_signal_t +(*osm_pfn_start_t)( + IN void *context1, + IN void *context2 ); + +typedef void +(*osm_pfn_done_t)( + IN void *context1, + IN void *context2 ); + +typedef struct _osm_idle_item +{ + cl_list_item_t list_item; + void* context1; + void* context2; + osm_pfn_start_t pfn_start; + osm_pfn_done_t pfn_done; +}osm_idle_item_t; + +/* +* FIELDS +* list_item +* list item. +* +* context1 +* Context pointer +* +* context2 +* Context pointer +* +* pfn_start +* Pointer to the start function. +* +* pfn_done +* Pointer to the dine function. +* SEE ALSO +* State Manager object +*********/ + +/****f* OpenSM: State Manager/osm_state_mgr_process_idle +* NAME +* osm_state_mgr_process_idle +* +* DESCRIPTION +* Formulates the osm_idle_item and inserts it into the queue and +* signals the state manager. +* +* SYNOPSIS +*/ + +ib_api_status_t +osm_state_mgr_process_idle( + IN osm_state_mgr_t* const p_mgr, + IN osm_pfn_start_t pfn_start, + IN osm_pfn_done_t pfn_done, + void* context1, + void* context2 + ); + +/* +* PARAMETERS +* p_mgr +* [in] Pointer to a State Manager object to construct. +* +* pfn_start +* [in] Pointer the start function which will be called at +* idle time. +* +* pfn_done +* [in] pointer the done function which will be called +* when outstanding smps is zero +* +* context1 +* [in] Pointer to void +* +* context2 +* [in] Pointer to void +* +* RETURN VALUE +* IB_SUCCESS or IB_ERROR +* +* NOTES +* Allows osm_state_mgr_destroy +* +* Calling osm_state_mgr_construct is a prerequisite to calling any other +* method except osm_state_mgr_init. +* +* SEE ALSO +* State Manager object, osm_state_mgr_init, +* osm_state_mgr_destroy +*********/ + +/****f* OpenSM: State Manager/osm_state_mgr_construct +* NAME +* osm_state_mgr_construct +* +* DESCRIPTION +* This function constructs a State Manager object. +* +* SYNOPSIS +*/ +void +osm_state_mgr_construct( + IN osm_state_mgr_t* const p_mgr ); +/* +* PARAMETERS +* p_mgr +* [in] Pointer to a State Manager object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows osm_state_mgr_destroy +* +* Calling osm_state_mgr_construct is a prerequisite to calling any other +* method except osm_state_mgr_init. +* +* SEE ALSO +* State Manager object, osm_state_mgr_init, +* osm_state_mgr_destroy +*********/ + +/****f* OpenSM: State Manager/osm_state_mgr_destroy +* NAME +* osm_state_mgr_destroy +* +* DESCRIPTION +* The osm_state_mgr_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_state_mgr_destroy( + IN osm_state_mgr_t* const p_mgr ); +/* +* PARAMETERS +* p_mgr +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* State Manager object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_state_mgr_construct or osm_state_mgr_init. +* +* SEE ALSO +* State Manager object, osm_state_mgr_construct, +* osm_state_mgr_init +*********/ + +/****f* OpenSM: State Manager/osm_state_mgr_init +* NAME +* osm_state_mgr_init +* +* DESCRIPTION +* The osm_state_mgr_init function initializes a +* State Manager object for use. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_state_mgr_init( + IN osm_state_mgr_t* const p_mgr, + IN osm_subn_t* const p_subn, + IN osm_lid_mgr_t* const p_lid_mgr, + IN osm_ucast_mgr_t* const p_ucast_mgr, + IN osm_mcast_mgr_t* const p_mcast_mgr, + IN osm_link_mgr_t* const p_link_mgr, + IN osm_drop_mgr_t* const p_drop_mgr, + IN osm_req_t* const p_req, + IN osm_stats_t* const p_stats, + IN struct _osm_sm_state_mgr* const p_sm_state_mgr, + IN const osm_sm_mad_ctrl_t* const p_mad_ctrl, + IN cl_plock_t* const p_lock, + IN cl_event_t* const p_subnet_up_event, + IN osm_log_t* const p_log ); +/* +* PARAMETERS +* p_mgr +* [in] Pointer to an osm_state_mgr_t object to initialize. +* +* p_subn +* [in] Pointer to the Subnet object for this subnet. +* +* p_lid_mgr +* [in] Pointer to the LID Manager object. +* +* p_ucast_mgr +* [in] Pointer to the Unicast Manager object. +* +* p_mcast_mgr +* [in] Pointer to the Multicast Manager object. +* +* p_link_mgr +* [in] Pointer to the Link Manager object. +* +* p_drop_mgr +* [in] Pointer to the Drop Manager object. +* +* p_req +* [in] Pointer to the Request Controller object. +* +* p_stats +* [in] Pointer to the OpenSM statistics block. +* +* p_sm_state_mgr +* [in] Pointer to the SM state mgr object. +* +* p_mad_ctrl +* [in] Pointer to the SM's mad controller. +* +* p_subnet_up_event +* [in] Pointer to the event to set if/when the subnet comes up. +* +* p_log +* [in] Pointer to the log object. +* +* RETURN VALUES +* IB_SUCCESS if the State Manager object was initialized +* successfully. +* +* NOTES +* Allows calling other State Manager methods. +* +* SEE ALSO +* State Manager object, osm_state_mgr_construct, +* osm_state_mgr_destroy +*********/ + +/****f* OpenSM: State Manager/osm_sm_is_greater_than +* NAME +* osm_sm_is_greater_than +* +* DESCRIPTION +* Compares two SM's (14.4.1.2) +* +* SYNOPSIS +*/ +static inline boolean_t +osm_sm_is_greater_than ( + IN const uint8_t l_priority, + IN const ib_net64_t l_guid, + IN const uint8_t r_priority, + IN const ib_net64_t r_guid ) +{ + if( l_priority > r_priority ) + { + return( TRUE ); + } + else + { + if( l_priority == r_priority ) + { + if( cl_ntoh64(l_guid) < cl_ntoh64(r_guid) ) + { + return( TRUE ); + } + } + } + return( FALSE ); +} +/* +* PARAMETERS +* l_priority +* [in] Priority of the SM on the "left" +* +* l_guid +* [in] GUID of the SM on the "left" +* +* r_priority +* [in] Priority of the SM on the "right" +* +* r_guid +* [in] GUID of the SM on the "right" +* +* RETURN VALUES +* Return TRUE if an sm with l_priority and l_guid is higher than an sm +* with r_priority and r_guid, +* return FALSE otherwise. +* +* NOTES +* +* SEE ALSO +* State Manager +*********/ + +/****f* OpenSM: State Manager/osm_state_mgr_process +* NAME +* osm_state_mgr_process +* +* DESCRIPTION +* Processes and maintains the states of the SM. +* +* SYNOPSIS +*/ +void +osm_state_mgr_process( + IN osm_state_mgr_t* const p_mgr, + IN osm_signal_t signal ); +/* +* PARAMETERS +* p_mgr +* [in] Pointer to an osm_state_mgr_t object. +* +* signal +* [in] Signal to the state engine. +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +* State Manager +*********/ + +END_C_DECLS + +#endif /* _OSM_STATE_MGR_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_state_mgr_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_state_mgr_ctrl.h new file mode 100644 index 00000000..d89493fc --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_state_mgr_ctrl.h @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_state_mgr_ctrl.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_state_mgr_ctrl_t. + * This object represents a controller that receives the + * State indication after a subnet sweep. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_STATE_MGR_CTRL_H_ +#define _OSM_STATE_MGR_CTRL_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/State Manager Controller +* NAME +* State Manager Controller +* +* DESCRIPTION +* The State Manager Controller object encapsulates the information +* needed to pass the dispatcher message from the dispatcher +* to the State Manager. +* +* The State Manager Controller object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: State Manager Controller/osm_state_mgr_ctrl_t +* NAME +* osm_state_mgr_ctrl_t +* +* DESCRIPTION +* State Manager Controller structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_state_mgr_ctrl +{ + osm_state_mgr_t *p_mgr; + osm_log_t *p_log; + cl_dispatcher_t *p_disp; + cl_disp_reg_handle_t h_disp; + +} osm_state_mgr_ctrl_t; +/* +* FIELDS +* p_mgr +* Pointer to the State Manager object. +* +* p_log +* Pointer to the log object. +* +* p_disp +* Pointer to the Dispatcher. +* +* h_disp +* Handle returned from dispatcher registration. +* +* SEE ALSO +* State Manager Controller object +*********/ + +/****f* OpenSM: State Manager Controller/osm_state_mgr_ctrl_construct +* NAME +* osm_state_mgr_ctrl_construct +* +* DESCRIPTION +* This function constructs a State Manager Controller object. +* +* SYNOPSIS +*/ +void +osm_state_mgr_ctrl_construct( + IN osm_state_mgr_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a State Manager Controller +* object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_state_mgr_ctrl_init, and osm_state_mgr_ctrl_destroy. +* +* Calling osm_state_mgr_ctrl_construct is a prerequisite to calling any +* other method except osm_state_mgr_ctrl_init. +* +* SEE ALSO +* State Manager Controller object, osm_state_mgr_ctrl_init, +* osm_state_mgr_ctrl_destroy +*********/ + +/****f* OpenSM: State Manager Controller/osm_state_mgr_ctrl_destroy +* NAME +* osm_state_mgr_ctrl_destroy +* +* DESCRIPTION +* The osm_state_mgr_ctrl_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_state_mgr_ctrl_destroy( + IN osm_state_mgr_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* State Manager Controller object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_state_mgr_ctrl_construct or osm_state_mgr_ctrl_init. +* +* SEE ALSO +* State Manager Controller object, osm_state_mgr_ctrl_construct, +* osm_state_mgr_ctrl_init +*********/ + +/****f* OpenSM: State Manager Controller/osm_state_mgr_ctrl_init +* NAME +* osm_state_mgr_ctrl_init +* +* DESCRIPTION +* The osm_state_mgr_ctrl_init function initializes a +* State Manager Controller object for use. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_state_mgr_ctrl_init( + IN osm_state_mgr_ctrl_t* const p_ctrl, + IN osm_state_mgr_t* const p_mgr, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_state_mgr_ctrl_t object to initialize. +* +* p_mgr +* [in] Pointer to an osm_state_mgr_t object. +* +* p_log +* [in] Pointer to the log object. +* +* p_disp +* [in] Pointer to the OpenSM central Dispatcher. +* +* RETURN VALUES +* IB_SUCCESS if the State Manager Controller object +* was initialized successfully. +* +* NOTES +* Allows calling other State Manager Controller methods. +* +* SEE ALSO +* State Manager Controller object, osm_state_mgr_ctrl_construct, +* osm_state_mgr_ctrl_destroy +*********/ + +END_C_DECLS + +#endif /* OSM_STATE_MGR_CTRL_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_stats.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_stats.h new file mode 100644 index 00000000..b2a70037 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_stats.h @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_stats.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_stats_t. + * This object represents the OpenSM statistics object. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_STATS_H_ +#define _OSM_STATS_H_ + +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Statistics +* NAME +* OpenSM +* +* DESCRIPTION +* The OpenSM object encapsulates the information needed by the +* OpenSM to track interesting traffic and internal statistics. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: Statistics/osm_stats_t +* NAME +* osm_stats_t +* +* DESCRIPTION +* OpenSM statistics block. +* +* SYNOPSIS +*/ +typedef struct _osm_stats +{ + atomic32_t qp0_mads_outstanding; + atomic32_t qp0_mads_outstanding_on_wire; + atomic32_t qp0_mads_rcvd; + atomic32_t qp0_mads_sent; + atomic32_t qp0_unicasts_sent; + atomic32_t qp1_mads_outstanding; + atomic32_t qp1_mads_rcvd; + atomic32_t qp1_mads_sent; + +} osm_stats_t; +/* +* FIELDS +* qp0_mads_outstanding +* Contains the number of MADs outstanding on QP0. +* When this value reaches zero, OpenSM has discovered all +* nodes on the subnet, and finished retrieving attributes. +* At that time, subnet configuration may begin. +* This variable must be manipulated using atomic instructions. +* +* qp0_mads_outstanding_on_wire +* The number of MADs outstanding on the wire at any moment. +* +* qp0_mads_rcvd +* Total number of QP0 MADs received. +* +* qp0_mads_sent +* Total number of QP0 MADs sent. +* +* qp0_unicasts_sent +* Total number of response-less MADs sent on the wire. This count +* includes getresp(), send() and trap() methods. +* +* SEE ALSO +***************/ + +END_C_DECLS + +#endif /* _OSM_STATS_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_subnet.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_subnet.h new file mode 100644 index 00000000..4732322a --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_subnet.h @@ -0,0 +1,1161 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_subnet.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_subn_t. + * This object represents an IBA subnet. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.12 $ + */ + +#ifndef _OSM_SUBNET_H_ +#define _OSM_SUBNET_H_ + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +#define OSM_SUBNET_VECTOR_MIN_SIZE 0 +#define OSM_SUBNET_VECTOR_GROW_SIZE 1 +#define OSM_SUBNET_VECTOR_CAPACITY 256 + +struct _osm_opensm_t; + +/****h* OpenSM/Subnet +* NAME +* Subnet +* +* DESCRIPTION +* The Subnet object encapsulates the information needed by the +* OpenSM to manage a subnet. The OpenSM allocates one Subnet object +* per IBA subnet. +* +* The Subnet object is not thread safe, thus callers must provide +* serialization. +* +* This object is essentially a container for the various components +* of a subnet. Callers may directly access the member variables. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****f* OpenSM: Subnet/osm_pfn_ui_extension +* NAME +* osm_pfn_ui_extension +* +* DESCRIPTION +* This typedef defines the prototype for UI extension functions +* The might be registered in the subnet options to handle pre_lid_assign, +* and ui_ucast_fwd_assign. +* +* SYNOPSIS +*/ +typedef int +(*osm_pfn_ui_extension_t)( + IN void* context ); +/* +* PARAMETERS +* context +* [in] Client specific context specified in the subnet opt +* Same prefix as the UI function (suffixed by ctx) +* +* RETURN VALUE +* This function returns an int (the semantic is different between +* the different calls) +* +* SEE ALSO +* +*********/ + +/****f* OpenSM: Subnet/osm_pfn_ui_mcast_extension +* NAME +* osm_pfn_ui_mcast_extension +* +* DESCRIPTION +* This typedef defines the prototype for UI extension functions +* They might be registered in the subnet options to handle ui_mcast_fwd_assign +* +* SYNOPSIS +*/ +typedef void +(*osm_pfn_ui_mcast_extension_t)( + IN void *context, + IN ib_net16_t mlid, + IN osm_mcast_req_type_t request_type, + IN ib_net64_t port_guid ); +/* +* PARAMETERS +* context +* [in] Client specific context specified in the subnet opt +* Same prefix as the UI function (suffixed by ctx) +* +* mlid +* [in] multicast lid of the group handled. +* +* request_type +* [in] Type of MC request being handled (create/join/leave) +* +* port_guid +* [in] port gui of the port that was added/removed from the +* multicast group handled. +* +* RETURN VALUE +* This function does not return a value. +* +* SEE ALSO +* +*********/ + +/****d* OpenSM: Subnet/osm_testability_modes_t +* NAME +* osm_testability_modes_t +* +* DESCRIPTION +* Enumerates the possible testability modes. +* +* SYNOPSIS +*/ +typedef enum _osm_testability_modes +{ + OSM_TEST_MODE_NONE = 0, + OSM_TEST_MODE_EXIT_BEFORE_SEND_HANDOVER, + OSM_TEST_MODE_MAX +} osm_testability_modes_t; +/***********/ + +/****s* OpenSM: Subnet/osm_qos_options_t +* NAME +* osm_qos_options_t +* +* DESCRIPTION +* Subnet QoS options structure. This structure contains the various +* QoS specific configuration parameters for the subnet. +* +* SYNOPSIS +*/ +typedef struct _osm_qos_options_t { + unsigned max_vls; + unsigned high_limit; + char *vlarb_high; + char *vlarb_low; + char *sl2vl; +} osm_qos_options_t; +/* +* FIELDS +* +* max_vls +* The number of maximum VLs on the Subnet +* +* high_limit +* The limit of High Priority component of VL Arbitration +* table (IBA 7.6.9) +* +* vlarb_high +* High priority VL Arbitration table template. +* +* vlarb_low +* Low priority VL Arbitration table template. +* +* sl2vl +* SL2VL Mapping table (IBA 7.6.6) template. +* +*********/ + +/****s* OpenSM: Subnet/osm_subn_opt_t +* NAME +* osm_subn_opt_t +* +* DESCRIPTION +* Subnet options structure. This structure contains the various +* site specific configuration parameters for the subnet. +* +* SYNOPSIS +*/ +typedef struct _osm_subn_opt +{ + ib_net64_t guid; + ib_net64_t m_key; + ib_net64_t sm_key; + ib_net64_t subnet_prefix; + ib_net16_t m_key_lease_period; + uint32_t sweep_interval; + uint32_t max_wire_smps; + uint32_t transaction_timeout; + uint8_t sm_priority; + uint8_t lmc; + boolean_t lmc_esp0; + uint8_t max_op_vls; + uint8_t force_link_speed; + boolean_t reassign_lids; + boolean_t reassign_lfts; + boolean_t ignore_other_sm; + boolean_t single_thread; + boolean_t no_multicast_option; + boolean_t disable_multicast; + boolean_t force_log_flush; + uint8_t subnet_timeout; + uint8_t packet_life_time; + uint8_t vl_stall_count; + uint8_t leaf_vl_stall_count; + uint8_t head_of_queue_lifetime; + uint8_t leaf_head_of_queue_lifetime; + uint8_t local_phy_errors_threshold; + uint8_t overrun_errors_threshold; + uint32_t sminfo_polling_timeout; + uint32_t polling_retry_number; + uint32_t max_msg_fifo_timeout; + boolean_t force_heavy_sweep; + uint8_t log_flags; + char * dump_files_dir; + char * log_file; + unsigned long log_max_size; + char * partition_config_file; + boolean_t no_partition_enforcement; + boolean_t no_qos; + boolean_t accum_log_file; + boolean_t console; + cl_map_t port_prof_ignore_guids; + boolean_t port_profile_switch_nodes; + osm_pfn_ui_extension_t pfn_ui_pre_lid_assign; + void * ui_pre_lid_assign_ctx; + osm_pfn_ui_mcast_extension_t pfn_ui_mcast_fdb_assign; + void * ui_mcast_fdb_assign_ctx; + boolean_t sweep_on_trap; + osm_testability_modes_t testability_mode; + char * routing_engine_name; + char * lid_matrix_dump_file; + char * ucast_dump_file; + char * updn_guid_file; + char * sa_db_file; + boolean_t exit_on_fatal; + boolean_t honor_guid2lid_file; + osm_qos_options_t qos_options; + osm_qos_options_t qos_ca_options; + osm_qos_options_t qos_sw0_options; + osm_qos_options_t qos_swe_options; + osm_qos_options_t qos_rtr_options; + boolean_t enable_quirks; + boolean_t no_clients_rereg; +} osm_subn_opt_t; +/* +* FIELDS +* +* guid +* The port guid that the SM is binding to. +* +* m_key +* M_Key value sent to all ports qualifing all Set(PortInfo). +* +* sm_key +* SM_Key value of the SM to qualify rcv SA queries as "trusted". +* +* subnet_prefix +* Subnet prefix used on this subnet. +* +* m_key_lease_period +* The lease period used for the M_Key on this subnet. +* +* sweep_interval +* The number of seconds between subnet sweeps. A value of 0 +* disables sweeping. +* +* sm_priority +* The priority of this SM as specified by the user. This +* value is made available in the SMInfo attribute. +* +* lmc +* The LMC value used on this subnet. +* +* lmc_esp0 +* Whether LMC value used on subnet should be used for +* enhanced switch port 0 or not. If TRUE, it is used. +* Otherwise (the default), LMC is set to 0 for ESP0. +* +* max_op_vls +* Limit the maximal operational VLs. default is 1. +* +* reassign_lids +* If TRUE cause all lids to be re-assigend. +* Otherwise (the default), +* OpenSM always tries to preserve as LIDs as much as possible. +* +* reassign_lfts +* If TRUE ignore existing LFT entries on first sweep (default). +* Otherwise only non minimal hop cases are modified. +* NOTE: A standby SM clears its first sweep flag - since the +* master SM already sweeps... +* +* ignore_other_sm_option +* This flag is TRUE if other SMs on the subnet should be ignored. +* +* no_multicast_option +* This flag is TRUE if OpenSM should disable multicast support. +* +* max_msg_fifo_timeout +* The maximal time a message can stay in the incoming message queue. +* If there is more than one message in the queue and the last +* message stayed in the queue more than this value the SA request +* will be immediately returned with a BUSY status. +* +* subnet_timeout +* The subnet_timeout that will be set for all the ports in the +* design SubnMgt.Set(PortInfo.vl_stall_life)) +* +* vl_stall_count +* The number of sequential packets dropped that cause the port +* to enter the VLStalled state. +* +* leaf_vl_stall_count +* The number of sequential packets dropped that cause the port +* to enter the VLStalled state. This is for switch ports driving +* a CA or router port. +* +* head_of_queue_lifetime +* The maximal time a packet can live at the head of a VL queue +* on any port not driving a CA or router port. +* +* leaf_head_of_queue_lifetime +* The maximal time a packet can live at the head of a VL queue +* on switch ports driving a CA or router. +* +* local_phy_errors_threshold +* Threshold of local phy errors for sending Trap 129 +* +* overrun_errors_threshold +* Threshold of credits overrun errors for sending Trap 129 +* +* sminfo_polling_timeout +* Specifies the polling timeout (in milliseconds) - the timeout +* between one poll to another. +* +* packet_life_time +* The maximal time a packet can stay in a switch. +* The value is send to all switches as SubnMgt.Set(SwitchInfo.life_state) +* +* dump_files_dir +* The directory to be used for subnet.lst osm.fdbs, osm.mcfdbs +* and default log file (the latter for Windows, not Linux). +* +* log_file +* Name of the log file (or NULL) for stdout. +* +* log_max_size +* This option defines maximal log file size in MB. When +* specified the log file will be truncated upon reaching +* this limit. +* +* accum_log_file +* If TRUE (default) - the log file will be accumulated. +* If FALSE - the log file will be erased before starting current opensm run. +* +* port_prof_ignore_guids +* A map of guids to be ignored by port profiling. +* +* port_profile_switch_nodes +* If TRUE will count the number of switch nodes routed through +* the link. If FALSE - only CA/RT nodes are counted. +* +* pfn_ui_pre_lid_assign +* A UI function to be invoked prior to lid assigment. It should +* return 1 if any change was made to any lid or 0 otherwise. +* +* ui_pre_lid_assign_ctx +* A UI context (void *) to be provided to the pfn_ui_pre_lid_assign +* +* pfn_ui_mcast_fdb_assign +* A UI function to be called inside the mcast manager instead of +* the call for the build spanning tree. This will be called on +* every multicast call for create, join and leave, and is +* responsible for the mcast FDB configuration. +* +* ui_mcast_fdb_assign_ctx +* A UI context (void *) to be provided to the pfn_ui_mcast_fdb_assign +* +* sweep_on_trap +* Received traps will initiate a new sweep. +* +* testability_mode +* Object that indicates if we are running in a special testability mode. +* +* routing_engine_name +* Name of used routing engine +* (other than default Min Hop Algorithm) +* +* lid_matrix_dump_file +* Name of the lid matrix dump file from where switch +* lid matrices (min hops tables) will be loaded +* +* ucast_dump_file +* Name of the unicast routing dump file from where switch +* forwarding tables will be loaded +* +* updn_guid_file +* Pointer to name of the UPDN guid file given by User +* +* sa_db_file +* Name of the SA database file. +* +* exit_on_fatal +* If TRUE (default) - SM will exit on fatal subnet initialization issues. +* If FALSE - SM will not exit. +* Fatal initialization issues: +* a. SM recognizes 2 different nodes with the same guid, or +* 12x link with lane reversal badly configured. +* +* honor_guid2lid_file +* Always honor the guid2lid file if it exists and is valid. This +* means that the file will be honored when SM is coming out of +* STANDBY. By default this is FALSE. +* +* qos_options +* Default set of QoS options +* +* qos_ca_options +* QoS options for CA ports +* +* qos_sw0_options +* QoS options for switches' port 0 +* +* qos_swe_options +* QoS options for switches' external ports +* +* qos_rtr_options +* QoS options for router ports +* +* enable_quirks +* Enable high risk new features and not fully qualified +* hardware specific work arounds +* +* no_clients_rereg +* When TRUE disables clients reregistration request. +* +* SEE ALSO +* Subnet object +*********/ + +/****s* OpenSM: Subnet/osm_subn_t +* NAME +* osm_subn_t +* +* DESCRIPTION +* Subnet structure. Callers may directly access member components, +* after grabbing a lock. +* +* TO DO +* This structure should probably be volatile. +* +* SYNOPSIS +*/ +typedef struct _osm_subn +{ + struct _osm_opensm_t *p_osm; + cl_qmap_t sw_guid_tbl; + cl_qmap_t node_guid_tbl; + cl_qmap_t port_guid_tbl; + cl_qmap_t rtr_guid_tbl; + cl_qmap_t prtn_pkey_tbl; + cl_qmap_t mgrp_mlid_tbl; + cl_qmap_t sm_guid_tbl; + cl_list_t light_sweep_physp_list; + cl_qlist_t sa_sr_list; + cl_qlist_t sa_infr_list; + cl_ptr_vector_t node_lid_tbl; + cl_ptr_vector_t port_lid_tbl; + ib_net16_t master_sm_base_lid; + ib_net16_t sm_base_lid; + ib_net64_t sm_port_guid; + uint8_t sm_state; + osm_subn_opt_t opt; + uint16_t max_unicast_lid_ho; + uint16_t max_multicast_lid_ho; + uint8_t min_ca_mtu; + uint8_t min_ca_rate; + boolean_t ignore_existing_lfts; + boolean_t subnet_initialization_error; + boolean_t force_immediate_heavy_sweep; + boolean_t force_delayed_heavy_sweep; + cl_list_t new_ports_list; + boolean_t in_sweep_hop_0; + boolean_t moved_to_master_state; + boolean_t first_time_master_sweep; + boolean_t coming_out_of_standby; +} osm_subn_t; +/* +* FIELDS +* sw_guid_tbl +* Container of pointers to all Switch objects in the subent. +* Indexed by node GUID. +* +* node_guid_tbl +* Container of pointers to all Node objects in the subent. +* Indexed by node GUID. +* +* port_guid_tbl +* Container of pointers to all Port objects in the subent. +* Indexed by port GUID - network order! +* +* rtr_guid_tbl +* Container of pointers to all Router objects in the subent. +* Indexed by node GUID. +* +* prtn_pkey_tbl +* Container of pointers to all Partition objects in the subnet. +* Indexed by P_KEY. +* +* mgrp_mlid_tbl +* Container of pointers to all Multicast Group objects in the subnet. +* Indexed by MLID. +* +* sm_guid_tbl +* Container of pointers to SM objects representing other SMs +* on the subnet. +* +* light_sweep_physp_list +* A list of all phys ports to scan for a change in remote +* side state in next light sweep. These ports are not down +* but for some reason the remote side did not answer. +* +* node_lid_tbl +* Container of pointers to all Node objects in the subent. +* Indexed by node LID. +* +* port_ptr_tbl +* Container of pointers to all Port objects in the subent. +* Indexed by port LID. +* +* master_sm_base_lid +* The base LID owned by the subnet's master SM. +* +* sm_base_lid +* The base LID of the local port where the SM is. +* +* sm_port_guid +* This SM's own port GUID. +* +* sm_state +* The high-level state of the SM. This value is made available +* in the SMInfo attribute. +* +* opt +* Subnet options structure contains site specific configuration. +* +* max_unicast_lid_ho +* The minimal max unicast lid reported by all switches +* +* max_multicast_lid_ho +* The minimal max multicast lid reported by all switches +* +* min_ca_mtu +* The minimal MTU reported by all CAs ports on the subnet +* +* min_ca_rate +* The minimal rate reported by all CA ports on the subnet +* +* ignore_existing_lfts +* This flag is a dynamic flag to instruct the LFT assignment to +* ignore existing legal LFT settings. +* The value will be set according to : +* - During SM init set to the reassign_lfts flag value +* - Coming out of STANDBY it will be cleared (other SM worked) +* - Any change to the list of switches will set it to high +* - Set to FALSE upon end of all lft assignments. +* +* subnet_initalization_error +* Similar to the force_immediate_heavy_sweep flag. If TRUE - +* means that we had errors during initialization (due to SubnSet requests +* that failed). We want to declare the subnet as unhealthy, and force +* another heavy sweep. +* +* force_immediate_heavy_sweep +* If TRUE - we want to force a heavy sweep. This can be done either +* due to receiving of trap - meaning there is some change on the subnet, +* or we received a handover from a remote sm. +* In this case we want to sweep and reconfigure the entire subnet. +* This will cause another heavy sweep to occure when the current sweep +* is done. +* +* force_delayed_heavy_sweep +* In some means - similar to the force_immediate_heavy_sweep flag, only +* it'll cause a heavy sweep in the next sweep. Note that this means that +* if we are running with -s 0 (no sweeps) - then this forced heavy sweep +* will not occur. +* If we had some trouble on the subnet, that caused a strange dropping +* of ports - we will try to do another heavy sweep on our next sweep. +* +* new_ports_list +* Container of pointers to port objects that were discovered for +* the first time during a current sweep. +* +* in_sweep_hop_0 +* When in_sweep_hop_0 flag is set to TRUE - this means we are +* in sweep_hop_0 - meaning we do not want to continue beyond +* the current node. +* This is relevant for the case of SM on switch, since in the +* switch info we need to signal somehow not to continue +* the sweeping. +* +* moved_to_master_state +* Used for the writing of "SUBNET UP" into /var/log/messages. +* Will be TRUE when the SM switches to Master state, and returned +* to FALSE once the sunbet is up. +* +* first_time_master_sweep +* This flag is used for the PortInfo setting. On the first sweep as master +* (meaning after moving from Standby|Discovering state), the SM must send +* a PortInfoSet to all ports. After that - we want to minimize the number of +* PortInfoSet requests sent, and to send only requests that change the value +* from what is updated in the port (or send a first request if this is a new +* port). We will set this flag to TRUE when entering the master state, and +* set it back to FALSE at the end of the drop manager. This is done since at +* the end of the drop manager we have updated all the ports that are +* reachable, and from now on these are the only ports we have data of. We +* don't want to send extra set requests to these ports anymore. +* +* coming_out_of_standby +* TRUE on the first sweep after the SM was in standby. +* Used for nulling any cache of LID and Routing. +* The flag is set true if the SM state was standby and now changed to MASTER +* it is reset at the end of the sweep. +* +* SEE ALSO +* Subnet object +*********/ + +/****f* OpenSM: Subnet/osm_subn_construct +* NAME +* osm_subn_construct +* +* DESCRIPTION +* This function constructs a Subnet object. +* +* SYNOPSIS +*/ +void +osm_subn_construct( + IN osm_subn_t* const p_subn ); +/* +* PARAMETERS +* p_subn +* [in] Pointer to a Subnet object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_subn_init, and osm_subn_destroy. +* +* Calling osm_subn_construct is a prerequisite to calling any other +* method except osm_subn_init. +* +* SEE ALSO +* Subnet object, osm_subn_init, osm_subn_destroy +*********/ + +/****f* OpenSM: Subnet/osm_subn_destroy +* NAME +* osm_subn_destroy +* +* DESCRIPTION +* The osm_subn_destroy function destroys a subnet, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_subn_destroy( + IN osm_subn_t* const p_subn ); +/* +* PARAMETERS +* p_subn +* [in] Pointer to a Subnet object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified Subnet object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to osm_subn_construct or +* osm_subn_init. +* +* SEE ALSO +* Subnet object, osm_subn_construct, osm_subn_init +*********/ + +/****f* OpenSM: Subnet/osm_subn_init +* NAME +* osm_subn_init +* +* DESCRIPTION +* The osm_subn_init function initializes a Subnet object for use. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_subn_init( + IN osm_subn_t* const p_subn, + IN struct _osm_opensm_t * const p_osm, + IN const osm_subn_opt_t* const p_opt ); +/* +* PARAMETERS +* p_subn +* [in] Pointer to an osm_subn_t object to initialize. +* +* p_opt +* [in] Pointer to the subnet options structure. +* +* RETURN VALUES +* IB_SUCCESS if the Subnet object was initialized successfully. +* +* NOTES +* Allows calling other Subnet methods. +* +* SEE ALSO +* Subnet object, osm_subn_construct, osm_subn_destroy +*********/ + +/* + Forward references. +*/ +struct _osm_mad_addr; +struct _osm_log; +struct _osm_switch; +struct _osm_physp; +struct _osm_port; + +/****f* OpenSM: Helper/osm_get_gid_by_mad_addr +* NAME +* osm_get_gid_by_mad_addr +* +* DESCRIPTION +* Looks for the requester gid in the mad address. +* +* Note: This code is not thread safe. Need to grab the lock before +* calling it. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_get_gid_by_mad_addr( + IN struct _osm_log *p_log, + IN const osm_subn_t *p_subn, + IN const struct _osm_mad_addr *p_mad_addr, + OUT ib_gid_t *p_gid); +/* +* PARAMETERS +* p_log +* [in] Pointer to a log object. +* +* p_subn +* [in] Pointer to subnet object. +* +* p_mad_addr +* [in] Pointer to mad address object. +* +* p_gid +* [out] Pointer to the GID structure to fill in. +* +* RETURN VALUES +* IB_SUCCESS if able to find the GID by address given. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Helper/osm_get_physp_by_mad_addr +* NAME +* osm_get_physp_by_mad_addr +* +* DESCRIPTION +* Looks for the requester physical port in the mad address. +* +* Note: This code is not thread safe. Need to grab the lock before +* calling it. +* +* SYNOPSIS +*/ +struct _osm_physp * +osm_get_physp_by_mad_addr( + IN struct _osm_log *p_log, + IN const osm_subn_t *p_subn, + IN struct _osm_mad_addr *p_mad_addr ); +/* +* PARAMETERS +* p_log +* [in] Pointer to a log object. +* +* p_subn +* [in] Pointer to subnet object. +* +* p_mad_addr +* [in] Pointer to mad address object. +* +* RETURN VALUES +* Pointer to requester physical port object if found. Null otherwise. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Helper/osm_get_port_by_mad_addr +* NAME +* osm_get_port_by_mad_addr +* +* DESCRIPTION +* Looks for the requester port in the mad address. +* +* Note: This code is not thread safe. Need to grab the lock before +* calling it. +* +* SYNOPSIS +*/ +struct _osm_port * +osm_get_port_by_mad_addr( + IN struct _osm_log *p_log, + IN const osm_subn_t *p_subn, + IN struct _osm_mad_addr *p_mad_addr ); +/* +* PARAMETERS +* p_log +* [in] Pointer to a log object. +* +* p_subn +* [in] Pointer to subnet object. +* +* p_mad_addr +* [in] Pointer to mad address object. +* +* RETURN VALUES +* Pointer to requester port object if found. Null otherwise. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Subnet/osm_get_switch_by_guid +* NAME +* osm_get_switch_by_guid +* +* DESCRIPTION +* Looks for the given switch guid in the subnet table of switches by guid. +* NOTE: this code is not thread safe. Need to grab the lock before +* calling it. +* +* SYNOPSIS +*/ +struct _osm_switch * +osm_get_switch_by_guid( + IN const osm_subn_t *p_subn, + IN uint64_t guid ); +/* +* PARAMETERS +* p_subn +* [in] Pointer to an osm_subn_t object +* +* guid +* [in] The node guid in host order +* +* RETURN VALUES +* The switch structure pointer if found. NULL otherwise. +* +* SEE ALSO +* Subnet object, osm_subn_construct, osm_subn_destroy, +* osm_switch_t +*********/ + +/****f* OpenSM: Subnet/osm_get_node_by_guid +* NAME +* osm_get_node_by_guid +* +* DESCRIPTION +* The looks for the given node giud in the subnet table of nodes by guid. +* NOTE: this code is not thread safe. Need to grab the lock before +* calling it. +* +* SYNOPSIS +*/ +struct _osm_node * +osm_get_node_by_guid( + IN osm_subn_t const *p_subn, + IN uint64_t guid ); +/* +* PARAMETERS +* p_subn +* [in] Pointer to an osm_subn_t object +* +* guid +* [in] The node guid in host order +* +* RETURN VALUES +* The node structure pointer if found. NULL otherwise. +* +* SEE ALSO +* Subnet object, osm_subn_construct, osm_subn_destroy, +* osm_node_t +*********/ + +/****f* OpenSM: Subnet/osm_get_port_by_guid +* NAME +* osm_get_port_by_guid +* +* DESCRIPTION +* The looks for the given port guid in the subnet table of ports by guid. +* NOTE: this code is not thread safe. Need to grab the lock before +* calling it. +* +* SYNOPSIS +*/ +struct _osm_port * +osm_get_port_by_guid( + IN osm_subn_t const *p_subn, + IN uint64_t guid ); +/* +* PARAMETERS +* p_subn +* [in] Pointer to an osm_subn_t object +* +* guid +* [in] The port guid in host order +* +* RETURN VALUES +* The port structure pointer if found. NULL otherwise. +* +* SEE ALSO +* Subnet object, osm_subn_construct, osm_subn_destroy, +* osm_port_t +*********/ + +/****f* OpenSM: Helper/osm_get_physp_by_mad_addr +* NAME +* osm_get_physp_by_mad_addr +* +* DESCRIPTION +* Looks for the requester physical port in the mad address. +* +* Note: This code is not thread safe. Need to grab the lock before +* calling it. +* +* SYNOPSIS +*/ +struct _osm_physp * +osm_get_physp_by_mad_addr( + IN struct _osm_log *p_log, + IN const osm_subn_t *p_subn, + IN struct _osm_mad_addr *p_mad_addr ); +/* +* PARAMETERS +* p_log +* [in] Pointer to a log object. +* +* p_subn +* [in] Pointer to subnet object. +* +* p_mad_addr +* [in] Pointer to mad address object. +* +* RETURN VALUES +* Pointer to requester physical port object if found. Null otherwise. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Subnet/osm_subn_set_default_opt +* NAME +* osm_subn_set_default_opt +* +* DESCRIPTION +* The osm_subn_set_default_opt function sets the default options. +* +* SYNOPSIS +*/ +void +osm_subn_set_default_opt( + IN osm_subn_opt_t* const p_opt ); +/* +* PARAMETERS +* +* p_opt +* [in] Pointer to the subnet options structure. +* +* RETURN VALUES +* None +* +* NOTES +* +* SEE ALSO +* Subnet object, osm_subn_construct, osm_subn_destroy +*********/ + +/****f* OpenSM: Subnet/osm_subn_set_default_opt +* NAME +* osm_subn_set_default_opt +* +* DESCRIPTION +* The osm_subn_set_default_opt function sets the default options. +* +* SYNOPSIS +*/ +void +osm_subn_set_default_opt( + IN osm_subn_opt_t* const p_opt ); +/* +* PARAMETERS +* +* p_opt +* [in] Pointer to the subnet options structure. +* +* RETURN VALUES +* None +* +* NOTES +* +* SEE ALSO +* Subnet object, osm_subn_construct, osm_subn_destroy +*********/ + +/****f* OpenSM: Subnet/osm_subn_parse_conf_file +* NAME +* osm_subn_parse_conf_file +* +* DESCRIPTION +* The osm_subn_parse_conf_file function parses the configuration file +* and sets the defaults accordingly. +* +* SYNOPSIS +*/ +void +osm_subn_parse_conf_file( + IN osm_subn_opt_t* const p_opt ); +/* +* PARAMETERS +* +* p_opt +* [in] Pointer to the subnet options structure. +* +* RETURN VALUES +* None +* +* NOTES +* Assumes the conf file is part of the cache dir which defaults to +* OSM_DEFAULT_CACHE_DIR or OSM_CACHE_DIR the name is opensm.opts +* +* SEE ALSO +* Subnet object, osm_subn_construct, osm_subn_destroy +*********/ + +/****f* OpenSM: Subnet/osm_subn_parse_conf_file +* NAME +* osm_subn_rescan_conf_file +* +* DESCRIPTION +* The osm_subn_rescan_conf_file function parses the configuration +* file and update selected subnet options +* +* SYNOPSIS +*/ +void +osm_subn_rescan_conf_file( + IN osm_subn_opt_t* const p_opts ); +/* +* PARAMETERS +* +* p_opt +* [in] Pointer to the subnet options structure. +* +* RETURN VALUES +* None +* +* NOTES +* This uses the same file as osm_subn_parse_conf_file() +* +*********/ + +/****f* OpenSM: Subnet/osm_subn_write_conf_file +* NAME +* osm_subn_write_conf_file +* +* DESCRIPTION +* Write the configuration file into the cache +* +* SYNOPSIS +*/ +void +osm_subn_write_conf_file( + IN osm_subn_opt_t* const p_opt ); +/* +* PARAMETERS +* +* p_opt +* [in] Pointer to the subnet options structure. +* +* RETURN VALUES +* None +* +* NOTES +* Assumes the conf file is part of the cache dir which defaults to +* OSM_DEFAULT_CACHE_DIR or OSM_CACHE_DIR the name is opensm.opts +* +* SEE ALSO +* Subnet object, osm_subn_construct, osm_subn_destroy +*********/ + +END_C_DECLS + +#endif /* _OSM_SUBNET_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sw_info_rcv.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sw_info_rcv.h new file mode 100644 index 00000000..ecb976cf --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sw_info_rcv.h @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sw_info_rcv.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_si_rcv_t. + * This object represents the SwitchInfo Receiver object. + * attribute from a node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_SI_RCV_H_ +#define _OSM_SI_RCV_H_ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Switch Info Receiver +* NAME +* Switch Info Receiver +* +* DESCRIPTION +* The Switch Info Receiver object encapsulates the information +* needed to receive the SwitchInfo attribute from a node. +* +* The Switch Info Receiver object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: Switch Info Receiver/osm_si_rcv_t +* NAME +* osm_si_rcv_t +* +* DESCRIPTION +* Switch Info Receiver structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_si_rcv +{ + osm_subn_t *p_subn; + osm_log_t *p_log; + osm_req_t *p_req; + osm_state_mgr_t *p_state_mgr; + cl_plock_t *p_lock; + +} osm_si_rcv_t; +/* +* FIELDS +* p_subn +* Pointer to the Subnet object for this subnet. +* +* p_log +* Pointer to the log object. +* +* p_req +* Pointer to the Request object. +* +* p_state_mgr +* Pointer to the State Manager object. +* +* p_lock +* Pointer to the serializing lock. +* +* SEE ALSO +* Switch Info Receiver object +*********/ + +/****f* OpenSM: Switch Info Receiver/osm_si_rcv_construct +* NAME +* osm_si_rcv_construct +* +* DESCRIPTION +* This function constructs a Switch Info Receiver object. +* +* SYNOPSIS +*/ +void osm_si_rcv_construct( + IN osm_si_rcv_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a Switch Info Receiver object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_si_rcv_init, osm_si_rcv_destroy, +* and osm_si_rcv_is_inited. +* +* Calling osm_si_rcv_construct is a prerequisite to calling any other +* method except osm_si_rcv_init. +* +* SEE ALSO +* Switch Info Receiver object, osm_si_rcv_init, +* osm_si_rcv_destroy, osm_si_rcv_is_inited +*********/ + +/****f* OpenSM: Switch Info Receiver/osm_si_rcv_destroy +* NAME +* osm_si_rcv_destroy +* +* DESCRIPTION +* The osm_si_rcv_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_si_rcv_destroy( + IN osm_si_rcv_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* Switch Info Receiver object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_si_rcv_construct or osm_si_rcv_init. +* +* SEE ALSO +* Switch Info Receiver object, osm_si_rcv_construct, +* osm_si_rcv_init +*********/ + +/****f* OpenSM: Switch Info Receiver/osm_si_rcv_init +* NAME +* osm_si_rcv_init +* +* DESCRIPTION +* The osm_si_rcv_init function initializes a +* Switch Info Receiver object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_si_rcv_init( + IN osm_si_rcv_t* const p_ctrl, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN osm_req_t* const p_req, + IN osm_state_mgr_t* const p_state_mgr, + IN cl_plock_t* const p_lock ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_si_rcv_t object to initialize. +* +* p_subn +* [in] Pointer to the Subnet object for this subnet. +* +* p_log +* [in] Pointer to the log object. +* +* p_req +* [in] Pointer to an osm_req_t object. +* +* p_state_mgr +* [in] Pointer to the State Manager object. +* +* p_lock +* [in] Pointer to the OpenSM serializing lock. +* +* RETURN VALUES +* IB_SUCCESS if the Switch Info Receiver object was initialized +* successfully. +* +* NOTES +* Allows calling other Switch Info Receiver methods. +* +* SEE ALSO +* Switch Info Receiver object, osm_si_rcv_construct, +* osm_si_rcv_destroy, osm_si_rcv_is_inited +*********/ + +/****f* OpenSM: Switch Info Receiver/osm_si_rcv_is_inited +* NAME +* osm_si_rcv_is_inited +* +* DESCRIPTION +* Indicates if the object has been initialized with osm_si_rcv_init. +* +* SYNOPSIS +*/ +boolean_t osm_si_rcv_is_inited( + IN const osm_si_rcv_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_si_rcv_t object. +* +* RETURN VALUES +* TRUE if the object was initialized successfully, +* FALSE otherwise. +* +* NOTES +* The osm_si_rcv_construct or osm_si_rcv_init must be +* called before using this function. +* +* SEE ALSO +* Switch Info Receiver object, osm_si_rcv_construct, +* osm_si_rcv_init +*********/ + +/****f* OpenSM: Switch Info Receiver/osm_si_rcv_process +* NAME +* osm_si_rcv_process +* +* DESCRIPTION +* Process the SwitchInfo attribute. +* +* SYNOPSIS +*/ +void osm_si_rcv_process( + IN const osm_si_rcv_t* const p_ctrl, + IN osm_madw_t* const p_madw ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_si_rcv_t object. +* +* p_madw +* [in] Pointer to the MAD Wrapper containing the MAD +* that contains the node's SwitchInfo attribute. +* +* RETURN VALUES +* CL_SUCCESS if the SwitchInfo processing was successful. +* +* NOTES +* This function processes a SwitchInfo attribute. +* +* SEE ALSO +* Switch Info Receiver, Switch Info Response Controller +*********/ + +END_C_DECLS + +#endif /* _OSM_SI_RCV_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sw_info_rcv_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sw_info_rcv_ctrl.h new file mode 100644 index 00000000..5f502cc1 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sw_info_rcv_ctrl.h @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sw_info_rcv_ctrl.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_si_rcv_ctrl_t. + * This object represents a controller that receives the IBA SwitchInfo + * attribute from a node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_SI_RCV_CTRL_H_ +#define _OSM_SI_RCV_CTRL_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Switch Info Receive Controller +* NAME +* Switch Info Receive Controller +* +* DESCRIPTION +* The Switch Info Receive Controller object encapsulates +* the information needed to receive the SwitchInfo attribute from a node. +* +* The Switch Info Receive Controller object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: Switch Info Receive Controller/osm_si_rcv_ctrl_t +* NAME +* osm_si_rcv_ctrl_t +* +* DESCRIPTION +* Switch Info Receive Controller structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_si_rcv_ctrl +{ + osm_si_rcv_t *p_rcv; + osm_log_t *p_log; + cl_dispatcher_t *p_disp; + cl_disp_reg_handle_t h_disp; + +} osm_si_rcv_ctrl_t; +/* +* FIELDS +* p_rcv +* Pointer to the Switch Info Receiver object. +* +* p_log +* Pointer to the log object. +* +* p_disp +* Pointer to the Dispatcher. +* +* h_disp +* Handle returned from dispatcher registration. +* +* SEE ALSO +* Switch Info Receive Controller object +* Switch Info Receiver object +*********/ + +/****f* OpenSM: Switch Info Receive Controller/osm_si_rcv_ctrl_construct +* NAME +* osm_si_rcv_ctrl_construct +* +* DESCRIPTION +* This function constructs a Switch Info Receive Controller object. +* +* SYNOPSIS +*/ +void osm_si_rcv_ctrl_construct( + IN osm_si_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a Switch Info Receive Controller +* object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_si_rcv_ctrl_init, osm_si_rcv_ctrl_destroy, +* and osm_si_rcv_ctrl_is_inited. +* +* Calling osm_si_rcv_ctrl_construct is a prerequisite to calling any other +* method except osm_si_rcv_ctrl_init. +* +* SEE ALSO +* Switch Info Receive Controller object, osm_si_rcv_ctrl_init, +* osm_si_rcv_ctrl_destroy, osm_si_rcv_ctrl_is_inited +*********/ + +/****f* OpenSM: Switch Info Receive Controller/osm_si_rcv_ctrl_destroy +* NAME +* osm_si_rcv_ctrl_destroy +* +* DESCRIPTION +* The osm_si_rcv_ctrl_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_si_rcv_ctrl_destroy( + IN osm_si_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* Switch Info Receive Controller object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_si_rcv_ctrl_construct or osm_si_rcv_ctrl_init. +* +* SEE ALSO +* Switch Info Receive Controller object, osm_si_rcv_ctrl_construct, +* osm_si_rcv_ctrl_init +*********/ + +/****f* OpenSM: Switch Info Receive Controller/osm_si_rcv_ctrl_init +* NAME +* osm_si_rcv_ctrl_init +* +* DESCRIPTION +* The osm_si_rcv_ctrl_init function initializes a +* Switch Info Receive Controller object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_si_rcv_ctrl_init( + IN osm_si_rcv_ctrl_t* const p_ctrl, + IN osm_si_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_si_rcv_ctrl_t object to initialize. +* +* p_rcv +* [in] Pointer to an osm_si_rcv_t object. +* +* p_log +* [in] Pointer to the log object. +* +* p_disp +* [in] Pointer to the OpenSM central Dispatcher. +* +* RETURN VALUES +* CL_SUCCESS if the Switch Info Receive Controller object was initialized +* successfully. +* +* NOTES +* Allows calling other Switch Info Receive Controller methods. +* +* SEE ALSO +* Switch Info Receive Controller object, osm_si_rcv_ctrl_construct, +* osm_si_rcv_ctrl_destroy, osm_si_rcv_ctrl_is_inited +*********/ + +/****f* OpenSM: Switch Info Receive Controller/osm_si_rcv_ctrl_is_inited +* NAME +* osm_si_rcv_ctrl_is_inited +* +* DESCRIPTION +* Indicates if the object has been initialized with osm_si_rcv_ctrl_init. +* +* SYNOPSIS +*/ +boolean_t osm_si_rcv_ctrl_is_inited( + IN const osm_si_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_si_rcv_ctrl_t object. +* +* RETURN VALUES +* TRUE if the object was initialized successfully, +* FALSE otherwise. +* +* NOTES +* The osm_si_rcv_ctrl_construct or osm_si_rcv_ctrl_init must be +* called before using this function. +* +* SEE ALSO +* Switch Info Receive Controller object, osm_si_rcv_ctrl_construct, +* osm_si_rcv_ctrl_init +*********/ + +END_C_DECLS + +#endif /* _OSM_SI_RCV_CTRL_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sweep_fail_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sweep_fail_ctrl.h new file mode 100644 index 00000000..3979a4d0 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sweep_fail_ctrl.h @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sweep_fail_ctrl.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_sweep_fail_ctrl_t. + * This object represents a controller that + * handles transport failures during sweeps. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_SWEEP_FAIL_CTRL_H_ +#define _OSM_SWEEP_FAIL_CTRL_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Sweep Fail Controller +* NAME +* Sweep Fail Controller +* +* DESCRIPTION +* The Sweep Fail Controller object encapsulates +* the information needed to handle transport failures during +* sweeps. +* +* The Sweep Fail Controller object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: Sweep Fail Controller/osm_sweep_fail_ctrl_t +* NAME +* osm_sweep_fail_ctrl_t +* +* DESCRIPTION +* Sweep Fail Controller structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_sweep_fail_ctrl +{ + osm_log_t *p_log; + osm_state_mgr_t *p_state_mgr; + cl_dispatcher_t *p_disp; + cl_disp_reg_handle_t h_disp; + + +} osm_sweep_fail_ctrl_t; +/* +* FIELDS +* p_log +* Pointer to the log object. +* +* p_sate_mgr +* Pointer to the state manager object. +* +* p_disp +* Pointer to the Dispatcher. +* +* h_disp +* Handle returned from dispatcher registration. +* +* SEE ALSO +* Sweep Fail Controller object +* Sweep Failr object +*********/ + +/****f* OpenSM: Sweep Fail Controller/osm_sweep_fail_ctrl_construct +* NAME +* osm_sweep_fail_ctrl_construct +* +* DESCRIPTION +* This function constructs a Sweep Fail Controller object. +* +* SYNOPSIS +*/ +void +osm_sweep_fail_ctrl_construct( + IN osm_sweep_fail_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a Sweep Fail Controller +* object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_sweep_fail_ctrl_init, osm_sweep_fail_ctrl_destroy +* +* Calling osm_sweep_fail_ctrl_construct is a prerequisite to calling any other +* method except osm_sweep_fail_ctrl_init. +* +* SEE ALSO +* Sweep Fail Controller object, osm_sweep_fail_ctrl_init, +* osm_sweep_fail_ctrl_destroy +*********/ + +/****f* OpenSM: Sweep Fail Controller/osm_sweep_fail_ctrl_destroy +* NAME +* osm_sweep_fail_ctrl_destroy +* +* DESCRIPTION +* The osm_sweep_fail_ctrl_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_sweep_fail_ctrl_destroy( + IN osm_sweep_fail_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* Sweep Fail Controller object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_sweep_fail_ctrl_construct or osm_sweep_fail_ctrl_init. +* +* SEE ALSO +* Sweep Fail Controller object, osm_sweep_fail_ctrl_construct, +* osm_sweep_fail_ctrl_init +*********/ + +/****f* OpenSM: Sweep Fail Controller/osm_sweep_fail_ctrl_init +* NAME +* osm_sweep_fail_ctrl_init +* +* DESCRIPTION +* The osm_sweep_fail_ctrl_init function initializes a +* Sweep Fail Controller object for use. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_sweep_fail_ctrl_init( + IN osm_sweep_fail_ctrl_t* const p_ctrl, + IN osm_log_t* const p_log, + IN osm_state_mgr_t* const p_state_mgr, + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_sweep_fail_ctrl_t object to initialize. +* +* p_rcv +* [in] Pointer to an osm_sweep_fail_t object. +* +* p_log +* [in] Pointer to the log object. +* +* p_state_mgr +* [in] Pointer to the state manager object. +* +* p_disp +* [in] Pointer to the OpenSM central Dispatcher. +* +* RETURN VALUES +* CL_SUCCESS if the Sweep Fail Controller object was initialized +* successfully. +* +* NOTES +* Allows calling other Sweep Fail Controller methods. +* +* SEE ALSO +* Sweep Fail Controller object, osm_sweep_fail_ctrl_construct, +* osm_sweep_fail_ctrl_destroy +*********/ + +END_C_DECLS + +#endif /* _OSM_SWEEP_FAIL_CTRL_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_switch.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_switch.h new file mode 100644 index 00000000..27e5f741 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_switch.h @@ -0,0 +1,1552 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_switch.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_switch_t. + * This object represents an IBA switch. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.6 $ + */ + +#ifndef _OSM_SWITCH_H_ +#define _OSM_SWITCH_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Switch +* NAME +* Switch +* +* DESCRIPTION +* The Switch object encapsulates the information needed by the +* OpenSM to manage switches. The OpenSM allocates one switch object +* per switch in the IBA subnet. +* +* The Switch object is not thread safe, thus callers must provide +* serialization. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: Switch/osm_switch_t +* NAME +* osm_switch_t +* +* DESCRIPTION +* Switch structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_switch +{ + cl_map_item_t map_item; + osm_node_t *p_node; + ib_switch_info_t switch_info; + osm_fwd_tbl_t fwd_tbl; + osm_lid_matrix_t lmx; + uint16_t max_lid_ho; + osm_port_profile_t *p_prof; + osm_mcast_tbl_t mcast_tbl; + uint32_t discovery_count; +} osm_switch_t; +/* +* FIELDS +* map_item +* Linkage structure for cl_qmap. MUST BE FIRST MEMBER! +* +* p_node +* Pointer to the Node object for this switch. +* +* switch_info +* IBA defined SwitchInfo structure for this switch. +* +* fwd_tbl +* This switch's forwarding table. +* +* lmx +* LID Matrix for this switch containing the hop count +* to every LID from every port. +* +* max_lid_ho +* Max LID that is accessible from this switch. +* +* p_pro +* Pointer to array of Port Profile objects for this switch. +* +* mcast_tbl +* Multicast forwarding table for this switch. +* +* discovery_count +* The number of times this switch has been discovered +* during the current fabric sweep. This number is reset +* to zero at the start of a sweep. +* +* SEE ALSO +* Switch object +*********/ + +/****f* OpenSM: Switch/osm_switch_construct +* NAME +* osm_switch_construct +* +* DESCRIPTION +* This function constructs a Switch object. +* +* SYNOPSIS +*/ +void +osm_switch_construct( + IN osm_switch_t* const p_sw ); +/* +* PARAMETERS +* p_sw +* [in] Pointer to a Switch object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_switch_init, and osm_switch_destroy. +* +* Calling osm_switch_construct is a prerequisite to calling any other +* method except osm_switch_init. +* +* SEE ALSO +* Switch object, osm_switch_init, osm_switch_destroy +*********/ + +/****f* OpenSM: Switch/osm_switch_destroy +* NAME +* osm_switch_destroy +* +* DESCRIPTION +* The osm_switch_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_switch_destroy( + IN osm_switch_t* const p_sw ); +/* +* PARAMETERS +* p_sw +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* None. +* +* NOTES +* Performs any necessary cleanup of the specified object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to osm_switch_construct +* or osm_switch_init. +* +* SEE ALSO +* Switch object, osm_switch_construct, osm_switch_init +*********/ + +/****f* OpenSM: Switch/osm_switch_destroy +* NAME +* osm_switch_destroy +* +* DESCRIPTION +* Destroys and deallocates the object. +* +* SYNOPSIS +*/ +void +osm_switch_delete( + IN OUT osm_switch_t** const pp_sw ); +/* +* PARAMETERS +* p_sw +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* None. +* +* NOTES +* +* SEE ALSO +* Switch object, osm_switch_construct, osm_switch_init +*********/ + +/****f* OpenSM: Switch/osm_switch_init +* NAME +* osm_switch_init +* +* DESCRIPTION +* The osm_switch_init function initializes a Switch object for use. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_switch_init( + IN osm_switch_t* const p_sw, + IN osm_node_t* const p_node, + IN const osm_madw_t* const p_madw ); +/* +* PARAMETERS +* p_sw +* [in] Pointer to an osm_switch_t object to initialize. +* +* p_node +* [in] Pointer to the node object of this switch +* +* p_madw +* [in] Pointer to the MAD Wrapper containing the switch's +* SwitchInfo attribute. +* +* RETURN VALUES +* IB_SUCCESS if the Switch object was initialized successfully. +* +* NOTES +* Allows calling other node methods. +* +* SEE ALSO +* Switch object, osm_switch_construct, osm_switch_destroy +*********/ + +/****f* OpenSM: Switch/osm_switch_new +* NAME +* osm_switch_new +* +* DESCRIPTION +* The osm_switch_init function initializes a Switch object for use. +* +* SYNOPSIS +*/ +osm_switch_t* +osm_switch_new( + IN osm_node_t* const p_node, + IN const osm_madw_t* const p_madw ); +/* +* PARAMETERS +* p_node +* [in] Pointer to the node object of this switch +* +* p_madw +* [in] Pointer to the MAD Wrapper containing the switch's +* SwitchInfo attribute. +* +* RETURN VALUES +* Pointer to the new initialized switch object. +* +* NOTES +* +* SEE ALSO +* Switch object, osm_switch_construct, osm_switch_destroy, +*********/ + +/****f* OpenSM: Switch/osm_switch_is_leaf_lid +* NAME +* osm_switch_is_leaf_lid +* +* DESCRIPTION +* Indicates if the specified LID is the switch's LID, or is a leaf +* of the switch. +* +* SYNOPSIS +*/ +static inline boolean_t +osm_switch_is_leaf_lid( + IN const osm_switch_t* const p_sw, + IN const uint16_t lid_ho ) +{ + return( osm_lid_matrix_get_least_hops( &p_sw->lmx, lid_ho ) <= 1 ); +} +/* +* PARAMETERS +* p_sw +* [in] Pointer to an osm_switch_t object. +* +* lid_ho +* [in] LID (host order) to compare. +* +* RETURN VALUES +* TRUE if the LID is the switch's LID or is a leaf of the switch, +* FALSE otherwise. +* +* NOTES +* +* SEE ALSO +* Switch object +*********/ + +/****f* OpenSM: Switch/osm_switch_get_hop_count +* NAME +* osm_switch_get_hop_count +* +* DESCRIPTION +* Returns the hop count at the specified LID/Port intersection. +* +* SYNOPSIS +*/ +static inline uint8_t +osm_switch_get_hop_count( + IN const osm_switch_t* const p_sw, + IN const uint16_t lid_ho, + IN const uint8_t port_num ) +{ + return( osm_lid_matrix_get( &p_sw->lmx, lid_ho, port_num ) ); +} +/* +* PARAMETERS +* p_sw +* [in] Pointer to a Switch object. +* +* lid_ho +* [in] LID value (host order) for which to return the hop count +* +* port_num +* [in] Port number in the switch +* +* RETURN VALUES +* Returns the hop count at the specified LID/Port intersection. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Switch/osm_switch_get_fwd_tbl_ptr +* NAME +* osm_switch_get_fwd_tbl_ptr +* +* DESCRIPTION +* Returns a pointer to the switch's forwarding table. +* +* SYNOPSIS +*/ +static inline osm_fwd_tbl_t* +osm_switch_get_fwd_tbl_ptr( + IN const osm_switch_t* const p_sw ) +{ + return( (osm_fwd_tbl_t*)&p_sw->fwd_tbl ); +} +/* +* PARAMETERS +* p_sw +* [in] Pointer to a Switch object. +* +* RETURN VALUES +* Returns a pointer to the switch's forwarding table. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Switch/osm_switch_set_hops +* NAME +* osm_switch_set_hops +* +* DESCRIPTION +* Sets the hop count at the specified LID/Port intersection. +* +* SYNOPSIS +*/ +static inline cl_status_t +osm_switch_set_hops( + IN osm_switch_t* const p_sw, + IN const uint16_t lid_ho, + IN const uint8_t port_num, + IN const uint8_t num_hops ) +{ + return( osm_lid_matrix_set( &p_sw->lmx, lid_ho, port_num, num_hops ) ); +} +/* +* PARAMETERS +* p_sw +* [in] Pointer to a Switch object. +* +* lid_ho +* [in] LID value (host order) for which to set the count. +* +* port_num +* [in] port number for which to set the count. +* +* num_hops +* [in] value to assign to this entry. +* +* RETURN VALUES +* Returns the hop count at the specified LID/Port intersection. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Switch/osm_switch_set_min_lid_size +* NAME +* osm_switch_set_min_lid_size +* +* DESCRIPTION +* Sets the size of the switch's routing table to at least accomodate the +* specified LID value (host ordered) +* +* SYNOPSIS +*/ +static inline cl_status_t +osm_switch_set_min_lid_size( + IN osm_switch_t* const p_sw, + IN const uint16_t lid_ho ) +{ + return( osm_lid_matrix_set_min_lid_size( &p_sw->lmx, lid_ho ) ); +} +/* +* PARAMETERS +* p_sw +* [in] Pointer to a Switch object. +* +* lid_ho +* [in] LID value (host order) for which to set the count. +* +* RETURN VALUES +* Sets the size of the switch's routing table to at least accomodate the +* specified LID value (host ordered) +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Switch/osm_switch_get_least_hops +* NAME +* osm_switch_get_least_hops +* +* DESCRIPTION +* Returns the number of hops in the short path to this lid from +* any port on the switch. +* +* SYNOPSIS +*/ +static inline uint8_t +osm_switch_get_least_hops( + IN const osm_switch_t* const p_sw, + IN const uint16_t lid_ho ) +{ + return( osm_lid_matrix_get_least_hops( &p_sw->lmx, lid_ho ) ); +} +/* +* PARAMETERS +* p_sw +* [in] Pointer to an osm_switch_t object. +* +* lid_ho +* [in] LID (host order) for which to retrieve the shortest hop count. +* +* RETURN VALUES +* Returns the number of hops in the short path to this lid from +* any port on the switch. +* +* NOTES +* +* SEE ALSO +* Switch object +*********/ + +/****f* OpenSM: Switch/osm_switch_get_port_by_lid +* NAME +* osm_switch_get_port_by_lid +* +* DESCRIPTION +* Returns the switch port number on which the specified LID is routed. +* +* SYNOPSIS +*/ +static inline uint8_t +osm_switch_get_port_by_lid( + IN const osm_switch_t* const p_sw, + IN const uint16_t lid_ho ) +{ + return( osm_fwd_tbl_get( &p_sw->fwd_tbl, lid_ho ) ); +} +/* +* PARAMETERS +* p_sw +* [in] Pointer to an osm_switch_t object. +* +* lid_ho +* [in] LID (host order) for which to retrieve the shortest hop count. +* +* RETURN VALUES +* Returns the switch port on which the specified LID is routed. +* +* NOTES +* +* SEE ALSO +* Switch object +*********/ + +/****f* OpenSM: Switch/osm_switch_get_physp_ptr +* NAME +* osm_switch_get_physp_ptr +* +* DESCRIPTION +* Gets the Physical Port Object at the specified port number. +* +* SYNOPSIS +*/ +osm_physp_t* +osm_switch_get_physp_ptr( + IN const osm_switch_t* const p_sw, + IN const uint32_t port_num ); +/* +* PARAMETERS +* p_sw +* [in] Pointer to an osm_switch_t object. +* +* port_num +* [in] Port number for which to retrieve the Physical Port Object. +* +* RETURN VALUES +* Returns a pointer to the Physical Port Object object at the specified +* port number. +* A return value of zero means the port number was out of range. +* +* +* NOTES +* +* SEE ALSO +* Switch object +*********/ + +/****f* OpenSM: Switch/osm_switch_get_route_by_lid +* NAME +* osm_switch_get_route_by_lid +* +* DESCRIPTION +* Gets the physical port object that routes the specified LID. +* +* SYNOPSIS +*/ +static inline osm_physp_t* +osm_switch_get_route_by_lid( + IN const osm_switch_t* const p_sw, + IN const ib_net16_t lid ) +{ + uint8_t port_num; + + CL_ASSERT( p_sw ); + CL_ASSERT( lid ); + + port_num = osm_fwd_tbl_get( &p_sw->fwd_tbl, cl_ntoh16( lid ) ); + /* + In order to avoid holes in the subnet (usually happens when + running UPDN algorithm), i.e. cases where port is + unreachable through a switch (we put an OSM_NO_PATH value at + the port entry, we do not assert on unreachable lid entries + at the fwd table but return NULL + */ + if (port_num != OSM_NO_PATH) + return( osm_node_get_physp_ptr( p_sw->p_node, port_num ) ); + else + return NULL; +} +/* +* PARAMETERS +* p_sw +* [in] Pointer to an osm_switch_t object. +* +* lid +* [in] LID for which to find a route. This must be a unicast +* LID value < 0xC000. +* +* RETURN VALUES +* Returns a pointer to the Physical Port Object object that +* routes the specified LID. A return value of zero means +* there is no route for the lid through this switch. +* The lid value must be a unicast LID. +* +* NOTES +* +* SEE ALSO +* Switch object +*********/ + +/****f* OpenSM: Switch/osm_switch_get_si_ptr +* NAME +* osm_switch_get_si_ptr +* +* DESCRIPTION +* Returns a pointer to the SwitchInfo for this switch. +* +* SYNOPSIS +*/ +static inline ib_switch_info_t* +osm_switch_get_si_ptr( + IN const osm_switch_t* const p_sw ) +{ + return( (ib_switch_info_t*)&p_sw->switch_info ); +} +/* +* PARAMETERS +* p_sw +* [in] Pointer to an osm_switch_t object. +* +* RETURN VALUES +* Returns a pointer to the SwitchInfo for this switch. +* +* NOTES +* +* SEE ALSO +* Switch object +*********/ + +/****f* OpenSM: Switch/osm_switch_sp0_is_lmc_capable +* NAME +* osm_switch_sp0_is_lmc_capable +* +* DESCRIPTION +* Returns whether switch port 0 (SP0) can support LMC +* +*/ +static inline unsigned +osm_switch_sp0_is_lmc_capable( + IN const osm_switch_t* const p_sw, + IN osm_subn_t *p_subn) +{ + return (p_subn->opt.lmc_esp0 && + ib_switch_info_is_enhanced_port0(&p_sw->switch_info)) ? 1 : 0; +} +/* +* PARAMETERS +* p_sw +* [in] Pointer to an osm_switch_t object. +* +* p_subn +* [in] Pointer to an osm_subn_t object. +* +* RETURN VALUES +* TRUE if SP0 is enhanced and globally enabled. FALSE otherwise. +* +* NOTES +* This is workaround function, it takes into account user defined +* p_subn->opt.lmc_esp0 parameter. +* +* SEE ALSO +*********/ + +/****f* OpenSM: Switch/osm_switch_get_max_block_id +* NAME +* osm_switch_get_max_block_id +* +* DESCRIPTION +* Returns the maximum block ID (host order) of this switch. +* +* SYNOPSIS +*/ +static inline uint32_t +osm_switch_get_max_block_id( + IN const osm_switch_t* const p_sw ) +{ + return( (uint32_t)(osm_fwd_tbl_get_size( &p_sw->fwd_tbl ) / + osm_fwd_tbl_get_lids_per_block( &p_sw->fwd_tbl ) ) ); +} +/* +* PARAMETERS +* p_sw +* [in] Pointer to an osm_switch_t object. +* +* RETURN VALUES +* Returns the maximum block ID (host order) of this switch. +* +* NOTES +* +* SEE ALSO +* Switch object +*********/ + +/****f* OpenSM: Switch/osm_switch_get_max_block_id_in_use +* NAME +* osm_switch_get_max_block_id_in_use +* +* DESCRIPTION +* Returns the maximum block ID (host order) of this switch that +* is used for unicast routing. +* +* SYNOPSIS +*/ +static inline uint16_t +osm_switch_get_max_block_id_in_use( + IN const osm_switch_t* const p_sw ) +{ + return( osm_fwd_tbl_get_max_block_id_in_use( &p_sw->fwd_tbl, + cl_ntoh16( p_sw->switch_info.lin_top ) ) ); +} +/* +* PARAMETERS +* p_sw +* [in] Pointer to an osm_switch_t object. +* +* RETURN VALUES +* Returns the maximum block ID (host order) of this switch. +* +* NOTES +* +* SEE ALSO +* Switch object +*********/ + +/****f* OpenSM: Switch/osm_switch_get_node_ptr +* NAME +* osm_switch_get_node_ptr +* +* DESCRIPTION +* Returns a pointer to the Node object for this switch. +* +* SYNOPSIS +*/ +static inline osm_node_t* +osm_switch_get_node_ptr( + IN const osm_switch_t* const p_sw ) +{ + return( p_sw->p_node ); +} +/* +* PARAMETERS +* p_sw +* [in] Pointer to an osm_switch_t object. +* +* RETURN VALUES +* Returns a pointer to the Node object for this switch. +* +* NOTES +* +* SEE ALSO +* Switch object +*********/ + +/****f* OpenSM: Switch/osm_switch_get_max_lid_ho +* NAME +* osm_switch_get_max_lid_ho +* +* DESCRIPTION +* Returns the maximum LID (host order) value contained +* in the switch routing tables. +* +* SYNOPSIS +*/ +static inline uint16_t +osm_switch_get_max_lid_ho( + IN const osm_switch_t* const p_sw ) +{ + if (p_sw->max_lid_ho != 0) + return p_sw->max_lid_ho; + return( osm_lid_matrix_get_max_lid_ho( &p_sw->lmx ) ); +} +/* +* PARAMETERS +* p_sw +* [in] Pointer to a switch object. +* +* RETURN VALUES +* Returns the maximum LID (host order) value contained +* in the switch routing tables. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Switch/osm_switch_get_num_ports +* NAME +* osm_switch_get_num_ports +* +* DESCRIPTION +* Returns the number of ports in this switch. +* +* SYNOPSIS +*/ +static inline uint8_t +osm_switch_get_num_ports( + IN const osm_switch_t* const p_sw ) +{ + return( osm_lid_matrix_get_num_ports( &p_sw->lmx ) ); +} +/* +* PARAMETERS +* p_sw +* [in] Pointer to an osm_switch_t object. +* +* RETURN VALUES +* Returns the number of ports in this switch. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Switch/osm_switch_get_fwd_tbl_block +* NAME +* osm_switch_get_fwd_tbl_block +* +* DESCRIPTION +* Retrieve a forwarding table block. +* +* SYNOPSIS +*/ +boolean_t +osm_switch_get_fwd_tbl_block( + IN const osm_switch_t* const p_sw, + IN const uint32_t block_id, + OUT uint8_t* const p_block ); +/* +* PARAMETERS +* p_sw +* [in] Pointer to an osm_switch_t object. +* +* block_ID +* [in] The block_id to retrieve. +* +* p_block +* [out] Pointer to the 64 byte array to store the +* forwarding table clock specified by block_id. +* +* RETURN VALUES +* Returns true if there are more blocks necessary to +* configure all the LIDs reachable from this switch. +* FALSE otherwise. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Switch/osm_switch_supports_mcast +* NAME +* osm_switch_supports_mcast +* +* DESCRIPTION +* Indicates if a switch supports multicast. +* +* SYNOPSIS +*/ +static inline boolean_t +osm_switch_supports_mcast( + IN const osm_switch_t* const p_sw ) +{ + return( p_sw->switch_info.mcast_cap != 0 ); +} +/* +* PARAMETERS +* p_sw +* [in] Pointer to an osm_switch_t object. +* +* RETURN VALUES +* Returns TRUE if the switch supports multicast. +* FALSE otherwise. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Switch/osm_switch_set_switch_info +* NAME +* osm_switch_set_switch_info +* +* DESCRIPTION +* Updates the switch info attribute of this switch. +* +* SYNOPSIS +*/ +static inline void +osm_switch_set_switch_info( + IN osm_switch_t* const p_sw, + IN const ib_switch_info_t* const p_si ) +{ + CL_ASSERT( p_sw ); + CL_ASSERT( p_si ); + p_sw->switch_info = *p_si; +} +/* +* PARAMETERS +* p_sw +* [in] Pointer to a Switch object. +* +* p_si +* [in] Pointer to the SwitchInfo attribute for this switch. +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Switch/osm_switch_count_path +* NAME +* osm_switch_count_path +* +* DESCRIPTION +* Counts this path in port profile. +* +* SYNOPSIS +*/ +static inline void +osm_switch_count_path( + IN osm_switch_t* const p_sw, + IN const uint8_t port + ) +{ + osm_port_prof_path_count_inc( &p_sw->p_prof[port] ); +} +/* +* PARAMETERS +* p_sw +* [in] Pointer to the switch object. +* +* port +* [in] Port to count path. +* +* RETURN VALUE +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Switch/osm_switch_set_ft_block +* NAME +* osm_switch_set_ft_block +* +* DESCRIPTION +* Copies in the specified block into the switch's Forwarding Table object. +* +* SYNOPSIS +*/ +static inline ib_api_status_t +osm_switch_set_ft_block( + IN osm_switch_t* const p_sw, + IN const uint8_t* const p_block, + IN const uint32_t block_num ) +{ + CL_ASSERT( p_sw ); + return( osm_fwd_tbl_set_block( &p_sw->fwd_tbl, p_block, block_num ) ); +} +/* +* PARAMETERS +* p_sw +* [in] Pointer to the switch object. +* +* p_block +* [in] Pointer to the forwarding table block. +* +* block_num +* [in] Block number for this block +* +* RETURN VALUE +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Switch/osm_switch_set_mft_block +* NAME +* osm_switch_set_mft_block +* +* DESCRIPTION +* Sets a block of multicast port masks into the multicast table. +* +* SYNOPSIS +*/ +static inline ib_api_status_t +osm_switch_set_mft_block( + IN osm_switch_t* const p_sw, + IN const ib_net16_t* const p_block, + IN const uint16_t block_num, + IN const uint8_t position ) +{ + CL_ASSERT( p_sw ); + return( osm_mcast_tbl_set_block( &p_sw->mcast_tbl, p_block, + block_num, position ) ); +} +/* +* PARAMETERS +* p_sw +* [in] Pointer to the switch object. +* +* p_block +* [in] Pointer to the block of port masks to set. +* +* block_num +* [in] Block number (0-511) to set. +* +* position +* [in] Port mask position (0-15) to set. +* +* RETURN VALUE +* IB_SUCCESS on success. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Switch/osm_switch_get_mft_block +* NAME +* osm_switch_get_mft_block +* +* DESCRIPTION +* Retrieve a block of multicast port masks from the multicast table. +* +* SYNOPSIS +*/ +static inline boolean_t +osm_switch_get_mft_block( + IN osm_switch_t* const p_sw, + IN const uint16_t block_num, + IN const uint8_t position, + OUT ib_net16_t* const p_block ) +{ + CL_ASSERT( p_sw ); + return( osm_mcast_tbl_get_block( &p_sw->mcast_tbl, + block_num, position, p_block ) ); +} +/* +* PARAMETERS +* p_sw +* [in] Pointer to the switch object. +* +* block_num +* [in] Block number (0-511) to set. +* +* position +* [in] Port mask position (0-15) to set. +* +* p_block +* [out] Pointer to the block of port masks stored. +* +* RETURN VALUES +* Returns true if there are more blocks necessary to +* configure all the MLIDs reachable from this switch. +* FALSE otherwise. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Switch/osm_switch_get_mft_max_block +* NAME +* osm_switch_get_mft_max_block +* +* DESCRIPTION +* Get the max_block from the associated multicast table. +* +* SYNOPSIS +*/ +static inline uint16_t +osm_switch_get_mft_max_block( + IN osm_switch_t* const p_sw ) +{ + CL_ASSERT( p_sw ); + return( osm_mcast_tbl_get_max_block( &p_sw->mcast_tbl ) ); +} +/* +* PARAMETERS +* p_sw +* [in] Pointer to the switch object. +* +* RETURN VALUE +*/ + +/****f* OpenSM: Switch/osm_switch_get_mft_max_block_in_use +* NAME +* osm_switch_get_mft_max_block_in_use +* +* DESCRIPTION +* Get the max_block_in_use from the associated multicast table. +* +* SYNOPSIS +*/ +static inline int16_t +osm_switch_get_mft_max_block_in_use( + IN osm_switch_t* const p_sw ) +{ + CL_ASSERT( p_sw ); + return( osm_mcast_tbl_get_max_block_in_use( &p_sw->mcast_tbl ) ); +} +/* +* PARAMETERS +* p_sw +* [in] Pointer to the switch object. +* +* RETURN VALUES +* Returns the maximum block ID in use in this switch's mcast table. +* A value of -1 indicates no blocks are in use. +* +* NOTES +* +* SEE ALSO +*/ + +/****f* OpenSM: Switch/osm_switch_get_mft_max_position +* NAME +* osm_switch_get_mft_max_position +* +* DESCRIPTION +* Get the max_position from the associated multicast table. +* +* SYNOPSIS +*/ +static inline uint8_t +osm_switch_get_mft_max_position( + IN osm_switch_t* const p_sw ) +{ + CL_ASSERT( p_sw ); + return( osm_mcast_tbl_get_max_position( &p_sw->mcast_tbl ) ); +} +/* +* PARAMETERS +* p_sw +* [in] Pointer to the switch object. +* +* RETURN VALUE +*/ + +/****f* OpenSM: Switch/osm_switch_recommend_path +* NAME +* osm_switch_recommend_path +* +* DESCRIPTION +* Returns the recommended port on which to route this LID. +* In cases where LMC > 0, the remote side system and node +* used for the routing are tracked in the provided arrays +* (and counts) such that other lid for the same port will +* try and avoid going through the same remote system/node. +* +* SYNOPSIS +*/ +uint8_t +osm_switch_recommend_path( + IN const osm_switch_t* const p_sw, + IN const uint16_t lid_ho, + IN const boolean_t ignore_existing, + IN OUT uint64_t *remote_sys_guids, + IN OUT uint16_t *p_num_used_sys, + IN OUT uint64_t *remote_node_guids, + IN OUT uint16_t *p_num_used_nodes + ); +/* +* PARAMETERS +* p_sw +* [in] Pointer to the switch object. +* +* lid_ho +* [in] LID value (host order) for which to get a path advisory. +* +* ignore_existing +* [in] Set to cause the switch to choose the optimal route +* regardless of existing paths. +* If false, the switch will choose an existing route if one +* exists, otherwise will choose the optimal route. +* +* remote_sys_guids +* [in out] The array of remote system guids already used to +* route the other lids of the same target port (if LMC > 0). +* +* p_num_used_sys +* [in out] The number of remote systems used for routing to +* the port. +* +* remote_node_guids +* [in out] The array of remote node guids already used to route +* the other lids of the same target port (if LMC > 0). +* +* p_num_used_nodes +* [in out] The number of remote nodes used for routing to +* the port. +* +* RETURN VALUE +* Returns the recommended port on which to route this LID. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Switch/osm_switch_recommend_mcast_path +* NAME +* osm_switch_recommend_mcast_path +* +* DESCRIPTION +* Returns the recommended port on which to route this LID. +* +* SYNOPSIS +*/ +uint8_t +osm_switch_recommend_mcast_path( + IN osm_switch_t* const p_sw, + IN const uint16_t lid_ho, + IN const uint16_t mlid_ho, + IN const boolean_t ignore_existing ); +/* +* PARAMETERS +* p_sw +* [in] Pointer to the switch object. +* +* lid_ho +* [in] LID value (host order) for of the node for with to get +* the multicast path. +* +* mlid_ho +* [in] MLID for the multicast group in question. +* +* ignore_existing +* [in] Set to cause the switch to choose the optimal route +* regardless of existing paths. +* If false, the switch will choose an existing route if one exists, +* otherwise will choose the optimal route. +* +* RETURN VALUE +* Returns the recommended port on which to route this LID. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Switch/osm_switch_get_fwd_tbl_size +* NAME +* osm_switch_get_fwd_tbl_size +* +* DESCRIPTION +* Returns the number of entries available in the forwarding table. +* +* SYNOPSIS +*/ +static inline uint16_t +osm_switch_get_fwd_tbl_size( + IN const osm_switch_t* const p_sw ) +{ + return( osm_fwd_tbl_get_size( &p_sw->fwd_tbl ) ); +} +/* +* PARAMETERS +* p_sw +* [in] Pointer to the switch. +* +* RETURN VALUE +* Returns the number of entries available in the forwarding table. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Switch/osm_switch_get_mcast_fwd_tbl_size +* NAME +* osm_switch_get_mcast_fwd_tbl_size +* +* DESCRIPTION +* Returns the number of entries available in the multicast forwarding table. +* +* SYNOPSIS +*/ +static inline uint16_t +osm_switch_get_mcast_fwd_tbl_size( + IN const osm_switch_t* const p_sw ) +{ + return( cl_ntoh16( p_sw->switch_info.mcast_cap ) ); +} +/* +* PARAMETERS +* p_sw +* [in] Pointer to the switch. +* +* RETURN VALUE +* Returns the number of entries available in the multicast forwarding table. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Switch/osm_switch_path_count_get +* NAME +* osm_switch_path_count_get +* +* DESCRIPTION +* Returns the count of the number of paths going through this port. +* +* SYNOPSIS +*/ +static inline uint32_t +osm_switch_path_count_get( + IN const osm_switch_t* const p_sw, + IN const uint8_t port_num ) +{ + return( osm_port_prof_path_count_get( &p_sw->p_prof[port_num] ) ); +} +/* +* PARAMETERS +* p_sw +* [in] Pointer to the Switch object. +* +* port_num +* [in] Port number for which to get path count. +* +* RETURN VALUE +* Returns the count of the number of paths going through this port. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Switch/osm_switch_prepare_path_rebuild +* NAME +* osm_switch_prepare_path_rebuild +* +* DESCRIPTION +* Prepares a switch to rebuild pathing information. +* +* SYNOPSIS +*/ +void +osm_switch_prepare_path_rebuild( + IN osm_switch_t* const p_sw ); +/* +* PARAMETERS +* p_sw +* [in] Pointer to the Switch object. +* +* RETURN VALUE +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Switch/osm_switch_get_mcast_tbl_ptr +* NAME +* osm_switch_get_mcast_tbl_ptr +* +* DESCRIPTION +* Returns a pointer to the switch's multicast table. +* +* SYNOPSIS +*/ +static inline osm_mcast_tbl_t* +osm_switch_get_mcast_tbl_ptr( + IN const osm_switch_t* const p_sw ) +{ + return( (osm_mcast_tbl_t*)&p_sw->mcast_tbl ); +} +/* +* PARAMETERS +* p_sw +* [in] Pointer to the switch. +* +* RETURN VALUE +* Returns a pointer to the switch's multicast table. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Switch/osm_switch_is_in_mcast_tree +* NAME +* osm_switch_is_in_mcast_tree +* +* DESCRIPTION +* Returns true if this switch already belongs in the tree for the specified +* multicast group. +* +* SYNOPSIS +*/ +static inline boolean_t +osm_switch_is_in_mcast_tree( + IN const osm_switch_t* const p_sw, + IN const uint16_t mlid_ho ) +{ + const osm_mcast_tbl_t* p_tbl; + + p_tbl = &p_sw->mcast_tbl; + if( p_tbl ) + return( osm_mcast_tbl_is_any_port( &p_sw->mcast_tbl, mlid_ho ) ); + else + return( FALSE ); +} +/* +* PARAMETERS +* p_sw +* [in] Pointer to the switch. +* +* mlid_ho +* [in] MLID (host order) of the multicast tree to check. +* +* RETURN VALUE +* Returns true if this switch already belongs in the tree for the specified +* multicast group. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM: Node/osm_switch_discovery_count_get +* NAME +* osm_switch_discovery_count_get +* +* DESCRIPTION +* Returns a pointer to the physical port object at the +* specified local port number. +* +* SYNOPSIS +*/ +static inline uint32_t +osm_switch_discovery_count_get( + IN const osm_switch_t* const p_switch ) +{ + return( p_switch->discovery_count ); +} +/* +* PARAMETERS +* p_switch +* [in] Pointer to an osm_switch_t object. +* +* RETURN VALUES +* Returns the discovery count for this node. +* +* NOTES +* +* SEE ALSO +* Node object +*********/ + +/****f* OpenSM: Node/osm_switch_discovery_count_reset +* NAME +* osm_switch_discovery_count_reset +* +* DESCRIPTION +* Resets the discovery count for this node to zero. +* This operation should be performed at the start of a sweep. +* +* SYNOPSIS +*/ +static inline void +osm_switch_discovery_count_reset( + IN osm_switch_t* const p_switch ) +{ + p_switch->discovery_count = 0; +} +/* +* PARAMETERS +* p_switch +* [in] Pointer to an osm_switch_t object. +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +* Node object +*********/ + +/****f* OpenSM: Node/osm_switch_discovery_count_inc +* NAME +* osm_switch_discovery_count_inc +* +* DESCRIPTION +* Increments the discovery count for this node. +* +* SYNOPSIS +*/ +static inline void +osm_switch_discovery_count_inc( + IN osm_switch_t* const p_switch ) +{ + p_switch->discovery_count++; +} +/* +* PARAMETERS +* p_switch +* [in] Pointer to an osm_switch_t object. +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +* Node object +*********/ + +END_C_DECLS + +#endif /* _OSM_SWITCH_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_trap_rcv.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_trap_rcv.h new file mode 100644 index 00000000..68938b82 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_trap_rcv.h @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_trap_rcv.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_trap_rcv_t. + * This object represents the Trap Receiver object. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.3 $ + */ + +#ifndef _OSM_TRAP_RCV_H_ +#define _OSM_TRAP_RCV_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/Trap Receiver +* NAME +* Trap Receiver +* +* DESCRIPTION +* The Trap Receiver object encapsulates the information +* needed to receive the Trap attribute from a node. +* +* The Trap Receiver object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: Trap Receiver/osm_trap_rcv_t +* NAME +* osm_trap_rcv_t +* +* DESCRIPTION +* Trap Receiver structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_trap_rcv +{ + osm_subn_t *p_subn; + osm_stats_t *p_stats; + osm_log_t *p_log; + osm_resp_t *p_resp; + osm_state_mgr_t *p_state_mgr; + cl_plock_t *p_lock; + cl_event_wheel_t trap_aging_tracker; +} osm_trap_rcv_t; +/* +* FIELDS +* p_subn +* Pointer to the Subnet object for this subnet. +* +* p_stats +* Pointer to the OpenSM statistics block. +* +* p_log +* Pointer to the log object. +* +* p_resp +* Pointer to the generic MAD responder object. +* +* p_state_mgr +* Pointer to the State Manager object. +* +* p_lock +* Pointer to the serializing lock. +* +* trap_aging_tracker +* An event wheel tracking erceived traps and their aging. +* Basically we can start a timer every time we receive a specific +* trap and check to seee if not expired next time it is received. +* +* SEE ALSO +* Trap Receiver object +*********/ + +/****f* OpenSM: Trap Receiver/osm_trap_rcv_construct +* NAME +* osm_trap_rcv_construct +* +* DESCRIPTION +* This function constructs a Trap Receiver object. +* +* SYNOPSIS +*/ +void osm_trap_rcv_construct( + IN osm_trap_rcv_t* const p_rcv ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to a Trap Receiver object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_trap_rcv_init, osm_trap_rcv_destroy +* +* Calling osm_trap_rcv_construct is a prerequisite to calling any other +* method except osm_trap_rcv_init. +* +* SEE ALSO +* Trap Receiver object, osm_trap_rcv_init, +* osm_trap_rcv_destroy +*********/ + +/****f* OpenSM: Trap Receiver/osm_trap_rcv_destroy +* NAME +* osm_trap_rcv_destroy +* +* DESCRIPTION +* The osm_trap_rcv_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_trap_rcv_destroy( + IN osm_trap_rcv_t* const p_rcv ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* Trap Receiver object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_trap_rcv_construct or osm_trap_rcv_init. +* +* SEE ALSO +* Trap Receiver object, osm_trap_rcv_construct, +* osm_trap_rcv_init +*********/ + +/****f* OpenSM: Trap Receiver/osm_trap_rcv_init +* NAME +* osm_trap_rcv_init +* +* DESCRIPTION +* The osm_trap_rcv_init function initializes a +* Trap Receiver object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_trap_rcv_init( + IN osm_trap_rcv_t* const p_rcv, + IN osm_subn_t* const p_subn, + IN osm_stats_t* const p_stats, + IN osm_resp_t* const p_resp, + IN osm_log_t* const p_log, + IN osm_state_mgr_t* const p_state_mgr, + IN cl_plock_t* const p_lock ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to an osm_trap_rcv_t object to initialize. +* +* p_subn +* [in] Pointer to the Subnet object for this subnet. +* +* p_stats +* [in] Pointer to the OpenSM statistics block. +* +* p_resp +* [in] Pointer to the generic MAD Responder object. +* +* p_log +* [in] Pointer to the log object. +* +* p_state_mgr +* [in] Pointer to the State Manager object. +* +* p_lock +* [in] Pointer to the OpenSM serializing lock. +* +* RETURN VALUES +* IB_SUCCESS if the Trap Receiver object was initialized +* successfully. +* +* NOTES +* Allows calling other Trap Receiver methods. +* +* SEE ALSO +* Trap Receiver object, osm_trap_rcv_construct, +* osm_trap_rcv_destroy +*********/ + +/****f* OpenSM: Trap Receiver/osm_trap_rcv_process +* NAME +* osm_trap_rcv_process +* +* DESCRIPTION +* Process the Trap attribute. +* +* SYNOPSIS +*/ +void osm_trap_rcv_process( + IN osm_trap_rcv_t* const p_rcv, + IN osm_madw_t* const p_madw ); +/* +* PARAMETERS +* p_rcv +* [in] Pointer to an osm_trap_rcv_t object. +* +* p_madw +* [in] Pointer to the MAD Wrapper containing the MAD +* that contains the node's Trap attribute. +* +* RETURN VALUES +* IB_SUCCESS if the Trap processing was successful. +* +* NOTES +* This function processes a Trap attribute. +* +* SEE ALSO +* Trap Receiver, Trap Response Controller +*********/ + +/****f* OpenSM: Trap Receiver/osm_trap_rcv_aging_tracker_callback +* NAME +* osm_trap_rcv_aging_tracker_callback +* +* DESCRIPTION +* Callback function called by the aging tracker mechanism. +* +* SYNOPSIS +*/ +uint64_t +osm_trap_rcv_aging_tracker_callback( + IN uint64_t key, + IN uint32_t num_regs, + IN void* context ); + +/* +* PARAMETERS +* key +* [in] The key by which the event was inserted. +* +* num_regs +* [in] The number of times the same event (key) was registered. +* +* context +* [in] Pointer to the context given in the registering of the event. +* +* RETURN VALUES +* None. +* +* NOTES +* This function is called by the cl_event_wheel when the aging tracker +* event has ended. +* +* SEE ALSO +* Trap Receiver, Trap Response Controller +*********/ + +END_C_DECLS + +#endif /* _OSM_TRAP_RCV_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_trap_rcv_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_trap_rcv_ctrl.h new file mode 100644 index 00000000..e30da0df --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_trap_rcv_ctrl.h @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_trap_rcv_ctrl.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_trap_rcv_ctrl_t. + * This object represents a controller that receives the IBA Trap + * attribute from a node. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.2 $ + */ + +#ifndef _OSM_TRAP_RCV_CTRL_H_ +#define _OSM_TRAP_RCV_CTRL_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/***** OpenSM/Trap Receive Controller +* NAME +* Trap Receive Controller +* +* DESCRIPTION +* The Trap Receive Controller object encapsulates the information +* needed to receive the Trap attribute from a node. +* +* The Trap Receive Controller object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Yael Kalka, Mellanox +* +*********/ + +/****s* OpenSM: Trap Receive Controller/osm_trap_rcv_ctrl_t +* NAME +* osm_trap_rcv_ctrl_t +* +* DESCRIPTION +* Trap Receive Controller structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_trap_rcv_ctrl +{ + osm_trap_rcv_t *p_rcv; + osm_log_t *p_log; + cl_dispatcher_t *p_disp; + cl_disp_reg_handle_t h_disp; + +} osm_trap_rcv_ctrl_t; +/* +* FIELDS +* p_rcv +* Pointer to the Trap Receiver object. +* +* p_log +* Pointer to the log object. +* +* p_disp +* Pointer to the Dispatcher. +* +* h_disp +* Handle returned from dispatcher registration. +* +* SEE ALSO +* Trap Receive Controller object +*********/ + +/****f* OpenSM: Trap Receive Controller/osm_trap_rcv_ctrl_construct +* NAME +* osm_trap_rcv_ctrl_construct +* +* DESCRIPTION +* This function constructs a Trap Receive Controller object. +* +* SYNOPSIS +*/ +void +osm_trap_rcv_ctrl_construct( + IN osm_trap_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a Trap Receive Controller object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_trap_rcv_ctrl_init, osm_trap_rcv_ctrl_destroy +* +* Calling osm_trap_rcv_ctrl_construct is a prerequisite to calling any other +* method except osm_trap_rcv_ctrl_init. +* +* SEE ALSO +* Trap Receive Controller object, osm_trap_rcv_ctrl_init, +* osm_trap_rcv_ctrl_destroy +*********/ + +/****f* OpenSM: Trap Receive Controller/osm_trap_rcv_ctrl_destroy +* NAME +* osm_trap_rcv_ctrl_destroy +* +* DESCRIPTION +* The osm_trap_rcv_ctrl_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_trap_rcv_ctrl_destroy( + IN osm_trap_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* Trap Receive Controller object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_trap_rcv_ctrl_construct or osm_trap_rcv_ctrl_init. +* +* SEE ALSO +* Trap Receive Controller object, osm_trap_rcv_ctrl_construct, +* osm_trap_rcv_ctrl_init +*********/ + +/****f* OpenSM: Trap Receive Controller/osm_trap_rcv_ctrl_init +* NAME +* osm_trap_rcv_ctrl_init +* +* DESCRIPTION +* The osm_trap_rcv_ctrl_init function initializes a +* Trap Receive Controller object for use. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_trap_rcv_ctrl_init( + IN osm_trap_rcv_ctrl_t* const p_ctrl, + IN osm_trap_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_trap_rcv_ctrl_t object to initialize. +* +* p_rcv +* [in] Pointer to an osm_trap_rcv_t object. +* +* p_log +* [in] Pointer to the log object. +* +* p_disp +* [in] Pointer to the OpenSM central Dispatcher. +* +* RETURN VALUES +* IB_SUCCESS if the Trap Receive Controller object was initialized +* successfully. +* +* NOTES +* Allows calling other Trap Receive Controller methods. +* +* SEE ALSO +* Trap Receive Controller object, osm_trap_rcv_ctrl_construct, +* osm_trap_rcv_ctrl_destroy +*********/ + +END_C_DECLS + +#endif /* OSM_TRAP_RCV_CTRL_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_ts_useraccess.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_ts_useraccess.h new file mode 100644 index 00000000..57cfceb4 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_ts_useraccess.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_ts_useraccess.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +#include "ts_ib_useraccess.h" + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +typedef struct ib_user_mad_filter osm_ts_user_mad_filter; +typedef struct ib_set_port_info_ioctl osm_ts_set_port_info_ioctl; +typedef struct ib_get_port_info_ioctl osm_ts_get_port_info_ioctl; +typedef struct ib_gid_entry_ioctl osm_ts_gid_entry_ioctl; + +END_C_DECLS + + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_ucast_mgr.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_ucast_mgr.h new file mode 100644 index 00000000..9ff81aa4 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_ucast_mgr.h @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_ucast_mgr.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_ucast_mgr_t. + * This object represents the Unicast Manager object. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_UCAST_MGR_H_ +#define _OSM_UCAST_MGR_H_ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +#define OSM_UCAST_MGR_LIST_SIZE_MIN 256 + +/****h* OpenSM/Unicast Manager +* NAME +* Unicast Manager +* +* DESCRIPTION +* The Unicast Manager object encapsulates the information +* needed to control unicast LID forwarding on the subnet. +* +* The Unicast Manager object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****s* OpenSM: Unicast Manager/osm_ucast_mgr_t +* NAME +* osm_ucast_mgr_t +* +* DESCRIPTION +* Unicast Manager structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_ucast_mgr +{ + osm_subn_t *p_subn; + osm_req_t *p_req; + osm_log_t *p_log; + cl_plock_t *p_lock; + boolean_t any_change; + uint8_t *lft_buf; +} osm_ucast_mgr_t; +/* +* FIELDS +* p_subn +* Pointer to the Subnet object for this subnet. +* +* p_req +* Pointer to the Requester object sending SMPs. +* +* p_log +* Pointer to the log object. +* +* p_lock +* Pointer to the serializing lock. +* +* any_change +* Initialized to FALSE at the beginning of the algorithm, +* set to TRUE by osm_ucast_mgr_set_fwd_table() if any mad +* was sent. +* +* lft_buf +* LFT buffer - used during LFT calculation/setup. +* +* SEE ALSO +* Unicast Manager object +*********/ + +/****f* OpenSM: Unicast Manager/osm_ucast_mgr_construct +* NAME +* osm_ucast_mgr_construct +* +* DESCRIPTION +* This function constructs a Unicast Manager object. +* +* SYNOPSIS +*/ +void +osm_ucast_mgr_construct( + IN osm_ucast_mgr_t* const p_mgr ); +/* +* PARAMETERS +* p_mgr +* [in] Pointer to a Unicast Manager object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows osm_ucast_mgr_destroy +* +* Calling osm_ucast_mgr_construct is a prerequisite to calling any other +* method except osm_ucast_mgr_init. +* +* SEE ALSO +* Unicast Manager object, osm_ucast_mgr_init, +* osm_ucast_mgr_destroy +*********/ + +/****f* OpenSM: Unicast Manager/osm_ucast_mgr_destroy +* NAME +* osm_ucast_mgr_destroy +* +* DESCRIPTION +* The osm_ucast_mgr_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_ucast_mgr_destroy( + IN osm_ucast_mgr_t* const p_mgr ); +/* +* PARAMETERS +* p_mgr +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* Unicast Manager object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_ucast_mgr_construct or osm_ucast_mgr_init. +* +* SEE ALSO +* Unicast Manager object, osm_ucast_mgr_construct, +* osm_ucast_mgr_init +*********/ + +/****f* OpenSM: Unicast Manager/osm_ucast_mgr_init +* NAME +* osm_ucast_mgr_init +* +* DESCRIPTION +* The osm_ucast_mgr_init function initializes a +* Unicast Manager object for use. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_ucast_mgr_init( + IN osm_ucast_mgr_t* const p_mgr, + IN osm_req_t* const p_req, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ); +/* +* PARAMETERS +* p_mgr +* [in] Pointer to an osm_ucast_mgr_t object to initialize. +* +* p_req +* [in] Pointer to the attribute Requester object. +* +* p_subn +* [in] Pointer to the Subnet object for this subnet. +* +* p_log +* [in] Pointer to the log object. +* +* p_lock +* [in] Pointer to the OpenSM serializing lock. +* +* RETURN VALUES +* IB_SUCCESS if the Unicast Manager object was initialized +* successfully. +* +* NOTES +* Allows calling other Unicast Manager methods. +* +* SEE ALSO +* Unicast Manager object, osm_ucast_mgr_construct, +* osm_ucast_mgr_destroy +*********/ + +/****f* OpenSM: Unicast Manager/osm_ucast_mgr_set_fwd_table +* NAME +* osm_ucast_mgr_set_fwd_table +* +* DESCRIPTION +* Setup forwarding table for the switch (from prepared lft_buf). +* +* SYNOPSIS +*/ +void +osm_ucast_mgr_set_fwd_table( + IN osm_ucast_mgr_t* const p_mgr, + IN osm_switch_t* const p_sw ); +/* +* PARAMETERS +* p_mgr +* [in] Pointer to an osm_ucast_mgr_t object. +* +* p_mgr +* [in] Pointer to an osm_switch_t object. +* +* SEE ALSO +* Unicast Manager +*********/ + +/****f* OpenSM: Unicast Manager/osm_ucast_mgr_build_lid_matrices +* NAME +* osm_ucast_mgr_build_lid_matrices +* +* DESCRIPTION +* Build switches's lid matrices. +* +* SYNOPSIS +*/ +void +osm_ucast_mgr_build_lid_matrices( + IN osm_ucast_mgr_t* const p_mgr ); +/* +* PARAMETERS +* p_mgr +* [in] Pointer to an osm_ucast_mgr_t object. +* +* NOTES +* This function processes the subnet, configuring switches' +* min hops tables (aka lid matrices). +* +* SEE ALSO +* Unicast Manager +*********/ + +/****f* OpenSM: Unicast Manager/osm_ucast_mgr_process +* NAME +* osm_ucast_mgr_process +* +* DESCRIPTION +* Process and configure the subnet's unicast forwarding tables. +* +* SYNOPSIS +*/ +osm_signal_t +osm_ucast_mgr_process( + IN osm_ucast_mgr_t* const p_mgr ); +/* +* PARAMETERS +* p_mgr +* [in] Pointer to an osm_ucast_mgr_t object. +* +* RETURN VALUES +* Returns the appropriate signal to the caller: +* OSM_SIGNAL_DONE - operation is complete +* OSM_SIGNAL_DONE_PENDING - local operations are complete, but +* transactions are still pending on the wire. +* +* NOTES +* This function processes the subnet, configuring switch +* unicast forwarding tables. +* +* SEE ALSO +* Unicast Manager, Node Info Response Controller +*********/ +END_C_DECLS + +#endif /* _OSM_UCAST_MGR_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_umadt.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_umadt.h new file mode 100644 index 00000000..c0bfed84 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_umadt.h @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_umadt.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_mad_wrapper_t. + * This object represents the context wrapper for OpenSM MAD processing. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_UMADT_h_ +#define _OSM_UMADT_h_ + +#include "iba/ib_types.h" +#include +#include +#include "umadt.h" +#include "ibt.h" + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +typedef struct _umadt_obj_t{ + void* umadt_handle; + UMADT_INTERFACE uMadtInterface; + IBT_INTERFACE IbtInterface; + boolean init_done; + cl_spinlock_t register_lock; + cl_qlist_t register_list; + osm_log_t *p_log; + uint32_t timeout; + +}umadt_obj_t; +/*********/ + +/****s* OpenSM: Umadt MAD Wrapper/osm_bind_info +* NAME +* osm_bind_info +* +* DESCRIPTION +* Context needed for processing individual MADs +* +* SYNOPSIS +*/ + +typedef struct _mad_bind_info_t{ + cl_list_item_t list_item; + umadt_obj_t *p_umadt_obj; + osm_mad_pool_t *p_mad_pool; + osm_vend_mad_recv_callback_t mad_recv_callback; + void *client_context; + cl_thread_t recv_processor_thread; + cl_spinlock_t trans_ctxt_lock; + cl_qlist_t trans_ctxt_list; + cl_timer_t timeout_timer; + cl_spinlock_t timeout_list_lock; + cl_qlist_t timeout_list; + RegisterClassStruct umadt_reg_class; + MADT_HANDLE umadt_handle; /* Umadt type */ + +}mad_bind_info_t; + +typedef struct _trans_context_t { + cl_list_item_t list_item; + uint64_t trans_id; + uint64_t sent_time; /* micro secs */ + void* context; +} trans_context_t; + +/* +* FIELDS +* list_item +* List linkage for pools and lists. MUST BE FIRST MEMBER! +* +* p_mad_pool +* Pointer to the MAD pool to be used by mads with this bind handle. +* +* mad_recv_callback +* Callback function called by the mad receive processor. +* +* client_context +* context to be passed to the receive callback. +* +* recv_processor_thread +* Thread structure for the receive processor thread. +* +* umadt_reg_class +* Umadt register class struct used to register with Umadt. +* +* umadt_handle +* Umadt returns this handle from a registration call. The transport layer +* uses this handle to talk to Umadt. +* +* SEE ALSO +*********/ + +END_C_DECLS + +#endif /*_OSM_UMADT_h_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_version.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_version.h new file mode 100644 index 00000000..4b1d03cf --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_version.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_version.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +#ifndef _OSM_VERSION_H_ +#define _OSM_VERSION_H_ + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****s* OpenSM: Base/OSM_VERSION +* NAME +* OSM_VERSION +* +* DESCRIPTION +* The version string for OpenSM +* +* SYNOPSIS +*/ +#define OSM_VERSION "OpenSM Rev:openib-3.0.0" +/********/ + +END_C_DECLS + +#endif /* _OSM_VERSION_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_vl15intf.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_vl15intf.h new file mode 100644 index 00000000..0a8b1774 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_vl15intf.h @@ -0,0 +1,417 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_vl15intf.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_vl15_t. + * This object represents an IBA subnet. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + +#ifndef _OSM_VL15INTF_H_ +#define _OSM_VL15INTF_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/VL15 +* NAME +* VL15 +* +* DESCRIPTION +* The VL15 object encapsulates the information needed by the +* OpenSM to instantiate the VL15 interface. The OpenSM allocates +* one VL15 object per subnet. +* +* The VL15 object transmits MADs to the wire at a throttled rate, +* so as to not overload the VL15 buffering of subnet components. +* OpenSM modules may post VL15 MADs to the VL15 interface as fast +* as possible. +* +* The VL15 object is thread safe. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* AUTHOR +* Steve King, Intel +* +*********/ + +/****d* OpenSM: SM/osm_vl15_state_t +* NAME +* osm_vl15_state_t +* +* DESCRIPTION +* Enumerates the possible states of SM object. +* +* SYNOPSIS +*/ +typedef enum _osm_vl15_state +{ + OSM_VL15_STATE_INIT = 0, + OSM_VL15_STATE_READY + +} osm_vl15_state_t; +/***********/ + +/****s* OpenSM: VL15/osm_vl15_t +* NAME +* osm_vl15_t +* +* DESCRIPTION +* VL15 structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_vl15 +{ + osm_thread_state_t thread_state; + osm_vl15_state_t state; + uint32_t max_wire_smps; + cl_event_t signal; + cl_thread_t poller; + cl_qlist_t rfifo; + cl_qlist_t ufifo; + cl_spinlock_t lock; + osm_vendor_t *p_vend; + osm_log_t *p_log; + osm_stats_t *p_stats; + osm_subn_t *p_subn; + cl_disp_reg_handle_t h_disp; + cl_plock_t *p_lock; + +} osm_vl15_t; +/* +* FIELDS +* thread_state +* Tracks the thread state of the poller thread. +* +* state +* Tracks the state of the VL15 interface itself. +* +* max_wire_smps +* Maximum number of VL15 MADs allowed on the wire at one time. +* +* signal +* Event on which the poller sleeps. +* +* rfifo +* First-in First-out queue for outbound VL15 MADs for which +* a response is expected, aka the "response fifo" +* +* ufifo +* First-in First-out queue for outbound VL15 MADs for which +* no response is expected, aka the "unicast fifo". +* +* poller +* Worker thread pool that services the fifo to transmit VL15 MADs +* +* lock +* Spinlock guarding the FIFO. +* +* p_vend +* Pointer to the vendor transport object. +* +* p_log +* Pointer to the log object. +* +* p_stats +* Pointer to the OpenSM statistics block. +* +* p_subn +* Pointer to the Subnet object for this subnet. +* +* h_disp +* Handle returned from dispatcher registration. +* +* p_lock +* Pointer to the serializing lock. +* +* SEE ALSO +* VL15 object +*********/ + +/****f* OpenSM: VL15/osm_vl15_construct +* NAME +* osm_vl15_construct +* +* DESCRIPTION +* This function constructs an VL15 object. +* +* SYNOPSIS +*/ +void +osm_vl15_construct( + IN osm_vl15_t* const p_vl15 ); +/* +* PARAMETERS +* p_vl15 +* [in] Pointer to a VL15 object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_vl15_init, osm_vl15_destroy, and osm_vl15_is_inited. +* +* Calling osm_vl15_construct is a prerequisite to calling any other +* method except osm_vl15_init. +* +* SEE ALSO +* VL15 object, osm_vl15_init, osm_vl15_destroy, osm_vl15_is_inited +*********/ + +/****f* OpenSM: VL15/osm_vl15_destroy +* NAME +* osm_vl15_destroy +* +* DESCRIPTION +* The osm_vl15_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void +osm_vl15_destroy( + IN osm_vl15_t* const p_vl15, + IN struct _osm_mad_pool *p_pool); +/* +* PARAMETERS +* p_vl15 +* [in] Pointer to a VL15 object to destroy. +* +* p_pool +* [in] The pointer to the mad pool to return outstanding mads to +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified VL15 object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to osm_vl15_construct or +* osm_vl15_init. +* +* SEE ALSO +* VL15 object, osm_vl15_construct, osm_vl15_init +*********/ + +/* + Initialization. + Rate specifies the minimum number of microseconds between transmissions + on VL15. +*/ +/****f* OpenSM: VL15/osm_vl15_init +* NAME +* osm_vl15_init +* +* DESCRIPTION +* The osm_vl15_init function initializes a VL15 object for use. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_vl15_init( + IN osm_vl15_t* const p_vl15, + IN osm_vendor_t* const p_vend, + IN osm_log_t* const p_log, + IN osm_stats_t* const p_stats, + IN const int32_t max_wire_smps, + IN osm_subn_t* const p_subn, + IN cl_dispatcher_t* const p_disp, + IN cl_plock_t* const p_lock ); +/* +* PARAMETERS +* p_vl15 +* [in] Pointer to an osm_vl15_t object to initialize. +* +* p_vend +* [in] Pointer to the vendor transport object. +* +* p_log +* [in] Pointer to the log object. +* +* p_stats +* [in] Pointer to the OpenSM stastics block. +* +* max_wire_smps +* [in] Maximum number of MADs allowed on the wire at one time. +* +* p_subn +* [in] Pointer to the subnet object. +* +* p_disp +* [in] Pointer to the dispatcher object. +* +* p_lock +* [in] Pointer to the OpenSM serializing lock. +* +* RETURN VALUES +* IB_SUCCESS if the VL15 object was initialized successfully. +* +* NOTES +* Allows calling other VL15 methods. +* +* SEE ALSO +* VL15 object, osm_vl15_construct, osm_vl15_destroy, +* osm_vl15_is_inited +*********/ + +/****f* OpenSM: VL15/osm_vl15_post +* NAME +* osm_vl15_post +* +* DESCRIPTION +* Posts a MAD to the VL15 interface for transmission. +* +* SYNOPSIS +*/ +void +osm_vl15_post( + IN osm_vl15_t* const p_vl15, + IN osm_madw_t* const p_madw ); +/* +* PARAMETERS +* p_vl15 +* [in] Pointer to an osm_vl15_t object. +* +* p_madw +* [in] Pointer to a MAD wrapper structure containing the MAD. +* +* RETURN VALUES +* This function does not return a value. +* +* NOTES +* The osm_vl15_construct or osm_vl15_init must be called before using +* this function. +* +* SEE ALSO +* VL15 object, osm_vl15_construct, osm_vl15_init +*********/ + +/****f* OpenSM: VL15/osm_vl15_poll +* NAME +* osm_vl15_poll +* +* DESCRIPTION +* Causes the VL15 Interface to consider sending another QP0 MAD. +* +* SYNOPSIS +*/ +void +osm_vl15_poll( + IN osm_vl15_t* const p_vl ); +/* +* PARAMETERS +* p_vl15 +* [in] Pointer to an osm_vl15_t object. +* +* RETURN VALUES +* None. +* +* NOTES +* This function signals the VL15 that it may be possible to send +* a SMP. This function checks three criteria before sending a SMP: +* 1) The VL15 worker is IDLE +* 2) There are no QP0 SMPs currently outstanding +* 3) There is something on the VL15 FIFO to send +* +* SEE ALSO +* VL15 object, osm_vl15_construct, osm_vl15_init +*********/ + +/****f* OpenSM: VL15/osm_vl15_shutdown +* NAME +* osm_vl15_shutdown +* +* DESCRIPTION +* Cleanup all outstanding MADs on both fifo's. +* This is required to return all outstanding MAD resources. +* +* SYNOPSIS +*/ +void +osm_vl15_shutdown( + IN osm_vl15_t* const p_vl, + IN osm_mad_pool_t* const p_mad_pool); +/* +* PARAMETERS +* p_vl15 +* [in] Pointer to an osm_vl15_t object. +* +* p_mad_pool +* [in] The MAD pool owning the mads. +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +* VL15 object, osm_vl15_construct, osm_vl15_init +*********/ + +END_C_DECLS + +#endif /* _OSM_VL15INTF_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_vl_arb_rcv.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_vl_arb_rcv.h new file mode 100644 index 00000000..d32c105f --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_vl_arb_rcv.h @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_vl_arb_rcv.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_vla_rcv_t. + * This object represents the VL Arbitration Receiver object. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.3 $ + */ + +#ifndef _OSM_VLA_RCV_H_ +#define _OSM_VLA_RCV_H_ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/VL Arbitration Receiver +* NAME +* VL Arbitration Receiver +* +* DESCRIPTION +* The VL Arbitration Receiver object encapsulates the information +* needed to set or get the vl arbitration attribute from a port. +* +* The VL Arbitration Receiver object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Eitan Zahavi, Mellanox +* +*********/ + +/****s* OpenSM: VL Arbitration Receiver/osm_vla_rcv_t +* NAME +* osm_vla_rcv_t +* +* DESCRIPTION +* VL Arbitration Receiver structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_vla_rcv +{ + osm_subn_t *p_subn; + osm_req_t *p_req; + osm_log_t *p_log; + cl_plock_t *p_lock; + +} osm_vla_rcv_t; +/* +* FIELDS +* p_subn +* Pointer to the Subnet object for this subnet. +* +* p_req +* Pointer to the generic attribute request object. +* +* p_log +* Pointer to the log object. +* +* p_lock +* Pointer to the serializing lock. +* +* SEE ALSO +* VL Arbitration Receiver object +*********/ + +/****f* OpenSM: VL Arbitration Receiver/osm_vla_rcv_construct +* NAME +* osm_vla_rcv_construct +* +* DESCRIPTION +* This function constructs a VL Arbitration Receiver object. +* +* SYNOPSIS +*/ +void osm_vla_rcv_construct( + IN osm_vla_rcv_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a VL Arbitration Receiver object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_vla_rcv_destroy +* +* Calling osm_vla_rcv_construct is a prerequisite to calling any other +* method except osm_vla_rcv_init. +* +* SEE ALSO +* VL Arbitration Receiver object, osm_vla_rcv_init, +* osm_vla_rcv_destroy +*********/ + +/****f* OpenSM: VL Arbitration Receiver/osm_vla_rcv_destroy +* NAME +* osm_vla_rcv_destroy +* +* DESCRIPTION +* The osm_vla_rcv_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_vla_rcv_destroy( + IN osm_vla_rcv_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* VL Arbitration Receiver object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_vla_rcv_construct or osm_vla_rcv_init. +* +* SEE ALSO +* VL Arbitration Receiver object, osm_vla_rcv_construct, +* osm_vla_rcv_init +*********/ + +/****f* OpenSM: VL Arbitration Receiver/osm_vla_rcv_init +* NAME +* osm_vla_rcv_init +* +* DESCRIPTION +* The osm_vla_rcv_init function initializes a +* VL Arbitration Receiver object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_vla_rcv_init( + IN osm_vla_rcv_t* const p_ctrl, + IN osm_req_t* const p_req, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_vla_rcv_t object to initialize. +* +* p_req +* [in] Pointer to an osm_req_t object. +* +* p_subn +* [in] Pointer to the Subnet object for this subnet. +* +* p_log +* [in] Pointer to the log object. +* +* p_lock +* [in] Pointer to the OpenSM serializing lock. +* +* RETURN VALUES +* CL_SUCCESS if the VL Arbitration Receiver object was initialized +* successfully. +* +* NOTES +* Allows calling other VL Arbitration Receiver methods. +* +* SEE ALSO +* VL Arbitration Receiver object, osm_vla_rcv_construct, +* osm_vla_rcv_destroy +*********/ + +/****f* OpenSM: VL Arbitration Receiver/osm_vla_rcv_process +* NAME +* osm_vla_rcv_process +* +* DESCRIPTION +* Process the vl arbitration attribute. +* +* SYNOPSIS +*/ +void osm_vla_rcv_process( + IN const osm_vla_rcv_t* const p_ctrl, + IN osm_madw_t* const p_madw ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_vla_rcv_t object. +* +* p_madw +* [in] Pointer to the MAD Wrapper containing the MAD +* that contains the node's SLtoVL attribute. +* +* RETURN VALUES +* CL_SUCCESS if the SLtoVL processing was successful. +* +* NOTES +* This function processes a SLtoVL attribute. +* +* SEE ALSO +* VL Arbitration Receiver, VL Arbitration Response Controller +*********/ + +END_C_DECLS + +#endif /* _OSM_VLA_RCV_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_vl_arb_rcv_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_vl_arb_rcv_ctrl.h new file mode 100644 index 00000000..7b66a40a --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_vl_arb_rcv_ctrl.h @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_vl_arb_rcv_ctrl.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osm_vla_rcv_ctrl_t. + * This object represents a controller that set or get resp the + * IBA VL Arbitration Table attribute from a port. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.3 $ + */ + +#ifndef _OSM_VLA_RCV_CTRL_H_ +#define _OSM_VLA_RCV_CTRL_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****h* OpenSM/VL Arbitration Table Receive Controller +* NAME +* VL Arbitration Receive Controller +* +* DESCRIPTION +* The VL Arbitration Receive Controller object encapsulates +* the information needed to get or set VL Arbitration of a port. +* +* The VL Arbitration Receive Controller object is thread safe. +* +* This object should be treated as opaque and should be +* manipulated only through the provided functions. +* +* AUTHOR +* Eitan Zahavi, Mellanox +* +*********/ + +/****s* OpenSM: VL Arbitration Receive Controller/osm_vla_rcv_ctrl_t +* NAME +* osm_vla_rcv_ctrl_t +* +* DESCRIPTION +* VL Arbitration Receive Controller structure. +* +* This object should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _osm_vla_rcv_ctrl +{ + osm_vla_rcv_t *p_rcv; + osm_log_t *p_log; + cl_dispatcher_t *p_disp; + cl_disp_reg_handle_t h_disp; + +} osm_vla_rcv_ctrl_t; +/* +* FIELDS +* p_rcv +* Pointer to the VL Arbitration Receiver object. +* +* p_log +* Pointer to the log object. +* +* p_disp +* Pointer to the Dispatcher. +* +* h_disp +* Handle returned from dispatcher registration. +* +* SEE ALSO +* VL Arbitration Receive Controller object +* VL Arbitration Receiver object +*********/ + +/****f* OpenSM: VL Arbitration Receive Controller/osm_vla_rcv_ctrl_construct +* NAME +* osm_vla_rcv_ctrl_construct +* +* DESCRIPTION +* This function constructs a VL Arbitration Receive Controller object. +* +* SYNOPSIS +*/ +void osm_vla_rcv_ctrl_construct( + IN osm_vla_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to a VL Arbitration Receive Controller +* object to construct. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Allows calling osm_vla_rcv_ctrl_init, osm_vla_rcv_ctrl_destroy, +* and osm_vla_rcv_ctrl_is_inited. +* +* Calling osm_vla_rcv_ctrl_construct is a prerequisite to calling any other +* method except osm_vla_rcv_ctrl_init. +* +* SEE ALSO +* VL Arbitration Receive Controller object, osm_vla_rcv_ctrl_init, +* osm_vla_rcv_ctrl_destroy, osm_vla_rcv_ctrl_is_inited +*********/ + +/****f* OpenSM: VL Arbitration Receive Controller/osm_vla_rcv_ctrl_destroy +* NAME +* osm_vla_rcv_ctrl_destroy +* +* DESCRIPTION +* The osm_vla_rcv_ctrl_destroy function destroys the object, releasing +* all resources. +* +* SYNOPSIS +*/ +void osm_vla_rcv_ctrl_destroy( + IN osm_vla_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to the object to destroy. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* Performs any necessary cleanup of the specified +* VL Arbitration Receive Controller object. +* Further operations should not be attempted on the destroyed object. +* This function should only be called after a call to +* osm_vla_rcv_ctrl_construct or osm_vla_rcv_ctrl_init. +* +* SEE ALSO +* VL Arbitration Receive Controller object, osm_vla_rcv_ctrl_construct, +* osm_vla_rcv_ctrl_init +*********/ + +/****f* OpenSM: VL Arbitration Receive Controller/osm_vla_rcv_ctrl_init +* NAME +* osm_vla_rcv_ctrl_init +* +* DESCRIPTION +* The osm_vla_rcv_ctrl_init function initializes a +* VL Arbitration Receive Controller object for use. +* +* SYNOPSIS +*/ +ib_api_status_t osm_vla_rcv_ctrl_init( + IN osm_vla_rcv_ctrl_t* const p_ctrl, + IN osm_vla_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_vla_rcv_ctrl_t object to initialize. +* +* p_rcv +* [in] Pointer to an osm_vla_rcv_t object. +* +* p_log +* [in] Pointer to the log object. +* +* p_disp +* [in] Pointer to the OpenSM central Dispatcher. +* +* RETURN VALUES +* CL_SUCCESS if the VL Arbitration Receive Controller object was initialized +* successfully. +* +* NOTES +* Allows calling other VL Arbitration Receive Controller methods. +* +* SEE ALSO +* VL Arbitration Receive Controller object, osm_vla_rcv_ctrl_construct, +* osm_vla_rcv_ctrl_destroy, osm_vla_rcv_ctrl_is_inited +*********/ + +/****f* OpenSM: VL Arbitration Receive Controller/osm_vla_rcv_ctrl_is_inited +* NAME +* osm_vla_rcv_ctrl_is_inited +* +* DESCRIPTION +* Indicates if the object has been initialized with osm_vla_rcv_ctrl_init. +* +* SYNOPSIS +*/ +boolean_t osm_vla_rcv_ctrl_is_inited( + IN const osm_vla_rcv_ctrl_t* const p_ctrl ); +/* +* PARAMETERS +* p_ctrl +* [in] Pointer to an osm_vla_rcv_ctrl_t object. +* +* RETURN VALUES +* TRUE if the object was initialized successfully, +* FALSE otherwise. +* +* NOTES +* The osm_vla_rcv_ctrl_construct or osm_vla_rcv_ctrl_init must be +* called before using this function. +* +* SEE ALSO +* VL Arbitration Receive Controller object, osm_vla_rcv_ctrl_construct, +* osm_vla_rcv_ctrl_init +*********/ + +END_C_DECLS + +#endif /* _OSM_VLA_RCV_CTRL_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/st.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/st.h new file mode 100644 index 00000000..b715a06c --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/st.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: st.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* @(#) st.h 5.1 89/12/14 */ + +#ifndef ST_INCLUDED +#define ST_INCLUDED + +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +#if (__WORDSIZE == 64) || defined (_WIN64) +#define st_ptr_t unsigned long long +#else +#define st_ptr_t unsigned long +#endif + +typedef st_ptr_t st_data_t; + +#define ST_DATA_T_DEFINED + +typedef struct st_table st_table; + +struct st_hash_type { + int (*compare)(void *, void *); + st_ptr_t (*hash)(void *); +}; + +struct st_table { + struct st_hash_type *type; + int num_bins; + int num_entries; + struct st_table_entry **bins; +}; + +#define st_is_member(table,key) st_lookup(table,key,(st_data_t *)0) + +enum st_retval {ST_CONTINUE, ST_STOP, ST_DELETE}; + +st_table *st_init_table(struct st_hash_type *); +st_table *st_init_table_with_size(struct st_hash_type *, size_t); +st_table *st_init_numtable(void); +st_table *st_init_numtable_with_size(size_t); +st_table *st_init_strtable(void); +st_table *st_init_strtable_with_size(size_t); +int st_delete(st_table *, st_data_t *, st_data_t *); +int st_delete_safe(st_table *, st_data_t *, st_data_t *, st_data_t); +int st_insert(st_table *, st_data_t, st_data_t); +int st_lookup(st_table *, st_data_t, st_data_t *); +void st_foreach(st_table *, int (*)(st_data_t key, st_data_t val, st_data_t arg), st_data_t); +void st_add_direct(st_table *, st_data_t, st_data_t); +void st_free_table(st_table *); +void st_cleanup_safe(st_table *, st_data_t); +st_table *st_copy(st_table *); + +#define ST_NUMCMP ((int (*)()) 0) +#define ST_NUMHASH ((int (*)()) -2) + +#define st_numcmp ST_NUMCMP +#define st_numhash ST_NUMHASH + +/* int st_strhash(void); */ + +END_C_DECLS + +#endif /* ST_INCLUDED */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/unistd.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/unistd.h new file mode 100644 index 00000000..08fb5372 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/unistd.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_base.h 1689 2006-09-12 20:55:47Z eitan $ + */ + + + +/* + * Abstract: + * Work around for cmpatibility mode with Linux. + * + */ diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/osm_vendor.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/osm_vendor.h new file mode 100644 index 00000000..77452721 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/osm_vendor.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_vendor.h 1923 2009-01-30 22:20:39Z stansmith $ + */ + + + +/* + * 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 + +#if defined( OSM_VENDOR_INTF_TEST ) +#include +#elif defined( OSM_VENDOR_INTF_UMADT ) +#include +#elif defined( OSM_VENDOR_INTF_MTL ) +/* HACK - I do not know how to prevent complib from loading kernel H files */ +#undef __init +#include +#elif defined( OSM_VENDOR_INTF_TS ) +#undef __init +#include +#elif defined( OSM_VENDOR_INTF_ANAFA ) +#undef __init +#include +#elif defined( OSM_VENDOR_INTF_SIM ) +#undef __init +#include +#elif defined( OSM_VENDOR_INTF_OPENIB ) +#include +#elif defined( OSM_VENDOR_INTF_AL ) +#include +#elif +#error No MAD Interface selected! +#error Choose an interface in osm_vendor_select.h +#endif + + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/osm_vendor_al.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/osm_vendor_al.h new file mode 100644 index 00000000..32ee0f4b --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/osm_vendor_al.h @@ -0,0 +1,372 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * Portions Copyright (c) 2008 Microsoft Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_vendor_al.h 1375 2008-07-13 08:55:53Z leonidk $ + */ + + + +/* + * 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 +#include +#include +#include +#include +#include + +#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; + size_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; + uint32_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 +*********/ + + +#define OSM_BIND_INVALID_HANDLE 0 + + +/****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/branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/osm_vendor_api.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/osm_vendor_api.h new file mode 100644 index 00000000..664dc999 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/osm_vendor_api.h @@ -0,0 +1,519 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_vendor_api.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Specification of the OpenSM transport API. This API is OpenSM's view + * of the Infiniband transport. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_VENDOR_API_H_ +#define _OSM_VENDOR_API_H_ + +#include +#include +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****s* OpenSM Vendor API/osm_vend_mad_recv_callback_t +* NAME +* osm_vend_mad_recv_callback_t +* +* DESCRIPTION +* Function prototype for the vendor MAD receive callback. +* The vendor layer calls this function for MAD receives. +* +* SYNOPSIS +*/ +typedef void (*osm_vend_mad_recv_callback_t)( + IN osm_madw_t *p_madw, + IN void* bind_context, + IN osm_madw_t *p_req_madw ); +/* +* PARAMETERS +* p_madw +* [in] The received MAD wrapper. +* +* bind_context +* [in] User context supplied during the bind call. +* +* p_req_madw +* [in] Pointer to the request mad wrapper that generated this response. +* If the inbound MAD is not a response, this field is NULL. +* +* RETURN VALUES +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +/****s* OpenSM Vendor API/osm_vend_mad_send_err_callback_t +* NAME +* osm_vend_mad_send_err_callback_t +* +* DESCRIPTION +* Function prototype for the vendor send failure callback. +* The vendor layer calls this function when MADs expecting +* a response are completed in error, most likely due to a +* timeout. +* +* SYNOPSIS +*/ +typedef void (*osm_vend_mad_send_err_callback_t)( + IN void* bind_context, + IN osm_madw_t *p_madw ); +/* +* PARAMETERS +* bind_context +* [in] User context supplied during the bind call. +* +* p_madw +* [in] Pointer to the request mad that failed. +* +* RETURN VALUES +* None. +* +* NOTES +* The vendor layer does not call this function (or any other) +* for MADs that were not expecting a response. +* +* SEE ALSO +*********/ + +/****f* OpenSM Vendor API/osm_vendor_new +* NAME +* osm_vendor_new +* +* DESCRIPTION +* Allocates and initializes a new osm_vendor_t object. +* OpenSM calls this function before any other in the vendor API. +* This object is passed as a parameter to all other vendor functions. +* +* SYNOPSIS +*/ +osm_vendor_t* +osm_vendor_new( + IN osm_log_t* const p_log, + IN const uint32_t timeout ); +/* +* PARAMETERS +* p_log +* [in] Pointer to the log object to use. +* +* timeout +* [in] transaction timeout +* +* RETURN VALUES +* Returns a pointer to the vendor object. +* +* NOTES +* +* SEE ALSO +*********/ + +/****s* OpenSM Vendor API/osm_vendor_delete +* NAME +* osm_vendor_delete +* +* DESCRIPTION +* Dealocate the vendor object. +* +* SYNOPSIS +*/ +void +osm_vendor_delete( + IN osm_vendor_t** const pp_vend ); +/* +* PARAMETERS +* pp_vend +* [in/out] pointer to pointer to vendor objcet to be deleted +* +* RETURN VALUES +* None +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM Vendor API/osm_vendor_get_ports +* NAME +* osm_vendor_get_ports +* +* DESCRIPTION +* Returns an array of available port attribute structures. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_vendor_get_all_port_attr( + IN osm_vendor_t* const p_vend, + IN ib_port_attr_t* const p_attr_array, + IN uint32_t* const p_num_ports ); +/* +* PARAMETERS +* p_vend +* [in] Pointer to the vendor object to initialize. +* +* p_attr_array +* [in/out] Pointer to pre-allocated array of port attributes. +* If it is NULL - then the command only updates the p_num_ports, +* and return IB_INSUFFICIENT_MEMORY. +* +* p_num_ports +* [in/out] Pointer to a variable to hold the total number of ports +* available on the local machine.. +* +* RETURN VALUES +* IB_SUCCESS on success. +* IB_INSUFFICIENT_MEMORY if the attribute array was not large enough. +* The number of attributes needed is returned in num_guids. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM Vendor API/osm_vendor_init +* NAME +* osm_vendor_init +* +* DESCRIPTION +* The osm_vendor_init function initializes the vendor transport layer. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_vendor_init( + IN osm_vendor_t* const p_vend, + IN osm_log_t * const p_log, + IN const uint32_t timeout ); +/* +* PARAMETERS +* p_vend +* [in] Pointer to the vendor object to initialize. +* +* p_log +* [in] Pointer to OpenSM's log object. Vendor code may +* use the log object to send messages to OpenSM's log. +* +* timeout +* [in] Transaction timeout value in milliseconds. +* A value of 0 disables timeouts. +* +* RETURN VALUE +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM Vendor API/osm_vendor_bind +* NAME +* osm_vendor_bind +* +* DESCRIPTION +* The osm_vendor_bind function registers with the vendor transport layer +* per Mad Class per PortGuid for mad transport capability. +* +* SYNOPSIS +*/ +osm_bind_handle_t +osm_vendor_bind( + IN osm_vendor_t* const p_vend, + IN osm_bind_info_t* const p_bind_info, + IN osm_mad_pool_t* const p_mad_pool, + IN osm_vend_mad_recv_callback_t mad_recv_callback, + IN osm_vend_mad_send_err_callback_t send_err_callback, + IN void* context ); +/* +* PARAMETERS +* p_vend +* [in] pointer to the vendor object +* +* p_osm_bind_info +* [in] pointer to a struct defining the type of bind to perform. +* +* p_mad_pool +* [in] pointer to a mad wrappers pool to be used for allocating +* mad wrappers on send and receive. +* +* mad_recv_callback +* [in] the callback function to be invoked on mad receive. +* +* send_err_callback +* [in] the callback function to be invoked on mad transaction errors. +* +* context +* [in] the context to be provided to the callbacks as bind_ctx. +* +* RETURN VALUE +* On success, a valid bind handle. +* OSM_BIND_INVALID_HANDLE otherwise. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM Vendor API/osm_vendor_unbind +* NAME +* osm_vendor_unbind +* +* DESCRIPTION +* Unbind the given bind handle (obtained by osm_vendor_bind). +* +* SYNOPSIS +*/ +void +osm_vendor_unbind( + IN osm_bind_handle_t h_bind ); +/* +* PARAMETERS +* h_bind +* [in] the bind handle to release. +* +* RETURN VALUE +* NONE. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM Vendor API/osm_vendor_get +* NAME +* osm_vendor_get +* +* DESCRIPTION +* Obtain a mad wrapper holding actual mad buffer to be sent via +* the transport. +* +* SYNOPSIS +*/ +ib_mad_t* +osm_vendor_get( + IN osm_bind_handle_t h_bind, + IN const uint32_t mad_size, + IN osm_vend_wrap_t* const p_vend_wrap ); +/* +* PARAMETERS +* h_bind +* [in] the bind handle obtained by calling osm_vendor_bind +* +* mad_size +* [in] the actual mad size required +* +* p_vend_wrap +* [out] the returned mad vendor wrapper +* +* RETURN VALUE +* IB_SUCCESS on succesful completion. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM Vendor API/osm_vendor_send +* NAME +* osm_vendor_send +* +* DESCRIPTION +* +* SYNOPSIS +*/ +ib_api_status_t +osm_vendor_send( + IN osm_bind_handle_t h_bind, + IN osm_madw_t* const p_madw, + IN boolean_t const resp_expected); +/* +* PARAMETERS +* h_bind +* [in] the bind handle obtained by calling osm_vendor_bind +* +* p_madw +* [in] pointer to the Mad Wrapper structure for the MAD to be sent. +* +* resp_expected +* [in] boolean value declaring the mad as a request (expecting a response). +* +* RETURN VALUE +* IB_SUCCESS on succesful completion. +* +* NOTES +* 1. Only mads that expect a response are tracked for transaction competion. +* 2. A mad that does not expect a response is being put back immediatly after +* being sent. +* +* SEE ALSO +*********/ + +/****f* OpenSM Vendor API/osm_vendor_put +* NAME +* osm_vendor_put +* +* DESCRIPTION +* Return a mad vandor wrapper to the mad pool. It also means that the +* mad buffer is returned to the transport. +* +* SYNOPSIS +*/ +void +osm_vendor_put( + IN osm_bind_handle_t h_bind, + IN osm_vend_wrap_t* const p_vend_wrap ); +/* +* PARAMETERS +* h_bind +* [in] the bind handle obtained by calling osm_vendor_bind +* +* p_vend_wrap +* [in] pointer to the mad vendor wrapper to put back into the pool. +* +* RETURN VALUE +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +/****i* OpenSM Vendor API/osm_vendor_local_lid_change +* NAME +* osm_vendor_local_lid_change +* +* DESCRIPTION +* Notifies the vendor transport layer that the local address +* has changed. This allows the vendor layer to perform housekeeping +* functions such as address vector updates. +* +* SYNOPSIS +*/ +ib_api_status_t +osm_vendor_local_lid_change( + IN osm_bind_handle_t h_bind ); +/* +* PARAMETERS +* h_bind +* [in] the bind handle obtained by calling osm_vendor_bind +* +* RETURN VALUE +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM Vendor API/osm_vendor_set_sm +* NAME +* osm_vendor_set_sm +* +* DESCRIPTION +* Modifies the port info for the bound port to set the "IS_SM" bit +* according to the value given (TRUE or FALSE). +* +* SYNOPSIS +*/ +void +osm_vendor_set_sm( + IN osm_bind_handle_t h_bind, + IN boolean_t is_sm_val ); +/* +* PARAMETERS +* h_bind +* [in] bind handle for this port. +* +* is_sm_val +* [in] If TRUE - will set the is_sm to TRUE, if FALSE - will set the +* the is_sm to FALSE. +* +* RETURN VALUE +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +/****f* OpenSM Vendor API/osm_vendor_set_debug +* NAME +* osm_vendor_set_debug +* +* DESCRIPTION +* Modifies the vendor specific debug level. +* +* SYNOPSIS +*/ +void +osm_vendor_set_debug( + IN osm_vendor_t* const p_vend, + IN int32_t level ); +/* +* PARAMETERS +* p_vend +* [in] vendor handle. +* +* level +* [in] vendor specific debug level. +* +* RETURN VALUE +* None. +* +* NOTES +* +* SEE ALSO +*********/ + +END_C_DECLS + +#endif /* _OSM_VENDOR_API_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/osm_vendor_sa_api.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/osm_vendor_sa_api.h new file mode 100644 index 00000000..b9198cb6 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/osm_vendor_sa_api.h @@ -0,0 +1,879 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_vendor_sa_api.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Specification of the OpenSM SA Client API. This API uses the basic osm + * vendor API to provide SA Client interface. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#ifndef _OSM_VENDOR_SA_API_H_ +#define _OSM_VENDOR_SA_API_H_ + +#include + +#ifdef __cplusplus +# define BEGIN_C_DECLS extern "C" { +# define END_C_DECLS } +#else /* !__cplusplus */ +# define BEGIN_C_DECLS +# define END_C_DECLS +#endif /* __cplusplus */ + +BEGIN_C_DECLS + +/****d* OpenSM Vendor SA Client/osmv_flags_t +* NAME +* osmv_flags_t +* +* DESCRIPTION +* Access layer flags used to direct the operation of various calls. +* +* SYNOPSIS +*/ +typedef uint32_t osmv_flags_t; +#define OSM_SA_FLAGS_SYNC 0x00000001 +/* +* VALUES +* OSM_SA_FLAGS_SYNC +* Indicates that the given operation should be performed synchronously. +* The call will block until it completes. Callbacks will still be +* invoked. +* +* SEE ALSO +* osmv_query_sa +*****/ + +/****d* OpenSM Vendor SA Client/osmv_query_type_t +* NAME +* osmv_query_type_t +* +* DESCRIPTION +* Abstracted queries supported by the access layer. +* +* SYNOPSIS +*/ +typedef enum _osmv_query_type +{ + OSMV_QUERY_USER_DEFINED, + + OSMV_QUERY_ALL_SVC_RECS, + OSMV_QUERY_SVC_REC_BY_NAME, + OSMV_QUERY_SVC_REC_BY_ID, + + OSMV_QUERY_CLASS_PORT_INFO, + + OSMV_QUERY_NODE_REC_BY_NODE_GUID, + OSMV_QUERY_PORT_REC_BY_LID, + OSMV_QUERY_PORT_REC_BY_LID_AND_NUM, + + OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK, + OSMV_QUERY_SLVL_BY_LID_AND_PORTS, + + OSMV_QUERY_PATH_REC_BY_PORT_GUIDS, + OSMV_QUERY_PATH_REC_BY_GIDS, + OSMV_QUERY_PATH_REC_BY_LIDS, + + OSMV_QUERY_UD_MULTICAST_SET, + OSMV_QUERY_UD_MULTICAST_DELETE, + + OSMV_QUERY_MULTIPATH_REC, + +} osmv_query_type_t; +/* +* VALUES +* OSMV_QUERY_USER_DEFINED +* Query the SA based on user-defined input. Queries of this type +* should reference an osmv_user_query_t structure as input to the +* query. +* +* OSMV_QUERY_SVC_REC_BY_NAME +* Query for service records based on the service name. Queries of +* this type should reference an ib_svc_name_t structure as input +* to the query. +* +* OSMV_QUERY_SVC_REC_BY_ID +* Query for service records based on the service ID. Queries of +* this type should reference an ib_net64_t value that indicates +* the ID of the service being requested. +* +* OSMV_QUERY_NODE_REC_BY_NODE_GUID +* Query for node information based on the node's GUID. Queries of +* this type should reference an ib_net64_t value that indicates +* the GUID of the node being requested. +* +* OSMV_QUERY_PORT_REC_BY_LID +* Query for port information based on the port's base LID. Queries +* of this type should reference an ib_net16_t value that indicates +* the base LID of the port being requested. +* +* OSMV_QUERY_PORT_REC_BY_LID_AND_NUM +* Query for port information based on the port's LID and port num. +* Queries of this type should reference an osmv_user_query_t +* structure as input to the query. The port num and lid should +* be provided by it. +* +* OSMV_QUERY_PATH_REC_BY_PORT_GUIDS +* Query for path records between the specified pair of port GUIDs. +* Queries of this type should reference an osmv_guid_pair_t +* structure that indicates the GUIDs of the path being requested. +* +* OSMV_QUERY_PATH_REC_BY_GIDS +* Query for path records between the specified pair of port GIDs. +* Queries of this type should reference an osmv_gid_pair_t +* structure that indicates the GIDs of the path being requested. +* +* OSMV_QUERY_PATH_REC_BY_LIDS +* Query for path records between the specified pair of port LIDs. +* Queries of this type should reference an osmv_lid_pair_t +* structure that indicates the LIDs of the path being requested. +* +* NOTES +* This enum is used to define abstracted queries provided by the access +* layer. Users may issue queries not listed here by sending MADs directly +* to subnet administration or a class manager. These queries are +* intended to represent those most often used by clients. +* +* SEE ALSO +* osmv_query, osmv_query_req_t, osmv_user_query_t, osmv_gid_pair_t, +* osmv_lid_pair_t osmv_guid_pair_t +*****/ + +/****s* OpenSM Vendor SA Client/osmv_user_query_t +* NAME +* osmv_user_query_t +* +* DESCRIPTION +* User-defined query information. +* +* SYNOPSIS +*/ +typedef struct _osmv_user_query +{ + uint8_t method; + ib_net16_t attr_id; + ib_net16_t attr_offset; + ib_net32_t attr_mod; + ib_net64_t comp_mask; + void *p_attr; +} osmv_user_query_t; +/* +* FIELDS +* +* method +* Method to be used +* +* attr_id +* Attribute identifier of query data. +* +* attr_offset +* Size of the query attribute, in 8-byte words. Users can set +* this value by passing in the sizeof( attribute ) into the +* ib_get_attr_offset() routine. +* +* attr_mod +* Attribute modifier for query request. +* +* comp_mask +* Indicates the attribute components that are specified for the +* query. +* +* p_attr +* References the attribute structure used as input into the query. +* This field is ignored if comp_mask is set to 0. +* +* NOTES +* This structure is used to describe a user-defined query. The attribute +* ID, attribute offset, component mask, and attribute structure must match +* those defined by the IBA specification. Users should refer to chapter +* 15 of the IBA specification for additional details. +* +* SEE ALSO +* osmv_query_type_t, ib_get_attr_offset, ib_get_attr_size, osmv_query_sa +*****/ + +/****s* OpenSM Vendor SA Client/osmv_gid_pair_t +* NAME +* osmv_gid_pair_t +* +* DESCRIPTION +* Source and destination GIDs. +* +* SYNOPSIS +*/ +typedef struct _osmv_gid_pair +{ + ib_gid_t src_gid; + ib_gid_t dest_gid; +} osmv_gid_pair_t; +/* +* FIELDS +* src_gid +* Source GID of a path. +* +* dest_gid +* Destination GID of a path. +* +* NOTES +* This structure is used to describe the endpoints of a path. +* +* SEE ALSO +* ib_gid_t +*****/ + +/****s* OpenSM Vendor SA Client/osmv_lid_pair_t +* NAME +* osmv_lid_pair_t +* +* DESCRIPTION +* Source and destination LIDs. +* +* SYNOPSIS +*/ +typedef struct _osmv_lid_pair +{ + ib_net16_t src_lid; + ib_net16_t dest_lid; +} osmv_lid_pair_t; +/* +* FIELDS +* src_lid +* Source LID of a path. +* +* dest_lid +* Destination LID of a path. +* +* NOTES +* This structure is used to describe the endpoints of a path. +*****/ + +/****s* OpenSM Vendor SA Client/osmv_guid_pair_t +* NAME +* osmv_guid_pair_t +* +* DESCRIPTION +* Source and destination GUIDs. These may be port or channel adapter +* GUIDs, depending on the context in which this structure is used. +* +* SYNOPSIS +*/ +typedef struct _osmv_guid_pair +{ + ib_net64_t src_guid; + ib_net64_t dest_guid; +} osmv_guid_pair_t; +/* +* FIELDS +* src_guid +* Source GUID of a path. +* +* dest_guid +* Destination GUID of a path. +* +* NOTES +* This structure is used to describe the endpoints of a path. The given +* GUID pair may belong to either ports or channel adapters. +* +* SEE ALSO +* ib_guid_t +*****/ + +/****s* OpenSM Vendor SA Client/osmv_multipath_req_t +* NAME +* osmv_multipath_req_t +* +* DESCRIPTION +* Fields from which to generate a MultiPathRecord request. +* +* SYNOPSIS +*/ +typedef struct _osmv_multipath_req_t +{ + ib_net64_t comp_mask; + uint16_t pkey; + boolean_t reversible; + uint8_t num_path; + uint8_t sl; + uint8_t independence; + uint8_t sgid_count; + uint8_t dgid_count; + ib_gid_t gids[IB_MULTIPATH_MAX_GIDS]; +} osmv_multipath_req_t; +/* +* FIELDS +* +* NOTES +* This structure is used to describe a multipath request. +* +* SEE ALSO +*****/ + +/****s* OpenSM Vendor SA Client/osmv_query_res_t +* NAME +* osmv_query_res_t +* +* DESCRIPTION +* Contains the results of a subnet administration query. +* +* SYNOPSIS +*/ +typedef struct _osmv_query_res +{ + const void *query_context; + ib_api_status_t status; + osmv_query_type_t query_type; + uint32_t result_cnt; + osm_madw_t *p_result_madw; +} osmv_query_res_t; +/* +* FIELDS +* query_context +* User-defined context information associated with the query +* through the osm_vendor_query_sa call. +* +* status +* Indicates the success of the query operation. +* +* query_type +* Indicates the type of query for which the results are being +* returned. This matches the query_type specified through the +* osm_vendor_query_sa call. +* +* result_cnt +* The number of result structures that were returned by the query. +* +* p_result_madw +* For queries returning IB_SUCCESS or IB_REMOTE_ERROR, this +* references the MAD wrapper returned by subnet administration +* containing the list of results or the returned error code. +* +* NOTES +* A query result structure is returned to a client through their +* osmv_pfn_query_cb_t routine to notify them of the results of a subnet +* administration query. If the query was successful or received an error +* from subnet administration, p_result_madw will reference a MAD wrapper +* containing the results. The MAD referenced by p_result_madw is owned by +* the user and remains available even after their callback returns. Users +* must call osm_mad_pool_put() to return the MAD wrapper back to the +* mad pool when they are done accessing the results. +* +* To retrieve individual result structures from the p_result_madw, users +* may call osmv_get_query_result(). +* +* SEE ALSO +* osmv_query_sa, osmv_pfn_query_cb_t, ib_api_status_t, +* osmv_query_status_t, osmv_query_type_t, +* osmv_get_query_result +*****/ + +/****f* OpenSM Vendor SA Client/osmv_get_query_result +* NAME +* osmv_get_query_result +* +* DESCRIPTION +* Retrieves a result structure from a MADW returned by a call to +* osmv_query_sa(). +* +* SYNOPSIS +*/ +static inline void* +osmv_get_query_result( + IN osm_madw_t *p_result_madw, + IN uint32_t result_index ) +{ + ib_sa_mad_t *p_sa_mad; + + CL_ASSERT( p_result_madw ); + p_sa_mad = (ib_sa_mad_t*)osm_madw_get_mad_ptr( p_result_madw ); + CL_ASSERT( p_sa_mad ); + CL_ASSERT( ib_get_attr_size( p_sa_mad->attr_offset ) * (result_index + 1) + + IB_SA_MAD_HDR_SIZE <= p_result_madw->mad_size ); + + return( p_sa_mad->data + + (ib_get_attr_size( p_sa_mad->attr_offset ) * result_index) ); +} +/* +* PARAMETERS +* p_result_madw +* [in] This is a reference to the MAD returned as a result of the +* query. +* +* result_index +* [in] A zero-based index indicating which result to return. +* +* NOTES +* This call returns a pointer to the start of a result structure from a +* call to osmv_query_sa(). The type of result structure must be known to +* the user either through the user's context or the query_type returned as +* part of the osmv_query_res_t structure. +* +* SEE ALSO +* osmv_query_res_t, osm_madw_t +*****/ + +/****f* OpenSM Vendor SA Client/osmv_get_query_path_rec +* NAME +* osmv_get_query_path_rec +* +* DESCRIPTION +* Retrieves a path record result from a MAD returned by a call to +* osmv_query_sa(). +* +* SYNOPSIS +*/ +static inline ib_path_rec_t* +osmv_get_query_path_rec( + IN osm_madw_t *p_result_madw, + IN uint32_t result_index ) +{ + ib_sa_mad_t *p_sa_mad; + + CL_ASSERT( p_result_madw ); + p_sa_mad = (ib_sa_mad_t*)osm_madw_get_mad_ptr( p_result_madw ); + CL_ASSERT( p_sa_mad && p_sa_mad->attr_id == IB_MAD_ATTR_PATH_RECORD ); + + return( (ib_path_rec_t*)osmv_get_query_result( p_result_madw, result_index ) ); +} +/* +* PARAMETERS +* p_result_madw +* [in] This is a reference to the MAD returned as a result of the +* query. +* +* result_index +* [in] A zero-based index indicating which result to return. +* +* NOTES +* This call returns a pointer to the start of a path record result from +* a call to osmv_query_sa(). +* +* SEE ALSO +* osmv_query_res_t, osm_madw_t, osmv_get_query_result, ib_path_rec_t +*****/ + +/****f* OpenSM Vendor SA Client/osmv_get_query_portinfo_rec +* NAME +* osmv_get_query_portinfo_rec +* +* DESCRIPTION +* Retrieves a port info record result from a MAD returned by a call to +* osmv_query_sa(). +* +* SYNOPSIS +*/ +static inline ib_portinfo_record_t* +osmv_get_query_portinfo_rec( + IN osm_madw_t *p_result_madw, + IN uint32_t result_index ) +{ + ib_sa_mad_t *p_sa_mad; + + CL_ASSERT( p_result_madw ); + p_sa_mad = (ib_sa_mad_t*)osm_madw_get_mad_ptr( p_result_madw ); + CL_ASSERT( p_sa_mad && p_sa_mad->attr_id == IB_MAD_ATTR_PORTINFO_RECORD ); + + return( (ib_portinfo_record_t*)osmv_get_query_result( p_result_madw, + result_index ) ); +} +/* +* PARAMETERS +* p_result_madw +* [in] This is a reference to the MAD returned as a result of the +* query. +* +* result_index +* [in] A zero-based index indicating which result to return. +* +* NOTES +* This call returns a pointer to the start of a port info record result +* from a call to osmv_query_sa(). +* +* SEE ALSO +* osmv_query_res_t, osm_madw_t, osmv_get_query_result, ib_portinfo_record_t +*****/ + +/****f* OpenSM Vendor SA Client/osmv_get_query_node_rec +* NAME +* osmv_get_query_node_rec +* +* DESCRIPTION +* Retrieves a node record result from a MAD returned by a call to +* osmv_query_sa(). +* +* SYNOPSIS +*/ +static inline ib_node_record_t* +osmv_get_query_node_rec( + IN osm_madw_t *p_result_madw, + IN uint32_t result_index ) +{ + ib_sa_mad_t *p_sa_mad; + + CL_ASSERT( p_result_madw ); + p_sa_mad = (ib_sa_mad_t*)osm_madw_get_mad_ptr( p_result_madw ); + CL_ASSERT( p_sa_mad && p_sa_mad->attr_id == IB_MAD_ATTR_NODE_RECORD ); + + return( (ib_node_record_t*)osmv_get_query_result( p_result_madw, + result_index ) ); +} +/* +* PARAMETERS +* p_result_madw +* [in] This is a reference to the MAD returned as a result of the +* query. +* +* result_index +* [in] A zero-based index indicating which result to return. +* +* NOTES +* This call returns a pointer to the start of a node record result from +* a call to osmv_query_sa(). +* +* SEE ALSO +* osmv_query_res_t, osm_madw_t, osmv_get_query_result, ib_node_record_t +*****/ + +/****f* OpenSM Vendor SA Client/osmv_get_query_svc_rec +* NAME +* osmv_get_query_svc_rec +* +* DESCRIPTION +* Retrieves a service record result from a MAD returned by a call to +* osmv_query_sa(). +* +* SYNOPSIS +*/ +static inline ib_service_record_t* +osmv_get_query_svc_rec( + IN osm_madw_t *p_result_madw, + IN uint32_t result_index ) +{ + ib_sa_mad_t *p_sa_mad; + + CL_ASSERT( p_result_madw ); + p_sa_mad = (ib_sa_mad_t*)osm_madw_get_mad_ptr( p_result_madw ); + CL_ASSERT( p_sa_mad && p_sa_mad->attr_id == IB_MAD_ATTR_SERVICE_RECORD ); + + return( (ib_service_record_t*)osmv_get_query_result( p_result_madw, + result_index ) ); +} +/* +* PARAMETERS +* p_result_madw +* [in] This is a reference to the MAD returned as a result of the +* query. +* +* result_index +* [in] A zero-based index indicating which result to return. +* +* NOTES +* This call returns a pointer to the start of a service record result from +* a call to osmv_query_sa(). +* +* SEE ALSO +* osmv_query_res_t, osm_madw_t, osmv_get_query_result, ib_service_record_t +*****/ + +/****f* OpenSM Vendor SA Client/osmv_get_query_mc_rec +* NAME +* osmv_get_query_mc_rec +* +* DESCRIPTION +* Retrieves a multicast record result from a MAD returned by a call to +* osmv_query_sa(). +* +* SYNOPSIS +*/ +static inline ib_member_rec_t* +osmv_get_query_mc_rec( + IN osm_madw_t *p_result_madw, + IN uint32_t result_index ) +{ + ib_sa_mad_t *p_sa_mad; + + CL_ASSERT( p_result_madw ); + p_sa_mad = (ib_sa_mad_t*)osm_madw_get_mad_ptr( p_result_madw ); + CL_ASSERT( p_sa_mad && p_sa_mad->attr_id == IB_MAD_ATTR_MCMEMBER_RECORD ); + + return( (ib_member_rec_t*)osmv_get_query_result( p_result_madw, + result_index ) ); +} +/* +* PARAMETERS +* p_result_madw +* [in] This is a reference to the MAD returned as a result of the +* query. +* +* result_index +* [in] A zero-based index indicating which result to return. +* +* NOTES +* This call returns a pointer to the start of a service record result from +* a call to osmv_query_sa(). +* +* SEE ALSO +* osmv_query_res_t, osm_madw_t, osmv_get_query_result, ib_member_rec_t +*****/ + +/****f* OpenSM Vendor SA Client/osmv_get_query_inform_info_rec +* NAME +* osmv_get_query_inform_info_rec +* +* DESCRIPTION +* Retrieves an InformInfo record result from a MAD returned by +* a call to osmv_query_sa(). +* +* SYNOPSIS +*/ +static inline ib_inform_info_record_t* +osmv_get_query_inform_info_rec( + IN osm_madw_t *p_result_madw, + IN uint32_t result_index ) +{ + ib_sa_mad_t *p_sa_mad; + + CL_ASSERT( p_result_madw ); + p_sa_mad = (ib_sa_mad_t*)osm_madw_get_mad_ptr( p_result_madw ); + CL_ASSERT( p_sa_mad && p_sa_mad->attr_id == IB_MAD_ATTR_INFORM_INFO_RECORD ); + + return( (ib_inform_info_record_t*)osmv_get_query_result( p_result_madw, + result_index ) ); +} +/* +* PARAMETERS +* p_result_madw +* [in] This is a reference to the MAD returned as a result of the +* query. +* +* result_index +* [in] A zero-based index indicating which result to return. +* +* NOTES +* This call returns a pointer to the start of a service record result from +* a call to osmv_query_sa(). +* +* SEE ALSO +* osmv_query_res_t, osm_madw_t, osmv_get_query_result, ib_inform_info_record_t +*****/ + +/****f* OpenSM Vendor SA Client/osmv_pfn_query_cb_t +* NAME +* osmv_pfn_query_cb_t +* +* DESCRIPTION +* User-defined callback invoked on completion of subnet administration +* query. +* +* SYNOPSIS +*/ +typedef void +(*osmv_pfn_query_cb_t)( + IN osmv_query_res_t *p_query_res ); +/* +* PARAMETERS +* p_query_res +* [in] This is a reference to a structure containing the result of +* the query. +* +* NOTES +* This routine is invoked to notify a client of the result of a subnet +* administration query. The p_query_rec parameter references the result +* of the query and, in the case of a successful query, any information +* returned by subnet administration. +* +* In the kernel, this callback is usually invoked using a tasklet, +* dependent on the implementation of the underlying verbs provider driver. +* +* SEE ALSO +* osmv_query_res_t +*****/ + +/****s* OpenSM Vendor SA Client/osmv_query_req_t +* NAME +* osmv_query_req_t +* +* DESCRIPTION +* Information used to request an access layer provided query of subnet +* administration. +* +* SYNOPSIS +*/ +typedef struct _osmv_query_req +{ + osmv_query_type_t query_type; + const void *p_query_input; + ib_net64_t sm_key; + + uint32_t timeout_ms; + uint32_t retry_cnt; + osmv_flags_t flags; + + const void *query_context; + osmv_pfn_query_cb_t pfn_query_cb; +} osmv_query_req_t; +/* +* FIELDS +* query_type +* Indicates the type of query that the access layer should +* perform. +* +* p_query_input +* A pointer to the input for the query. The data referenced by +* this structure is dependent on the type of query being requested +* and is determined by the specified query_type. +* +* sm_key +* The M_Key to be provided with the SA MAD for authentication. +* Normally 0 is used. +* +* timeout_ms +* Specifies the number of milliseconds to wait for a response for +* this query until retrying or timing out the request. +* +* retry_cnt +* Specifies the number of times that the query will be retried +* before failing the request. +* +* flags +* Used to describe the mode of operation. Set to IB_FLAGS_SYNC to +* process the called routine synchronously. +* +* query_context +* User-defined context information associated with this query. +* The context data is returned to the user as a part of their +* query callback. +* +* pfn_query_cb +* A user-defined callback that is invoked upon completion of the +* query. +* +* NOTES +* This structure is used when requesting an osm vendor provided query +* of subnet administration. Clients specify the type of query through +* the query_type field. Based on the type of query, the p_query_input +* field is set to reference the appropriate data structure. +* +* The information referenced by the p_query_input field is one of the +* following: +* +* -- a NULL terminated service name +* -- a service id +* -- a single GUID +* -- a pair of GUIDs specified through an osmv_guid_pair_t structure +* -- a pair of GIDs specified through an osmv_gid_pair_t structure +* +* SEE ALSO +* osmv_query_type_t, osmv_pfn_query_cb_t, osmv_guid_pair_t, +* osmv_gid_pair_t +*****/ + +/****f* OpenSM Vendor SA Client/osmv_bind_sa +* NAME +* osmv_bind_sa +* +* DESCRIPTION +* Bind to the SA service and return a handle to be used for later +* queries. +* +* +* SYNOPSIS +*/ +osm_bind_handle_t +osmv_bind_sa( + IN osm_vendor_t * const p_vend, + IN osm_mad_pool_t * const p_mad_pool, + IN ib_net64_t port_guid + ); +/* +* PARAMETERS +* p_vend +* [in] an osm_vendor object to work with +* +* p_mad_pool +* [in] mad pool to obtain madw from +* +* port_guid +* [in] the port guid to attach to. +* +* RETURN VALUE +* Bind handle to be used for later SA queries or OSM_BIND_INVALID_HANDLE +* +* NOTES +* +* SEE ALSO +* osmv_query_sa +*********/ + +/****f* OpenSM Vendor SA Client/osmv_query_sa +* NAME +* osmv_query_sa +* +* DESCRIPTION +* Query the SA given an SA query request (similar to IBAL ib_query). +* +* SYNOPSIS +*/ +ib_api_status_t +osmv_query_sa( + IN osm_bind_handle_t h_bind, + IN const osmv_query_req_t * const p_query_req + ); +/* +* PARAMETERS +* h_bind +* [in] bind handle for this port. Should be previously +* obtained by calling osmv_bind_sa +* +* p_query_req +* [in] an SA query request structure. +* +* RETURN VALUE +* IB_SUCCESS if completed successfuly (or in ASYNC mode +* if the request was sent). +* +* NOTES +* +* SEE ALSO +* osmv_bind_sa +*********/ + +END_C_DECLS + +#endif /* _OSM_VENDOR_SA_API_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/osm_vendor_select.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/osm_vendor_select.h new file mode 100644 index 00000000..3c6394ab --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/osm_vendor_select.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_vendor_select.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Include file that defines which vendor files to compile. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.6 $ + */ + +#ifndef _OSM_VENDOR_SELECT_H_ +#define _OSM_VENDOR_SELECT_H_ + +///////////////////////////////////////////////////// +// +// MAD INTERFACE SELECTION +// +///////////////////////////////////////////////////// + +/* + TEST and UMADT must be specified in the 'make' command line, + with VENDOR=test or VENDOR=umadt. +*/ +#ifndef OSM_VENDOR_INTF_OPENIB +#ifndef OSM_VENDOR_INTF_TEST +#ifndef OSM_VENDOR_INTF_UMADT +#ifndef OSM_VENDOR_INTF_MTL +#ifndef OSM_VENDOR_INTF_TS +#ifndef OSM_VENDOR_INTF_SIM +#ifndef OSM_VENDOR_INTF_AL +#define OSM_VENDOR_INTF_AL +#endif /* AL */ +#endif /* TS */ +#endif /* SIM */ +#endif /* MTL */ +#endif /* UMADT */ +#endif /* TEST */ +#endif /* OPENIB */ + +#endif /* _OSM_VENDOR_SELECT_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/winosm_common.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/winosm_common.h new file mode 100644 index 00000000..cb2a2864 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/winosm_common.h @@ -0,0 +1,251 @@ +#ifndef _OSM_COMMON_H_ +#define _OSM_COMMON_H_ + +#include +#include +#include +#include +#include +#include +#include + +#pragma warning(disable : 4996) +#pragma warning(disable : 4100) + +struct timezone { + int tz_minuteswest; /* minutes west of Greenwich */ + int tz_dsttime; /* type of dst correction */ +}; + + + +#ifndef _GETOPT_H_ + +# define no_argument 0 +# define required_argument 1 +# define optional_argument 2 + +/* Global variables for getopt_long */ +char *optarg; + +struct option +{ + const char *name; + int has_arg; + int *flag; + int val; +}; +#endif + + +/************************************************************************/ +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) */ +/*****************************************************************************/ + + +#ifndef getpid +#define getpid() GetCurrentProcessId() +#endif + +#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 + +#ifndef strtoull +#define strtoull _strtoui64 +#endif + +#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_INFO 0 +#define LOG_WARNING 1 +#define LOG_ERR 2 +/*****************************************/ + +/****f* OpenSM: osm_common/GetOsmTempPath +* NAME +* GetOsmTempPath +* +* DESCRIPTION +* The function retrieves the temp path defined in Windows using its API +* +* SYNOPSIS +*/ +char* +GetOsmTempPath(void); +/* +* PARAMETERS +* NONE +* +* RETURN VALUE +* This function returns string containing the default temp path in windows +* +* NOTES +*/ + +/****f* OpenSM: osm_common/GetOsmCachePath +* NAME +* GetOsmCachePath +* +* DESCRIPTION +* The function retrieves the path the cache directory. This directory is +* the etc dir under the installation directory of the mellanox stack. +* The installation directory should be pointed out by the WinIB_HOME variable. +* If WinIB_HOME variable is missing, or there is not /etc/ dir under it - then +* the function will return the getOsmTempPath() value. +* +* SYNOPSIS +*/ +char* +GetOsmCachePath(void); +/* +* PARAMETERS +* NONE +* +* RETURN VALUE +* This function returns string containing the default cache path for osm use. +* +* 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/branches/WOF2-2/ulp/opensm/user_3_0_0/libopensm/Makefile b/branches/WOF2-2/ulp/opensm/user_3_0_0/libopensm/Makefile new file mode 100644 index 00000000..58189757 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/libopensm/Makefile @@ -0,0 +1,7 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the driver components of the Windows NT DDK +# + +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/libopensm/SOURCES b/branches/WOF2-2/ulp/opensm/user_3_0_0/libopensm/SOURCES new file mode 100644 index 00000000..47350409 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/libopensm/SOURCES @@ -0,0 +1,62 @@ +!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_3_0_0.lib + +!else + $(LIBPATH)\*\ibald.lib \ + $(LIBPATH)\*\complibd.lib \ + $(TARGETPATH)\*\osmv_ibal_3_0_0d.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 +C_DEFINES=$(C_DEFINES) -I.. -DHAVE_CONFIG_H +!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/branches/WOF2-2/ulp/opensm/user_3_0_0/libopensm/osm_helper.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/libopensm/osm_helper.c new file mode 100644 index 00000000..11912fc2 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/libopensm/osm_helper.c @@ -0,0 +1,2534 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_helper.c 1930 2009-02-04 15:26:22Z tzachid $ + */ + + + +/* + * Abstract: + * Implementation of opensm helper functions. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.19 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include + +#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 */ + "UNKNOWN", /* 3D */ + "UNKNOWN", /* 3E */ + "UNKNOWN", /* 3F */ + "UNKNOWN", /* 40 */ + "UNKNOWN", /* 41 */ + "UNKNOWN", /* 42 */ + "UNKNOWN", /* 43 */ + "UNKNOWN", /* 44 */ + "UNKNOWN", /* 45 */ + "UNKNOWN", /* 46 */ + "UNKNOWN", /* 47 */ + "UNKNOWN", /* 48 */ + "UNKNOWN", /* 49 */ + "UNKNOWN", /* 4A */ + "UNKNOWN", /* 4B */ + "UNKNOWN", /* 4C */ + "UNKNOWN", /* 4D */ + "UNKNOWN", /* 4E */ + "UNKNOWN", /* 4F */ + "UNKNOWN", /* 50 */ + "UNKNOWN", /* 51 */ + "UNKNOWN", /* 52 */ + "UNKNOWN", /* 53 */ + "UNKNOWN", /* 54 */ + "UNKNOWN", /* 55 */ + "UNKNOWN", /* 56 */ + "UNKNOWN", /* 57 */ + "UNKNOWN", /* 58 */ + "UNKNOWN", /* 59 */ + "UNKNOWN", /* 5A */ + "UNKNOWN", /* 5B */ + "UNKNOWN", /* 5C */ + "UNKNOWN", /* 5D */ + "UNKNOWN", /* 5E */ + "UNKNOWN", /* 5F */ + "UNKNOWN", /* 60 */ + "UNKNOWN", /* 61 */ + "UNKNOWN", /* 62 */ + "UNKNOWN", /* 63 */ + "UNKNOWN", /* 64 */ + "UNKNOWN", /* 65 */ + "UNKNOWN", /* 66 */ + "UNKNOWN", /* 67 */ + "UNKNOWN", /* 68 */ + "UNKNOWN", /* 69 */ + "UNKNOWN", /* 6A */ + "UNKNOWN", /* 6B */ + "UNKNOWN", /* 6C */ + "UNKNOWN", /* 6D */ + "UNKNOWN", /* 6E */ + "UNKNOWN", /* 6F */ + "UNKNOWN", /* 70 */ + "UNKNOWN", /* 71 */ + "UNKNOWN", /* 72 */ + "UNKNOWN", /* 73 */ + "UNKNOWN", /* 74 */ + "UNKNOWN", /* 75 */ + "UNKNOWN", /* 76 */ + "UNKNOWN", /* 77 */ + "UNKNOWN", /* 78 */ + "UNKNOWN", /* 79 */ + "UNKNOWN", /* 7A */ + "UNKNOWN", /* 7B */ + "UNKNOWN", /* 7C */ + "UNKNOWN", /* 7D */ + "UNKNOWN", /* 7E */ + "UNKNOWN", /* 7F */ + "UNKNOWN", /* 80 */ + "UNKNOWN", /* 81 */ + "UNKNOWN", /* 82 */ + "UNKNOWN", /* 83 */ + "UNKNOWN", /* 84 */ + "UNKNOWN", /* 85 */ + "UNKNOWN", /* 86 */ + "UNKNOWN", /* 87 */ + "UNKNOWN", /* 88 */ + "UNKNOWN", /* 89 */ + "UNKNOWN", /* 8A */ + "UNKNOWN", /* 8B */ + "UNKNOWN", /* 8C */ + "UNKNOWN", /* 8D */ + "UNKNOWN", /* 8E */ + "UNKNOWN", /* 8F */ + "UNKNOWN", /* 90 */ + "UNKNOWN", /* 91 */ + "UNKNOWN", /* 92 */ + "UNKNOWN", /* 93 */ + "UNKNOWN", /* 94 */ + "UNKNOWN", /* 95 */ + "UNKNOWN", /* 96 */ + "UNKNOWN", /* 97 */ + "UNKNOWN", /* 98 */ + "UNKNOWN", /* 99 */ + "UNKNOWN", /* 9A */ + "UNKNOWN", /* 9B */ + "UNKNOWN", /* 9C */ + "UNKNOWN", /* 9D */ + "UNKNOWN", /* 9E */ + "UNKNOWN", /* 9F */ + "UNKNOWN", /* A0 */ + "UNKNOWN", /* A1 */ + "UNKNOWN", /* A2 */ + "UNKNOWN", /* A3 */ + "UNKNOWN", /* A4 */ + "UNKNOWN", /* A5 */ + "UNKNOWN", /* A6 */ + "UNKNOWN", /* A7 */ + "UNKNOWN", /* A8 */ + "UNKNOWN", /* A9 */ + "UNKNOWN", /* AA */ + "UNKNOWN", /* AB */ + "UNKNOWN", /* AC */ + "UNKNOWN", /* AD */ + "UNKNOWN", /* AE */ + "UNKNOWN", /* AF */ + "UNKNOWN", /* B0 */ + "UNKNOWN", /* B1 */ + "UNKNOWN", /* B2 */ + "UNKNOWN", /* B3 */ + "UNKNOWN", /* B4 */ + "UNKNOWN", /* B5 */ + "UNKNOWN", /* B6 */ + "UNKNOWN", /* B7 */ + "UNKNOWN", /* B8 */ + "UNKNOWN", /* B9 */ + "UNKNOWN", /* BA */ + "UNKNOWN", /* BB */ + "UNKNOWN", /* BC */ + "UNKNOWN", /* BD */ + "UNKNOWN", /* BE */ + "UNKNOWN", /* BF */ + "UNKNOWN", /* C0 */ + "UNKNOWN", /* C1 */ + "UNKNOWN", /* C2 */ + "UNKNOWN", /* C3 */ + "UNKNOWN", /* C4 */ + "UNKNOWN", /* C5 */ + "UNKNOWN", /* C6 */ + "UNKNOWN", /* C7 */ + "UNKNOWN", /* C8 */ + "UNKNOWN", /* C9 */ + "UNKNOWN", /* CA */ + "UNKNOWN", /* CB */ + "UNKNOWN", /* CC */ + "UNKNOWN", /* CD */ + "UNKNOWN", /* CE */ + "UNKNOWN", /* CF */ + "UNKNOWN", /* D0 */ + "UNKNOWN", /* D1 */ + "UNKNOWN", /* D2 */ + "UNKNOWN", /* D3 */ + "UNKNOWN", /* D4 */ + "UNKNOWN", /* D5 */ + "UNKNOWN", /* D6 */ + "UNKNOWN", /* D7 */ + "UNKNOWN", /* D8 */ + "UNKNOWN", /* D9 */ + "UNKNOWN", /* DA */ + "UNKNOWN", /* DB */ + "UNKNOWN", /* DC */ + "UNKNOWN", /* DD */ + "UNKNOWN", /* DE */ + "UNKNOWN", /* DF */ + "UNKNOWN", /* E0 */ + "UNKNOWN", /* E1 */ + "UNKNOWN", /* E2 */ + "UNKNOWN", /* E3 */ + "UNKNOWN", /* E4 */ + "UNKNOWN", /* E5 */ + "UNKNOWN", /* E6 */ + "UNKNOWN", /* E7 */ + "UNKNOWN", /* E8 */ + "UNKNOWN", /* E9 */ + "UNKNOWN", /* EA */ + "UNKNOWN", /* EB */ + "UNKNOWN", /* EC */ + "UNKNOWN", /* ED */ + "UNKNOWN", /* EE */ + "UNKNOWN", /* EF */ + "UNKNOWN", /* F0 */ + "UNKNOWN", /* F1 */ + "UNKNOWN", /* F2 */ + "InformInfoRecord", /* F3 */ + "UNKNOWN" /* F4 - always highest value */ +}; + +#define OSM_SA_ATTR_STR_UNKNOWN_VAL 0xF4 + + +/********************************************************************** + **********************************************************************/ +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 response 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, "Capability 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\tclient_reregister.......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_client_rereg( p_pi ), + 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_guidinfo_record( + IN osm_log_t* const p_log, + IN const ib_guidinfo_record_t* const p_gir, + IN const osm_log_level_t log_level ) +{ + const ib_guid_info_t * const p_gi = &p_gir->guid_info; + + if( osm_log_is_active( p_log, log_level ) ) + { + osm_log( p_log, log_level, + "GUIDInfo Record dump:\n" + "\t\t\t\tRID\n" + "\t\t\t\tLid.....................0x%X\n" + "\t\t\t\tBlockNum................0x%X\n" + "\t\t\t\tReserved................0x%X\n" + "\t\t\t\tGUIDInfo dump:\n" + "\t\t\t\tReserved................0x%X\n" + "\t\t\t\tGUID 0..................0x%016" PRIx64 "\n" + "\t\t\t\tGUID 1..................0x%016" PRIx64 "\n" + "\t\t\t\tGUID 2..................0x%016" PRIx64 "\n" + "\t\t\t\tGUID 3..................0x%016" PRIx64 "\n" + "\t\t\t\tGUID 4..................0x%016" PRIx64 "\n" + "\t\t\t\tGUID 5..................0x%016" PRIx64 "\n" + "\t\t\t\tGUID 6..................0x%016" PRIx64 "\n" + "\t\t\t\tGUID 7..................0x%016" PRIx64 "\n", + cl_ntoh16(p_gir->lid), + p_gir->block_num, + p_gir->resv, + cl_ntoh32(p_gir->reserved), + cl_ntoh64(p_gi->guid[0]), + cl_ntoh64(p_gi->guid[1]), + cl_ntoh64(p_gi->guid[2]), + cl_ntoh64(p_gi->guid[3]), + cl_ntoh64(p_gi->guid[4]), + cl_ntoh64(p_gi->guid[5]), + cl_ntoh64(p_gi->guid[6]), + cl_ntoh64(p_gi->guid[7]) + ); + } +} + +/********************************************************************** + **********************************************************************/ +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 ) ) + { + char desc[sizeof(p_nr->node_desc.description) + 1]; + + memcpy(desc, p_nr->node_desc.description, + sizeof(p_nr->node_desc.description)); + desc[sizeof(desc) - 1] = '\0'; + osm_log( p_log, log_level, + "Node Record dump:\n" + "\t\t\t\tRID\n" + "\t\t\t\tLid.....................0x%X\n" + "\t\t\t\tReserved................0x%X\n" + "\t\t\t\tNodeInfo 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" + "\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 )), + desc + ); + } +} + +/********************************************************************** + **********************************************************************/ +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\tservice_id..............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->service_id, + 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->qos_class_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_multipath_record( + IN osm_log_t* const p_log, + IN const ib_multipath_rec_t* const p_mpr, + IN const osm_log_level_t log_level ) +{ + int i; + char buf_line[1024]; + ib_gid_t const *p_gid; + + if( osm_log_is_active( p_log, log_level ) ) + { + memset(buf_line, 0, sizeof(buf_line)); + p_gid = p_mpr->gids; + if ( p_mpr->sgid_count ) + { + for (i = 0; i < p_mpr->sgid_count; i++) + { + sprintf( buf_line, "%s\t\t\t\tsgid%02d.................." + "0x%016" PRIx64 " : 0x%016" PRIx64 "\n", + buf_line, i + 1, cl_ntoh64( p_gid->unicast.prefix ), + cl_ntoh64( p_gid->unicast.interface_id ) ); + p_gid++; + } + } + if ( p_mpr->dgid_count ) + { + for (i = 0; i < p_mpr->dgid_count; i++) + { + sprintf( buf_line, "%s\t\t\t\tdgid%02d.................." + "0x%016" PRIx64 " : 0x%016" PRIx64 "\n", + buf_line, i + 1, cl_ntoh64( p_gid->unicast.prefix ), + cl_ntoh64( p_gid->unicast.interface_id ) ); + p_gid++; + } + } + osm_log( p_log, log_level, + "MultiPath Record dump:\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\tresv0...................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\tresv1...................0x%X\n" + "\t\t\t\tindependence............0x%X\n" + "\t\t\t\tsgid_count..............0x%X\n" + "\t\t\t\tdgid_count..............0x%X\n" + "%s\n" + "", + cl_ntoh32( p_mpr->hop_flow_raw ), + p_mpr->tclass, + p_mpr->num_path, + cl_ntoh16( p_mpr->pkey ), + p_mpr->resv0, + cl_ntoh16( p_mpr->sl ), + p_mpr->mtu, + p_mpr->rate, + p_mpr->pkt_life, + p_mpr->resv1, + p_mpr->independence, + p_mpr->sgid_count, + p_mpr->dgid_count, + buf_line + ); + } +} + +/********************************************************************** + **********************************************************************/ +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\tmtu.....................0x%X\n" + "\t\t\t\tTClass..................0x%X\n" + "\t\t\t\tpkey....................0x%X\n" + "\t\t\t\trate....................0x%X\n" + "\t\t\t\tpkt_life................0x%X\n" + "\t\t\t\tSLFlowLabelHopLimit.....0x%X\n" + "\t\t\t\tScopeState..............0x%X\n" + "\t\t\t\tProxyJoin...............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->mtu, + p_mcmr->tclass, + cl_ntoh16( p_mcmr->pkey ), + p_mcmr->rate, + p_mcmr->pkt_life, + cl_ntoh32( p_mcmr->sl_flow_hop ), + p_mcmr->scope_state, + p_mcmr->proxy_join + ); + } +} + +/********************************************************************** + **********************************************************************/ +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[35]; + char buf_service_name[65]; + + if( osm_log_is_active( p_log, log_level ) ) + { + sprintf(buf_service_key, + "0x%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, + "Service Record 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; + + if( osm_log_is_active( p_log, log_level ) ) + { + + ib_inform_info_get_qpn_resp_time(p_ii->g_or_v.generic.qpn_resp_time_val, + &qpn, &resp_time_val); + + if (p_ii->is_generic) + { + osm_log( p_log, log_level, + "InformInfo dump:\n" + "\t\t\t\tgid.....................0x%016" PRIx64 " : 0x%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................%u\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 " : 0x%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_inform_info_record( + IN osm_log_t* const p_log, + IN const ib_inform_info_record_t* const p_iir, + IN const osm_log_level_t log_level ) +{ + uint32_t qpn; + uint8_t resp_time_val; + + ib_inform_info_get_qpn_resp_time(p_iir->inform_info.g_or_v.generic.qpn_resp_time_val, + &qpn, &resp_time_val); + + if( osm_log_is_active( p_log, log_level ) ) + { + + ib_inform_info_get_qpn_resp_time(p_iir->inform_info.g_or_v.generic.qpn_resp_time_val, + &qpn, &resp_time_val); + + if (p_iir->inform_info.is_generic) + { + osm_log( p_log, log_level, + "InformInfo Record dump:\n" + "\t\t\t\tRID\n" + "\t\t\t\tSubscriberGID...........0x%016" PRIx64 " : " + "0x%016" PRIx64 "\n" + "\t\t\t\tSubscriberEnum..........0x%X\n" + "\t\t\t\tInformInfo dump:\n" + "\t\t\t\tgid.....................0x%016" PRIx64 " : 0x%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................%u\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_iir->subscriber_gid.unicast.prefix ), + cl_ntoh64( p_iir->subscriber_gid.unicast.interface_id ), + cl_ntoh16( p_iir->subscriber_enum ), + cl_ntoh64( p_iir->inform_info.gid.unicast.prefix ), + cl_ntoh64( p_iir->inform_info.gid.unicast.interface_id ), + cl_ntoh16( p_iir->inform_info.lid_range_begin ), + cl_ntoh16( p_iir->inform_info.lid_range_end ), + p_iir->inform_info.is_generic, + p_iir->inform_info.subscribe, + cl_ntoh16( p_iir->inform_info.trap_type ), + cl_ntoh16( p_iir->inform_info.g_or_v.generic.trap_num ), + cl_ntoh32(qpn), + resp_time_val, + cl_ntoh32(ib_inform_info_get_node_type( &p_iir->inform_info )) + ); + } + else + { + osm_log( p_log, log_level, + "InformInfo Record dump:\n" + "\t\t\t\tRID\n" + "\t\t\t\tSubscriberGID...........0x%016" PRIx64 " : " + "0x%016" PRIx64 "\n" + "\t\t\t\tSubscriberEnum..........0x%X\n" + "\t\t\t\tInformInfo dump:\n" + "\t\t\t\tgid.....................0x%016" PRIx64 " : 0x%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_iir->subscriber_gid.unicast.prefix ), + cl_ntoh64( p_iir->subscriber_gid.unicast.interface_id ), + cl_ntoh16( p_iir->subscriber_enum ), + cl_ntoh64( p_iir->inform_info.gid.unicast.prefix ), + cl_ntoh64( p_iir->inform_info.gid.unicast.interface_id ), + cl_ntoh16( p_iir->inform_info.lid_range_begin ), + cl_ntoh16( p_iir->inform_info.lid_range_end ), + p_iir->inform_info.is_generic, + p_iir->inform_info.subscribe, + cl_ntoh16( p_iir->inform_info.trap_type ), + cl_ntoh16( p_iir->inform_info.g_or_v.vend.dev_id ), + cl_ntoh32(qpn), + resp_time_val, + cl_ntoh32(ib_inform_info_get_node_type( &p_iir->inform_info )) + ); + } + } +} + +/********************************************************************** + **********************************************************************/ +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, + "Link Record 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\tpartition_enf_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_switch_info_record( + IN osm_log_t* const p_log, + IN const ib_switch_info_record_t* const p_sir, + IN const osm_log_level_t log_level ) +{ + if( osm_log_is_active( p_log, log_level ) ) + { + osm_log( p_log, log_level, + "SwitchInfo Record dump:\n" + "\t\t\t\tRID\n" + "\t\t\t\tlid.....................0x%X\n" + "\t\t\t\tSwitchInfo 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\tpartition_enf_cap.......0x%X\n" + "\t\t\t\tflags...................0x%X\n" + "", + cl_ntoh16( p_sir->lid ), + cl_ntoh16( p_sir->switch_info.lin_cap ), + cl_ntoh16( p_sir->switch_info.rand_cap ), + cl_ntoh16( p_sir->switch_info.mcast_cap ), + cl_ntoh16( p_sir->switch_info.lin_top ), + p_sir->switch_info.def_port, + p_sir->switch_info.def_mcast_pri_port, + p_sir->switch_info.def_mcast_not_port, + p_sir->switch_info.life_state, + cl_ntoh16( p_sir->switch_info.lids_per_port ), + cl_ntoh16( p_sir->switch_info.enforce_cap ), + p_sir->switch_info.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_sm_info_record( + IN osm_log_t* const p_log, + IN const ib_sminfo_record_t* const p_smir, + IN const osm_log_level_t log_level ) +{ + if( osm_log_is_active( p_log, log_level ) ) + { + osm_log( p_log, OSM_LOG_DEBUG, + "SMInfo Record dump:\n" + "\t\t\t\tRID\n" + "\t\t\t\tLid.....................0x%X\n" + "\t\t\t\tReserved................0x%X\n" + "\t\t\t\tSMInfo 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_ntoh16( p_smir->lid ), + cl_ntoh16( p_smir->resv0 ), + cl_ntoh64( p_smir->sm_info.guid ), + cl_ntoh64( p_smir->sm_info.sm_key ), + cl_ntoh32( p_smir->sm_info.act_count ), + ib_sminfo_get_priority( &p_smir->sm_info ), + ib_sminfo_get_state( &p_smir->sm_info ) + ); + } +} + +/********************************************************************** + **********************************************************************/ +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", + 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) + ); + strcat( buf, line ); + + if (p_smp->mgmt_class == IB_MCLASS_SUBN_DIR) + { + sprintf( line, + "\t\t\t\tdr_slid.................0x%X\n" + "\t\t\t\tdr_dlid.................0x%X\n", + cl_ntoh16(p_smp->dr_slid), + cl_ntoh16(p_smp->dr_dlid) + ); + strcat( buf, line ); + + 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 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", /* 22 */ + "OSM_SM_STATE_SET_ARMED_WAIT", /* 23 */ + "OSM_SM_STATE_SET_ARMED_DONE", /* 24 */ + "OSM_SM_STATE_SET_ACTIVE", /* 25 */ + "OSM_SM_STATE_SET_ACTIVE_WAIT", /* 26 */ + "OSM_SM_STATE_LOST_NEGOTIATION", /* 27 */ + "OSM_SM_STATE_STANDBY", /* 28 */ + "OSM_SM_STATE_SUBNET_UP", /* 29 */ + "OSM_SM_STATE_PROCESS_REQUEST", /* 30 */ + "OSM_SM_STATE_PROCESS_REQUEST_WAIT", /* 31 */ + "OSM_SM_STATE_PROCESS_REQUEST_DONE", /* 32 */ + "OSM_SM_STATE_MASTER_OR_HIGHER_SM_DETECTED",/* 33 */ + "OSM_SM_STATE_SET_PKEY", /* 34 */ + "OSM_SM_STATE_SET_PKEY_WAIT", /* 35 */ + "OSM_SM_STATE_SET_PKEY_DONE", /* 36 */ + "UNKNOWN STATE!!" /* 37 */ +}; + +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", + "OSM_MSG_MAD_GUIDINFO_RECORD", + "OSM_MSG_MAD_INFORM_INFO_RECORD", +#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP) + "OSM_MSG_MAD_MULTIPATH_RECORD", +#endif + "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] ); +} + +/********************************************************************** + **********************************************************************/ +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* yotta_str = "YottaYotta "; + static const char* pathscale_str = "PathScale "; + static const char* ibm_str = "IBM "; + static const char* divergenet_str = "DivergeNet "; + static const char* flextronics_str = "Flextronics"; + static const char* agilent_str = "Agilent "; + static const char* obsidian_str = "Obsidian "; + static const char* baymicro_str = "BayMicro "; + static const char* lsilogic_str = "LSILogic "; + static const char* ddn_str = "DataDirect "; + static const char* panta_str = "Panta "; + static const char* hp_str = "HP "; + static const char* rioworks_str = "Rioworks "; + 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 ); + case OSM_VENDOR_ID_YOTTAYOTTA: + return( yotta_str ); + case OSM_VENDOR_ID_PATHSCALE: + return( pathscale_str ); + case OSM_VENDOR_ID_IBM: + return( ibm_str ); + case OSM_VENDOR_ID_DIVERGENET: + return( divergenet_str ); + case OSM_VENDOR_ID_FLEXTRONICS: + return( flextronics_str ); + case OSM_VENDOR_ID_AGILENT: + return( agilent_str ); + case OSM_VENDOR_ID_OBSIDIAN: + return( obsidian_str ); + case OSM_VENDOR_ID_BAYMICRO: + return( baymicro_str ); + case OSM_VENDOR_ID_LSILOGIC: + return( lsilogic_str ); + case OSM_VENDOR_ID_DDN: + return( ddn_str ); + case OSM_VENDOR_ID_PANTA: + return( panta_str ); + case OSM_VENDOR_ID_HP: + return( hp_str ); + case OSM_VENDOR_ID_RIOWORKS: + return( rioworks_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/branches/WOF2-2/ulp/opensm/user_3_0_0/libopensm/osm_log.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/libopensm/osm_log.c new file mode 100644 index 00000000..c62f926f --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/libopensm/osm_log.c @@ -0,0 +1,327 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_log.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementaion of osm_log_t. + * This object represents the log file. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.8 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static int log_exit_count = 0; + +#ifndef WIN32 +#include +#include +#include + +static char *month_str[] = { + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec" +}; +#else +void +OsmReportState( + IN const char *p_str); +#endif /* ndef WIN32 */ + +#ifndef WIN32 + +static void truncate_log_file(osm_log_t* const p_log) +{ + int fd = fileno(p_log->out_port); + if (ftruncate(fd, 0) < 0) + fprintf(stderr, "truncate_log_file: cannot truncate: %s\n", + strerror(errno)); + if (lseek(fd, 0, SEEK_SET) < 0) + fprintf(stderr, "truncate_log_file: cannot rewind: %s\n", + strerror(errno)); + p_log->count = 0; +} + +#else /* Windows */ + +static void truncate_log_file(osm_log_t* const p_log) +{ + fprintf(stderr, "truncate_log_file: cannot truncate on windows system (yet)\n"); +} +#endif /* ndef WIN32 */ + +int osm_log_printf(osm_log_t *p_log, osm_log_level_t level, + const char *fmt, ...) +{ + va_list args; + int ret; + + if (!(p_log->level&level)) + return 0; + + va_start(args, fmt); + ret = vfprintf(stdout, fmt, args); + va_end(args); + + if (p_log->flush || level&OSM_LOG_ERROR) + fflush( stdout ); + + return ret; +} + +void +osm_log( + IN osm_log_t* const p_log, + IN const osm_log_level_t verbosity, + IN const char *p_str, ... ) +{ + char buffer[LOG_ENTRY_SIZE_MAX]; + va_list args; + int ret; + +#ifdef WIN32 + SYSTEMTIME st; + uint32_t pid = GetCurrentThreadId(); +#else + pid_t pid = 0; + time_t tim; + struct tm result; + uint64_t time_usecs; + uint32_t usecs; + + time_usecs = cl_get_time_stamp(); + tim = time_usecs/1000000; + usecs = time_usecs % 1000000; + localtime_r(&tim, &result); +#endif /* WIN32 */ + + /* If this is a call to syslog - always print it */ + if ( verbosity & (OSM_LOG_SYS | p_log->level) ) + { + va_start( args, p_str ); + vsprintf( buffer, p_str, args ); + va_end(args); + + /* this is a call to the syslog */ + if (verbosity & OSM_LOG_SYS) + { + cl_log_event("OpenSM", LOG_INFO, buffer , NULL, 0); + + /* SYSLOG should go to stdout too */ + if (p_log->out_port != stdout) + { + printf("%s\n", buffer); + fflush( stdout ); + } +#ifdef WIN32 + OsmReportState(buffer); +#endif /* WIN32 */ + } + + /* regular log to default out_port */ + cl_spinlock_acquire( &p_log->lock ); + + if (p_log->max_size && p_log->count > p_log->max_size) + { + /* truncate here */ + fprintf(stderr, "osm_log: log file exceeds the limit %lu. Truncating.\n", + p_log->max_size); + truncate_log_file(p_log); + } + +#ifdef WIN32 + GetLocalTime(&st); + _retry: + ret = fprintf( p_log->out_port, "[%02d:%02d:%02d:%03d][%04X] -> %s", + st.wHour, st.wMinute, st.wSecond, st.wMilliseconds, + pid, buffer ); +#else + pid = pthread_self(); + _retry: + ret = fprintf( p_log->out_port, "%s %02d %02d:%02d:%02d %06d [%04X] -> %s", + (result.tm_mon < 12 ? month_str[result.tm_mon] : "???"), + result.tm_mday, result.tm_hour, + result.tm_min, result.tm_sec, + usecs, pid, buffer ); +#endif + + /* flush log */ + if (ret > 0 && (p_log->flush || (verbosity & OSM_LOG_ERROR)) && + fflush( p_log->out_port ) < 0) + ret = -1; + + if (ret >= 0) + { + log_exit_count = 0; + p_log->count += ret; + } + else if (log_exit_count < 3) + { + log_exit_count++; + if (errno == ENOSPC && p_log->max_size) { + fprintf(stderr, "osm_log: write failed: %s. Truncating log file.\n", + strerror(errno)); + truncate_log_file(p_log); + goto _retry; + } + fprintf(stderr, "osm_log: write failed: %s\n", strerror(errno)); + } + + cl_spinlock_release( &p_log->lock ); + } +} + +void +osm_log_raw( + IN osm_log_t* const p_log, + IN const osm_log_level_t verbosity, + IN const char *p_buf ) +{ + if( p_log->level & verbosity ) + { + cl_spinlock_acquire( &p_log->lock ); + printf( "%s", p_buf ); + cl_spinlock_release( &p_log->lock ); + + /* + Flush log on errors too. + */ + if( p_log->flush || (verbosity & OSM_LOG_ERROR) ) + fflush( stdout ); + } +} + +boolean_t +osm_is_debug(void) +{ +#if defined( _DEBUG_ ) + return TRUE; +#else + return FALSE; +#endif /* defined( _DEBUG_ ) */ +} + +ib_api_status_t +osm_log_init_v2( + IN osm_log_t* const p_log, + IN const boolean_t flush, + IN const uint8_t log_flags, + IN const char *log_file, + IN const unsigned long max_size, + IN const boolean_t accum_log_file ) +{ + struct stat st; + + p_log->level = log_flags; + p_log->flush = flush; + p_log->count = 0; + p_log->max_size = 0; + + if (log_file == NULL || !strcmp(log_file, "-") || + !strcmp(log_file, "stdout")) + { + p_log->out_port = stdout; + } + else if (!strcmp(log_file, "stderr")) + { + p_log->out_port = stderr; + } + else + { + if (accum_log_file) + p_log->out_port = fopen(log_file, "a+"); + else + p_log->out_port = fopen(log_file, "w+"); + + if (!p_log->out_port) + { + if (accum_log_file) + printf("Cannot open %s for appending. Permission denied\n", log_file); + else + printf("Cannot open %s for writing. Permission denied\n", log_file); + + return(IB_UNKNOWN_ERROR); + } + + if (fstat(fileno(p_log->out_port), &st) == 0) + p_log->count = st.st_size; + + p_log->max_size = max_size; + } + + openlog("OpenSM", LOG_CONS | LOG_PID, LOG_USER); + + if (cl_spinlock_init( &p_log->lock ) == CL_SUCCESS) + return IB_SUCCESS; + else + return IB_ERROR; +} + +ib_api_status_t +osm_log_init( + IN osm_log_t* const p_log, + IN const boolean_t flush, + IN const uint8_t log_flags, + IN const char *log_file, + IN const boolean_t accum_log_file ) +{ + return osm_log_init_v2( p_log, flush, log_flags, log_file, 0, accum_log_file ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/libopensm/osm_mad_pool.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/libopensm/osm_mad_pool.c new file mode 100644 index 00000000..d648cfee --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/libopensm/osm_mad_pool.c @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_mad_pool.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_mad_pool_t. + * This object represents a pool of management datagram (MAD) objects. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include + +#define OSM_MAD_POOL_MIN_SIZE 256 +#define OSM_MAD_POOL_GROW_SIZE 256 + + +/********************************************************************** + **********************************************************************/ +cl_status_t +__osm_mad_pool_ctor( + IN void* const p_object, + IN void* context, + OUT cl_pool_item_t** const pp_pool_item ) +{ + osm_madw_t *p_madw = p_object; + + UNUSED_PARAM( context ); + osm_madw_construct( p_madw ); + /* CHECK THIS. DOCS DON'T DESCRIBE THIS OUT PARAM. */ + *pp_pool_item = &p_madw->pool_item; + return( CL_SUCCESS ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_mad_pool_construct( + IN osm_mad_pool_t* const p_pool ) +{ + CL_ASSERT( p_pool ); + + memset( p_pool, 0, sizeof(*p_pool) ); + cl_qlock_pool_construct( &p_pool->madw_pool ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_mad_pool_destroy( + IN osm_mad_pool_t* const p_pool ) +{ + CL_ASSERT( p_pool ); + + /* HACK: we still rarely see some mads leaking - so ignore this */ + /* cl_qlock_pool_destroy( &p_pool->madw_pool ); */ +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_mad_pool_init( + IN osm_mad_pool_t* const p_pool, + IN osm_log_t* const p_log ) +{ + ib_api_status_t status; + + OSM_LOG_ENTER( p_log, osm_mad_pool_init ); + + p_pool->p_log = p_log; + + status = cl_qlock_pool_init( + &p_pool->madw_pool, + OSM_MAD_POOL_MIN_SIZE, + 0, + OSM_MAD_POOL_GROW_SIZE, + sizeof( osm_madw_t ), + __osm_mad_pool_ctor, + NULL, + p_pool ); + if( status != IB_SUCCESS ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_mad_pool_init: ERR 0702: " + "Grow pool initialization failed (%s)\n", + ib_get_err_str(status) ); + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +osm_madw_t* +osm_mad_pool_get( + IN osm_mad_pool_t* const p_pool, + IN osm_bind_handle_t h_bind, + IN const uint32_t total_size, + IN const osm_mad_addr_t* const p_mad_addr ) +{ + osm_madw_t *p_madw; + ib_mad_t *p_mad; + + OSM_LOG_ENTER( p_pool->p_log, osm_mad_pool_get ); + + CL_ASSERT( h_bind != OSM_BIND_INVALID_HANDLE ); + CL_ASSERT( total_size ); + + /* + First, acquire a mad wrapper from the mad wrapper pool. + */ + p_madw = (osm_madw_t*)cl_qlock_pool_get( &p_pool->madw_pool ); + if( p_madw == NULL ) + { + osm_log( p_pool->p_log, OSM_LOG_ERROR, + "osm_mad_pool_get: ERR 0703: " + "Unable to acquire MAD wrapper object\n" ); + goto Exit; + } + + osm_madw_init( p_madw, h_bind, total_size, p_mad_addr ); + + /* + Next, acquire a wire mad of the specified size. + */ + p_mad = osm_vendor_get( h_bind, total_size, &p_madw->vend_wrap ); + if( p_mad == NULL ) + { + osm_log( p_pool->p_log, OSM_LOG_ERROR, + "osm_mad_pool_get: ERR 0704: " + "Unable to acquire wire MAD\n" ); + + /* Don't leak wrappers! */ + cl_qlock_pool_put( &p_pool->madw_pool, (cl_pool_item_t*)p_madw ); + p_madw = NULL; + goto Exit; + } + + cl_atomic_inc( &p_pool->mads_out ); + /* + Finally, attach the wire MAD to this wrapper. + */ + osm_madw_set_mad( p_madw, p_mad ); + + osm_log( p_pool->p_log, OSM_LOG_DEBUG, + "osm_mad_pool_get: Acquired p_madw = %p, p_mad = %p, " + "size = %u\n", p_madw, p_madw->p_mad, total_size ); + + Exit: + OSM_LOG_EXIT( p_pool->p_log ); + return( p_madw ); +} + +/********************************************************************** + **********************************************************************/ +osm_madw_t* +osm_mad_pool_get_wrapper( + IN osm_mad_pool_t* const p_pool, + IN osm_bind_handle_t h_bind, + IN const uint32_t total_size, + IN const ib_mad_t* const p_mad, + IN const osm_mad_addr_t* const p_mad_addr ) +{ + osm_madw_t *p_madw; + + OSM_LOG_ENTER( p_pool->p_log, osm_mad_pool_get_wrapper ); + + CL_ASSERT( h_bind != OSM_BIND_INVALID_HANDLE ); + CL_ASSERT( total_size ); + CL_ASSERT( p_mad ); + + /* + First, acquire a mad wrapper from the mad wrapper pool. + */ + p_madw = (osm_madw_t*)cl_qlock_pool_get( &p_pool->madw_pool ); + if( p_madw == NULL ) + { + osm_log( p_pool->p_log, OSM_LOG_ERROR, + "osm_mad_pool_get_wrapper: ERR 0705: " + "Unable to acquire MAD wrapper object\n" ); + goto Exit; + } + + /* + Finally, initialize the wrapper object. + */ + cl_atomic_inc( &p_pool->mads_out ); + osm_madw_init( p_madw, h_bind, total_size, p_mad_addr ); + osm_madw_set_mad( p_madw, p_mad ); + + osm_log( p_pool->p_log, OSM_LOG_DEBUG, + "osm_mad_pool_get_wrapper: Acquired p_madw = %p, p_mad = %p " + "size = %u\n", p_madw, p_madw->p_mad, total_size ); + + Exit: + OSM_LOG_EXIT( p_pool->p_log ); + return( p_madw ); +} + +/********************************************************************** + **********************************************************************/ +osm_madw_t* +osm_mad_pool_get_wrapper_raw( + IN osm_mad_pool_t* const p_pool ) +{ + osm_madw_t *p_madw; + + OSM_LOG_ENTER( p_pool->p_log, osm_mad_pool_get_wrapper_raw ); + + p_madw = (osm_madw_t*)cl_qlock_pool_get( &p_pool->madw_pool ); + + osm_log( p_pool->p_log, OSM_LOG_DEBUG, + "osm_mad_pool_get_wrapper_raw: " + "Getting p_madw = %p\n", p_madw ); + + osm_madw_init( p_madw, 0, 0, 0 ); + osm_madw_set_mad( p_madw, 0 ); + cl_atomic_inc( &p_pool->mads_out ); + + OSM_LOG_EXIT( p_pool->p_log ); + return( p_madw ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_mad_pool_put( + IN osm_mad_pool_t* const p_pool, + IN osm_madw_t* const p_madw ) +{ + OSM_LOG_ENTER( p_pool->p_log, osm_mad_pool_put ); + + CL_ASSERT( p_madw ); + + osm_log( p_pool->p_log, OSM_LOG_DEBUG, + "osm_mad_pool_put: Releasing p_madw = %p, p_mad = %p\n", + p_madw, p_madw->p_mad ); + + /* + First, return the wire mad to the pool + */ + if( p_madw->p_mad ) + osm_vendor_put( p_madw->h_bind, &p_madw->vend_wrap ); + + /* + Return the mad wrapper to the wrapper pool + */ + cl_qlock_pool_put( &p_pool->madw_pool, (cl_pool_item_t*)p_madw ); + cl_atomic_dec( &p_pool->mads_out ); + + OSM_LOG_EXIT( p_pool->p_log ); +} + + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/libvendor/Makefile b/branches/WOF2-2/ulp/opensm/user_3_0_0/libvendor/Makefile new file mode 100644 index 00000000..58189757 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/libvendor/Makefile @@ -0,0 +1,7 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the driver components of the Windows NT DDK +# + +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/libvendor/SOURCES b/branches/WOF2-2/ulp/opensm/user_3_0_0/libvendor/SOURCES new file mode 100644 index 00000000..6c23c9d7 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/libvendor/SOURCES @@ -0,0 +1,60 @@ +!if $(FREEBUILD) +TARGETNAME=osmv_ibal_3_0_0 +!else +TARGETNAME=osmv_ibal_3_0_0d +!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 +USE_NATIVE_EH=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 +!else + $(LIBPATH)\*\ibald.lib \ + $(LIBPATH)\*\complibd.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) +#Add preproccessor definitions +C_DEFINES=$(C_DEFINES) -DWIN32 -D__WIN__ -D__i386__ -Dinline=__inline -DMT_LITTLE_ENDIAN -DOSM_VENDOR_INTF_AL +C_DEFINES=$(C_DEFINES) -I.. -DHAVE_CONFIG_H +!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/branches/WOF2-2/ulp/opensm/user_3_0_0/libvendor/osm_vendor_al.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/libvendor/osm_vendor_al.c new file mode 100644 index 00000000..e683b05b --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/libvendor/osm_vendor_al.c @@ -0,0 +1,1533 @@ +/* + * 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. + * Portions Copyright (c) 2008 Microsoft Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_vendor_al.c 1375 2008-07-13 08:55:53Z leonidk $ + */ + + +/* + * 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 + +#ifdef OSM_VENDOR_INTF_AL + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/****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 ); + osm_log( p_vend->p_log, OSM_LOG_DEBUG, + "__osm_al_rcv_callback: " + "Acquired implicitly MAD %p.\n", p_new_mad ); + + /* + 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 ) ) + { + /* + The acquiring was done in the ib_get_mad_buf function. + If this is a request - then we impllicitly allocate the MAD. + In this case - it was allocated in the lower layer. The message + is for tracking down messages - locate how/where this mad was + allocated. + */ + 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, + (uint32_t*)&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 ); + /* convert lid to host order */ + p_attr_array[port_count].lid = cl_ntoh16(p_attr_array[port_count].lid); + 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; + + 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 ); + + /* + 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 ) + { + 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 ) ); + cl_free( p_bind ); + p_bind = 0; + 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 ) + { + 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 ) ); + cl_free( p_bind ); + p_bind = 0; + 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 ) ); + + cl_free( p_bind ); + p_bind = 0; + 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: " + "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; + + OSM_LOG_ENTER( p_vend->p_log, osm_vendor_local_lid_change ); + + OSM_LOG_EXIT( p_vend->p_log ); + return( IB_SUCCESS ); +} + +/********************************************************************** + **********************************************************************/ +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/branches/WOF2-2/ulp/opensm/user_3_0_0/libvendor/osm_vendor_mlx_sa.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/libvendor/osm_vendor_mlx_sa.c new file mode 100644 index 00000000..6ba5888e --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/libvendor/osm_vendor_mlx_sa.c @@ -0,0 +1,879 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_vendor_mlx_sa.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include + + +/***************************************************************************** + *****************************************************************************/ + +/* this struct is the internal rep of the bind handle */ +typedef struct _osmv_sa_bind_info { + osm_bind_handle_t h_bind; + osm_log_t *p_log; + osm_vendor_t *p_vendor; + osm_mad_pool_t *p_mad_pool; + uint64_t port_guid; + cl_event_t sync_event; + uint64_t last_lids_update_sec; + uint16_t lid; + uint16_t sm_lid; +} osmv_sa_bind_info_t; + +/***************************************************************************** + *****************************************************************************/ + +/* + Call back on new mad received: + + We basically only need to set the context of the query. + Or report an error. + + A pointer to the actual context of the request (a copy of the oriignal + request structure) is attached as the p_madw->context.ni_context.node_guid +*/ +void +__osmv_sa_mad_rcv_cb( + IN osm_madw_t *p_madw, + IN void* bind_context, + IN osm_madw_t *p_req_madw) +{ + osmv_sa_bind_info_t *p_bind = (osmv_sa_bind_info_t *)bind_context; + osmv_query_req_t *p_query_req_copy = NULL; + osmv_query_res_t query_res; + ib_sa_mad_t *p_sa_mad; + ib_net16_t mad_status; + + OSM_LOG_ENTER( p_bind->p_log, __osmv_sa_mad_rcv_cb ); + + if (! p_req_madw) + { + osm_log( p_bind->p_log, OSM_LOG_DEBUG, + "__osmv_sa_mad_rcv_cb: " + "Ignoring a non-response mad\n"); + osm_mad_pool_put(p_bind->p_mad_pool, p_madw); + goto Exit; + } + + /* obtain the sent context */ + p_query_req_copy = + (osmv_query_req_t *)(p_req_madw->context.arb_context.context1); + + /* provide the context of the original request in the result */ + query_res.query_context = p_query_req_copy->query_context; + + /* provide the resulting madw */ + query_res.p_result_madw = p_madw; + + /* update the req fields */ + p_sa_mad = ( ib_sa_mad_t * ) p_madw->p_mad; + + /* if we got a remote error track it in the status */ + mad_status = ( ib_net16_t ) ( p_sa_mad->status & IB_SMP_STATUS_MASK ); + if (mad_status != IB_SUCCESS) + { + osm_log( p_bind->p_log, OSM_LOG_ERROR, + "__osmv_sa_mad_rcv_cb: ERR 0501: " + "Remote error:0x%04X .\n", mad_status + ); + query_res.status = IB_REMOTE_ERROR; + } + else + { + query_res.status = IB_SUCCESS; + } + + /* what if we have got back an empty mad ? */ + if (! p_madw->mad_size) + { + osm_log( p_bind->p_log, OSM_LOG_ERROR, + "__osmv_sa_mad_rcv_cb: ERR 0502: " + "Got an empty mad.\n" + ); + query_res.status = IB_ERROR; + } + + if (IB_SUCCESS == mad_status) + { + + /* if we are in not in a method response of an rmpp nature we must get only 1 */ + /* HACK: in the future we might need to be smarter for other methods... */ + if (p_sa_mad->method != IB_MAD_METHOD_GETTABLE_RESP) + { + query_res.result_cnt = 1; + } + else + { +#ifndef VENDOR_RMPP_SUPPORT + if (mad_status != IB_SUCCESS) + query_res.result_cnt = 0; + else + query_res.result_cnt = 1; +#else + /* we used the offset value to calculate the number of + records in here */ + query_res.result_cnt = + (uintn_t) + ( ( p_madw->mad_size - IB_SA_MAD_HDR_SIZE ) / + ib_get_attr_size( p_sa_mad->attr_offset ) ); + osm_log( p_bind->p_log, OSM_LOG_DEBUG, + "__osmv_sa_mad_rcv_cb: Count = %u = %u / %u (%u)\n", + query_res.result_cnt, p_madw->mad_size - IB_SA_MAD_HDR_SIZE, + ib_get_attr_size( p_sa_mad->attr_offset ), + ( p_madw->mad_size - IB_SA_MAD_HDR_SIZE ) % + ib_get_attr_size( p_sa_mad->attr_offset ) + ); +#endif + } + } + + query_res.query_type = p_query_req_copy->query_type; + + p_query_req_copy->pfn_query_cb( &query_res ); + + if ((p_query_req_copy->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC) + cl_event_signal( &p_bind->sync_event ); + + Exit: + + /* free the copied query request if found */ + if (p_query_req_copy) free(p_query_req_copy); + + /* put back the request madw */ + if (p_req_madw) + osm_mad_pool_put(p_bind->p_mad_pool, p_req_madw); + + OSM_LOG_EXIT( p_bind->p_log ); +} + +/***************************************************************************** + ****************************************************************************/ +/* + Send Error Callback: + + Only report the error and get rid of the mad wrapper +*/ +void +__osmv_sa_mad_err_cb( + IN void* bind_context, + IN osm_madw_t *p_madw) +{ + osmv_sa_bind_info_t *p_bind = (osmv_sa_bind_info_t *)bind_context; + osmv_query_req_t *p_query_req_copy = NULL; + osmv_query_res_t query_res; + + OSM_LOG_ENTER( p_bind->p_log, __osmv_sa_mad_err_cb ); + + /* Obtain the sent context etc */ + p_query_req_copy = + (osmv_query_req_t *)(p_madw->context.arb_context.context1); + + /* provide the context of the original request in the result */ + query_res.query_context = p_query_req_copy->query_context; + + query_res.p_result_madw = p_madw; + + query_res.status = IB_TIMEOUT; + query_res.result_cnt = 0; + query_res.p_result_madw->status = IB_TIMEOUT; + p_madw->status = IB_TIMEOUT; + query_res.query_type = p_query_req_copy->query_type; + + p_query_req_copy->pfn_query_cb( &query_res ); + + if ((p_query_req_copy->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC) + cl_event_signal( &p_bind->sync_event ); + + if (p_query_req_copy) free(p_query_req_copy); + OSM_LOG_EXIT( p_bind->p_log ); +} + +/***************************************************************************** + This routine needs to be invoked on every send - since the SM LID and Local + lid might change. To do that without any major perfoermance impact we cache + the results and time they were obtained. Refresh only twice a minute. + To avoid the need to use statics and risk a race - we require the refresh time + to be stored in the context of the results. Also this coveres cases were + we query for multiple guids. + *****************************************************************************/ +ib_api_status_t +__osmv_get_lid_and_sm_lid_by_port_guid( + IN osm_vendor_t* const p_vend, + IN ib_net64_t port_guid, + IN OUT uint64_t* p_lids_update_time_sec, + OUT uint16_t* lid, + OUT uint16_t* sm_lid) +{ + + ib_api_status_t status; + ib_port_attr_t *p_attr_array; + uint32_t num_ports; + uint32_t port_num; + + OSM_LOG_ENTER( p_vend->p_log, __osmv_get_lid_and_sm_lid_by_port_guid ); + + /* use prevous values if current time is close enough to previous query */ + if (cl_get_time_stamp_sec() <= *p_lids_update_time_sec + 30) + { + osm_log( p_vend->p_log, OSM_LOG_DEBUG, + "__osmv_get_lid_and_sm_lid_by_port_guid: " + "Using previously stored lid:0x%04x sm_lid:0x%04x\n", + *lid, *sm_lid + ); + status = IB_SUCCESS; + goto Exit; + } + + /* obtain the number of available ports */ + num_ports = 0; + status = osm_vendor_get_all_port_attr(p_vend, NULL, &num_ports); + if (status != IB_INSUFFICIENT_MEMORY) + { + osm_log( p_vend->p_log, OSM_LOG_ERROR, + "__osmv_get_lid_and_sm_lid_by_port_guid: ERR 0503: " + "expected to get the IB_INSUFFICIENT_MEMORY but got: %s\n", + ib_get_err_str(status) + ); + status = IB_ERROR; + goto Exit; + } + + osm_log( p_vend->p_log, OSM_LOG_DEBUG, + "__osmv_get_lid_and_sm_lid_by_port_guid: " + "Found total of %u ports. Looking for guid:0x%016" PRIx64 "\n", + num_ports, cl_ntoh64(port_guid) + ); + + /* allocate the attributes */ + p_attr_array = + (ib_port_attr_t *)malloc(sizeof(ib_port_attr_t)*num_ports); + + /* obtain the attributes */ + status = osm_vendor_get_all_port_attr(p_vend, p_attr_array, &num_ports); + if (status != IB_SUCCESS) + { + osm_log( p_vend->p_log, OSM_LOG_ERROR, + "__osmv_get_lid_and_sm_lid_by_port_guid: ERR 0504: " + "Fail to get port attributes (error: %s)\n", + ib_get_err_str(status) + ); + free(p_attr_array); + goto Exit; + } + + status = IB_ERROR; + /* find the port requested in the list */ + for (port_num = 0; (port_nump_log, OSM_LOG_DEBUG, + "__osmv_get_lid_and_sm_lid_by_port_guid: " + "Found guid:0x%016" PRIx64 " with idx:%d\n", + cl_ntoh64(port_guid), port_num); + } + } + + free(p_attr_array); + + Exit: + OSM_LOG_EXIT( p_vend->p_log ); + return ( status ); +} + +/***************************************************************************** + *****************************************************************************/ +osm_bind_handle_t +osmv_bind_sa( + IN osm_vendor_t* const p_vend, + IN osm_mad_pool_t* const p_mad_pool, + IN ib_net64_t port_guid + ) +{ + osm_bind_info_t bind_info; + osm_log_t *p_log = p_vend->p_log; + ib_api_status_t status = IB_SUCCESS; + osmv_sa_bind_info_t *p_sa_bind_info; + cl_status_t cl_status; + + OSM_LOG_ENTER( p_log, osmv_bind_sa ); + + osm_log( p_log, OSM_LOG_DEBUG, + "osmv_bind_sa: " + "Binding to port 0x%" PRIx64 ".\n", + cl_ntoh64( port_guid ) ); + + bind_info.port_guid = port_guid; + bind_info.mad_class = IB_MCLASS_SUBN_ADM; + bind_info.class_version = 2; + bind_info.is_responder = TRUE; + bind_info.is_trap_processor = FALSE; + bind_info.is_report_processor = TRUE; + bind_info.send_q_size = 256; + bind_info.recv_q_size = 256; + + /* allocate the new sa bind info */ + p_sa_bind_info = + (osmv_sa_bind_info_t *)malloc(sizeof(osmv_sa_bind_info_t)); + if (! p_sa_bind_info) + { + osm_log( p_log, OSM_LOG_ERROR, + "osmv_bind_sa: ERR 0505: " + "Fail to allocate new bidn structure\n" ); + p_sa_bind_info = OSM_BIND_INVALID_HANDLE; + goto Exit; + } + + /* store some important context */ + p_sa_bind_info->p_log = p_log; + p_sa_bind_info->port_guid = port_guid; + p_sa_bind_info->p_mad_pool = p_mad_pool; + p_sa_bind_info->p_vendor = p_vend; + p_sa_bind_info->last_lids_update_sec = 0; + + /* Bind to the lower level */ + p_sa_bind_info->h_bind = + osm_vendor_bind( p_vend, + &bind_info, + p_mad_pool, + __osmv_sa_mad_rcv_cb, + __osmv_sa_mad_err_cb, + p_sa_bind_info); /* context provided to CBs */ + + if (p_sa_bind_info->h_bind == OSM_BIND_INVALID_HANDLE) + { + free(p_sa_bind_info); + p_sa_bind_info = OSM_BIND_INVALID_HANDLE; + osm_log( p_log, OSM_LOG_ERROR, + "osmv_bind_sa: ERR 0506: " + "Fail to bind to vendor SMI.\n" ); + goto Exit; + } + + /* obtain the sm_lid from the vendor */ + status = + __osmv_get_lid_and_sm_lid_by_port_guid( + p_vend, port_guid, + &p_sa_bind_info->last_lids_update_sec, + &p_sa_bind_info->lid, + &p_sa_bind_info->sm_lid); + if (status != IB_SUCCESS) + { + free(p_sa_bind_info); + p_sa_bind_info = OSM_BIND_INVALID_HANDLE; + osm_log( p_log, OSM_LOG_ERROR, + "osmv_bind_sa: ERR 0507: " + "Fail to obtain the sm lid.\n" ); + goto Exit; + } + + /* initialize the sync_event */ + cl_event_construct( &p_sa_bind_info->sync_event ); + cl_status = cl_event_init( &p_sa_bind_info->sync_event, TRUE ); + if( cl_status != CL_SUCCESS ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osmv_bind_sa: ERR 0508: " + "cl_init_event failed: %s\n", + ib_get_err_str(cl_status) + ); + free(p_sa_bind_info); + p_sa_bind_info = OSM_BIND_INVALID_HANDLE; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return ( p_sa_bind_info ); +} + +/***************************************************************************** + *****************************************************************************/ + +/****t* OSM Vendor SA Client/osmv_sa_mad_data + * NAME + * osmv_sa_mad_data + * + * DESCRIPTION + * Extra fields required to perform a mad query + * This struct is passed to the actual send method + * + * SYNOPSIS + */ +typedef struct _osmv_sa_mad_data +{ + /* MAD data. */ + uint8_t method; + ib_net16_t attr_id; + ib_net16_t attr_offset; + ib_net32_t attr_mod; + ib_net64_t comp_mask; + void *p_attr; +} osmv_sa_mad_data_t; +/* + * method + * The method of the mad to be sent + * + * attr_id + * Attribute ID + * + * attr_offset + * Offset as defined by RMPP + * + * attr_mod + * Attribute modifier + * + * comp_mask + * The component mask of the query + * + * p_attr + * A pointer to the record of the attribute to be sent. + * + *****/ + +/***************************************************************************** + *****************************************************************************/ +/* Send a MAD out on the GSI interface */ +ib_api_status_t +__osmv_send_sa_req( + IN osmv_sa_bind_info_t* p_bind, + IN const osmv_sa_mad_data_t * const p_sa_mad_data, + IN const osmv_query_req_t * const p_query_req ) +{ + ib_api_status_t status; + ib_mad_t *p_mad_hdr; + ib_sa_mad_t *p_sa_mad; + osm_madw_t *p_madw; + osm_log_t *p_log = p_bind->p_log; + static atomic32_t trans_id; + boolean_t sync; + osmv_query_req_t *p_query_req_copy; + + OSM_LOG_ENTER( p_log, __osmv_send_sa_req ); + + /* + since the sm_lid might change we obtain it every send + (actually it is cached in the bind object and refreshed + every 30sec by this proc ) + */ + status = + __osmv_get_lid_and_sm_lid_by_port_guid( + p_bind->p_vendor, p_bind->port_guid, + &p_bind->last_lids_update_sec, + &p_bind->lid, + &p_bind->sm_lid); + if (status != IB_SUCCESS) + { + osm_log( p_log, OSM_LOG_ERROR, + "__osmv_send_sa_req: ERR 0509: " + "Fail to obtain the sm lid.\n" ); + goto Exit; + } + + /* Get a MAD wrapper for the send */ + p_madw = osm_mad_pool_get( + p_bind->p_mad_pool, + p_bind->h_bind, + MAD_BLOCK_SIZE, + NULL ); + + if( p_madw == NULL ) + { + osm_log( p_log, OSM_LOG_ERROR, + "__osmv_send_sa_req: ERR 0510: " + "Unable to acquire MAD.\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + /* Initialize the Sent MAD: */ + + /* Initialize the MAD buffer for the send operation. */ + p_mad_hdr = osm_madw_get_mad_ptr( p_madw ); + p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw ); + + /* Get a new transaction Id */ + cl_atomic_inc( &trans_id ); + + /* Cleanup the MAD from any residue */ + memset(p_sa_mad, 0, MAD_BLOCK_SIZE); + + /* Initialize the standard MAD header. */ + ib_mad_init_new( + p_mad_hdr, /* mad pointer */ + IB_MCLASS_SUBN_ADM, /* class */ + ( uint8_t ) 2, /* version */ + p_sa_mad_data->method, /* method */ + cl_hton64( ( uint64_t ) trans_id ),/* tid */ + p_sa_mad_data->attr_id, /* attr id */ + p_sa_mad_data->attr_mod /* attr mod */ + ); + + /* Set the query information. */ + p_sa_mad->sm_key = p_query_req->sm_key; + p_sa_mad->attr_offset = 0; + p_sa_mad->comp_mask = p_sa_mad_data->comp_mask; + if( p_sa_mad->comp_mask ) + { + memcpy( p_sa_mad->data, p_sa_mad_data->p_attr, + ib_get_attr_size(p_sa_mad_data->attr_offset)); + } + + /* + Provide the address to send to + */ + /* Patch to handle IBAL - host order , where it should take destination lid in network order */ +#ifdef OSM_VENDOR_INTF_AL + p_madw->mad_addr.dest_lid = p_bind->sm_lid; +#else + p_madw->mad_addr.dest_lid = cl_hton16(p_bind->sm_lid); +#endif + p_madw->mad_addr.addr_type.smi.source_lid = + cl_hton16(p_bind->lid); + p_madw->mad_addr.addr_type.gsi.remote_qp = CL_HTON32(1); + p_madw->mad_addr.addr_type.gsi.remote_qkey = IB_QP1_WELL_KNOWN_Q_KEY; + p_madw->mad_addr.addr_type.gsi.pkey = IB_DEFAULT_PKEY; + p_madw->resp_expected = TRUE; + p_madw->fail_msg = CL_DISP_MSGID_NONE; + + /* + Provide MAD context such that the call back will know what to do. + We have to keep the entire request structure so we know the CB. + Since we can not rely on the client to keep it arroud until + the response - we duplicate it and will later dispose it (in CB). + To store on the MADW we cast it into what opensm has: + p_madw->context.arb_context.context1 + */ + p_query_req_copy = malloc(sizeof(*p_query_req_copy)); + *p_query_req_copy = *p_query_req; + p_madw->context.arb_context.context1 = p_query_req_copy; + + /* we can support async as well as sync calls */ + sync = ((p_query_req->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC); + + /* send the mad asynchronously */ + status = osm_vendor_send( + osm_madw_get_bind_handle( p_madw ), + p_madw, + p_madw->resp_expected ); + + /* if synchronous - wait on the event */ + if (sync) + { + osm_log( p_log, OSM_LOG_DEBUG, + "__osmv_send_sa_req: " + "Waiting for async event.\n" ); + cl_event_wait_on( &p_bind->sync_event, EVENT_NO_TIMEOUT, FALSE ); + cl_event_reset(&p_bind->sync_event); + status = p_madw->status; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return status; +} + +/***************************************************************************** + *****************************************************************************/ +/* + * Query the SA based on the user's request. + */ +ib_api_status_t +osmv_query_sa( + IN osm_bind_handle_t h_bind, + IN const osmv_query_req_t * const p_query_req + ) +{ + osmv_sa_bind_info_t *p_bind = (osmv_sa_bind_info_t *)h_bind; + osmv_sa_mad_data_t sa_mad_data; + osmv_user_query_t *p_user_query; + ib_service_record_t svc_rec; + ib_node_record_t node_rec; + ib_portinfo_record_t port_info; + ib_path_rec_t path_rec; + ib_class_port_info_t class_port_info; + osm_log_t *p_log = p_bind->p_log; + ib_api_status_t status; + + OSM_LOG_ENTER( p_log, osmv_query_sa ); + + /* Set the request information. */ + sa_mad_data.method = IB_MAD_METHOD_GETTABLE; + sa_mad_data.attr_mod = 0; + + /* Set the MAD attributes and component mask correctly. */ + switch ( p_query_req->query_type ) + { + + case OSMV_QUERY_USER_DEFINED: + osm_log( p_log, OSM_LOG_DEBUG, + "osmv_query_sa DBG:001 %s", "USER_DEFINED\n" ); + p_user_query = ( osmv_user_query_t * ) p_query_req->p_query_input; + if (p_user_query->method) sa_mad_data.method = p_user_query->method; + sa_mad_data.attr_offset = p_user_query->attr_offset; + sa_mad_data.attr_id = p_user_query->attr_id; + sa_mad_data.attr_mod = p_user_query->attr_mod; + sa_mad_data.comp_mask = p_user_query->comp_mask; + sa_mad_data.p_attr = p_user_query->p_attr; +#if (0) +#ifdef OSM_VENDOR_INTF_AL + /* HACK for OFED OSM: convert lid order from network to + host for IB_MAD_ATTR_PORTINFO_RECORD */ + if ( (sa_mad_data.attr_id == IB_MAD_ATTR_PORTINFO_RECORD) && + (sa_mad_data.comp_mask & IB_PIR_COMPMASK_LID)) + { + ib_portinfo_record_t * p_pir = (ib_portinfo_record_t *)sa_mad_data.p_attr; + p_pir->lid = cl_ntoh16(p_pir->lid); + } +#endif +#endif + break; + + case OSMV_QUERY_ALL_SVC_RECS: + osm_log( p_log, OSM_LOG_DEBUG, + "osmv_query_sa DBG:001 %s", "SVC_REC_BY_NAME\n" ); + sa_mad_data.method = IB_MAD_METHOD_GETTABLE; + sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD; + sa_mad_data.attr_offset = + ib_get_attr_offset( sizeof( ib_service_record_t ) ); + sa_mad_data.comp_mask = 0; + sa_mad_data.p_attr = &svc_rec; + break; + + case OSMV_QUERY_SVC_REC_BY_NAME: + osm_log( p_log, OSM_LOG_DEBUG, + "osmv_query_sa DBG:001 %s", "SVC_REC_BY_NAME\n" ); + sa_mad_data.method = IB_MAD_METHOD_GET; + sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD; + sa_mad_data.comp_mask = IB_SR_COMPMASK_SNAME; + sa_mad_data.attr_offset = + ib_get_attr_offset( sizeof( ib_service_record_t ) ); + sa_mad_data.p_attr = &svc_rec; + memcpy( svc_rec.service_name, p_query_req->p_query_input, + sizeof( ib_svc_name_t ) ); + break; + + case OSMV_QUERY_SVC_REC_BY_ID: + osm_log( p_log, OSM_LOG_DEBUG, + "osmv_query_sa DBG:001 %s", "SVC_REC_BY_ID\n" ); + sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD; + sa_mad_data.comp_mask = IB_SR_COMPMASK_SID; + sa_mad_data.attr_offset = + ib_get_attr_offset( sizeof( ib_service_record_t ) ); + sa_mad_data.p_attr = &svc_rec; + svc_rec.service_id = *( ib_net64_t * ) ( p_query_req->p_query_input ); + break; + + case OSMV_QUERY_CLASS_PORT_INFO: + osm_log( p_log, OSM_LOG_DEBUG, + "osmv_query_sa DBG:001 %s","CLASS_PORT_INFO\n" ); + sa_mad_data.method = IB_MAD_METHOD_GET; + sa_mad_data.attr_id = IB_MAD_ATTR_CLASS_PORT_INFO; + sa_mad_data.attr_offset = + ib_get_attr_offset( sizeof( ib_class_port_info_t ) ); + sa_mad_data.comp_mask = 0; + sa_mad_data.p_attr = &class_port_info; + + break; + + case OSMV_QUERY_NODE_REC_BY_NODE_GUID: + osm_log( p_log, OSM_LOG_DEBUG, + "osmv_query_sa DBG:001 %s","NODE_REC_BY_NODE_GUID\n" ); + sa_mad_data.method = IB_MAD_METHOD_GETTABLE; + sa_mad_data.attr_id = IB_MAD_ATTR_NODE_RECORD; + sa_mad_data.attr_offset = + ib_get_attr_offset( sizeof( ib_node_record_t ) ); + sa_mad_data.comp_mask = IB_NR_COMPMASK_NODEGUID; + sa_mad_data.p_attr = &node_rec; + node_rec.node_info.node_guid = + *( ib_net64_t * ) ( p_query_req->p_query_input ); + + break; + + case OSMV_QUERY_PORT_REC_BY_LID: + osm_log( p_log, OSM_LOG_DEBUG, + "osmv_query_sa DBG:001 %s","PORT_REC_BY_LID\n" ); + sa_mad_data.attr_id = IB_MAD_ATTR_PORTINFO_RECORD; + sa_mad_data.attr_offset = + ib_get_attr_offset( sizeof( ib_portinfo_record_t ) ); + sa_mad_data.comp_mask = IB_PIR_COMPMASK_LID; + sa_mad_data.p_attr = &port_info; + port_info.lid = *( ib_net16_t * ) ( p_query_req->p_query_input ); + break; + + case OSMV_QUERY_PORT_REC_BY_LID_AND_NUM: + sa_mad_data.method = IB_MAD_METHOD_GET; + p_user_query = ( osmv_user_query_t * ) p_query_req->p_query_input; + osm_log( p_log, OSM_LOG_DEBUG, + "osmv_query_sa DBG:001 %s","PORT_REC_BY_LID_AND_NUM\n" ); + sa_mad_data.attr_id = IB_MAD_ATTR_PORTINFO_RECORD; + sa_mad_data.attr_offset = + ib_get_attr_offset( sizeof( ib_portinfo_record_t ) ); + sa_mad_data.comp_mask = IB_PIR_COMPMASK_LID | IB_PIR_COMPMASK_PORTNUM; + sa_mad_data.p_attr = p_user_query->p_attr; + break; + + case OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK: + sa_mad_data.method = IB_MAD_METHOD_GET; + p_user_query = ( osmv_user_query_t * ) p_query_req->p_query_input; + osm_log( p_log, OSM_LOG_DEBUG, + "osmv_query_sa DBG:001 %s","OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK\n" ); + sa_mad_data.attr_id = IB_MAD_ATTR_VLARB_RECORD; + sa_mad_data.attr_offset = + ib_get_attr_offset( sizeof( ib_vl_arb_table_record_t ) ); + sa_mad_data.comp_mask = IB_VLA_COMPMASK_LID | IB_VLA_COMPMASK_OUT_PORT | IB_VLA_COMPMASK_BLOCK; + sa_mad_data.p_attr = p_user_query->p_attr; + break; + + case OSMV_QUERY_SLVL_BY_LID_AND_PORTS: + sa_mad_data.method = IB_MAD_METHOD_GET; + p_user_query = ( osmv_user_query_t * ) p_query_req->p_query_input; + osm_log( p_log, OSM_LOG_DEBUG, + "osmv_query_sa DBG:001 %s","OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK\n" ); + sa_mad_data.attr_id = IB_MAD_ATTR_SLVL_RECORD; + sa_mad_data.attr_offset = + ib_get_attr_offset( sizeof( ib_slvl_table_record_t ) ); + sa_mad_data.comp_mask = IB_SLVL_COMPMASK_LID | IB_SLVL_COMPMASK_OUT_PORT | IB_SLVL_COMPMASK_IN_PORT; + sa_mad_data.p_attr = p_user_query->p_attr; + break; + + case OSMV_QUERY_PATH_REC_BY_PORT_GUIDS: + osm_log( p_log, OSM_LOG_DEBUG, + "osmv_query_sa DBG:001 %s","PATH_REC_BY_PORT_GUIDS\n" ); + memset(&path_rec, 0, sizeof(ib_path_rec_t )); + sa_mad_data.attr_id = IB_MAD_ATTR_PATH_RECORD; + sa_mad_data.attr_offset = + ib_get_attr_offset( sizeof( ib_path_rec_t ) ); + sa_mad_data.comp_mask = ( IB_PR_COMPMASK_DGID | IB_PR_COMPMASK_SGID ); + sa_mad_data.p_attr = &path_rec; + ib_gid_set_default( &path_rec.dgid, + ( ( osmv_guid_pair_t * ) ( p_query_req-> + p_query_input ) )-> + dest_guid ); + ib_gid_set_default( &path_rec.sgid, + ( ( osmv_guid_pair_t * ) ( p_query_req-> + p_query_input ) )-> + src_guid ); + break; + + case OSMV_QUERY_PATH_REC_BY_GIDS: + osm_log( p_log, OSM_LOG_DEBUG, + "osmv_query_sa DBG:001 %s","PATH_REC_BY_GIDS\n" ); + memset(&path_rec, 0, sizeof(ib_path_rec_t )); + sa_mad_data.attr_id = IB_MAD_ATTR_PATH_RECORD; + sa_mad_data.attr_offset = + ib_get_attr_offset( sizeof( ib_path_rec_t ) ); + sa_mad_data.comp_mask = ( IB_PR_COMPMASK_DGID | IB_PR_COMPMASK_SGID ); + sa_mad_data.p_attr = &path_rec; + memcpy( &path_rec.dgid, + &( ( osmv_gid_pair_t * ) ( p_query_req->p_query_input ) )-> + dest_gid, sizeof( ib_gid_t ) ); + memcpy( &path_rec.sgid, + &( ( osmv_gid_pair_t * ) ( p_query_req->p_query_input ) )-> + src_gid, sizeof( ib_gid_t ) ); + break; + + case OSMV_QUERY_PATH_REC_BY_LIDS: + osm_log( p_log, OSM_LOG_DEBUG, + "osmv_query_sa DBG:001 %s","PATH_REC_BY_LIDS\n" ); + memset(&path_rec, 0, sizeof(ib_path_rec_t )); + sa_mad_data.method = IB_MAD_METHOD_GET; + sa_mad_data.attr_id = IB_MAD_ATTR_PATH_RECORD; + sa_mad_data.attr_offset = + ib_get_attr_offset( sizeof( ib_path_rec_t ) ); + sa_mad_data.comp_mask = ( IB_PR_COMPMASK_DLID | IB_PR_COMPMASK_SLID ); + sa_mad_data.p_attr = &path_rec; + path_rec.dlid = + ( ( osmv_lid_pair_t * ) ( p_query_req->p_query_input ) )->dest_lid; + path_rec.slid = + ( ( osmv_lid_pair_t * ) ( p_query_req->p_query_input ) )->src_lid; + break; + + case OSMV_QUERY_UD_MULTICAST_SET: + sa_mad_data.method = IB_MAD_METHOD_SET; + p_user_query = ( osmv_user_query_t * ) p_query_req->p_query_input; + osm_log( p_log, OSM_LOG_DEBUG, + "osmv_query_sa DBG:001 %s","OSMV_QUERY_UD_MULTICAST_SET\n" ); + sa_mad_data.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD; + sa_mad_data.attr_offset = + ib_get_attr_offset( sizeof( ib_member_rec_t ) ); + sa_mad_data.comp_mask = p_user_query->comp_mask; + sa_mad_data.p_attr = p_user_query->p_attr; + break; + + case OSMV_QUERY_UD_MULTICAST_DELETE: + sa_mad_data.method = IB_MAD_METHOD_DELETE; + p_user_query = ( osmv_user_query_t * ) p_query_req->p_query_input; + osm_log( p_log, OSM_LOG_DEBUG, + "osmv_query_sa DBG:001 %s","OSMV_QUERY_UD_MULTICAST_DELETE\n" ); + sa_mad_data.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD; + sa_mad_data.attr_offset = + ib_get_attr_offset( sizeof( ib_member_rec_t ) ); + sa_mad_data.comp_mask = p_user_query->comp_mask; + sa_mad_data.p_attr = p_user_query->p_attr; + break; + + default: + osm_log( p_log, OSM_LOG_ERROR, + "osmv_query_sa DBG:001 %s","UNKNOWN\n" ); + CL_ASSERT( 0 ); + return IB_ERROR; + } + + status = __osmv_send_sa_req( h_bind, &sa_mad_data, p_query_req ); + + OSM_LOG_EXIT( p_log ); + return status; +} + + +/***************************************************************************** + *****************************************************************************/ + + + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/libvendor/winosm_common.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/libvendor/winosm_common.c new file mode 100644 index 00000000..361d2c00 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/libvendor/winosm_common.c @@ -0,0 +1,249 @@ +#include +#include +#include +#include + +int optind=1; +int opterr=1; +int optopt='?'; +int iArg=1; + +char* +GetOsmTempPath(void) +{ + char* temp_path; + int length; + temp_path = (char*)cl_malloc(OSM_MAX_LOG_NAME_SIZE); + length = GetTempPath(OSM_MAX_LOG_NAME_SIZE,temp_path); + if (length > OSM_MAX_LOG_NAME_SIZE) + { + cl_free(temp_path); + temp_path = (char*)cl_malloc(length+1); + GetTempPath(length+1,temp_path); + } + return temp_path; +} + +char* +GetOsmCachePath(void) +{ + char* cache_path; + char* tmp_file_name; + char* winib_home, tmp; + HANDLE hFile; + + winib_home = (char*)cl_malloc(OSM_MAX_LOG_NAME_SIZE); + winib_home = getenv("WinIB_HOME"); + if (winib_home == NULL) + { + /* The WinIB_HOME variable isn't defined. Use the + default temp path */ + return GetOsmTempPath(); + } + cache_path = (char*)cl_malloc(OSM_MAX_LOG_NAME_SIZE); + strcpy(cache_path, winib_home); + + strcat(cache_path, "\\etc\\"); + tmp_file_name = (char*)cl_malloc(OSM_MAX_LOG_NAME_SIZE); + strcpy(tmp_file_name, cache_path); + strcat(tmp_file_name, "opensm.opts"); + hFile = CreateFile(tmp_file_name, + GENERIC_READ, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (hFile == INVALID_HANDLE_VALUE) + { + cl_free(cache_path); + return GetOsmTempPath(); + } + /* Such file exists. This means the directory is usable */ + CloseHandle(hFile); + + return cache_path; +} + +/****************************************************************************/ +int getopt_long_only(int argc, char *const*argv, + const char *optstring, + const struct option *longopts, int *longindex) +{ + char chOpt; + char tmp_str[256]; + char* tmp_arg = NULL; + char* tok=NULL; + int i; + char tokens[2] = {'='}; + + if (iArg == argc) + { + + return (EOF); + } + + if (argv[iArg][0] != '-') + { + /* Does not start with a - - we are done scanning */ + + return (EOF); + } + + /*termination of scanning */ + if (!strcmp("--",argv[iArg])) { + return EOF; + + } + + + /* char option : -d 5 */ + if ((argv[iArg][0] == '-') &&(argv[iArg][1] != '-') ) { + optarg = get_char_option(optstring,argv,argc,iArg,&optind,&chOpt); + iArg = optind; + + return chOpt; + } + + /* Look for this string in longopts */ + strcpy(tmp_str,&(argv[iArg][2])); + + /*get the option */ + tok = strtok(tmp_str,tokens); + + for (i = 0; longopts[i].name; i++) + { + if (strcmp (tok, longopts[i].name) == 0) + { + /* We have a match */ + if (longindex != NULL ) + *longindex = i; + + if (longopts[i].flag != NULL) { + *(longopts[i].flag) = longopts[i].val; + } + + + + if (longopts[i].has_arg != no_argument) + { + /*get the argument */ + + if (strchr(argv[iArg],'=') != NULL) + { + optarg = strtok(NULL,tokens); + }else { /*the next arg in cmd line is the param */ + tmp_arg = argv[iArg+1]; + if (*tmp_arg == '-') { + + /*no param is found */ + chOpt = '?'; + if ((longopts[i].has_arg == required_argument) && opterr) + { + fprintf (stderr, "Option %s requires argument\n",tok); + } + + }else + { + optarg = tmp_arg; + iArg++; + optind++; + } + } + + }/*longopts */ + + iArg++; + optind++; + if (longopts[i].flag == 0) + return (longopts[i].val); + else return 0; + + }/*end if strcmp */ + } + + return ('?'); +} + +/******************************************************************************/ +static char* get_char_option(const char* optstring,char*const* argv,int argc, + int iArg, int* opt_ind,char* opt_p) + { + char chOpt; + char* tmp_str; + char* prm = NULL; + + chOpt = argv[iArg][1]; + + + /*non valid argument*/ + if (!isalpha(chOpt)) + { + chOpt = EOF; + goto end; + } + + tmp_str = strchr(optstring, chOpt); + + /*the argument wasn't found in optstring */ + if (tmp_str == NULL){ + chOpt = EOF; + optopt = chOpt; + goto end; + } + + /* don't need argument */ + if (tmp_str[1]!= ':' ) { + goto end; + } + + if (argv[iArg][2] != '\0') + { + // param is attached to option: -po8889 + prm = &(argv[iArg][2]); + goto end; + } + + // must look at next argv for param + /*at the end of arg list */ + if ((iArg)+1 == argc) { + /* no param will be found */ + if (tmp_str[2]== ':' ) { + /* optional argument ::*/ + goto end; + } + else + { + chOpt = EOF; + goto end; + } + } + + prm = &(argv[(iArg)+1][0]); + if (*prm == '-' ) + { + // next argv is a new option, so param + // not given for current option + if (tmp_str[2]== ':' ) { + /* optional argument ::*/ + goto end; + } + else + { + chOpt = EOF; + goto end; + } + } + + // next argv is the param + (*opt_ind)++; + + +end: + (*opt_ind)++; + *opt_p = chOpt; + return prm; +} + + +/******************************************************************************/ diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/Makefile b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/Makefile new file mode 100644 index 00000000..a0c06273 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/Makefile @@ -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 OpenIB Windows project. +# + +!INCLUDE ..\..\..\..\inc\openib.def diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/SOURCES b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/SOURCES new file mode 100644 index 00000000..03321e9e --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/SOURCES @@ -0,0 +1,62 @@ +TARGETNAME=opensm_3_0_0 + +!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_MSVCRT=1 +SOURCES=\ + osm.mc \ + opensm.rc \ + osm_files.c\ + osm_drop_mgr.c\ + osm_prtn_config.c\ + osm_sa_mcmember_record.c\ + osm_sa_path_record.c\ + +OSM_HOME=.. + +TARGETLIBS=\ +!if $(FREEBUILD) + $(LIBPATH)\*\ibal.lib \ + $(LIBPATH)\*\complib.lib \ + $(TARGETPATH)\*\osmv_ibal_3_0_0.lib \ + $(TARGETPATH)\*\opensm_ibal.lib + +!else + $(LIBPATH)\*\ibald.lib \ + $(LIBPATH)\*\complibd.lib \ + $(TARGETPATH)\*\osmv_ibal_3_0_0d.lib \ + $(TARGETPATH)\*\opensm_ibald.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 +C_DEFINES=$(C_DEFINES) -I.. -DHAVE_CONFIG_H +!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/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/cl_dispatcher.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/cl_dispatcher.c new file mode 100644 index 00000000..252ceee8 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/cl_dispatcher.c @@ -0,0 +1,405 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: cl_dispatcher.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Implementation of Dispatcher abstraction. + * + * Environment: + * All + * + * $Revision: 1.5 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/* give some guidance when we build our cl_pool of messages */ +#define CL_DISP_INITIAL_MSG_COUNT 256 +#define CL_DISP_MSG_GROW_SIZE 64 + +/* give some guidance when we build our cl_pool of registration elements */ +#define CL_DISP_INITIAL_REG_COUNT 16 +#define CL_DISP_REG_GROW_SIZE 16 + +/******************************************************************** + __cl_disp_worker + + Description: + This function takes messages off the FIFO and calls Processmsg() + This function executes as passive level. + + Inputs: + p_disp - Pointer to Dispatcher object + + Outputs: + None + + Returns: + None +********************************************************************/ +void +__cl_disp_worker( + IN void* context ) +{ + cl_disp_msg_t *p_msg; + cl_dispatcher_t *p_disp = (cl_dispatcher_t*)context; + + cl_spinlock_acquire( &p_disp->lock ); + + /* Process the FIFO until we drain it dry. */ + while( cl_qlist_count( &p_disp->msg_fifo ) ) + { + /* Pop the message at the head from the FIFO. */ + p_msg = (cl_disp_msg_t*)cl_qlist_remove_head( &p_disp->msg_fifo ); + + /* we track the tim ethe last message spent in the queue */ + p_disp->last_msg_queue_time_us = cl_get_time_stamp() - p_msg->in_time; + + /* + * Release the spinlock while the message is processed. + * The user's callback may reenter the dispatcher + * and cause the lock to be reaquired. + */ + cl_spinlock_release( &p_disp->lock ); + p_msg->p_dest_reg->pfn_rcv_callback( + (void*)p_msg->p_dest_reg->context, (void*)p_msg->p_data ); + + cl_atomic_dec( &p_msg->p_dest_reg->ref_cnt ); + + /* The client has seen the data. Notify the sender as appropriate. */ + if( p_msg->pfn_xmt_callback ) + { + p_msg->pfn_xmt_callback( (void*)p_msg->context, + (void*)p_msg->p_data ); + cl_atomic_dec( &p_msg->p_src_reg->ref_cnt ); + } + + /* Grab the lock for the next iteration through the list. */ + cl_spinlock_acquire(&p_disp->lock); + + /* Return this message to the pool. */ + cl_qpool_put( &p_disp->msg_pool, (cl_pool_item_t *)p_msg ); + } + + cl_spinlock_release( &p_disp->lock ); +} + +/******************************************************************** + ********************************************************************/ +void +cl_disp_construct( + IN cl_dispatcher_t* const p_disp ) +{ + CL_ASSERT( p_disp ); + + cl_qlist_init( &p_disp->reg_list ); + cl_ptr_vector_construct( &p_disp->reg_vec ); + cl_thread_pool_construct( &p_disp->worker_threads ); + cl_qlist_init( &p_disp->msg_fifo ); + cl_spinlock_construct( &p_disp->lock ); + cl_qpool_construct( &p_disp->msg_pool ); +} + +/******************************************************************** + ********************************************************************/ +void +cl_disp_shutdown( + IN cl_dispatcher_t* const p_disp ) +{ + CL_ASSERT( p_disp ); + + /* Stop the thread pool. */ + cl_thread_pool_destroy( &p_disp->worker_threads ); + + /* Process all outstanding callbacks. */ + __cl_disp_worker( p_disp ); + + /* Free all registration info. */ + while( !cl_is_qlist_empty( &p_disp->reg_list ) ) + free( cl_qlist_remove_head( &p_disp->reg_list ) ); +} + +/******************************************************************** + ********************************************************************/ +void +cl_disp_destroy( + IN cl_dispatcher_t* const p_disp ) +{ + CL_ASSERT( p_disp ); + + cl_spinlock_destroy( &p_disp->lock ); + /* Destroy the message pool */ + cl_qpool_destroy( &p_disp->msg_pool ); + /* Destroy the pointer vector of registrants. */ + cl_ptr_vector_destroy( &p_disp->reg_vec ); +} + +/******************************************************************** + ********************************************************************/ +cl_status_t +cl_disp_init( + IN cl_dispatcher_t* const p_disp, + IN const uint32_t thread_count, + IN const char* const name ) +{ + cl_status_t status; + + CL_ASSERT( p_disp ); + + cl_disp_construct( p_disp ); + + status = cl_spinlock_init( &p_disp->lock ); + if( status != CL_SUCCESS ) + { + cl_disp_destroy( p_disp ); + return( status ); + } + + /* Specify no upper limit to the number of messages in the pool */ + status = cl_qpool_init( &p_disp->msg_pool, CL_DISP_INITIAL_MSG_COUNT, + 0, CL_DISP_MSG_GROW_SIZE, sizeof(cl_disp_msg_t), NULL, + NULL, NULL ); + if( status != CL_SUCCESS ) + { + cl_disp_destroy( p_disp ); + return( status ); + } + + status = cl_ptr_vector_init( &p_disp->reg_vec, CL_DISP_INITIAL_REG_COUNT, + CL_DISP_REG_GROW_SIZE ); + if( status != CL_SUCCESS ) + { + cl_disp_destroy( p_disp ); + return( status ); + } + + status = cl_thread_pool_init( &p_disp->worker_threads, thread_count, + __cl_disp_worker, p_disp, name ); + if( status != CL_SUCCESS ) + cl_disp_destroy( p_disp ); + + return( status ); +} + +/******************************************************************** + ********************************************************************/ +cl_disp_reg_handle_t +cl_disp_register( + IN cl_dispatcher_t* const p_disp, + IN const cl_disp_msgid_t msg_id, + IN cl_pfn_msgrcv_cb_t pfn_callback OPTIONAL, + IN const void* const context OPTIONAL ) +{ + cl_disp_reg_info_t *p_reg; + cl_status_t status; + + CL_ASSERT( p_disp ); + + /* Check that the requested registrant ID is available. */ + cl_spinlock_acquire( &p_disp->lock ); + if( (msg_id != CL_DISP_MSGID_NONE ) && + (msg_id < cl_ptr_vector_get_size( &p_disp->reg_vec )) && + (cl_ptr_vector_get( &p_disp->reg_vec, msg_id )) ) + { + cl_spinlock_release( &p_disp->lock ); + return( NULL ); + } + + /* Get a registration info from the pool. */ + p_reg = (cl_disp_reg_info_t*)malloc( sizeof(cl_disp_reg_info_t) ); + if( !p_reg ) + { + cl_spinlock_release( &p_disp->lock ); + return( NULL ); + } + else + { + memset( p_reg, 0, sizeof(cl_disp_reg_info_t) ); + } + + p_reg->p_disp = p_disp; + p_reg->ref_cnt = 0; + p_reg->pfn_rcv_callback = pfn_callback; + p_reg->context = context; + p_reg->msg_id = msg_id; + + /* Insert the registration in the list. */ + cl_qlist_insert_tail( &p_disp->reg_list, (cl_list_item_t*)p_reg ); + + /* Set the array entry to the registrant. */ + /* The ptr_vector grow automatically as necessary. */ + if( msg_id != CL_DISP_MSGID_NONE ) + { + status = cl_ptr_vector_set( &p_disp->reg_vec, msg_id, p_reg ); + if( status != CL_SUCCESS ) + { + free( p_reg ); + cl_spinlock_release( &p_disp->lock ); + return( NULL ); + } + } + + cl_spinlock_release( &p_disp->lock ); + + return( p_reg ); +} + +/******************************************************************** + ********************************************************************/ +void +cl_disp_unregister( + IN const cl_disp_reg_handle_t handle ) +{ + cl_disp_reg_info_t *p_reg; + cl_dispatcher_t *p_disp; + + if( handle == CL_DISP_INVALID_HANDLE ) + return; + + p_reg = (cl_disp_reg_info_t*)handle; + p_disp = p_reg->p_disp; + CL_ASSERT( p_disp ); + + cl_spinlock_acquire( &p_disp->lock ); + /* + * Clear the registrant vector entry. This will cause any further + * post calls to fail. + */ + if( p_reg->msg_id != CL_DISP_MSGID_NONE ) + { + CL_ASSERT( p_reg->msg_id < cl_ptr_vector_get_size(&p_disp->reg_vec)); + cl_ptr_vector_set( &p_disp->reg_vec, p_reg->msg_id, NULL ); + } + cl_spinlock_release( &p_disp->lock ); + + while( p_reg->ref_cnt > 0) + cl_thread_suspend( 1 ); + + cl_spinlock_acquire(&p_disp->lock); + /* Remove the registrant from the list. */ + cl_qlist_remove_item( &p_disp->reg_list, (cl_list_item_t*)p_reg ); + /* Return the registration info to the pool */ + free( p_reg ); + + cl_spinlock_release( &p_disp->lock ); +} + +/******************************************************************** + ********************************************************************/ +cl_status_t +cl_disp_post( + IN const cl_disp_reg_handle_t handle, + IN const cl_disp_msgid_t msg_id, + IN const void* const p_data, + IN cl_pfn_msgdone_cb_t pfn_callback OPTIONAL, + IN const void* const context OPTIONAL ) +{ + cl_disp_reg_info_t *p_src_reg = (cl_disp_reg_info_t*)handle; + cl_disp_reg_info_t *p_dest_reg; + cl_dispatcher_t *p_disp; + cl_disp_msg_t *p_msg; + + p_disp = handle->p_disp; + CL_ASSERT( p_disp ); + CL_ASSERT( msg_id != CL_DISP_MSGID_NONE ); + + cl_spinlock_acquire( &p_disp->lock ); + /* Check that the recipient exists. */ + p_dest_reg = cl_ptr_vector_get( &p_disp->reg_vec, msg_id ); + if( !p_dest_reg ) + { + cl_spinlock_release( &p_disp->lock ); + return( CL_NOT_FOUND ); + } + + /* Get a free message from the pool. */ + p_msg = (cl_disp_msg_t*)cl_qpool_get( &p_disp->msg_pool ); + if( !p_msg ) + { + cl_spinlock_release( &p_disp->lock ); + return( CL_INSUFFICIENT_MEMORY ); + } + + /* Initialize the message */ + p_msg->p_src_reg = p_src_reg; + p_msg->p_dest_reg = p_dest_reg; + p_msg->p_data = p_data; + p_msg->pfn_xmt_callback = pfn_callback; + p_msg->context = context; + p_msg->in_time = cl_get_time_stamp(); + + /* + * Increment the sender's reference count if they request a completion + * notification. + */ + if( pfn_callback ) + cl_atomic_inc( &p_src_reg->ref_cnt ); + + /* Increment the recipient's reference count. */ + cl_atomic_inc( &p_dest_reg->ref_cnt ); + + /* Queue the message in the FIFO. */ + cl_qlist_insert_tail( &p_disp->msg_fifo, (cl_list_item_t *)p_msg ); + cl_spinlock_release( &p_disp->lock ); + + /* Signal the thread pool that there is work to be done. */ + cl_thread_pool_signal( &p_disp->worker_threads ); + return( CL_SUCCESS ); +} + +void +cl_disp_get_queue_status( + IN const cl_disp_reg_handle_t handle, + OUT uint32_t *p_num_queued_msgs, + OUT uint64_t *p_last_msg_queue_time_ms) +{ + cl_dispatcher_t *p_disp = ((cl_disp_reg_info_t*)handle)->p_disp; + + cl_spinlock_acquire( &p_disp->lock ); + + if (p_last_msg_queue_time_ms) + *p_last_msg_queue_time_ms = p_disp->last_msg_queue_time_us/1000; + + if (p_num_queued_msgs) + *p_num_queued_msgs = cl_qlist_count( &p_disp->msg_fifo ); + + cl_spinlock_release( &p_disp->lock ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/cl_event_wheel.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/cl_event_wheel.c new file mode 100644 index 00000000..8e65c709 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/cl_event_wheel.c @@ -0,0 +1,663 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: cl_event_wheel.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include + +cl_status_t +__event_will_age_before( + IN const cl_list_item_t* const p_list_item, + IN void* context ) +{ + uint64_t aging_time = *((uint64_t*)context); + cl_event_wheel_reg_info_t *p_event; + + p_event = + PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t, list_item); + + if (p_event->aging_time < aging_time) + return CL_SUCCESS; + else + return CL_NOT_FOUND; +} + +void +__cl_event_wheel_callback( IN void* context ) +{ + cl_event_wheel_t *p_event_wheel = (cl_event_wheel_t *)context; + cl_list_item_t *p_list_item, *p_prev_event_list_item; + cl_list_item_t *p_list_next_item; + cl_event_wheel_reg_info_t *p_event; + uint64_t current_time; + uint64_t next_aging_time; + uint32_t new_timeout; + cl_status_t cl_status; + + OSM_LOG_ENTER( p_event_wheel->p_log, __cl_event_wheel_callback); + + /* might be during closing ... */ + if (p_event_wheel->closing) + { + goto JustExit; + } + + current_time = cl_get_time_stamp(); + + if (NULL != p_event_wheel->p_external_lock) { + + /* Take care of the order of acquiring locks to avoid the deadlock! + * The external lock goes first. + */ + CL_SPINLOCK_ACQUIRE(p_event_wheel->p_external_lock); + } + + CL_SPINLOCK_ACQUIRE(&p_event_wheel->lock); + + p_list_item = cl_qlist_head(&p_event_wheel->events_wheel); + if (p_list_item == cl_qlist_end(&p_event_wheel->events_wheel)) + { + /* the list is empty - nothing to do */ + goto Exit; + } + + /* we found such an item. get the p_event */ + p_event = PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t, list_item); + + while (p_event->aging_time <= current_time) + { + /* this object has aged - invoke it's callback */ + if (p_event->pfn_aged_callback) + { + next_aging_time = + p_event->pfn_aged_callback( + p_event->key, p_event->num_regs, p_event->context); + } + else + { + next_aging_time = 0; + } + + /* point to the next object in the wheel */ + p_list_next_item = cl_qlist_next(p_list_item); + + /* We need to retire the event if the next aging time passed */ + if (next_aging_time < current_time) + { + /* remove it from the map */ + cl_qmap_remove_item(&p_event_wheel->events_map, &(p_event->map_item)); + + /* pop p_event from the wheel */ + cl_qlist_remove_head(&p_event_wheel->events_wheel); + + /* delete the event info object - allocated by cl_event_wheel_reg */ + free(p_event); + } + else + { + /* update the required aging time */ + p_event->aging_time = next_aging_time; + p_event->num_regs++; + + /* do not remove from the map - but remove from the list head and + place in the correct position */ + + /* pop p_event from the wheel */ + cl_qlist_remove_head(&p_event_wheel->events_wheel); + + /* find the event that ages just before */ + p_prev_event_list_item = cl_qlist_find_from_tail( + &p_event_wheel->events_wheel, + __event_will_age_before, + &p_event->aging_time); + + /* insert just after */ + cl_qlist_insert_next( + &p_event_wheel->events_wheel, + p_prev_event_list_item , + &p_event->list_item); + + /* as we have modified the list - restart from first item: */ + p_list_next_item = cl_qlist_head(&p_event_wheel->events_wheel); + } + + /* advance to next event */ + p_list_item = p_list_next_item; + if (p_list_item == cl_qlist_end(&p_event_wheel->events_wheel)) + { + /* the list is empty - nothing to do */ + break; + } + + /* get the p_event */ + p_event = PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t, list_item); + } + + /* We need to restart the timer only if the list is not empty now */ + if (p_list_item != cl_qlist_end(&p_event_wheel->events_wheel)) + { + /* get the p_event */ + p_event = PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t, list_item); + + /* start the timer to the timeout [msec] */ + new_timeout = (uint32_t)(((p_event->aging_time - current_time)/1000)+0.5); + osm_log (p_event_wheel->p_log, OSM_LOG_DEBUG, + "__cl_event_wheel_callback : " + "Restart timer in : %u [msec]\n", + new_timeout); + cl_status = cl_timer_start(&p_event_wheel->timer, new_timeout); + if (cl_status != CL_SUCCESS) + { + osm_log (p_event_wheel->p_log, OSM_LOG_ERROR, + "__cl_event_wheel_callback : ERR 6100: " + "Failed to start timer\n" ); + } + } + + /* release the lock */ + Exit: + CL_SPINLOCK_RELEASE( &p_event_wheel->lock ); + if (NULL != p_event_wheel->p_external_lock) { + CL_SPINLOCK_RELEASE(p_event_wheel->p_external_lock); + } + JustExit: + OSM_LOG_EXIT( p_event_wheel->p_log ); +} + +/* + * Construct and Initialize + */ +void +cl_event_wheel_construct( + IN cl_event_wheel_t* const p_event_wheel ) +{ + cl_spinlock_construct( &(p_event_wheel->lock) ); + cl_timer_construct( &(p_event_wheel->timer) ); +} + +cl_status_t +cl_event_wheel_init( + IN cl_event_wheel_t* const p_event_wheel, + IN osm_log_t *p_log) +{ + cl_status_t cl_status = CL_SUCCESS; + + OSM_LOG_ENTER( p_log, cl_event_wheel_init ); + + /* initialize */ + p_event_wheel->p_log = p_log; + p_event_wheel->p_external_lock = NULL; + p_event_wheel->closing = FALSE; + cl_status = cl_spinlock_init( &(p_event_wheel->lock) ); + if (cl_status != CL_SUCCESS) + { + osm_log (p_event_wheel->p_log, OSM_LOG_ERROR, + "cl_event_wheel_init : ERR 6101: " + "Failed to initialize cl_spinlock\n" ); + goto Exit; + } + cl_qlist_init( &p_event_wheel->events_wheel); + cl_qmap_init( &p_event_wheel->events_map ); + + /* init the timer with timeout */ + cl_status = cl_timer_init(&p_event_wheel->timer, + __cl_event_wheel_callback, + p_event_wheel ); /* cb context */ + + if (cl_status != CL_SUCCESS) + { + osm_log (p_event_wheel->p_log, OSM_LOG_ERROR, + "cl_event_wheel_init : ERR 6102: " + "Failed to initialize cl_timer\n" ); + goto Exit; + } + Exit: + OSM_LOG_EXIT( p_event_wheel->p_log ); + return(cl_status); +} + +cl_status_t +cl_event_wheel_init_ex( + IN cl_event_wheel_t* const p_event_wheel, + IN osm_log_t *p_log, + IN cl_spinlock_t *p_external_lock) +{ + cl_status_t cl_status; + + cl_status = cl_event_wheel_init(p_event_wheel, p_log); + if (CL_SUCCESS != cl_status) + { + return cl_status; + } + + p_event_wheel->p_external_lock = p_external_lock; + return cl_status; +} + +void +cl_event_wheel_dump( + IN cl_event_wheel_t* const p_event_wheel ) +{ + cl_list_item_t *p_list_item; + cl_event_wheel_reg_info_t *p_event; + + OSM_LOG_ENTER( p_event_wheel->p_log, cl_event_wheel_dump ); + + p_list_item = cl_qlist_head(&p_event_wheel->events_wheel); + osm_log( p_event_wheel->p_log, OSM_LOG_DEBUG, + "cl_event_wheel_dump: " + "event_wheel ptr:%p\n", + p_event_wheel); + + while (p_list_item != cl_qlist_end(&p_event_wheel->events_wheel) ) + { + p_event = PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t, list_item); + osm_log( p_event_wheel->p_log, OSM_LOG_DEBUG, + "cl_event_wheel_dump: " + "Found event key:<0x%"PRIx64">, aging time:%" PRIu64"\n", + p_event->key, p_event->aging_time ); + p_list_item = cl_qlist_next( p_list_item ); + } + OSM_LOG_EXIT( p_event_wheel->p_log ); +} + +void +cl_event_wheel_destroy( + IN cl_event_wheel_t* const p_event_wheel ) +{ + cl_list_item_t *p_list_item; + cl_map_item_t *p_map_item; + cl_event_wheel_reg_info_t *p_event; + + OSM_LOG_ENTER( p_event_wheel->p_log, cl_event_wheel_destroy ); + + /* we need to get a lock */ + CL_SPINLOCK_ACQUIRE( &p_event_wheel->lock ); + + cl_event_wheel_dump( p_event_wheel); + + /* go over all the items in the list and remove them */ + p_list_item = cl_qlist_remove_head(&p_event_wheel->events_wheel); + while ( p_list_item != cl_qlist_end(&p_event_wheel->events_wheel) ) + { + p_event = PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t, list_item); + + osm_log( p_event_wheel->p_log, OSM_LOG_DEBUG, + "cl_event_wheel_destroy: " + "Found outstanding event key:<0x%"PRIx64">\n", + p_event->key ); + + /* remove it from the map */ + p_map_item = &(p_event->map_item); + cl_qmap_remove_item(&p_event_wheel->events_map, p_map_item); + free(p_event); /* allocated by cl_event_wheel_reg */ + p_list_item = cl_qlist_remove_head(&p_event_wheel->events_wheel); + } + + /* destroy the timer */ + cl_timer_destroy( &p_event_wheel->timer ); + + /* destroy the lock (this should be done without releasing - we don't want + any other run to grab the lock at this point. */ + CL_SPINLOCK_RELEASE( &p_event_wheel->lock ); + cl_spinlock_destroy( &(p_event_wheel->lock) ); + + OSM_LOG_EXIT( p_event_wheel->p_log ); +} + +cl_status_t +cl_event_wheel_reg( + IN cl_event_wheel_t* const p_event_wheel, + IN const uint64_t key, + IN const uint64_t aging_time_usec, + IN cl_pfn_event_aged_cb_t pfn_callback, + IN void* const context ) +{ + cl_event_wheel_reg_info_t *p_event; + uint64_t timeout; + uint32_t to; + cl_status_t cl_status = CL_SUCCESS; + cl_list_item_t *prev_event_list_item; + cl_map_item_t *p_map_item; + + OSM_LOG_ENTER( p_event_wheel->p_log, cl_event_wheel_reg ); + + /* Get the lock on the manager */ + CL_SPINLOCK_ACQUIRE( &(p_event_wheel->lock) ); + + cl_event_wheel_dump( p_event_wheel); + + /* Make sure such a key does not exists */ + p_map_item = cl_qmap_get( &p_event_wheel->events_map, key ); + if (p_map_item != cl_qmap_end( &p_event_wheel->events_map )) + { + osm_log( p_event_wheel->p_log, OSM_LOG_DEBUG, + "cl_event_wheel_reg: " + "Already exists key:0x%"PRIx64"\n", key); + + /* already there - remove it from the list as it is getting a new time */ + p_event = PARENT_STRUCT(p_map_item, cl_event_wheel_reg_info_t, map_item); + + /* remove the item from the qlist */ + cl_qlist_remove_item( &p_event_wheel->events_wheel, &p_event->list_item ); + /* and the qmap */ + cl_qmap_remove_item( &p_event_wheel->events_map, &p_event->map_item ); + } + else + { + /* make a new one */ + p_event = (cl_event_wheel_reg_info_t *) + malloc( sizeof (cl_event_wheel_reg_info_t) ); + p_event->num_regs = 0; + } + + p_event->key = key; + p_event->aging_time = aging_time_usec; + p_event->pfn_aged_callback = pfn_callback; + p_event->context = context; + p_event->num_regs++; + + osm_log( p_event_wheel->p_log, OSM_LOG_DEBUG, + "cl_event_wheel_reg: " + "Registering event key:0x%"PRIx64" aging in %u [msec]\n", + p_event->key, + (uint32_t)((p_event->aging_time - cl_get_time_stamp()) / 1000 )); + + /* If the list is empty - need to start the timer */ + if (cl_is_qlist_empty(&p_event_wheel->events_wheel)) + { + /* Edward Bortnikov 03/29/2003 + * ++TBD Consider moving the timer manipulation behind the list manipulation. + */ + + /* calculate the new timeout */ + timeout = (p_event->aging_time - cl_get_time_stamp() + 500) / 1000; + + /* stop the timer if it is running */ + + /* Edward Bortnikov 03/29/2003 + * Don't call cl_timer_stop() because it spins forever. + * cl_timer_start() will invoke cl_timer_stop() by itself. + * + * The problematic scenario is when __cl_event_wheel_callback() + * is in race condition with this code. It sets timer.in_timer_cb + * to TRUE and then blocks on p_event_wheel->lock. Following this, + * the call to cl_timer_stop() hangs. Following this, the whole system + * enters into a deadlock. + * + * cl_timer_stop(&p_event_wheel->timer); + */ + + /* The timeout for the cl_timer_start should be given as uint32_t. + if there is an overflow - warn about it. */ + to = (uint32_t)timeout; + if ( timeout > (uint32_t)timeout ) + { + to = 0xffffffff; /* max 32 bit timer */ + osm_log (p_event_wheel->p_log, OSM_LOG_INFO, + "cl_event_wheel_reg: " + "timeout requested is too large. Using timeout: %u\n", + to ); + } + + /* start the timer to the timeout [msec] */ + cl_status = cl_timer_start(&p_event_wheel->timer, to); + if (cl_status != CL_SUCCESS) + { + osm_log (p_event_wheel->p_log, OSM_LOG_ERROR, + "cl_event_wheel_reg : ERR 6103: " + "Failed to start timer\n" ); + goto Exit; + } + } + + /* insert the object to the qlist and the qmap */ + + /* BUT WE MUST INSERT IT IN A SORTED MANNER */ + prev_event_list_item = cl_qlist_find_from_tail( + &p_event_wheel->events_wheel, + __event_will_age_before, + &p_event->aging_time); + + cl_qlist_insert_next( + &p_event_wheel->events_wheel, + prev_event_list_item , + &p_event->list_item); + + cl_qmap_insert( &p_event_wheel->events_map, key, &(p_event->map_item)); + + Exit: + CL_SPINLOCK_RELEASE( &p_event_wheel->lock ); + OSM_LOG_EXIT( p_event_wheel->p_log ); + + return cl_status; +} + +void +cl_event_wheel_unreg( + IN cl_event_wheel_t* const p_event_wheel, + IN uint64_t key ) +{ + cl_event_wheel_reg_info_t *p_event; + cl_map_item_t* p_map_item; + + OSM_LOG_ENTER( p_event_wheel->p_log, cl_event_wheel_unreg ); + + osm_log( p_event_wheel->p_log, OSM_LOG_DEBUG, + "cl_event_wheel_unreg: " + "Removing key:0x%"PRIx64"\n", key ); + + CL_SPINLOCK_ACQUIRE( &p_event_wheel->lock ); + p_map_item = cl_qmap_get( &p_event_wheel->events_map, key ); + if (p_map_item != cl_qmap_end( &p_event_wheel->events_map )) + { + /* we found such an item. */ + p_event = PARENT_STRUCT(p_map_item, cl_event_wheel_reg_info_t, map_item); + + /* remove the item from the qlist */ + cl_qlist_remove_item( &p_event_wheel->events_wheel, &(p_event->list_item)); + /* remove the item from the qmap */ + cl_qmap_remove_item( &p_event_wheel->events_map, &(p_event->map_item) ); + + osm_log( p_event_wheel->p_log, OSM_LOG_DEBUG, + "cl_event_wheel_unreg: " + "Removed key:0x%"PRIx64"\n", key ); + + /* free the item */ + free(p_event); + } + else + { + osm_log( p_event_wheel->p_log, OSM_LOG_DEBUG, + "cl_event_wheel_unreg: " + "Did not find key:0x%"PRIx64"\n", key ); + } + + CL_SPINLOCK_RELEASE( &p_event_wheel->lock ); + OSM_LOG_EXIT( p_event_wheel->p_log ); + +} + +uint32_t +cl_event_wheel_num_regs( + IN cl_event_wheel_t* const p_event_wheel, + IN uint64_t key ) +{ + + cl_event_wheel_reg_info_t *p_event; + cl_map_item_t* p_map_item; + uint32_t num_regs = 0; + + OSM_LOG_ENTER( p_event_wheel->p_log, cl_event_wheel_num_regs ); + + /* try to find the key in the map */ + osm_log( p_event_wheel->p_log, OSM_LOG_DEBUG, + "cl_event_wheel_num_regs: " + "Looking for key:0x%"PRIx64"\n", key ); + + CL_SPINLOCK_ACQUIRE( &p_event_wheel->lock ); + p_map_item = cl_qmap_get( &p_event_wheel->events_map, key ); + if (p_map_item != cl_qmap_end( &p_event_wheel->events_map )) + { + /* ok so we can simply return it's num_regs */ + p_event = PARENT_STRUCT(p_map_item, cl_event_wheel_reg_info_t, map_item); + num_regs = p_event->num_regs; + } + + CL_SPINLOCK_RELEASE( &p_event_wheel->lock ); + OSM_LOG_EXIT( p_event_wheel->p_log ); + return(num_regs); +} + +#ifdef __CL_EVENT_WHEEL_TEST__ + +/* Dump out the complete state of the event wheel */ +void __cl_event_wheel_dump( + IN cl_event_wheel_t* const p_event_wheel) +{ + cl_list_item_t *p_list_item; + cl_map_item_t *p_map_item; + cl_event_wheel_reg_info_t *p_event; + + printf("************** Event Wheel Dump ***********************\n"); + printf("Event Wheel List has %u items:\n", + cl_qlist_count( &p_event_wheel->events_wheel )); + + p_list_item = cl_qlist_head(&p_event_wheel->events_wheel); + while (p_list_item != cl_qlist_end(&p_event_wheel->events_wheel)) + { + p_event = PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t, list_item); + printf("Event key:0x%"PRIx64" Conetxt:%s NumRegs:%u\n", + p_event->key, (char *)p_event->context, p_event->num_regs); + + /* next */ + p_list_item = cl_qlist_next(p_list_item); + } + + printf("Event Map has %u items:\n", + cl_qmap_count( &p_event_wheel->events_map )); + + p_map_item = cl_qmap_head(&p_event_wheel->events_map); + while (p_map_item != cl_qmap_end(&p_event_wheel->events_map)) + { + p_event = PARENT_STRUCT(p_map_item, cl_event_wheel_reg_info_t, map_item); + printf("Event key:0x%"PRIx64" Conetxt:%s NumRegs:%u\n", + p_event->key, (char *)p_event->context, p_event->num_regs); + + /* next */ + p_map_item = cl_qmap_next(p_map_item); + } + +} + +/* The callback for aging event */ +/* We assume we pass a text context */ +void __test_event_aging(uint64_t key, void *context) +{ + printf("*****************************************************\n"); + printf("Aged key: 0x%"PRIx64" Conetxt:%s\n", key, (char *)context); +} + +int +main () +{ + osm_log_t log; + cl_event_wheel_t event_wheel; + /* uint64_t key; */ + + /* construct */ + osm_log_construct( &log ); + cl_event_wheel_construct( &event_wheel ); + + /* init */ + osm_log_init_v2( &log, TRUE, 0xff, NULL, 0, FALSE); + cl_event_wheel_init( &event_wheel, &log ); + + /* Start Playing */ + cl_event_wheel_reg( &event_wheel, + 1, /* key */ + cl_get_time_stamp() + 3000000, /* 3 sec lifetime */ + __test_event_aging, /* cb */ + "The first Aging Event" + ); + + cl_event_wheel_reg( &event_wheel, + 2, /* key */ + cl_get_time_stamp() + 3000000, /* 3 sec lifetime */ + __test_event_aging, /* cb */ + "The Second Aging Event" + ); + + cl_event_wheel_reg( &event_wheel, + 3, /* key */ + cl_get_time_stamp() + 3500000, /* 3 sec lifetime */ + __test_event_aging, /* cb */ + "The Third Aging Event" + ); + + __cl_event_wheel_dump(&event_wheel); + + sleep(2); + cl_event_wheel_reg( &event_wheel, + 2, /* key */ + cl_get_time_stamp() + 8000000, /* 3 sec lifetime */ + __test_event_aging, /* cb */ + "The Second Aging Event Moved" + ); + + __cl_event_wheel_dump(&event_wheel); + + sleep(1); + /* remove the third event */ + cl_event_wheel_unreg( &event_wheel, + 3); /* key */ + + /* get the number of registrations for the keys */ + printf("Event 1 Registred: %u\n", cl_event_wheel_num_regs(&event_wheel, 1)); + printf("Event 2 Registred: %u\n", cl_event_wheel_num_regs(&event_wheel, 2)); + + sleep(5); + /* destroy */ + cl_event_wheel_destroy( &event_wheel ); + + return(0); +} + +#endif /* __CL_EVENT_WHEEL_TEST__ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/main.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/main.c new file mode 100644 index 00000000..0aed5cc6 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/main.c @@ -0,0 +1,1158 @@ +/* + * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: main.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Command line interface for opensm. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.23 $ + */ +#pragma warning(disable : 4996) + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include "stdio.h" +#include +#include +#include +#include +#include +#include +#include + +/******************************************************************** + D E F I N E G L O B A L V A R I A B L E S +*********************************************************************/ +/* + This is the global opensm object. + One opensm object is required per subnet. + Future versions could support multiple subnets by + instantiating more than one opensm object. +*/ +osm_opensm_t osm; +volatile unsigned int osm_exit_flag = 0; +HANDLE osm_exit_event = NULL; + +#define GUID_ARRAY_SIZE 64 +#define INVALID_GUID (0xFFFFFFFFFFFFFFFFULL) + +typedef struct _osm_main_args_t +{ + int argc; + char** argv; + boolean_t is_service; +} osm_main_args_t; + +osm_main_args_t osm_main_args; + +enum service_state { + SERVICE_STATE_STARTING, + SERVICE_STATE_STARTED_OK, + SERVICE_STATE_START_FAILED +}; + +enum service_state g_service_state = SERVICE_STATE_STARTING; + +void OsmReportState(IN const char *p_str) +{ + if ( !strcmp(p_str, "SUBNET UP\n") || + !strcmp(p_str, "SM port is down\n") || + !strcmp(p_str, "Errors during initialization\n") || + !strcmp(p_str, "Entering STANDBY state\n") ) + { + InterlockedCompareExchange((LONG *)&g_service_state , SERVICE_STATE_STARTED_OK, SERVICE_STATE_STARTING); + return; + } + + if ( !strcmp(p_str, "Found remote SM with non-matching sm_key. Exiting\n") || + !strcmp(p_str, "Errors on subnet. Duplicate GUID found ""by link from a port to itself. ""See osm log for more details\n") || + !strcmp(p_str, "Errors on subnet. SM found duplicated guids or 12x ""link with lane reversal badly configured. ""See osm log for more details\n") || + !strcmp(p_str, "Fatal: Error restoring Guid-to-Lid persistent database\n") ) + + { + InterlockedCompareExchange((LONG *)&g_service_state , SERVICE_STATE_START_FAILED, SERVICE_STATE_STARTING); + return; + } + + if( !strcmp(p_str, "OpenSM Rev:openib-1.2.0\n") || + !strcmp(p_str, "OpenSM Rev:openib-2.0.3\n") || + !strcmp(p_str, "OpenSM Rev:openib-3.0.0\n") || + !strcmp(p_str, "Entering MASTER state\n") || + !strcmp(p_str, "Exiting SM\n") ) + { + // This are messages that it is safe to ignore + return; + } + CL_ASSERT(FALSE); + +} + +/********************************************************************** + **********************************************************************/ +void show_usage(void); + +void +show_usage(void) +{ + printf( "\n------- OpenSM - Usage and options ----------------------\n" ); + printf( "Usage: opensm [options]\n"); + printf( "Options:\n" ); + printf( "-c\n" + "--cache-options\n" + " Cache the given command line options into the file\n" + " /var/cache/osm/opensm.opts for use next invocation\n" + " The cache directory can be changed by the environment\n" + " variable OSM_CACHE_DIR\n\n"); + printf( "-g[=]\n" + "--guid[=]\n" + " This option specifies the local port GUID value\n" + " with which OpenSM should bind. OpenSM may be\n" + " bound to 1 port at a time.\n" + " If GUID given is 0, OpenSM displays a list\n" + " of possible port GUIDs and waits for user input.\n" + " Without -g, OpenSM tries to use the default port.\n\n"); + printf( "-l \n" + "--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 \n" + "--priority \n" + " This option specifies the SM's PRIORITY.\n" + " This will effect the handover cases, where master\n" + " is chosen by priority and GUID.\n\n" ); + printf( "-smkey \n" + " This option specifies the SM's SM_Key (64 bits).\n" + " This will effect SM authentication.\n\n" ); + printf( "-r\n" + "--reassign_lids\n" + " This option causes OpenSM to reassign LIDs to all\n" + " end nodes. Specifying -r on a running subnet\n" + " may disrupt subnet traffic.\n" + " Without -r, OpenSM attempts to preserve existing\n" + " LID assignments resolving multiple use of same LID.\n\n"); + printf( "-R\n" + "--routing_engine \n" + " This option chooses routing engine instead of Min Hop\n" + " algorithm (default). Supported engines: updn, file\n\n"); + printf( "-U\n" + "--ucast_file \n" + " This option specifies name of the unicast dump file\n" + " from where switch forwarding tables will be loaded.\n\n"); + printf ("-a\n" + "--add_guid_file \n" + " Set the root nodes for the Up/Down routing algorithm\n" + " to the guids provided in the given file (one to a line)\n" + "\n"); + printf( "-o\n" + "--once\n" + " This option causes OpenSM to configure the subnet\n" + " once, then exit. Ports remain in the ACTIVE state.\n\n" ); + printf( "-s \n" + "--sweep \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 \n" + "--timeout \n" + " This option specifies the time in milliseconds\n" + " used for transaction timeouts.\n" + " Specifying -t 0 disables timeouts.\n" + " Without -t, OpenSM defaults to a timeout value of\n" + " 200 milliseconds.\n\n" ); + printf( "-maxsmps \n" + " This option specifies the number of VL15 SMP MADs\n" + " allowed on the wire at any one time.\n" + " Specifying -maxsmps 0 allows unlimited outstanding\n" + " SMPs.\n" + " Without -maxsmps, OpenSM defaults to a maximum of\n" + " 4 outstanding SMPs.\n\n" ); + printf( "-i \n" + "-ignore-guids \n" + " This option provides the means to define a set of ports\n" + " (by guid) that will be ignored by the link load\n" + " equalization algorithm.\n\n" ); + printf( "-x\n" + "--honor_guid2lid\n" + " This option forces OpenSM to honor the guid2lid file,\n" + " when it comes out of Standby state, if such file exists\n" + " under OSM_CACHE_DIR, and is valid. By default, this is FALSE.\n\n" ); + printf( "-f\n" + "--log_file\n" + " This option defines the log to be the given file.\n" + " By default, the log goes to %temp%/log/osm.log.\n" + " For the log to go to standard output use -f stdout.\n\n"); + printf( "-e\n" + "--erase_log_file\n" + " This option will cause deletion of the log file\n" + " (if it previously exists). By default, the log file\n" + " is accumulative.\n\n"); + printf( "-P\n" + "--Pconfig\n" + " This option defines the optional partition configuration file.\n" + " The default name is '%s'.\n\n", OSM_DEFAULT_PARTITION_CONFIG_FILE); + printf( "-Q\n" + "--no_qos\n" + " This option disables QoS setup.\n\n"); + printf( "-N\n" + "--no_part_enforce\n" + " This option disables partition enforcement on switch external ports.\n\n"); + printf( "-y\n" + "--stay_on_fatal\n" + " This option will cause SM not to exit on fatal initialization\n" + " issues: if SM discovers duplicated guids or 12x link with\n" + " lane reversal badly configured.\n" + " By default, the SM will exit on these errors.\n\n"); + printf( "-v\n" + "--verbose\n" + " This option increases the log verbosity level.\n" + " The -v option may be specified multiple times\n" + " to further increase the verbosity level.\n" + " See the -D option for more information about\n" + " log verbosity.\n\n" ); + printf( "-V\n" + " This option sets the maximum verbosity level and\n" + " forces log flushing.\n" + " The -V is equivalent to '-D 0xFF -d 2'.\n" + " See the -D option for more information about\n" + " log verbosity.\n\n" ); + printf( "-D \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 \n" + "--debug \n" + " This option specifies a debug option.\n" + " These options are not normally needed.\n" + " The number following -d selects the debug\n" + " option to enable as follows:\n" + " OPT Description\n" + " --- -----------------\n" + " -d0 - Ignore other SM nodes\n" + " -d1 - Force single threaded dispatching\n" + " -d2 - Force log flushing after each log message\n" + " -d3 - Disable multicast support\n" + " -d10 - Put OpenSM in testability mode\n" + " Without -d, no debug options are enabled\n\n" ); + printf( "-h\n" + "--help\n" + " Display this usage info then exit.\n\n" ); + printf( "-?\n" + " Display this usage info then exit.\n\n" ); + fflush( stdout ); + osm_exit_flag = TRUE; +} + +/********************************************************************** + **********************************************************************/ +void show_menu(void); + +void +show_menu(void) +{ + printf("\n------- Interactive Menu -------\n"); + printf("X - Exit.\n\n"); +} + +/********************************************************************** + **********************************************************************/ +ib_net64_t +get_port_guid( + IN osm_opensm_t *p_osm, uint64_t port_guid, + IN boolean_t is_service) +{ + uint32_t i; + uint32_t choice = 0; + char junk[128]; + boolean_t done_flag = FALSE; + ib_api_status_t status; + uint32_t num_ports = GUID_ARRAY_SIZE; + ib_port_attr_t attr_array[GUID_ARRAY_SIZE]; + + /* + Call the transport layer for a list of local port + GUID values. + */ + status = osm_vendor_get_all_port_attr( p_osm->p_vendor, attr_array, &num_ports ); + if( status != IB_SUCCESS ) + { + printf( "\nError from osm_vendor_get_all_port_attr (%x)\n", status); + return( 0 ); + } + + /* if num_ports is 0 - return 0 */ + if( num_ports == 0 ) + { + printf( "\nNo local ports detected!\n" ); + return( 0 ); + } + /* If num_ports is 1, then there is only one possible port to use. Use it. */ + if ( num_ports == 1 ) + { + printf("Using default GUID 0x%" PRIx64 "\n", cl_hton64(attr_array[0].port_guid)); + return( attr_array[0].port_guid ); + } + +#if defined ( OSM_VENDOR_INTF_OPENIB ) + /* If port_guid is 0, and this is gen2 - use the default port whose info is in attr_array[0] */ + if ( port_guid == 0 ) + { + printf("Using default GUID 0x%" PRIx64 "\n", cl_hton64(attr_array[0].port_guid)); + return( attr_array[0].port_guid ); + } +#endif /* OSM_VENDOR_INTF_OPENIB */ + + /* If port_guid is 0, and we are in windows - find the first port with link_state != DOWN and + use it as default port. */ + if ( port_guid == 0 ) + { + for ( i = 0; i < num_ports; i++ ) + { + if (attr_array[i].link_state > IB_LINK_DOWN) + { + /* Use this port */ + printf("Using default guid 0x%" PRIx64 "\n", cl_hton64(attr_array[i].port_guid)); + return( attr_array[i].port_guid ); + } + } + /* If we are running as a service, and all ports are doen we return the + first port (we can't open a window, as a service)*/ + if (is_service) { + return( attr_array[0].port_guid ); + } + } + + /* More than one possible port - list all ports and let the user to choose. */ + while( done_flag == FALSE ) + { + printf( "\nChoose a local port number with which to bind:\n\n" ); + /* If this is gen2 code - then port 0 has details of the default port used. + no need to print it. + If this is not gen2 code - need to print details of all ports. */ +#if defined ( OSM_VENDOR_INTF_OPENIB ) + for( i = 1; i < num_ports; i++ ) + { + printf("\t%u: GUID = 0x%8" PRIx64 ", lid = 0x%04X, state = %s\n", + i, cl_ntoh64( attr_array[i].port_guid ), + attr_array[i].lid, + ib_get_port_state_str( attr_array[i].link_state ) ); + } + printf( "\nEnter choice (1-%u): ", i-1 ); +# else + for( i = 0; i < num_ports; i++ ) + { + /* + Print the index + 1 since by convention, port numbers + start with 1 on host channel adapters. + */ + + printf("\t%u: GUID = 0x%8" PRIx64 ", lid = 0x%04X, state = %s\n", + i+1, cl_ntoh64( attr_array[i].port_guid ), + attr_array[i].lid, + ib_get_port_state_str( attr_array[i].link_state ) ); + } + printf( "\nEnter choice (1-%u): ", i ); +#endif /* OSM_VENDOR_INTF_OPENIB */ + + fflush( stdout ); + if (scanf( "%u", &choice )) + { + /* If gen2 code - choice can be between 1 to num_ports-1 + if not gen2 code - choice can be between 1 to num_ports */ +#if defined ( OSM_VENDOR_INTF_OPENIB ) + if( choice >= num_ports ) +# else + if( choice > num_ports || choice < 1 ) +#endif /* OSM_VENDOR_INTF_OPENIB */ + { + printf("\nError: Lame choice!\n"); + fflush( stdin ); + } + else + { + done_flag = TRUE; + } + } + else + { + /* get rid of the junk in the selection line */ + scanf( "%s", junk ); + printf("\nError: Lame choice!\n"); + fflush( stdin ); + } + } +#if defined ( OSM_VENDOR_INTF_OPENIB ) + printf("Choice guid=0x%8" PRIx64 "\n", cl_ntoh64( attr_array[choice].port_guid )); + return( attr_array[choice].port_guid ); +# else + return( attr_array[choice - 1].port_guid ); +#endif /* OSM_VENDOR_INTF_OPENIB */ +} + +/********************************************************************** + **********************************************************************/ +#define OSM_MAX_IGNORE_GUID_LINES_LEN 128 +int +parse_ignore_guids_file(IN char *guids_file_name, + IN osm_opensm_t *p_osm) +{ + FILE *fh; + char line[OSM_MAX_IGNORE_GUID_LINES_LEN]; + char *p_c, *p_ec; + uint32_t line_num = 0; + uint64_t port_guid; + ib_api_status_t status = IB_SUCCESS; + unsigned int port_num; + + OSM_LOG_ENTER( &p_osm->log, parse_ignore_guids_file ); + + fh = fopen( guids_file_name, "r" ); + if( fh == NULL ) + { + osm_log( &p_osm->log, OSM_LOG_ERROR, + "parse_ignore_guids_file: ERR 0601: " + "Unable to open ignore guids file (%s)\n" ); + status = IB_ERROR; + goto Exit; + } + + /* + * Parse the file and add to the ignore guids map. + */ + while( fgets( line, OSM_MAX_IGNORE_GUID_LINES_LEN, fh ) != NULL ) + { + line_num++; + p_c = line; + while ( (*p_c == ' ') && (*p_c != '\0')) p_c++ ; + port_guid = cl_hton64( strtoull( p_c, &p_ec, 16 ) ); + if (p_ec == p_c) + { + osm_log( &p_osm->log, OSM_LOG_ERROR, + "parse_ignore_guids_file: ERR 0602: " + "Error in line (%u): %s\n" , + line_num, line + ); + status = IB_ERROR; + goto Exit; + } + + while ( (*p_ec == ' ') && (*p_ec != '\0')) p_ec++ ; + if (! sscanf(p_ec, "%d", &port_num)) + { + osm_log( &p_osm->log, OSM_LOG_ERROR, + "parse_ignore_guids_file: ERR 0603: " + "Error in line (%u): %s\n" , + line_num, p_ec + ); + status = IB_ERROR; + goto Exit; + } + /* Make sure the port_num isn't greater than 256 */ + if (port_num > 256) + { + osm_log( &p_osm->log, OSM_LOG_ERROR, + "parse_ignore_guids_file: ERR 0604: " + "Error in line (%u): %s. " + "port number is greater than 256 (%d) \n", + line_num, p_ec, port_num + ); + status = IB_ERROR; + goto Exit; + } + /* ok insert it */ + osm_port_prof_set_ignored_port(&p_osm->subn, port_guid, (uint8_t)port_num); + osm_log( &p_osm->log, OSM_LOG_DEBUG, + "parse_ignore_guids_file: " + "Inserted Port: 0x%" PRIx64 " into ignored guids list\n" , + port_guid + ); + + } + + fclose( fh ); + + Exit: + OSM_LOG_EXIT( &p_osm->log ); + return ( status ); + +} + +/********************************************************************** + **********************************************************************/ +int +opensm_main( + void *osm_main_args) +{ + int argc = ((osm_main_args_t*)osm_main_args)->argc; + char** argv = ((osm_main_args_t*)osm_main_args)->argv; + osm_subn_opt_t opt; + ib_net64_t sm_key = 0; + ib_api_status_t status; + uint32_t log_flags = OSM_LOG_DEFAULT_LEVEL; + int long temp; + uint32_t dbg_lvl; + boolean_t run_once_flag = FALSE; + boolean_t mem_track = FALSE; + uint32_t next_option; + uint32_t exitTimeout; + boolean_t cache_options = FALSE; + char *ignore_guids_file_name = NULL; + uint32_t val; + const char * const short_option = "i:f:ed:g:l:L:s:t:a:R:U:P:NQvVhorcyx"; + + + /* + In the array below, the 2nd parameter specified the number + of arguments as follows: + 0: no arguments + 1: argument + 2: optional + */ + const struct option long_option[] = + { + { "service", 0, NULL, 'Z'}, + { "debug", 1, NULL, 'd'}, + { "guid", 1, NULL, 'g'}, + { "ignore_guids", 1, NULL, 'i'}, + { "lmc", 1, NULL, 'l'}, + { "sweep", 1, NULL, 's'}, + { "timeout", 1, NULL, 't'}, + { "verbose", 0, NULL, 'v'}, + { "D", 1, NULL, 'D'}, + { "log_file", 1, NULL, 'f'}, + { "log_limit", 1, NULL, 'L'}, + { "erase_log_file",0, NULL, 'e'}, + { "Pconfig", 1, NULL, 'P'}, + { "no_part_enforce",0,NULL, 'N'}, + { "no_qos", 0, NULL, 'Q'}, + { "maxsmps", 1, NULL, 'n'}, + { "console", 0, NULL, 'q'}, + { "V", 0, NULL, 'V'}, + { "help", 0, NULL, 'h'}, + { "once", 0, NULL, 'o'}, + { "reassign_lids", 0, NULL, 'r'}, + { "priority", 1, NULL, 'p'}, + { "smkey", 1, NULL, 'k'}, + { "routing_engine",1, NULL, 'R'}, + { "ucast_file" ,1, NULL, 'U'}, + { "add_guid_file", 1, NULL, 'a'}, + { "cache-options", 0, NULL, 'c'}, + { "stay_on_fatal", 0, NULL, 'y'}, + { "honor_guid2lid", 0, NULL, 'x'}, + { NULL, 0, NULL, 0 } /* Required at the end of the array */ + }; + printf("-------------------------------------------------\n"); + printf("%s\n", OSM_VERSION); + + osm_subn_set_default_opt(&opt); + osm_subn_parse_conf_file(&opt); + + printf("Command Line Arguments:\n"); + do + { + next_option = getopt_long_only(argc, argv, short_option, + long_option, NULL); + switch(next_option) + { + case 'Z': + /* + service option - nothing to do + */ + break; + + case 'o': + /* + Run once option. + */ + run_once_flag = TRUE; + printf(" Run Once\n"); + break; + + case 'r': + /* + Reassign LIDs subnet option. + */ + opt.reassign_lids = TRUE; + printf(" Reassign LIDs\n"); + break; + + case 'i': + /* + Specifies ignore guids file. + */ + ignore_guids_file_name = optarg; + printf(" Ignore Guids File = %s\n", ignore_guids_file_name); + break; + + case 'g': + /* + Specifies port guid with which to bind. + */ + opt.guid = cl_hton64( strtoull( optarg, NULL, 16 )); + if (! opt.guid) + { + /* If guid is 0 - need to display the guid list */ + opt.guid = INVALID_GUID; + } + else + printf(" Guid <0x%"PRIx64">\n", cl_hton64( opt.guid )); + break; + + case 's': + val = strtol(optarg, NULL, 0); + /* Check that the number is not too large */ + if ( ((uint32_t)(val * 1000000)) / 1000000 != val ) + fprintf(stderr, "ERROR: sweep interval given is too large. Ignoring it.\n"); + else + { + opt.sweep_interval = val; + printf(" sweep interval = %d\n", opt.sweep_interval); + } + break; + + case 't': + opt.transaction_timeout = strtol(optarg, NULL, 0); + printf(" Transaction timeout = %d\n", opt.transaction_timeout); + break; + + case 'n': + opt.max_wire_smps = strtol(optarg, NULL, 0); + if( opt.max_wire_smps <= 0 ) + opt.max_wire_smps = 0x7FFFFFFF; + printf(" Max wire smp's = %d\n", opt.max_wire_smps); + break; + + case 'q': + /* + * OpenSM interactive console + */ + opt.console = TRUE; + printf(" Enabling OpenSM interactive console\n"); + break; + + case 'd': + dbg_lvl = strtol(optarg, NULL, 0); + printf(" d level = 0x%x\n", dbg_lvl); + if (dbg_lvl == 0) + { + printf(" Debug mode: Ignore Other SMs\n"); + opt.ignore_other_sm = TRUE; + } + else if(dbg_lvl == 1) + { + printf(" Debug mode: Forcing Single Thread\n"); + opt.single_thread = TRUE; + } + else if(dbg_lvl == 2) + { + printf(" Debug mode: Force Log Flush\n"); + opt.force_log_flush = TRUE; + } + else if(dbg_lvl == 3) + { + printf(" Debug mode: Disable multicast support\n"); + opt.disable_multicast = TRUE; + } + /* + * NOTE: Debug level 4 used to be used for memory tracking + * but this is now deprecated + */ + else if(dbg_lvl >= 10) + { + /* Please look at osm_subnet.h for list of testability modes. */ + opt.testability_mode = dbg_lvl - 9; + } + else + printf( " OpenSM: Unknown debug option %d ignored\n", + dbg_lvl ); + break; + + case 'l': + temp = strtol(optarg, NULL, 0); + if( temp > 7 ) + { + fprintf(stderr, "ERROR: LMC must be 7 or less."); + return( -1 ); + } + opt.lmc = (uint8_t)temp; + printf(" LMC = %d\n", temp); + break; + + case 'D': + log_flags = strtol(optarg, NULL, 0); + printf(" verbose option -D = 0x%x\n", log_flags); + break; + + case 'f': + if (!strcmp(optarg, "stdout")) + /* output should be to standard output */ + opt.log_file = NULL; + else + opt.log_file = optarg; + break; + + case 'L': + opt.log_max_size = strtoul(optarg, NULL, 0) * (1024*1024); + printf(" Log file max size is %lu bytes\n", opt.log_max_size); + break; + + case 'e': + opt.accum_log_file = FALSE; + printf(" Creating new log file\n"); + break; + + case 'P': + opt.partition_config_file = optarg; + break; + + case 'N': + opt.no_partition_enforcement = TRUE; + break; + + case 'Q': + opt.no_qos = TRUE; + break; + + case 'y': + opt.exit_on_fatal = FALSE; + printf(" Staying on fatal initialization errors\n"); + break; + + case 'v': + log_flags = (log_flags <<1 )|1; + printf(" Verbose option -v (log flags = 0x%X)\n", log_flags ); + break; + + case 'V': + log_flags = 0xFFFFFFFF; + opt.force_log_flush = TRUE; + printf(" Big V selected\n"); + break; + + case 'p': + temp = strtol(optarg, NULL, 0); + if (0 > temp || 15 < temp) { + fprintf(stderr, "ERROR: priority must be between 0 and 15\n"); + return (-1); + } + opt.sm_priority = (uint8_t)temp; + printf(" Priority = %d\n", temp); + break; + + case 'k': + sm_key = cl_hton64( strtoull( optarg, NULL, 16 )); + printf(" SM Key <0x%"PRIx64">\n", cl_hton64( sm_key )); + opt.sm_key = sm_key; + break; + + case 'R': + opt.routing_engine_name = optarg; + printf(" Activate \'%s\' routing engine\n", optarg); + break; + + case 'U': + opt.ucast_dump_file = optarg; + printf(" Ucast dump file is \'%s\'\n", optarg); + break; + + case 'a': + /* + Specifies port guids file + */ + opt.updn_guid_file = optarg; + printf (" UPDN Guid File: %s\n", opt.updn_guid_file ); + break; + + case 'c': + cache_options = TRUE; + printf (" Caching command line options\n"); + break; + + case 'x': + opt.honor_guid2lid_file = TRUE; + printf (" Honor guid2lid file, if possible\n"); + break; + + case 'h': + case '?': + case ':': + show_usage(); + return 0; + break; + + case -1: + break; /* done with option */ + default: /* something wrong */ + abort(); + } + } + while(next_option != -1); + + if (opt.log_file != NULL ) + printf(" Log File: %s\n", opt.log_file ); + /* Done with options description */ + printf("-------------------------------------------------\n"); + + opt.log_flags = (uint8_t)log_flags; + + status = osm_opensm_init( &osm, &opt ); + if( status != IB_SUCCESS ) + { + char buffer[LOG_ENTRY_SIZE_MAX]; + const char *err_str = ib_get_err_str( status ); + if (err_str == NULL) + { + err_str = "Unknown Error Type"; + } + printf( "\nError from osm_opensm_init: %s.\n", + err_str); + sprintf(buffer, "Error from osm_opensm_init: %s. See opensm log file for more details", err_str); + /* We will just exit, and not go to Exit, since we don't + want the destroy to be called. */ + cl_log_event("OpenSM", LOG_ERR, buffer , NULL, 0); + g_service_state = SERVICE_STATE_START_FAILED; + return( status ); + } + + /* + If the user didn't specify a GUID on the command line, + then get a port GUID value with which to bind. + */ + if( opt.guid == 0 || cl_hton64(opt.guid) == CL_HTON64(INVALID_GUID)) + opt.guid = get_port_guid( &osm, opt.guid, ((osm_main_args_t*)osm_main_args)->is_service ); + + if ( opt.guid == 0 ) + { + printf( "Error: Could not get port guid \n" ); + status = IB_ERROR; + goto Exit; + } + + if ( cache_options == TRUE ) + osm_subn_write_conf_file( &opt ); + + status = osm_opensm_bind( &osm, opt.guid ); + if( status != IB_SUCCESS ) + { + printf( "\nError from osm_opensm_bind (0x%X)\n", status ); + goto Exit; + } + + /* + * Define some port guids to ignore during path equalization + */ + if (ignore_guids_file_name != NULL) + { + status = parse_ignore_guids_file(ignore_guids_file_name, &osm); + if( status != IB_SUCCESS ) + { + printf( "\nError from parse_ignore_guids_file (0x%X)\n", status ); + goto Exit; + } + } + + osm_opensm_sweep( &osm ); + + status = osm_opensm_wait_for_subnet_up( + &osm, EVENT_NO_TIMEOUT, TRUE ); + + if( status != CL_SUCCESS ) + { + printf( "\nError from osm_opensm_wait_for_subnet_up (0x%X)\n", status ); + goto Exit; + } + + if( run_once_flag == FALSE ) + { + /* + Sit here forever + In the future, some sort of console interactivity could + be implemented in this loop. + */ + WaitForSingleObject(osm_exit_event, INFINITE); + osm_exit_flag = TRUE; + } + + /* wait for all transactions to end */ + CL_ASSERT( ((opt.polling_retry_number + 1) * opt.transaction_timeout / 1000.0) < 0x100000000ULL ); + exitTimeout = + (uint32_t) ((opt.polling_retry_number + 1) * opt.transaction_timeout / 1000.0); + + if (exitTimeout < 3) exitTimeout = 3; + + /* + printf( "\n------- OpenSM Exiting (in %u seconds) -------\n", + exitTimeout); + sleep(exitTimeout); + */ + + if (osm.mad_pool.mads_out) + fprintf(stdout, + "There are still %u MADs out. Forcing the exit of the OpenSM application...\n", + osm.mad_pool.mads_out); + + Exit: + g_service_state = SERVICE_STATE_START_FAILED; + osm_opensm_destroy( &osm ); + + exit( 0 ); +} + +SERVICE_STATUS OsmServiceStatus; +SERVICE_STATUS_HANDLE OsmServiceStatusHandle; + +VOID SvcDebugOut(LPSTR String, DWORD Status); +VOID WINAPI OsmServiceCtrlHandler (DWORD opcode); +__stdcall OsmServiceStart (DWORD argc, LPTSTR *argv); + +DWORD OsmServiceInitialization (DWORD argc, LPTSTR *argv, + DWORD *specificError); + +int __cdecl +main ( + int argc, + char* argv[] ) +{ + int i; + boolean_t run_as_service = FALSE; + osm_main_args.argc = argc; + osm_main_args.argv = argv; + /* If there are arguments that the executable is ran with, then this is + not running as service - just run the opensm_main. */ + for (i = 0 ; i< argc ; i++) + if (!strcmp(argv[i], "--service")) + { + run_as_service = TRUE; + osm_main_args.is_service = TRUE; + break; + } + osm_exit_event = CreateEvent(NULL, FALSE, FALSE, NULL); + if(osm_exit_event == NULL) + { + printf( "\nCreateEvent failed gle=%d\n", GetLastError()); + return( 1 ); + } + + if (!run_as_service) + { + /* Running as executable */ + osm_main_args.is_service = FALSE; + return opensm_main(&osm_main_args); + } + else + { + /* Running as service */ + SERVICE_TABLE_ENTRY DispatchTable[] = + { + { "OsmService", OsmServiceStart }, + { NULL, NULL } + }; + // Give older versions of opensm a chance to stop + Sleep(3000); + + if (!StartServiceCtrlDispatcher( DispatchTable)) + { + SvcDebugOut(" [OSM_SERVICE] StartServiceCtrlDispatcher (%d)\n", + GetLastError()); + } + } +} + +VOID SvcDebugOut(LPSTR String, DWORD Status) +{ + CHAR Buffer[1024]; + if (strlen(String) < 1000) + { + sprintf(Buffer, String, Status); + OutputDebugStringA(Buffer); + } +} + +VOID WINAPI OsmServiceCtrlHandler (DWORD Opcode) +{ + DWORD status; + + switch(Opcode) + { + case SERVICE_CONTROL_SHUTDOWN: + case SERVICE_CONTROL_STOP: + // Do whatever it takes to stop here. + osm_exit_flag = TRUE; + SetEvent(osm_exit_event); + OsmServiceStatus.dwWin32ExitCode = 0; + OsmServiceStatus.dwCurrentState = SERVICE_STOPPED; + OsmServiceStatus.dwCheckPoint = 0; + OsmServiceStatus.dwWaitHint = 0; + + if (!SetServiceStatus (OsmServiceStatusHandle, + &OsmServiceStatus)) + { + status = GetLastError(); + SvcDebugOut(" [OSM_SERVICE] SetServiceStatus error %ld\n", + status); + } + + SvcDebugOut(" [OSM_SERVICE] Leaving OsmService \n",0); + return; + + case SERVICE_CONTROL_INTERROGATE: + // Fall through to send current status. + break; + + default: + SvcDebugOut(" [OSM_SERVICE] Unrecognized opcode %ld\n", + Opcode); + } + + // Send current status. + if (!SetServiceStatus (OsmServiceStatusHandle, &OsmServiceStatus)) + { + status = GetLastError(); + SvcDebugOut(" [OSM_SERVICE] SetServiceStatus error %ld\n", + status); + } + return; +} + +__stdcall OsmServiceStart (DWORD argc, LPTSTR *argv) +{ + DWORD status; + DWORD specificError; + + OsmServiceStatus.dwServiceType = SERVICE_WIN32; + OsmServiceStatus.dwCurrentState = SERVICE_START_PENDING; + OsmServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | + SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_SHUTDOWN; + OsmServiceStatus.dwWin32ExitCode = 0; + OsmServiceStatus.dwServiceSpecificExitCode = 0; + OsmServiceStatus.dwCheckPoint = 0; + OsmServiceStatus.dwWaitHint = 2000; + + OsmServiceStatusHandle = RegisterServiceCtrlHandler( + "OsmService", + OsmServiceCtrlHandler); + + if (OsmServiceStatusHandle == (SERVICE_STATUS_HANDLE)0) + { + SvcDebugOut(" [OSM_SERVICE] RegisterServiceCtrlHandler failed %d\n", GetLastError()); + return 0; + } + + // Initialization code goes here. + status = OsmServiceInitialization(argc,argv, &specificError); + while (status == NO_ERROR && g_service_state == SERVICE_STATE_STARTING) + { + Sleep(1000); + OsmServiceStatus.dwCheckPoint++; + if (!SetServiceStatus (OsmServiceStatusHandle, &OsmServiceStatus)) + { + status = GetLastError(); + SvcDebugOut(" [OSM_SERVICE] SetServiceStatus error %ld\n",status); + } + + } + CL_ASSERT(g_service_state == SERVICE_STATE_STARTED_OK || + g_service_state == SERVICE_STATE_START_FAILED || + status != NO_ERROR); + + // Handle error condition + if (status != NO_ERROR || g_service_state == SERVICE_STATE_START_FAILED) + { + OsmServiceStatus.dwCurrentState = SERVICE_STOPPED; + OsmServiceStatus.dwCheckPoint = 0; + OsmServiceStatus.dwWaitHint = 0; + OsmServiceStatus.dwWin32ExitCode = status; + OsmServiceStatus.dwServiceSpecificExitCode = specificError; + + SetServiceStatus (OsmServiceStatusHandle, &OsmServiceStatus); + return 0; + } + + // Initialization complete - report running status. + OsmServiceStatus.dwCurrentState = SERVICE_RUNNING; + OsmServiceStatus.dwCheckPoint = 0; + OsmServiceStatus.dwWaitHint = 0; + + if (!SetServiceStatus (OsmServiceStatusHandle, &OsmServiceStatus)) + { + status = GetLastError(); + SvcDebugOut(" [OSM_SERVICE] SetServiceStatus error %ld\n",status); + } + + // This is where the service does its work. + SvcDebugOut(" [OSM_SERVICE] Returning the Main Thread \n",0); + + return 1; +} + +// Stub initialization function. +DWORD OsmServiceInitialization(DWORD argc, LPTSTR *argv, + DWORD *specificError) +{ + if (CreateThread(NULL, 0, opensm_main, &osm_main_args, 0, NULL) == NULL) + { + SvcDebugOut(" [OSM_SERVICE] failed to create thread (%d)\n", + GetLastError()); + return(1); + } + return(0); +} diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/opensm.opts b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/opensm.opts new file mode 100644 index 00000000..122e151e --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/opensm.opts @@ -0,0 +1,139 @@ +# +# DEVICE ATTRIBUTES OPTIONS +# +# The port GUID on which the OpenSM is running. +#guid + +# M_Key value sent to all ports qualifing all Set(PortInfo). +#m_key 0x0000000000000000 + +# The lease period used for the M_Key on this subnet in [msec] +#m_key_lease_period 0 + +# SM_Key value of the SM to qualify rcv SA queries as 'trusted' +#sm_key 0x0100000000000000 + +# Subnet prefix used on this subnet +#subnet_prefix 0xfe80000000000000 + +# The LMC value used on this subnet +#lmc 0 + +# The code of maximal time a packet can live in a switch +# The actual time is 4.096usec * 2^ +# The value 0x14 disables this mechanism +#packet_life_time 0x12 + +# The code of maximal time a packet can wait at the head of +# transmission queue. +# The actual time is 4.096usec * 2^ +# The value 0x14 disables this mechanism +#head_of_queue_lifetime 0x12 + +# The maximal time a packet can wait at the head of queue on +# switch port connected to a HCA +#leaf_head_of_queue_lifetime 0x0c + +# Limit the maximal operational VLs +#max_op_vls 5 + +# The subnet_timeout code that will be set for all the ports +# The actual timeout is 4.096usec * 2^ +#subnet_timeout 18 + +# Threshold of local phy errors for sending Trap 129 +#local_phy_errors_threshold 0x08 + +# Threshold of credits over-run errors for sending Trap 129 +#overrun_errors_threshold 0x08 + +# +# SWEEP OPTIONS +# +# The number of seconds between subnet sweeps (0 disables it) +#sweep_interval 10 + +# If TRUE cause all lids to be re-assigned +#reassign_lids FALSE + +# 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... +#reassign_lfts TRUE + +# If true forces every sweep to be a heavy sweep +#force_heavy_sweep FALSE + +# If true every trap will cause a heavy sweep. +# NOTE: successive same traps (>10) are supressed +#sweep_on_trap TRUE + +# +# ROUTING OPTIONS +# +# If true do not count switches as link subscriptions +#port_profile_switch_nodes FALSE + +# Activate the Up/Down routing algorithm +#updn_activate FALSE + +# +# HANDOVER - MULTIPLE SM's OPTIONS +# +# SM priority used for deciding who is the master +#sm_priority 1 + +# If TRUE other SM's on the subnet should be ignored +#ignore_other_sm FALSE + +# Timeout in [sec] between two polls of active master SM +#sminfo_polling_timeout 10000 + +# Number of failing polls of remote SM that declares it dead +#polling_retry_number 4 + +# +# TIMING AND THREADING OPTIONS +# +# Number of MADs sent in parallel +#max_wire_smps 4 + +# The time taken to a transaction to finish in [msec] +#transaction_timeout 200 + +# Maximal time in [msec] 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 any SA request will be +# immediately returned with a BUSY status. +#max_msg_fifo_timeout 10000 + +# Use a single thread for handling SA queries +#single_thread FALSE + +# +# DEBUG FEATURES +# +# The log flags used +#log_flags 0x03 + +# Force flush of the log file after each log message +#force_log_flush TRUE + +# Log file to be used +#log_file + +#accum_log_file TRUE + +# The directory to hold the file OpenSM dumps +#dump_files_dir + +# If TRUE if OpenSM should disable multicast support +#no_multicast_option FALSE + +# No multicast routing is performed if TRUE +#disable_multicast FALSE + +# If TRUE opensm will exit on fatal initialization issues +#exit_on_fatal TRUE + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/opensm.rc b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/opensm.rc new file mode 100644 index 00000000..68e4faad --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/opensm.rc @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2005 Mellanox Technologies. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: opensm.rc 2624 2009-12-07 18:06:48Z stansmith $ + */ + + +#include + +#define VER_FILETYPE VFT_APP +#define VER_FILESUBTYPE VFT2_UNKNOWN +#ifdef _DEBUG_ +#define VER_FILEDESCRIPTION_STR "Debug OpenSM Subnet Manager (3.0.0)" +#define VER_INTERNALNAME_STR "opensm.exe" +#define VER_ORIGINALFILENAME_STR "opensm.exe" +#else +#define VER_FILEDESCRIPTION_STR "OpenSM Subnet Manager (3.0.0)" +#define VER_INTERNALNAME_STR "opensm.exe" +#define VER_ORIGINALFILENAME_STR "opensm.exe" +#endif +#include diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm.mc b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm.mc new file mode 100644 index 00000000..3030f718 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm.mc @@ -0,0 +1,29 @@ +;/*++ +;============================================================================= +;Copyright (c) 2005 Mellanox Technologies +; +;Module Name: +; +; osm.mc +; +;Abstract: +; +; OpenSM event log messages +; +;Authors: +; +; Leonid Keller +; +;Environment: +; +; Kernel Mode . +; +;============================================================================= +;--*/ +; + +MessageId=0x0000 SymbolicName=EVENT_OSM_ANY_INFO +Language=English +%1 +. + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_console.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_console.c new file mode 100644 index 00000000..45c16e10 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_console.c @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_console.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#define _GNU_SOURCE /* for getline */ +#include +#include +#include +#include + +#define OSM_COMMAND_LINE_LEN 120 +#define OSM_COMMAND_PROMPT "$ " + +struct command { + char *name; + void (*help_function)(void); + void (*parse_function)(char **p_last, osm_opensm_t *p_osm); +}; + +static const struct command console_cmds[]; + +static inline char *next_token(char **p_last) +{ + return strtok_r(NULL, " \t\n", p_last); +} + +static void help_command() +{ + int i; + + printf("Supported commands and syntax:\n"); + printf("help []\n"); + /* skip help command */ + for (i = 1; console_cmds[i].name; i++) + console_cmds[i].help_function(); +} + +static void help_loglevel() +{ + printf("loglevel []\n"); +} + +static void help_priority() +{ + printf("priority []\n"); +} + +/* more help routines go here */ + +static void help_parse(char **p_last, osm_opensm_t *p_osm) +{ + char *p_cmd; + int i, found = 0; + + p_cmd = next_token(p_last); + if (!p_cmd) + help_command(); + else { + for (i = 1; console_cmds[i].name; i++) { + if (!strcmp(p_cmd, console_cmds[i].name)) { + found = 1; + console_cmds[i].help_function(); + break; + } + } + if (!found) { + printf("Command %s not found\n\n", p_cmd); + help_command(); + } + } +} + +static void loglevel_parse(char **p_last, osm_opensm_t *p_osm) +{ + char *p_cmd; + int level; + + p_cmd = next_token(p_last); + if (!p_cmd) + printf("Current log level is 0x%x\n", osm_log_get_level(&p_osm->log)); + else { + /* Handle x, 0x, and decimal specification of log level */ + if (!strncmp(p_cmd, "x", 1)) { + p_cmd++; + level = strtoul(p_cmd, NULL, 16); + } else { + if (!strncmp(p_cmd, "0x", 2)) { + p_cmd += 2; + level = strtoul(p_cmd, NULL, 16); + } else + level = strtol(p_cmd, NULL, 10); + } + if ((level >= 0) && (level < 256)) { + printf("Setting log level to 0x%x\n", level); + osm_log_set_level(&p_osm->log, level); + } else + printf("Invalid log level 0x%x\n", level); + } +} + +static void priority_parse(char **p_last, osm_opensm_t *p_osm) +{ + char *p_cmd; + int priority; + + p_cmd = next_token(p_last); + if (!p_cmd) + printf("Current sm-priority is %d\n", p_osm->subn.opt.sm_priority); + else { + priority = strtol(p_cmd, NULL, 0); + if (0 > priority || 15 < priority) + printf("Invalid sm-priority %d; must be between 0 and 15\n", priority); + else { + printf("Setting sm-priority to %d\n", priority); + p_osm->subn.opt.sm_priority = (uint8_t)priority; + /* Does the SM state machine need a kick now ? */ + } + } +} + +/* more parse routines go here */ + +static const struct command console_cmds[] = +{ + { "help", &help_command, &help_parse}, + { "loglevel", &help_loglevel, &loglevel_parse}, + { "priority", &help_priority, &priority_parse}, + { NULL, NULL, NULL} /* end of array */ +}; + +static void parse_cmd_line(char *line, osm_opensm_t *p_osm) +{ + char *p_cmd, *p_last; + int i, found = 0; + + /* find first token which is the command */ + p_cmd = strtok_r(line, " \t\n", &p_last); + if (p_cmd) { + for (i = 0; console_cmds[i].name; i++) { + if (!strcmp(p_cmd, console_cmds[i].name)) { + found = 1; + console_cmds[i].parse_function(&p_last, p_osm); + break; + } + } + if (!found) { + printf("Command %s not found\n\n", p_cmd); + help_command(); + } + } else { + printf("Error parsing command line: %s\n", line); + return; + } +} + +void osm_console_prompt(void) +{ + printf("%s", OSM_COMMAND_PROMPT); + fflush(stdout); +} + +void osm_console(osm_opensm_t *p_osm) +{ + struct pollfd pollfd; + char *p_line; + size_t len; + ssize_t n; + + pollfd.fd = 0; + pollfd.events = POLLIN; + pollfd.revents = 0; + + if (poll(&pollfd, 1, 10000) <= 0) + return; + + if (pollfd.revents|POLLIN) { + p_line = NULL; + /* Get input line */ + n = getline(&p_line, &len, stdin); + if (n > 0) { + /* Parse and act on input */ + parse_cmd_line(p_line, p_osm); + free(p_line); + } else { + printf("Input error\n"); + fflush(stdin); + } + osm_console_prompt(); + } +} + + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_db_files.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_db_files.c new file mode 100644 index 00000000..ebbb3071 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_db_files.c @@ -0,0 +1,796 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_db_files.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implemntation of the osm_db interface using simple text files + * + * $Revision: 1.4 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include + +/****d* Database/OSM_DB_MAX_LINE_LEN + * NAME + * OSM_DB_MAX_LINE_LEN + * + * DESCRIPTION + * The Maximal line length allowed for the file + * + * SYNOPSIS + */ +#define OSM_DB_MAX_LINE_LEN 1024 +/**********/ + +/****d* Database/OSM_DB_MAX_GUID_LEN + * NAME + * OSM_DB_MAX_GUID_LEN + * + * DESCRIPTION + * The Maximal word length allowed for the file (guid or lid) + * + * SYNOPSIS + */ +#define OSM_DB_MAX_GUID_LEN 32 +/**********/ + +/****s* OpenSM: Database/osm_db_domain_imp + * NAME + * osm_db_domain_imp + * + * DESCRIPTION + * An implementation for domain of the database based on text files and + * hash tables. + * + * SYNOPSIS + */ +typedef struct _osm_db_domain_imp { + char *file_name; + st_table *p_hash; + cl_spinlock_t lock; +} osm_db_domain_imp_t; +/* + * FIELDS + * + * SEE ALSO + * osm_db_domain_t + *********/ + +/****s* OpenSM: Database/osm_db_imp_t + * NAME + * osm_db_imp_t + * + * DESCRIPTION + * An implementation for file based database + * + * SYNOPSIS + */ +typedef struct _osm_db_imp { + char *db_dir_name; +} osm_db_imp_t; +/* + * FIELDS + * + * db_dir_name + * The directory holding the database + * + * SEE ALSO + * osm_db_t + *********/ + +/*************************************************************************** + ***************************************************************************/ +void +osm_db_construct( + IN osm_db_t* const p_db ) +{ + memset(p_db, 0, sizeof(osm_db_t)); + cl_list_construct( &p_db->domains ); +} + +/*************************************************************************** + ***************************************************************************/ +void +osm_db_domain_destroy( + IN osm_db_domain_t* const p_db_domain) +{ + osm_db_domain_imp_t *p_domain_imp; + p_domain_imp = (osm_db_domain_imp_t *)p_db_domain->p_domain_imp; + + osm_db_clear( p_db_domain ); + + cl_spinlock_destroy( &p_domain_imp->lock ); + + st_free_table( p_domain_imp->p_hash ); + free( p_domain_imp->file_name ); + free( p_domain_imp ); +} + +/*************************************************************************** + ***************************************************************************/ +void +osm_db_destroy( + IN osm_db_t* const p_db ) +{ + osm_db_domain_t *p_domain; + + while ((p_domain = cl_list_remove_head( &p_db->domains )) != NULL ) + { + osm_db_domain_destroy( p_domain ); + free( p_domain ); + } + cl_list_destroy( &p_db->domains ); + free( p_db->p_db_imp ); +} + +/*************************************************************************** + ***************************************************************************/ +int +osm_db_init( + IN osm_db_t* const p_db, + IN osm_log_t *p_log ) +{ + osm_db_imp_t *p_db_imp; + struct stat dstat; + + OSM_LOG_ENTER( p_log, osm_db_init ); + + p_db_imp = (osm_db_imp_t *)malloc(sizeof(osm_db_imp_t)); + CL_ASSERT( p_db_imp != NULL); + + p_db_imp->db_dir_name = getenv("OSM_CACHE_DIR"); + if (!p_db_imp->db_dir_name || !(*p_db_imp->db_dir_name)) + p_db_imp->db_dir_name = OSM_DEFAULT_CACHE_DIR; + + /* Create the directory if it doesn't exist */ + /* There is a difference in creating directory between windows and linux */ +#ifdef __WIN__ + /* Check if the directory exists. If not - create it. */ + CreateDirectory(p_db_imp->db_dir_name, NULL); +#else /* __WIN__ */ + /* make sure the directory exists */ + if (lstat(p_db_imp->db_dir_name, &dstat)) + { + if (mkdir(p_db_imp->db_dir_name, 0755)) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_db_init: ERR 6101: " + " Failed to create the db directory:%s\n", + p_db_imp->db_dir_name); + OSM_LOG_EXIT( p_log ); + return 1; + } + } +#endif + + p_db->p_log = p_log; + p_db->p_db_imp = (void*)p_db_imp; + + cl_list_init( &p_db->domains, 5 ); + + OSM_LOG_EXIT( p_log ); + + return 0; +} + +/*************************************************************************** + ***************************************************************************/ +osm_db_domain_t* +osm_db_domain_init( + IN osm_db_t* const p_db, + IN char *domain_name) +{ + osm_db_domain_t *p_domain; + osm_db_domain_imp_t *p_domain_imp; + int dir_name_len; + osm_log_t *p_log = p_db->p_log; + FILE *p_file; + + OSM_LOG_ENTER( p_log, osm_db_domain_init ); + + /* allocate a new domain object */ + p_domain = (osm_db_domain_t *)malloc(sizeof(osm_db_domain_t)); + CL_ASSERT( p_domain != NULL ); + + p_domain_imp = + (osm_db_domain_imp_t *)malloc(sizeof(osm_db_domain_imp_t)); + CL_ASSERT( p_domain_imp != NULL ); + + dir_name_len = strlen(((osm_db_imp_t*)p_db->p_db_imp)->db_dir_name); + + /* set the domain file name */ + p_domain_imp->file_name = + (char *)malloc(sizeof(char)*(dir_name_len) + strlen(domain_name) + 2); + CL_ASSERT(p_domain_imp->file_name != NULL); + strcpy(p_domain_imp->file_name,((osm_db_imp_t*)p_db->p_db_imp)->db_dir_name); + strcat(p_domain_imp->file_name,domain_name); + + /* make sure the file exists - or exit if not writable */ + p_file = fopen(p_domain_imp->file_name, "a+"); + if (! p_file) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_db_domain_init: ERR 6102: " + " Failed to open the db file:%s\n", + p_domain_imp->file_name); + free(p_domain_imp); + free(p_domain); + p_domain = NULL; + goto Exit; + } + fclose(p_file); + + /* initialize the hash table object */ + p_domain_imp->p_hash = st_init_strtable(); + CL_ASSERT( p_domain_imp->p_hash != NULL ); + + p_domain->p_db = p_db; + cl_list_insert_tail( &p_db->domains, p_domain ); + p_domain->p_domain_imp = p_domain_imp; + cl_spinlock_construct( &p_domain_imp->lock ); + cl_spinlock_init( &p_domain_imp->lock ); + + Exit: + OSM_LOG_EXIT( p_log ); + return p_domain; +} + +/*************************************************************************** + ***************************************************************************/ +int +osm_db_restore( + IN osm_db_domain_t *p_domain) +{ + + osm_log_t *p_log = p_domain->p_db->p_log; + osm_db_domain_imp_t *p_domain_imp = + (osm_db_domain_imp_t *)p_domain->p_domain_imp; + FILE *p_file; + int status; + char sLine[OSM_DB_MAX_LINE_LEN]; + boolean_t before_key; + char *p_first_word, *p_rest_of_line, *p_last; + char *p_key = NULL; + char *p_prev_val, *p_accum_val = NULL; + unsigned int line_num; + + OSM_LOG_ENTER( p_log, osm_db_restore ); + + /* take the lock on the domain */ + cl_spinlock_acquire( &p_domain_imp->lock ); + + /* open the file - read mode */ + p_file = fopen(p_domain_imp->file_name, "r"); + + if (! p_file) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_db_restore: ERR 6103: " + " Failed to open the db file:%s\n", + p_domain_imp->file_name); + status = 1; + goto Exit; + } + + /* parse the file allocating new hash tables as required */ + /* + states: + before_key (0) -> in_key (1) + + before_key: if a word on the first byte - it is the key. state=in_key + the rest of the line is start of the value. + in_key: unless the line is empty - add it (with newlines) to the value. + if empty: state=before_key + */ + status = 0; + before_key = TRUE; + line_num = 0; + /* if we got to EOF in the middle of a key we add a last newline */ + while ( + (fgets(sLine, OSM_DB_MAX_LINE_LEN, p_file) != NULL) || + ((before_key == FALSE) && strcpy(sLine,"\n")) + ) + { + line_num++; + if (before_key) + { + if ((sLine[0] != ' ') && (sLine[0] != '\t') && (sLine[0] != '\n')) + { + /* we got a new key */ + before_key = FALSE; + + /* handle the key */ + p_first_word = strtok_r(sLine, " \t\n", &p_last); + if (! p_first_word) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_db_restore: ERR 6104: " + " Failed to get key from line:%u : %s (file:%s)\n", + line_num, sLine, p_domain_imp->file_name); + status = 1; + goto EndParsing; + } + if (strlen(p_first_word) > OSM_DB_MAX_GUID_LEN) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_db_restore: ERR 610A: " + " Illegal key from line:%u : %s (file:%s)\n", + line_num, sLine, p_domain_imp->file_name); + status = 1; + goto EndParsing; + } + + p_key = (char *)malloc(sizeof(char)*(strlen(p_first_word) + 1)); + strcpy(p_key, p_first_word); + + p_rest_of_line = strtok_r(NULL, "\n", &p_last); + if (p_rest_of_line != NULL) + { + p_accum_val = + (char*)malloc(sizeof(char)*(strlen(p_rest_of_line) + 1)); + strcpy(p_accum_val, p_rest_of_line); + } + else + { + p_accum_val = (char*)malloc(2); + strcpy(p_accum_val, "\0"); + } + } + else if (sLine[0] != '\n') + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_db_restore: ERR 6105: " + " How did we get here? line:%u : %s (file:%s)\n", + line_num, sLine, p_domain_imp->file_name); + status = 1; + goto EndParsing; + } + } /* before key */ + else + { + /* we already have a key */ + + if (sLine[0] == '\n') + { + /* got an end of key */ + before_key = TRUE; + + /* make sure the key was not previously used */ + if (st_lookup(p_domain_imp->p_hash, + (st_data_t)p_key, + (st_data_t*)&p_prev_val)) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_db_restore: ERR 6106: " + " Key:%s already exists in:%s with value:%s." + " Removing it\n", + p_key, + p_domain_imp->file_name, + p_prev_val); + } + else + { + p_prev_val = NULL; + } + + /* store our key and value */ + st_insert(p_domain_imp->p_hash, + (st_data_t)p_key, (st_data_t)p_accum_val); + osm_log( p_log, OSM_LOG_DEBUG, + "osm_db_restore: " + "Got key:%s value:%s\n", p_key, p_accum_val); + } + else + { + /* accumulate into the value */ + p_prev_val = p_accum_val; + p_accum_val = + (char *)malloc(strlen(p_prev_val) + strlen(sLine) + 1); + strcpy(p_accum_val, p_prev_val); + free(p_prev_val); + strcat(p_accum_val, sLine); + } + } /* in key */ + } /* while lines or last line */ + + EndParsing: + fclose(p_file); + + Exit: + cl_spinlock_release( &p_domain_imp->lock ); + OSM_LOG_EXIT( p_log ); + return status; +} + +/*************************************************************************** + ***************************************************************************/ +int +__osm_dump_tbl_entry(st_data_t key, st_data_t val, st_data_t arg) +{ + FILE *p_file = (FILE*)arg; + char *p_key = (char*)key; + char *p_val = (char *)val; + + fprintf(p_file, "%s %s\n\n", p_key, p_val); + return ST_CONTINUE; +} + +int +osm_db_store( + IN osm_db_domain_t *p_domain) +{ + osm_log_t *p_log = p_domain->p_db->p_log; + osm_db_domain_imp_t *p_domain_imp; + FILE *p_file; + int status = 0; + char *p_tmp_file_name; + + OSM_LOG_ENTER( p_log, osm_db_store ); + + p_domain_imp = (osm_db_domain_imp_t *)p_domain->p_domain_imp; + p_tmp_file_name = + (char *)malloc(sizeof(char)*(strlen(p_domain_imp->file_name)+8)); + strcpy(p_tmp_file_name, p_domain_imp->file_name); + strcat(p_tmp_file_name,".tmp"); + + cl_spinlock_acquire( &p_domain_imp->lock ); + + /* open up the output file */ + p_file = fopen(p_tmp_file_name, "w"); + if (! p_file) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_db_store: ERR 6107: " + " Failed to open the db file:%s for writing\n", + p_domain_imp->file_name); + status = 1; + goto Exit; + } + + st_foreach(p_domain_imp->p_hash, __osm_dump_tbl_entry, (st_data_t)p_file); + fclose(p_file); + + /* move the domain file */ + status = remove(p_domain_imp->file_name); + if (status) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_db_store: ERR 6109: " + " Failed to remove file:%s (err:%u)\n", + p_domain_imp->file_name, status); + } + + status = rename(p_tmp_file_name, p_domain_imp->file_name); + if (status) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_db_store: ERR 6108: " + " Failed to rename the db file to:%s (err:%u)\n", + p_domain_imp->file_name, status); + } + Exit: + cl_spinlock_release( &p_domain_imp->lock ); + free(p_tmp_file_name); + OSM_LOG_EXIT( p_log ); + return status; +} + +/*************************************************************************** + ***************************************************************************/ +/* simply de-allocate the key and the value and return the code + that makes the st_foreach delete the entry */ +int +__osm_clear_tbl_entry(st_data_t key, st_data_t val, st_data_t arg) +{ + free((char*)key); + free((char*)val); + return ST_DELETE; +} + +int +osm_db_clear( + IN osm_db_domain_t *p_domain) +{ + osm_db_domain_imp_t *p_domain_imp = + (osm_db_domain_imp_t *)p_domain->p_domain_imp; + + cl_spinlock_acquire( &p_domain_imp->lock ); + st_foreach(p_domain_imp->p_hash, __osm_clear_tbl_entry, (st_data_t)NULL); + cl_spinlock_release( &p_domain_imp->lock ); + + return 0; +} + +/*************************************************************************** + ***************************************************************************/ +int +__osm_get_key_of_tbl_entry(st_data_t key, st_data_t val, st_data_t arg) +{ + cl_list_t *p_list = (cl_list_t *)arg; + cl_list_insert_tail(p_list, (void*)key); + return ST_CONTINUE; +} + +int +osm_db_keys( + IN osm_db_domain_t *p_domain, + OUT cl_list_t* p_key_list) +{ + osm_db_domain_imp_t *p_domain_imp = + (osm_db_domain_imp_t *)p_domain->p_domain_imp; + + cl_spinlock_acquire( &p_domain_imp->lock ); + + st_foreach(p_domain_imp->p_hash, + __osm_get_key_of_tbl_entry, (st_data_t)p_key_list); + + cl_spinlock_release( &p_domain_imp->lock ); + + return 0; +} + +/*************************************************************************** + ***************************************************************************/ +char * +osm_db_lookup( + IN osm_db_domain_t *p_domain, + IN char *const p_key) +{ + osm_db_domain_imp_t *p_domain_imp = + (osm_db_domain_imp_t *)p_domain->p_domain_imp; + char *p_val = NULL; + + cl_spinlock_acquire( &p_domain_imp->lock ); + + if (!st_lookup(p_domain_imp->p_hash, (st_data_t)p_key, (st_data_t*)&p_val)) + p_val = NULL; + + cl_spinlock_release( &p_domain_imp->lock ); + + return p_val; +} + +/*************************************************************************** + ***************************************************************************/ +int +osm_db_update( + IN osm_db_domain_t *p_domain, + IN char *const p_key, + IN char *const p_val) +{ + osm_log_t *p_log = p_domain->p_db->p_log; + osm_db_domain_imp_t *p_domain_imp = + (osm_db_domain_imp_t *)p_domain->p_domain_imp; + char *p_prev_val = NULL; + char *p_new_key; + char *p_new_val; + + cl_spinlock_acquire( &p_domain_imp->lock ); + + if (st_lookup(p_domain_imp->p_hash, + (st_data_t)p_key, (st_data_t*)&p_prev_val)) + { + osm_log( p_log, OSM_LOG_DEBUG, + "osm_db_update: " + " Key:%s previously exists in:%s with value:%s\n", + p_key, + p_domain_imp->file_name, + p_prev_val); + p_new_key = p_key; + } + else + { + /* need to allocate the key */ + p_new_key = malloc(sizeof(char)*(strlen(p_key) + 1)); + strcpy(p_new_key, p_key); + } + + /* need to arange a new copy of the value */ + p_new_val = malloc(sizeof(char)*(strlen(p_val) + 1)); + strcpy(p_new_val, p_val); + + st_insert(p_domain_imp->p_hash, (st_data_t)p_new_key, (st_data_t)p_new_val); + + if (p_prev_val) + free(p_prev_val); + + cl_spinlock_release( &p_domain_imp->lock ); + + return 0; +} + +/*************************************************************************** + ***************************************************************************/ +int +osm_db_delete( + IN osm_db_domain_t *p_domain, + IN char *const p_key) +{ + osm_log_t *p_log = p_domain->p_db->p_log; + osm_db_domain_imp_t *p_domain_imp = + (osm_db_domain_imp_t *)p_domain->p_domain_imp; + char *p_prev_val = NULL; + int res; + + OSM_LOG_ENTER( p_log, osm_db_delete ); + + cl_spinlock_acquire( &p_domain_imp->lock ); + if (st_delete(p_domain_imp->p_hash, + (st_data_t*)&p_key, (st_data_t*)&p_prev_val)) + { + if (st_lookup(p_domain_imp->p_hash, + (st_data_t)p_key, (st_data_t*)&p_prev_val)) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_db_delete: " + " key:%s still exists in:%s with value:%s\n", + p_key, + p_domain_imp->file_name, + p_prev_val); + res = 1; + } + else + { + free(p_key); + free(p_prev_val); + res = 0; + } + } + else + { + osm_log( p_log, OSM_LOG_DEBUG, + "osm_db_update: " + " fail to find key:%s. delete failed\n", + p_key); + res = 1; + } + cl_spinlock_release( &p_domain_imp->lock ); + + OSM_LOG_EXIT( p_log ); + return res; +} + +#ifdef TEST_OSMDB +#include +#include + +int +main(int argc, char **argv) +{ + osm_db_t db; + osm_log_t log; + osm_db_domain_t *p_dbd; + cl_list_t keys; + cl_list_iterator_t kI; + char *p_key; + char *p_val; + int i; + + cl_list_construct( &keys ); + cl_list_init( &keys, 10 ); + + osm_log_init_v2( &log, TRUE, 0xff, "/var/log/osm_db_test.log", 0, FALSE); + + osm_db_construct(&db); + if (osm_db_init(&db, &log)) + { + printf("db init failed\n"); + exit(1); + } + + p_dbd = osm_db_domain_init(&db, "lid_by_guid"); + + if (osm_db_restore(p_dbd)) + { + printf("failed to restore\n"); + } + + if (osm_db_keys(p_dbd, &keys)) + { + printf("failed to get keys\n"); + } + else + { + kI = cl_list_head( &keys ); + while (kI != cl_list_end( & keys )) + { + p_key = cl_list_obj(kI); + kI = cl_list_next( kI ); + + p_val = osm_db_lookup(p_dbd, p_key); + printf("key = %s val = %s\n", p_key, p_val); + } + } + + cl_list_remove_all(&keys); + + /* randomly add and remove numbers */ + for (i = 0; i < 10; i++) + { + int k; + float v; + int is_add; + char val_buf[16]; + char key_buf[16]; + + k = floor(1.0 * rand()/ RAND_MAX * 100); + v = rand(); + sprintf(key_buf, "%u", k); + sprintf(val_buf, "%u", v); + + is_add = (rand() < RAND_MAX/ 2); + + if (is_add) + { + osm_db_update(p_dbd, key_buf, val_buf); + } + else + { + osm_db_delete(p_dbd, key_buf); + } + } + if (osm_db_keys(p_dbd, &keys)) + { + printf("failed to get keys\n"); + } + else + { + kI = cl_list_head( &keys ); + while (kI != cl_list_end( & keys )) + { + p_key = cl_list_obj(kI); + kI = cl_list_next( kI ); + + p_val = osm_db_lookup(p_dbd, p_key); + printf("key = %s val = %s\n", p_key, p_val); + } + } + if (osm_db_store(p_dbd)) + printf("failed to store\n"); + + osm_db_destroy( &db ); + cl_list_destroy( &keys ); +} +#endif + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_db_pack.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_db_pack.c new file mode 100644 index 00000000..29450e89 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_db_pack.c @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_db_pack.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +static inline void +__osm_pack_guid(uint64_t guid, char *p_guid_str) +{ + sprintf(p_guid_str, "0x%016" PRIx64, guid); +} + +static inline uint64_t +__osm_unpack_guid(char *p_guid_str) +{ +#if __WORDSIZE == 64 + return (strtoul(p_guid_str, NULL, 0)); +#else + return (strtoull(p_guid_str, NULL, 0)); +#endif +} + +static inline void +__osm_pack_lids(uint16_t min_lid, uint16_t max_lid, char *p_lid_str) +{ + sprintf(p_lid_str, "0x%04x 0x%04x", min_lid, max_lid); +} + +static inline int +__osm_unpack_lids( + IN char *p_lid_str, + OUT uint16_t *p_min_lid, + OUT uint16_t *p_max_lid ) +{ + unsigned long tmp; + char *p_next; + char *p_num; + char lids_str[24]; + + strncpy(lids_str, p_lid_str, 23); + lids_str[23] = '\0'; + p_num = strtok_r(lids_str, " \t", &p_next); + if (! p_num) return 1; + tmp = strtoul(p_num, NULL, 0); + CL_ASSERT( tmp < 0x10000 ); + *p_min_lid = (uint16_t)tmp; + + p_num = strtok_r(NULL, " \t", &p_next); + if (! p_num) return 1; + tmp = strtoul(p_num, NULL, 0); + CL_ASSERT( tmp < 0x10000 ); + *p_max_lid = (uint16_t)tmp; + + return 0; +} + +int +osm_db_guid2lid_guids( + IN osm_db_domain_t* const p_g2l, + OUT cl_qlist_t* p_guid_list ) +{ + char *p_key; + cl_list_t keys; + osm_db_guid_elem_t *p_guid_elem; + + cl_list_construct( &keys ); + cl_list_init( &keys , 10); + + if (osm_db_keys(p_g2l, &keys)) + return 1; + + while ( (p_key = cl_list_remove_head( &keys )) != NULL ) + { + p_guid_elem = (osm_db_guid_elem_t*)malloc(sizeof(osm_db_guid_elem_t)); + CL_ASSERT( p_guid_elem != NULL ); + + p_guid_elem->guid = __osm_unpack_guid(p_key); + cl_qlist_insert_head(p_guid_list, &p_guid_elem->item); + } + + cl_list_destroy( &keys ); + return 0; +} + +int +osm_db_guid2lid_get( + IN osm_db_domain_t* const p_g2l, + IN uint64_t guid, + OUT uint16_t *p_min_lid, + OUT uint16_t *p_max_lid) +{ + char guid_str[20]; + char *p_lid_str; + uint16_t min_lid, max_lid; + + __osm_pack_guid(guid, guid_str); + p_lid_str = osm_db_lookup(p_g2l, guid_str); + if (! p_lid_str) + return 1; + if (__osm_unpack_lids(p_lid_str, &min_lid, &max_lid)) + return 1; + + if (p_min_lid) *p_min_lid = min_lid; + if (p_max_lid) *p_max_lid = max_lid; + + return 0; +} + +int +osm_db_guid2lid_set( + IN osm_db_domain_t* const p_g2l, + IN uint64_t guid, + IN uint16_t min_lid, + IN uint16_t max_lid) +{ + char guid_str[20]; + char lid_str[16]; + + __osm_pack_guid(guid, guid_str); + __osm_pack_lids(min_lid, max_lid, lid_str); + + return( osm_db_update( p_g2l, guid_str, lid_str) ); +} + +int +osm_db_guid2lid_delete( + IN osm_db_domain_t* const p_g2l, + IN uint64_t guid ) +{ + char guid_str[20]; + __osm_pack_guid(guid, guid_str); + return( osm_db_delete( p_g2l, guid_str) ); +} + + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_drop_mgr.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_drop_mgr.c new file mode 100644 index 00000000..15370446 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_drop_mgr.c @@ -0,0 +1,721 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_drop_mgr.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_drop_mgr_t. + * This object represents the Drop Manager object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.7 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +osm_drop_mgr_construct( + IN osm_drop_mgr_t* const p_mgr ) +{ + CL_ASSERT( p_mgr ); + memset( p_mgr, 0, sizeof(*p_mgr) ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_drop_mgr_destroy( + IN osm_drop_mgr_t* const p_mgr ) +{ + CL_ASSERT( p_mgr ); + + OSM_LOG_ENTER( p_mgr->p_log, osm_drop_mgr_destroy ); + + OSM_LOG_EXIT( p_mgr->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_drop_mgr_init( + IN osm_drop_mgr_t* const p_mgr, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN osm_req_t* const p_req, + IN cl_plock_t* const p_lock ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_drop_mgr_init ); + + osm_drop_mgr_construct( p_mgr ); + + p_mgr->p_log = p_log; + p_mgr->p_subn = p_subn; + p_mgr->p_lock = p_lock; + p_mgr->p_req = p_req; + + OSM_LOG_EXIT( p_mgr->p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_drop_mgr_remove_router( + IN const osm_drop_mgr_t* const p_mgr, + IN const ib_net64_t portguid ) +{ + osm_router_t *p_rtr; + cl_qmap_t* p_rtr_guid_tbl; + + p_rtr_guid_tbl = &p_mgr->p_subn->rtr_guid_tbl; + p_rtr = (osm_router_t*)cl_qmap_remove( p_rtr_guid_tbl, portguid ); + if( p_rtr != (osm_router_t*)cl_qmap_end( p_rtr_guid_tbl ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_drop_mgr_remove_router: " + "Cleaned router for port guid 0x%016" PRIx64 "\n", + cl_ntoh64( portguid ) ); + osm_router_delete( &p_rtr ); + } +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_drop_mgr_remove_port( + IN const osm_drop_mgr_t* const p_mgr, + IN osm_port_t* p_port ) +{ + ib_net64_t port_guid; + osm_port_t *p_port_check; + cl_list_t* p_new_ports_list; + cl_list_iterator_t cl_list_item; + cl_qmap_t* p_port_guid_tbl; + cl_qmap_t* p_sm_guid_tbl; + osm_mcm_info_t* p_mcm; + osm_mgrp_t* p_mgrp; + cl_ptr_vector_t* p_port_lid_tbl; + uint16_t min_lid_ho; + uint16_t max_lid_ho; + uint16_t lid_ho; + uint32_t port_num; + uint32_t remote_port_num; + uint32_t num_physp; + osm_node_t *p_node; + osm_node_t *p_remote_node; + osm_physp_t *p_physp; + osm_physp_t *p_remote_physp; + osm_remote_sm_t *p_sm; + ib_gid_t port_gid; + ib_mad_notice_attr_t notice; + ib_api_status_t status; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_drop_mgr_remove_port ); + + port_guid = osm_port_get_guid( p_port ); + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_drop_mgr_remove_port: " + "Unreachable port 0x%016" PRIx64 "\n", + cl_ntoh64( port_guid ) ); + + /* + Remove this port from the new_ports_list, if it exists there. + Remove this port from the guid and LID tables. + Remove also from the sm guid table - if the object + exists there. + */ + p_new_ports_list = &p_mgr->p_subn->new_ports_list; + cl_list_item = cl_list_head(p_new_ports_list); + while( cl_list_item != cl_list_end(p_new_ports_list) ) + { + if ( (osm_port_t*)(cl_list_obj(cl_list_item)) == p_port ) + { + /* Found the port in the new_ports_list. Remove it from there. */ + cl_list_remove_item(p_new_ports_list, cl_list_item); + break; + } + cl_list_item = cl_list_next(cl_list_item); + } + + p_port_guid_tbl = &p_mgr->p_subn->port_guid_tbl; + p_port_check = (osm_port_t*)cl_qmap_remove( p_port_guid_tbl, port_guid ); + if( p_port_check != p_port ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_drop_mgr_remove_port: ERR 0101: " + "Port 0x%016" PRIx64 " not in guid table\n", + cl_ntoh64( port_guid ) ); + goto Exit; + } + + p_sm_guid_tbl = &p_mgr->p_subn->sm_guid_tbl; + p_sm = (osm_remote_sm_t*)cl_qmap_remove( p_sm_guid_tbl, port_guid ); + if( p_sm != (osm_remote_sm_t*)cl_qmap_end( p_sm_guid_tbl ) ) + { + /* need to remove this item */ + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_drop_mgr_remove_port: " + "Cleaned SM for port guid\n" ); + + free(p_sm); + } + + __osm_drop_mgr_remove_router( p_mgr, port_guid ); + + osm_port_get_lid_range_ho( p_port, &min_lid_ho, &max_lid_ho ); + + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_drop_mgr_remove_port: " + "Clearing abandoned LID range [0x%X,0x%X]\n", + min_lid_ho, max_lid_ho ); + + p_port_lid_tbl = &p_mgr->p_subn->port_lid_tbl; + for( lid_ho = min_lid_ho; lid_ho <= max_lid_ho; lid_ho++ ) + cl_ptr_vector_set( p_port_lid_tbl, lid_ho, NULL ); + + /* + For each Physical Port associated with this port: + Unlink the remote Physical Port, if any + Re-initialize each Physical Port. + */ + + num_physp = osm_port_get_num_physp( p_port ); + for( port_num = 0; port_num < num_physp; port_num++ ) + { + p_physp = osm_port_get_phys_ptr( p_port, (uint8_t)port_num ); + + if( p_physp ) + { + p_remote_physp = osm_physp_get_remote( p_physp ); + if( p_remote_physp && osm_physp_is_valid( p_remote_physp ) ) + { + osm_port_t* p_remote_port; + + p_node = osm_physp_get_node_ptr( p_physp ); + p_remote_node = osm_physp_get_node_ptr( p_remote_physp ); + remote_port_num = osm_physp_get_port_num( p_remote_physp ); + p_remote_port = (osm_port_t*)cl_qmap_get( p_port_guid_tbl, p_remote_physp->port_guid ); + + if ( p_remote_port != (osm_port_t*)cl_qmap_end( p_port_guid_tbl ) ) + { + /* Let's check if this is a case of link that is lost (both ports + weren't recognized), or a "hiccup" in the subnet - in which case + the remote port was recognized, and its state is ACTIVE. + If this is just a "hiccup" - force a heavy sweep in the next sweep. + We don't want to lose that part of the subnet. */ + if (osm_port_discovery_count_get( p_remote_port ) && + osm_physp_get_port_state( p_remote_physp ) == IB_LINK_ACTIVE ) + { + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_drop_mgr_remove_port: " + "Forcing delayed heavy sweep. Remote " + "port 0x%016" PRIx64 " port num: 0x%X " + "was recognized in ACTIVE state\n", + cl_ntoh64( p_remote_physp->port_guid ), + remote_port_num ); + p_mgr->p_subn->force_delayed_heavy_sweep = TRUE; + } + } + + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_drop_mgr_remove_port: " + "Unlinking local node 0x%016" PRIx64 ", port 0x%X" + "\n\t\t\t\tand remote node 0x%016" PRIx64 + ", port 0x%X\n", + cl_ntoh64( osm_node_get_node_guid( p_node ) ), + port_num, + cl_ntoh64( osm_node_get_node_guid( p_remote_node ) ), + remote_port_num ); + + osm_node_unlink( p_node, (uint8_t)port_num, + p_remote_node, (uint8_t)remote_port_num ); + + /* If the remote node is ca or router - need to remove the remote port, + since it is no longer reachable. This can be done if we reset the + discovery count of the remote port. */ + if ( osm_node_get_type( p_remote_node ) != IB_NODE_TYPE_SWITCH ) + { + if ( p_remote_port != (osm_port_t*)cl_qmap_end( p_port_guid_tbl ) ) + { + osm_port_discovery_count_reset( p_remote_port ); + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_drop_mgr_remove_port: " + "Resetting discovery count of node: " + "0x%016" PRIx64 " port num:0x%X\n", + cl_ntoh64( osm_node_get_node_guid( p_remote_node ) ), + remote_port_num ); + } + } + } + + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_drop_mgr_remove_port: " + "Clearing physical port number 0x%X\n", + port_num ); + + osm_physp_destroy( p_physp ); + } + } + + p_mcm = (osm_mcm_info_t*)cl_qlist_remove_head( &p_port->mcm_list ); + while( p_mcm != (osm_mcm_info_t *)cl_qlist_end( &p_port->mcm_list ) ) + { + p_mgrp = (osm_mgrp_t *)cl_qmap_get( &p_mgr->p_subn->mgrp_mlid_tbl, + p_mcm->mlid ); + if(p_mgrp != (osm_mgrp_t *)cl_qmap_end( &p_mgr->p_subn->mgrp_mlid_tbl ) ) + { + osm_mgrp_remove_port(p_mgr->p_subn, p_mgr->p_log, p_mgrp, p_port->guid ); + osm_mcm_info_delete( (osm_mcm_info_t*)p_mcm ); + } + p_mcm = (osm_mcm_info_t*)cl_qlist_remove_head( &p_port->mcm_list ); + } + + /* initialize the p_node - may need to get node_desc later */ + p_node = p_port->p_node; + + osm_port_delete( &p_port ); + + /* issue a notice - trap 65 */ + + /* details of the notice */ + notice.generic_type = 0x83; /* is generic subn mgt type */ + ib_notice_set_prod_type_ho(¬ice, 4); /* A class manager generator */ + /* endport ceases to be reachable */ + notice.g_or_v.generic.trap_num = CL_HTON16(65); + /* The sm_base_lid is saved in network order already. */ + notice.issuer_lid = p_mgr->p_subn->sm_base_lid; + /* following C14-72.1.2 and table 119 p725 */ + /* we need to provide the GID */ + port_gid.unicast.prefix = p_mgr->p_subn->opt.subnet_prefix; + port_gid.unicast.interface_id = port_guid; + memcpy(&(notice.data_details.ntc_64_67.gid), + &(port_gid), + sizeof(ib_gid_t)); + + /* According to page 653 - the issuer gid in this case of trap + is the SM gid, since the SM is the initiator of this trap. */ + notice.issuer_gid.unicast.prefix = p_mgr->p_subn->opt.subnet_prefix; + notice.issuer_gid.unicast.interface_id = p_mgr->p_subn->sm_port_guid; + + status = osm_report_notice(p_mgr->p_log, p_mgr->p_subn, ¬ice); + if( status != IB_SUCCESS ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_drop_mgr_remove_port: ERR 0103: " + "Error sending trap reports (%s)\n", + ib_get_err_str( status ) ); + goto Exit; + } + + if (osm_log_is_active( p_mgr->p_log, OSM_LOG_INFO )) + { + char desc[IB_NODE_DESCRIPTION_SIZE + 1]; + + if (p_node) + { + memcpy(desc, p_node->node_desc.description, IB_NODE_DESCRIPTION_SIZE); + desc[IB_NODE_DESCRIPTION_SIZE] = '\0'; + } + osm_log( p_mgr->p_log, OSM_LOG_INFO, + "__osm_drop_mgr_remove_port: " + "Removed port with GUID:0x%016" PRIx64 + " LID range [0x%X,0x%X] of node:%s\n", + cl_ntoh64( port_gid.unicast.interface_id ), + min_lid_ho, max_lid_ho, p_node ? desc : "UNKNOWN" ); + } + + Exit: + OSM_LOG_EXIT( p_mgr->p_log ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_drop_mgr_remove_switch( + IN const osm_drop_mgr_t* const p_mgr, + IN osm_node_t* p_node ) +{ + osm_switch_t *p_sw; + cl_qmap_t* p_sw_guid_tbl; + ib_net64_t node_guid; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_drop_mgr_remove_switch ); + + node_guid = osm_node_get_node_guid( p_node ); + p_sw_guid_tbl = &p_mgr->p_subn->sw_guid_tbl; + + p_sw = (osm_switch_t*)cl_qmap_remove( p_sw_guid_tbl, node_guid ); + if( p_sw == (osm_switch_t*)cl_qmap_end( p_sw_guid_tbl ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_drop_mgr_remove_switch: ERR 0102: " + "Node 0x%016" PRIx64 " not in switch table\n", + cl_ntoh64( osm_node_get_node_guid( p_node ) ) ); + } + else + { + p_node->sw = NULL; + osm_switch_delete( &p_sw ); + } + + OSM_LOG_EXIT( p_mgr->p_log ); +} + +/********************************************************************** + **********************************************************************/ +static boolean_t +__osm_drop_mgr_process_node( + IN const osm_drop_mgr_t* const p_mgr, + IN osm_node_t* p_node ) +{ + osm_physp_t *p_physp; + osm_port_t *p_port; + osm_node_t *p_node_check; + cl_qmap_t *p_node_guid_tbl; + uint32_t port_num; + uint32_t max_ports; + ib_net64_t port_guid; + cl_qmap_t* p_port_guid_tbl; + boolean_t return_val = FALSE; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_drop_mgr_process_node ); + + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_drop_mgr_process_node: " + "Unreachable node 0x%016" PRIx64 "\n", + cl_ntoh64( osm_node_get_node_guid( p_node ) ) ); + + /* + Delete all the logical and physical port objects + associated with this node. + */ + p_port_guid_tbl = &p_mgr->p_subn->port_guid_tbl; + + max_ports = osm_node_get_num_physp( p_node ); + for( port_num = 0; port_num < max_ports; port_num++ ) + { + p_physp = osm_node_get_physp_ptr( p_node, port_num ); + if( osm_physp_is_valid( p_physp ) ) + { + port_guid = osm_physp_get_port_guid( p_physp ); + + p_port = (osm_port_t*)cl_qmap_get( p_port_guid_tbl, port_guid ); + + if( p_port != (osm_port_t*)cl_qmap_end( p_port_guid_tbl ) ) + __osm_drop_mgr_remove_port( p_mgr, p_port ); + } + } + + return_val = TRUE; + + if (p_node->sw) + __osm_drop_mgr_remove_switch( p_mgr, p_node ); + + p_node_guid_tbl = &p_mgr->p_subn->node_guid_tbl; + p_node_check = (osm_node_t*)cl_qmap_remove( p_node_guid_tbl, + osm_node_get_node_guid( p_node ) ); + if( p_node_check != p_node ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_drop_mgr_process_node: ERR 0105: " + "Node 0x%016" PRIx64 " not in guid table\n", + cl_ntoh64( osm_node_get_node_guid( p_node ) ) ); + } + + /* free memory allocated to node */ + osm_node_delete( &p_node ); + + OSM_LOG_EXIT( p_mgr->p_log ); + return( return_val ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_drop_mgr_check_node( + IN const osm_drop_mgr_t* const p_mgr, + IN osm_node_t* p_node ) +{ + ib_net64_t node_guid; + osm_physp_t *p_physp; + osm_port_t *p_port; + cl_qmap_t* p_port_guid_tbl; + ib_net64_t port_guid; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_drop_mgr_check_node ); + + node_guid = osm_node_get_node_guid( p_node ); + + if ( osm_node_get_type( p_node ) != IB_NODE_TYPE_SWITCH ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_drop_mgr_check_node: ERR 0107: " + "Node 0x%016" PRIx64 " is not a switch node\n", + cl_ntoh64( node_guid ) ); + goto Exit; + } + + /* Make sure we have a switch object for this node */ + if (!p_node->sw) + { + /* We do not have switch info for this node */ + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_drop_mgr_check_node: " + "Node 0x%016" PRIx64 " no switch in table\n", + cl_ntoh64( node_guid ) ); + + __osm_drop_mgr_process_node( p_mgr, p_node ); + goto Exit; + } + + /* Make sure we have a port object for port zero */ + p_port_guid_tbl = &p_mgr->p_subn->port_guid_tbl; + p_physp = osm_node_get_physp_ptr( p_node, 0 ); + if ( !osm_physp_is_valid( p_physp ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_drop_mgr_check_node: " + "Node 0x%016" PRIx64 " no valid physical port 0\n", + cl_ntoh64( node_guid ) ); + + __osm_drop_mgr_process_node( p_mgr, p_node ); + goto Exit; + } + + port_guid = osm_physp_get_port_guid( p_physp ); + + p_port = (osm_port_t*)cl_qmap_get( + p_port_guid_tbl, port_guid ); + + if( p_port == (osm_port_t*)cl_qmap_end( p_port_guid_tbl ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_drop_mgr_check_node: " + "Node 0x%016" PRIx64 " has no port object\n", + cl_ntoh64( node_guid ) ); + + __osm_drop_mgr_process_node( p_mgr, p_node ); + goto Exit; + } + + if ( osm_port_discovery_count_get( p_port ) == 0 ) + { + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_drop_mgr_check_node: " + "Node 0x%016" PRIx64 " port has discovery count zero\n", + cl_ntoh64( node_guid ) ); + + __osm_drop_mgr_process_node( p_mgr, p_node ); + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_mgr->p_log ); + return; +} + +/********************************************************************** + **********************************************************************/ +void +osm_drop_mgr_process( + IN const osm_drop_mgr_t* const p_mgr ) +{ + cl_qmap_t *p_node_guid_tbl; + cl_qmap_t *p_port_guid_tbl; + cl_list_t *p_lsweep_ports; + osm_port_t *p_port; + osm_port_t *p_next_port; + osm_node_t *p_node; + osm_node_t *p_next_node; + ib_net64_t port_guid; + ib_net64_t node_guid; + uint8_t port_num; + osm_physp_t *p_physp; + + CL_ASSERT( p_mgr ); + + OSM_LOG_ENTER( p_mgr->p_log, osm_drop_mgr_process ); + + p_node_guid_tbl = &p_mgr->p_subn->node_guid_tbl; + p_port_guid_tbl = &p_mgr->p_subn->port_guid_tbl; + p_lsweep_ports = &p_mgr->p_subn->light_sweep_physp_list; + + CL_PLOCK_EXCL_ACQUIRE( p_mgr->p_lock ); + + p_next_node = (osm_node_t*)cl_qmap_head( p_node_guid_tbl ); + while( p_next_node != (osm_node_t*)cl_qmap_end( p_node_guid_tbl ) ) + { + p_node = p_next_node; + p_next_node = (osm_node_t*)cl_qmap_next( &p_next_node->map_item ); + + CL_ASSERT( cl_qmap_key( &p_node->map_item ) == + osm_node_get_node_guid( p_node ) ); + + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) ) + { + node_guid = osm_node_get_node_guid( p_node ); + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "osm_drop_mgr_process: " + "Checking node 0x%016" PRIx64 "\n", + cl_ntoh64( node_guid ) ); + } + + /* + Check if this node was discovered during the last sweep. + If not, it is unreachable in the current subnet, and + should therefore be removed from the subnet object. + */ + if( osm_node_discovery_count_get( p_node ) == 0 ) + __osm_drop_mgr_process_node( p_mgr, p_node ); + } + + /* + Go over all the nodes. If the node is a switch - make sure + there is also a switch record for it, and a portInfo record for + port zero of of the node. + If not - this means that there was some error in getting the data + of this node. Drop the node. + */ + p_next_node = (osm_node_t*)cl_qmap_head( p_node_guid_tbl ); + while( p_next_node != (osm_node_t*)cl_qmap_end( p_node_guid_tbl ) ) + { + p_node = p_next_node; + p_next_node = (osm_node_t*)cl_qmap_next( &p_next_node->map_item ); + + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) ) + { + node_guid = osm_node_get_node_guid( p_node ); + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "osm_drop_mgr_process: " + "Checking full discovery of node 0x%016" PRIx64 "\n", + cl_ntoh64( node_guid ) ); + } + + if ( osm_node_get_type( p_node ) != IB_NODE_TYPE_SWITCH ) + continue; + + /* We are handling a switch node */ + __osm_drop_mgr_check_node( p_mgr, p_node ); + } + + p_next_port = (osm_port_t*)cl_qmap_head( p_port_guid_tbl ); + while( p_next_port != (osm_port_t*)cl_qmap_end( p_port_guid_tbl ) ) + { + p_port = p_next_port; + p_next_port = (osm_port_t*)cl_qmap_next( &p_next_port->map_item ); + + CL_ASSERT( cl_qmap_key( &p_port->map_item ) == + osm_port_get_guid( p_port ) ); + + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) ) + { + port_guid = osm_port_get_guid( p_port ); + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "osm_drop_mgr_process: " + "Checking port 0x%016" PRIx64 "\n", + cl_ntoh64( port_guid ) ); + } + + /* + If the port is unreachable, remove it from the guid table. + */ + if( osm_port_discovery_count_get( p_port ) == 0 ) + __osm_drop_mgr_remove_port( p_mgr, p_port ); + } + + /* + scan through all the ports left - if the port is not DOWN and + it does not have a valid remote port - we need to track it for + next light sweep scan... + */ + cl_list_remove_all( p_lsweep_ports ); + p_next_node = (osm_node_t*)cl_qmap_head( p_node_guid_tbl ); + while( p_next_node != (osm_node_t*)cl_qmap_end( p_node_guid_tbl ) ) + { + p_node = p_next_node; + p_next_node = (osm_node_t*)cl_qmap_next( &p_next_node->map_item ); + + for (port_num = 1; port_num < osm_node_get_num_physp(p_node); port_num++) + { + p_physp = osm_node_get_physp_ptr(p_node, port_num); + if (osm_physp_is_valid(p_physp) && + (osm_physp_get_port_state(p_physp) != IB_LINK_DOWN) && + ! osm_physp_get_remote(p_physp)) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "osm_drop_mgr_process: ERR 0108: " + "Unknown remote side for node 0x%016" PRIx64 + " port %u. Adding to light sweep sampling list\n", + cl_ntoh64( osm_node_get_node_guid( p_node )), + port_num); + + osm_dump_dr_path(p_mgr->p_log, + osm_physp_get_dr_path_ptr( p_physp ), + OSM_LOG_ERROR); + + cl_list_insert_head( p_lsweep_ports, p_physp ); + } + } + } + + CL_PLOCK_RELEASE( p_mgr->p_lock ); + OSM_LOG_EXIT( p_mgr->p_log ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_files.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_files.c new file mode 100644 index 00000000..c7f6fbf7 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_files.c @@ -0,0 +1,99 @@ +#include +#include +#include +#include +#include +#include +#include +#include + #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_fwd_tbl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_fwd_tbl.c new file mode 100644 index 00000000..a8d08208 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_fwd_tbl.c @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_fwd_tbl.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_fwd_tbl_t. + * This object represents a unicast forwarding table. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_fwd_tbl_init( + IN osm_fwd_tbl_t* const p_tbl, + IN const ib_switch_info_t* const p_si ) +{ + uint16_t tbl_cap; + ib_api_status_t status = IB_SUCCESS; + + /* + Determine the type and size of the forwarding table + used by this switch, then initialize accordingly. + The current implementation only supports switches + with linear forwarding tables. + */ + tbl_cap = cl_ntoh16( p_si->lin_cap ); + + if( tbl_cap == 0 ) + { + /* + This switch does not support linear forwarding + tables. Error out for now. + */ + status = IB_UNSUPPORTED; + goto Exit; + } + + p_tbl->p_rnd_tbl = NULL; + + p_tbl->p_lin_tbl = osm_lin_tbl_new( tbl_cap ); + + if( p_tbl->p_lin_tbl == NULL ) + { + status = IB_INSUFFICIENT_MEMORY; + goto Exit; + } + + Exit: + return( status ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_fwd_tbl_destroy( + IN osm_fwd_tbl_t* const p_tbl ) +{ + if( p_tbl->p_lin_tbl ) + { + CL_ASSERT( p_tbl->p_rnd_tbl == NULL ); + osm_lin_tbl_delete( &p_tbl->p_lin_tbl ); + } + else + { + osm_rand_tbl_delete( &p_tbl->p_rnd_tbl ); + } +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_inform.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_inform.c new file mode 100644 index 00000000..83a8d1ec --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_inform.c @@ -0,0 +1,763 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_inform.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Implementation of inform record functions. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.18 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct _osm_infr_match_ctxt +{ + cl_list_t *p_remove_infr_list; + ib_mad_notice_attr_t *p_ntc; +} osm_infr_match_ctxt_t; + +/********************************************************************** + **********************************************************************/ +void +osm_infr_construct( + IN osm_infr_t* const p_infr ) +{ + memset( p_infr, 0, sizeof(osm_infr_t) ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_infr_destroy( + IN osm_infr_t* const p_infr ) +{ + free( p_infr ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_infr_init( + IN osm_infr_t* const p_infr, + IN const osm_infr_t *p_infr_rec ) +{ + CL_ASSERT( p_infr ); + + /* what else do we need in the inform_record ??? */ + + /* copy the contents of the provided informinfo */ + memcpy( p_infr, p_infr_rec, sizeof(osm_infr_t) ); +} + +/********************************************************************** + **********************************************************************/ +osm_infr_t* +osm_infr_new( + IN const osm_infr_t *p_infr_rec ) +{ + osm_infr_t* p_infr; + + CL_ASSERT(p_infr_rec); + + p_infr = (osm_infr_t*)malloc( sizeof(osm_infr_t) ); + if( p_infr ) + { + osm_infr_init( p_infr, p_infr_rec ); + } + + return( p_infr ); +} + +/********************************************************************** + **********************************************************************/ +void +__dump_all_informs( + IN osm_subn_t const *p_subn, + IN osm_log_t *p_log) +{ + cl_list_item_t* p_list_item; + + OSM_LOG_ENTER( p_log, __dump_all_informs ); + + if( !osm_log_is_active( p_log, OSM_LOG_DEBUG ) ) + goto Exit; + + p_list_item = cl_qlist_head( &p_subn->sa_infr_list ); + while (p_list_item != cl_qlist_end( &p_subn->sa_infr_list )) + { + osm_dump_inform_info( p_log, + &((osm_infr_t*)p_list_item)->inform_record.inform_info, + OSM_LOG_DEBUG ); + p_list_item = cl_qlist_next( p_list_item ); + } + + Exit: + OSM_LOG_EXIT( p_log ); +} + +/********************************************************************** + * Match an infr by the InformInfo and Address vector + **********************************************************************/ +static cl_status_t +__match_inf_rec( + IN const cl_list_item_t* const p_list_item, + IN void* context ) +{ + osm_infr_t* p_infr_rec = (osm_infr_t *)context; + osm_infr_t* p_infr = (osm_infr_t*)p_list_item; + osm_log_t *p_log = p_infr_rec->p_infr_rcv->p_log; + cl_status_t status = CL_NOT_FOUND; + ib_gid_t all_zero_gid; + + OSM_LOG_ENTER( p_log, __match_inf_rec); + + if ( memcmp( &p_infr->report_addr, + &p_infr_rec->report_addr, + sizeof(p_infr_rec->report_addr)) ) + { + osm_log( p_log, OSM_LOG_DEBUG, + "__match_inf_rec: " + "Differ by Address\n" ); + goto Exit; + } + + memset( &all_zero_gid, 0, sizeof(ib_gid_t) ); + + /* if inform_info.gid is not zero, ignore lid range */ + if ( !memcmp( &p_infr_rec->inform_record.inform_info.gid, + &all_zero_gid, + sizeof(p_infr_rec->inform_record.inform_info.gid)) ) + { + if ( memcmp( &p_infr->inform_record.inform_info.gid, + &p_infr_rec->inform_record.inform_info.gid, + sizeof(p_infr->inform_record.inform_info.gid)) ) + { + osm_log( p_log, OSM_LOG_DEBUG, + "__match_inf_rec: " + "Differ by InformInfo.gid\n" ); + goto Exit; + } + } + else + { + if ( (p_infr->inform_record.inform_info.lid_range_begin != + p_infr_rec->inform_record.inform_info.lid_range_begin) || + (p_infr->inform_record.inform_info.lid_range_end != + p_infr_rec->inform_record.inform_info.lid_range_end) ) + { + osm_log( p_log, OSM_LOG_DEBUG, + "__match_inf_rec: " + "Differ by InformInfo.LIDRange\n" ); + goto Exit; + } + } + + if ( p_infr->inform_record.inform_info.trap_type != + p_infr_rec->inform_record.inform_info.trap_type ) + { + osm_log( p_log, OSM_LOG_DEBUG, + "__match_inf_rec: " + "Differ by InformInfo.TrapType\n" ); + goto Exit; + } + + if ( p_infr->inform_record.inform_info.is_generic != + p_infr_rec->inform_record.inform_info.is_generic ) + { + osm_log( p_log, OSM_LOG_DEBUG, + "__match_inf_rec: " + "Differ by InformInfo.IsGeneric\n" ); + goto Exit; + } + + if (p_infr->inform_record.inform_info.is_generic) + { + if ( p_infr->inform_record.inform_info.g_or_v.generic.trap_num != + p_infr_rec->inform_record.inform_info.g_or_v.generic.trap_num ) + osm_log( p_log, OSM_LOG_DEBUG, + "__match_inf_rec: " + "Differ by InformInfo.Generic.TrapNumber\n" ); + else if ( p_infr->inform_record.inform_info.g_or_v.generic.qpn_resp_time_val != + p_infr_rec->inform_record.inform_info.g_or_v.generic.qpn_resp_time_val ) + osm_log( p_log, OSM_LOG_DEBUG, + "__match_inf_rec: " + "Differ by InformInfo.Generic.QPNRespTimeVal\n" ); + else if ( p_infr->inform_record.inform_info.g_or_v.generic.node_type_msb != + p_infr_rec->inform_record.inform_info.g_or_v.generic.node_type_msb ) + osm_log( p_log, OSM_LOG_DEBUG, + "__match_inf_rec: " + "Differ by InformInfo.Generic.NodeTypeMSB\n" ); + else if ( p_infr->inform_record.inform_info.g_or_v.generic.node_type_lsb != + p_infr_rec->inform_record.inform_info.g_or_v.generic.node_type_lsb ) + osm_log( p_log, OSM_LOG_DEBUG, + "__match_inf_rec: " + "Differ by InformInfo.Generic.NodeTypeLSB\n" ); + else + status = CL_SUCCESS; + } + else + { + if ( p_infr->inform_record.inform_info.g_or_v.vend.dev_id != + p_infr_rec->inform_record.inform_info.g_or_v.vend.dev_id ) + osm_log( p_log, OSM_LOG_DEBUG, + "__match_inf_rec: " + "Differ by InformInfo.Vendor.DeviceID\n" ); + else if ( p_infr->inform_record.inform_info.g_or_v.vend.qpn_resp_time_val != + p_infr_rec->inform_record.inform_info.g_or_v.vend.qpn_resp_time_val ) + osm_log( p_log, OSM_LOG_DEBUG, + "__match_inf_rec: " + "Differ by InformInfo.Vendor.QPNRespTimeVal\n" ); + else if ( p_infr->inform_record.inform_info.g_or_v.vend.vendor_id_msb != + p_infr_rec->inform_record.inform_info.g_or_v.vend.vendor_id_msb ) + osm_log( p_log, OSM_LOG_DEBUG, + "__match_inf_rec: " + "Differ by InformInfo.Vendor.VendorIdMSB\n" ); + else if ( p_infr->inform_record.inform_info.g_or_v.vend.vendor_id_lsb != + p_infr_rec->inform_record.inform_info.g_or_v.vend.vendor_id_lsb ) + osm_log( p_log, OSM_LOG_DEBUG, + "__match_inf_rec: " + "Differ by InformInfo.Vendor.VendorIdLSB\n" ); + else + status = CL_SUCCESS; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return status; +} + +/********************************************************************** + **********************************************************************/ +osm_infr_t* +osm_infr_get_by_rec( + IN osm_subn_t const *p_subn, + IN osm_log_t *p_log, + IN osm_infr_t* const p_infr_rec ) +{ + cl_list_item_t* p_list_item; + + OSM_LOG_ENTER( p_log, osm_infr_get_by_rec ); + + __dump_all_informs( p_subn, p_log ); + + osm_log( p_log, OSM_LOG_DEBUG, + "osm_infr_get_by_rec: " + "Looking for Inform Record\n" ); + osm_dump_inform_info( p_log, &(p_infr_rec->inform_record.inform_info), + OSM_LOG_DEBUG ); + osm_log( p_log, OSM_LOG_DEBUG, + "osm_infr_get_by_rec: " + "InformInfo list size %d\n", + cl_qlist_count(&p_subn->sa_infr_list) ); + + p_list_item = cl_qlist_find_from_head( + &p_subn->sa_infr_list, + __match_inf_rec, + p_infr_rec ); + + if( p_list_item == cl_qlist_end( &p_subn->sa_infr_list ) ) + p_list_item = NULL; + + OSM_LOG_EXIT( p_log ); + return (osm_infr_t*)p_list_item; +} + +/********************************************************************** + **********************************************************************/ +void +osm_infr_insert_to_db( + IN osm_subn_t *p_subn, + IN osm_log_t *p_log, + IN osm_infr_t *p_infr) +{ + OSM_LOG_ENTER( p_log, osm_infr_insert_to_db ); + + osm_log( p_log, OSM_LOG_DEBUG, + "osm_infr_insert_to_db: " + "Inserting new InformInfo Record into Database\n" ); + osm_log( p_log, OSM_LOG_DEBUG, + "osm_infr_insert_to_db: " + "Dump before insertion (size %d)\n", + cl_qlist_count(&p_subn->sa_infr_list) ); + __dump_all_informs( p_subn, p_log ); + +#if 0 + osm_dump_inform_info( p_log, + &(p_infr->inform_record.inform_info), OSM_LOG_DEBUG ); +#endif + + cl_qlist_insert_head( &p_subn->sa_infr_list, + &p_infr->list_item ); + + osm_log( p_log, OSM_LOG_DEBUG, + "osm_infr_insert_to_db: " + "Dump after insertion (size %d)\n", + cl_qlist_count(&p_subn->sa_infr_list) ); + __dump_all_informs( p_subn, p_log ); + OSM_LOG_EXIT( p_log ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_infr_remove_from_db( + IN osm_subn_t *p_subn, + IN osm_log_t *p_log, + IN osm_infr_t *p_infr) +{ + OSM_LOG_ENTER( p_log, osm_infr_remove_from_db ); + + osm_log( p_log, OSM_LOG_DEBUG, + "osm_infr_remove_from_db: " + "Removing InformInfo Subscribing GID:0x%016" PRIx64 " : 0x%016" PRIx64 + " Enum:0x%X from Database\n", + cl_ntoh64(p_infr->inform_record.subscriber_gid.unicast.prefix), + cl_ntoh64(p_infr->inform_record.subscriber_gid.unicast.interface_id), + p_infr->inform_record.subscriber_enum + ); + + osm_dump_inform_info( p_log, &(p_infr->inform_record.inform_info), OSM_LOG_DEBUG ); + + cl_qlist_remove_item( &p_subn->sa_infr_list, + &p_infr->list_item ); + + osm_infr_destroy( p_infr ); + + OSM_LOG_EXIT( p_log ); +} + +/********************************************************************** + * Send a report: + * Given a target address to send to and the notice. + * We need to send SubnAdmReport + **********************************************************************/ +static ib_api_status_t +__osm_send_report( + IN osm_infr_t* p_infr_rec, /* the informinfo */ + IN ib_mad_notice_attr_t* p_ntc /* notice to send */ + ) +{ + osm_madw_t* p_report_madw; + ib_mad_notice_attr_t* p_report_ntc; + ib_mad_t* p_mad; + ib_sa_mad_t* p_sa_mad; + static atomic32_t trap_fwd_trans_id = 0x02DAB000; + ib_api_status_t status; + osm_log_t * p_log = p_infr_rec->p_infr_rcv->p_log; + + OSM_LOG_ENTER( p_log, __osm_send_report ); + + /* HACK: who switches or uses the src and dest GIDs in the grh_info ?? */ + + /* it is better to use LIDs since the GIDs might not be there for SMI traps */ + osm_log( p_log, OSM_LOG_DEBUG, + "__osm_send_report: " + "Forwarding Notice Event from LID:0x%X" + " to InformInfo LID: 0x%X TID:0x%X\n", + cl_ntoh16(p_ntc->issuer_lid), + cl_ntoh16(p_infr_rec->report_addr.dest_lid), + trap_fwd_trans_id + ); + + /* get the MAD to send */ + p_report_madw = osm_mad_pool_get( p_infr_rec->p_infr_rcv->p_mad_pool, + p_infr_rec->h_bind, + MAD_BLOCK_SIZE, + &(p_infr_rec->report_addr) ); + + p_report_madw->resp_expected = TRUE; + + if( !p_report_madw ) + { + osm_log( p_log, OSM_LOG_ERROR, + "__osm_send_report: ERR 0203: " + "osm_mad_pool_get failed\n" ); + status = IB_ERROR; + goto Exit; + } + + /* advance trap trans id (cant simply ++ on some systems inside ntoh) */ + p_mad = osm_madw_get_mad_ptr( p_report_madw ); + ib_mad_init_new( p_mad, + IB_MCLASS_SUBN_ADM, + 2, + IB_MAD_METHOD_REPORT, + cl_hton64( (uint64_t)cl_atomic_inc( &trap_fwd_trans_id ) ), + IB_MAD_ATTR_NOTICE, + 0 ); + + p_sa_mad = osm_madw_get_sa_mad_ptr( p_report_madw ); + + p_report_ntc = (ib_mad_notice_attr_t*)&(p_sa_mad->data); + + /* copy the notice */ + *p_report_ntc = *p_ntc; + + /* The TRUE is for: response is expected */ + status = osm_vendor_send( p_report_madw->h_bind, p_report_madw, TRUE ); + if ( status != IB_SUCCESS ) + { + osm_log( p_log, OSM_LOG_ERROR, + "__osm_send_report: ERR 0204: " + "osm_vendor_send status = %s\n", + ib_get_err_str(status) ); + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return(status); +} + +/********************************************************************** + * This routine compares a given Notice and a ListItem of InformInfo type. + * PREREQUISITE: + * The Notice.GID should be pre-filled with the trap generator GID + **********************************************************************/ +static void +__match_notice_to_inf_rec( + IN cl_list_item_t* const p_list_item, + IN void* context ) +{ + osm_infr_match_ctxt_t* p_infr_match = (osm_infr_match_ctxt_t *)context; + ib_mad_notice_attr_t* p_ntc = p_infr_match->p_ntc; + cl_list_t* p_infr_to_remove_list = p_infr_match->p_remove_infr_list; + osm_infr_t* p_infr_rec = (osm_infr_t*)p_list_item; + ib_inform_info_t *p_ii = &(p_infr_rec->inform_record.inform_info); + cl_status_t status = CL_NOT_FOUND; + osm_log_t *p_log = p_infr_rec->p_infr_rcv->p_log; + osm_subn_t *p_subn = p_infr_rec->p_infr_rcv->p_subn; + ib_gid_t source_gid; + osm_port_t* p_src_port; + osm_port_t* p_dest_port; + + OSM_LOG_ENTER( p_log, __match_notice_to_inf_rec ); + + /* matching rules + * InformInfo Notice + * GID IssuerGID if non zero must match the trap + * LIDRange IssuerLID apply only if GID=0 + * IsGeneric IsGeneric is compulsory and must match the trap + * Type Type if not 0xFFFF must match + * TrapNumber TrapNumber if not 0xFFFF must match + * DeviceId DeviceID if not 0xFFFF must match + * QPN dont care + * ProducerType ProducerType match or 0xFFFFFF // EZ: actually my interpretation + * VendorID VendorID match or 0xFFFFFF + */ + + /* GID IssuerGID if non zero must match the trap */ + if ( p_ii->gid.unicast.prefix != 0 || p_ii->gid.unicast.interface_id != 0 ) + { + /* match by GID */ + if ( memcmp(&(p_ii->gid), &(p_ntc->issuer_gid), sizeof(ib_gid_t)) ) + { + osm_log( p_log, OSM_LOG_DEBUG, + "__match_notice_to_inf_rec: " + "Mismatch by GID\n" ); + goto Exit; + } + } + else + { + /* LIDRange IssuerLID apply only if GID=0 */ + /* If lid_range_begin of the informInfo is 0xFFFF - then it should be ignored. */ + if ( p_ii->lid_range_begin != 0xFFFF ) + { + /* a real lid range is given - check it */ + if ( (cl_hton16(p_ii->lid_range_begin) > cl_hton16(p_ntc->issuer_lid)) || + (cl_hton16(p_ntc->issuer_lid) > cl_hton16(p_ii->lid_range_end)) ) { + osm_log( p_log, OSM_LOG_DEBUG, + "__match_notice_to_inf_rec: " + "Mismatch by LID Range. Needed: 0x%X <= 0x%X <= 0x%X\n", + cl_hton16(p_ii->lid_range_begin), + cl_hton16(p_ntc->issuer_lid), + cl_hton16(p_ii->lid_range_end) + ); + goto Exit; + } + } + } + + /* IsGeneric IsGeneric is compulsory and must match the trap */ + if ( (p_ii->is_generic && ! ib_notice_is_generic(p_ntc)) || + (!p_ii->is_generic && ib_notice_is_generic(p_ntc)) ) + { + osm_log( p_log, OSM_LOG_DEBUG, + "__match_notice_to_inf_rec: " + "Mismatch by Generic/Vendor\n" ); + goto Exit; + } + + /* Type Type if not 0xFFFF must match */ + if ( (p_ii->trap_type != 0xFFFF) && + (cl_ntoh16(p_ii->trap_type) != ib_notice_get_type(p_ntc)) ) + { + osm_log( p_log, OSM_LOG_DEBUG, + "__match_notice_to_inf_rec: " + "Mismatch by Type\n" ); + goto Exit; + } + + /* based on generic type */ + if ( p_ii->is_generic ) + { + /* TrapNumber TrapNumber if not 0xFFFF must match */ + if ( (p_ii->g_or_v.generic.trap_num != 0xFFFF) && + (p_ii->g_or_v.generic.trap_num != p_ntc->g_or_v.generic.trap_num) ) + { + osm_log( p_log, OSM_LOG_DEBUG, + "__match_notice_to_inf_rec: " + "Mismatch by Trap Num\n" ); + goto Exit; + } + + /* ProducerType ProducerType match or 0xFFFFFF */ + if ( (cl_ntoh32(ib_inform_info_get_node_type(p_ii)) != 0xFFFFFF) && + (ib_inform_info_get_node_type(p_ii) != ib_notice_get_prod_type(p_ntc)) ) + { + osm_log( p_log, OSM_LOG_DEBUG, + "__match_notice_to_inf_rec: " + "Mismatch by Node Type: II=0x%06X Trap=0x%06X\n", + cl_ntoh32(ib_inform_info_get_node_type(p_ii)), + cl_ntoh32(ib_notice_get_prod_type(p_ntc)) + ); + goto Exit; + } + } + else + { + /* DeviceId DeviceID if not 0xFFFF must match */ + if ( (p_ii->g_or_v.vend.dev_id != 0xFFFF) && + (p_ii->g_or_v.vend.dev_id != p_ntc->g_or_v.vend.dev_id) ) + { + osm_log( p_log, OSM_LOG_DEBUG, + "__match_notice_to_inf_rec: " + "Mismatch by Dev Id\n" ); + goto Exit; + } + + /* VendorID VendorID match or 0xFFFFFF */ + if ( (ib_inform_info_get_vend_id(p_ii) != CL_HTON32(0xFFFFFF)) && + (ib_inform_info_get_vend_id(p_ii) != ib_notice_get_vend_id(p_ntc)) ) + { + osm_log( p_log, OSM_LOG_DEBUG, + "__match_notice_to_inf_rec: " + "Mismatch by Vendor ID\n" ); + goto Exit; + } + } + + /* Check if there is a pkey match. o13-17.1.1 */ + /* Check if the issuer of the trap is the SM. If it is, then the gid + comparison should be done on the trap source (saved as the gid in the + data details field). + If the issuer gid is not the SM - then it is the guid of the trap + source */ + if ( (cl_ntoh64(p_ntc->issuer_gid.unicast.prefix) == p_subn->opt.subnet_prefix) && + (cl_ntoh64(p_ntc->issuer_gid.unicast.interface_id) == p_subn->sm_port_guid) ) + { + /* The issuer is the SM then this is trap 64-67 - compare the gid + with the gid saved on the data details */ + source_gid = p_ntc->data_details.ntc_64_67.gid; + } + else + { + source_gid = p_ntc->issuer_gid; + } + p_src_port = (osm_port_t*)cl_qmap_get( &p_subn->port_guid_tbl, + source_gid.unicast.interface_id ); + + if( p_src_port == (osm_port_t*)cl_qmap_end( &(p_subn->port_guid_tbl)) ) + { + osm_log( p_log, OSM_LOG_INFO, + "__match_notice_to_inf_rec: " + "Cannot find source port with GUID:0x%016" PRIx64 "\n", + cl_ntoh64(source_gid.unicast.interface_id) ); + goto Exit; + } + + p_dest_port = + cl_ptr_vector_get( &p_subn->port_lid_tbl, + cl_ntoh16(p_infr_rec->report_addr.dest_lid) ); + if( !p_dest_port ) + { + osm_log( p_log, OSM_LOG_INFO, + "__match_notice_to_inf_rec: " + "Cannot find destination port with LID:0x%04x\n", + cl_ntoh16(p_infr_rec->report_addr.dest_lid) ); + goto Exit; + } + + if (osm_port_share_pkey( p_log, p_src_port, p_dest_port ) == FALSE ) + { + osm_log( p_log, OSM_LOG_DEBUG, + "__match_notice_to_inf_rec: " + "Mismatch by Pkey\n" ); + /* According to o13-17.1.2 - If this informInfo does not have + lid_range_begin of 0xFFFF, then this informInfo request + should be removed from database */ + if ( p_ii->lid_range_begin != 0xFFFF ) + { + osm_log( p_log, OSM_LOG_VERBOSE, + "__match_notice_to_inf_rec: " + "Pkey mismatch on lid_range_begin != 0xFFFF. " + "Need to remove this informInfo from db\n" ); + /* add the informInfo record to the remove_infr list */ + cl_list_insert_tail( p_infr_to_remove_list, p_infr_rec ); + } + goto Exit; + } + + /* send the report to the address provided in the inform record */ + osm_log( p_log, OSM_LOG_DEBUG, + "__match_notice_to_inf_rec: " + "MATCH! Sending Report...\n" ); + __osm_send_report( p_infr_rec, p_ntc ); + status = CL_SUCCESS; + + Exit: + OSM_LOG_EXIT( p_log ); +} + +/********************************************************************** + * Once a Trap was received by osm_trap_rcv, or a Trap sourced by + * the SM was sent (Traps 64-67), this routine is called with a copy of + * the notice data. + * Given a notice attribute - compare and see if it matches the InformInfo + * element and if it does - call the Report(Notice) for the + * target QP registered by the address stored in the InformInfo element + **********************************************************************/ +ib_api_status_t +osm_report_notice( + IN osm_log_t* const p_log, + IN osm_subn_t* p_subn, + IN ib_mad_notice_attr_t *p_ntc ) +{ + osm_infr_match_ctxt_t context; + cl_list_t infr_to_remove_list; + osm_infr_t* p_infr_rec; + osm_infr_t* p_next_infr_rec; + + OSM_LOG_ENTER( p_log, osm_report_notice ); + + /* + * we must make sure we are ready for this... + * note that the trap receivers might be initialized before + * the osm_infr_init call is performed. + */ + if ( p_subn->sa_infr_list.state != CL_INITIALIZED ) + { + osm_log( p_log, OSM_LOG_DEBUG, + "osm_report_notice: " + "Ignoring Notice Reports since Inform List is not initialized yet!\n" ); + return IB_ERROR; + } + + /* an official Event information log */ + if ( ib_notice_is_generic(p_ntc) ) + { + osm_log( p_log, OSM_LOG_INFO, + "osm_report_notice: " + "Reporting Generic Notice type:%u num:%u" + " from LID:0x%04X GID:0x%016" PRIx64 + ",0x%016" PRIx64 "\n", + ib_notice_get_type(p_ntc), + cl_ntoh16(p_ntc->g_or_v.generic.trap_num), + cl_ntoh16(p_ntc->issuer_lid), + cl_ntoh64(p_ntc->issuer_gid.unicast.prefix), + cl_ntoh64(p_ntc->issuer_gid.unicast.interface_id) + ); + } + else + { + osm_log( p_log, OSM_LOG_INFO, + "osm_report_notice: " + "Reporting Vendor Notice type:%u vend:%u dev:%u" + " from LID:0x%04X GID:0x%016" PRIx64 + ",0x%016" PRIx64 "\n", + ib_notice_get_type(p_ntc), + cl_ntoh32(ib_notice_get_vend_id(p_ntc)), + cl_ntoh16(p_ntc->g_or_v.vend.dev_id), + cl_ntoh16(p_ntc->issuer_lid), + cl_ntoh64(p_ntc->issuer_gid.unicast.prefix), + cl_ntoh64(p_ntc->issuer_gid.unicast.interface_id) + ); + } + + /* Create a list that will hold all the infr records that should + be removed due to violation. o13-17.1.2 */ + cl_list_construct( &infr_to_remove_list ); + cl_list_init( &infr_to_remove_list, 5 ); + context.p_remove_infr_list = &infr_to_remove_list; + context.p_ntc = p_ntc; + + /* go over all inform info available at the subnet */ + /* try match to the given notice and send if match */ + cl_qlist_apply_func(&(p_subn->sa_infr_list), + __match_notice_to_inf_rec, + &context ); + + /* If we inserted items into the infr_to_remove_list - we need to + remove them */ + p_infr_rec = (osm_infr_t*)cl_list_remove_head(&infr_to_remove_list); + while ( p_infr_rec != NULL ) + { + p_next_infr_rec = (osm_infr_t*)cl_list_remove_head(&infr_to_remove_list); + osm_infr_remove_from_db ( p_subn, p_log, p_infr_rec ); + p_infr_rec = p_next_infr_rec; + } + cl_list_destroy(&infr_to_remove_list); + + OSM_LOG_EXIT( p_log ); + + return(IB_SUCCESS); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_lid_mgr.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_lid_mgr.c new file mode 100644 index 00000000..3e087374 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_lid_mgr.c @@ -0,0 +1,1494 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_lid_mgr.c 1738 2008-11-06 20:24:37Z tzachid $ + */ + + +/* + * Abstract: + * Implementation of osm_lid_mgr_t. + * This file implements the LID Manager object which is responsible for + * assigning LIDs to all ports on the subnet. + * + * DATA STRUCTURES: + * p_subn->port_lid_tbl : a vector pointing from lid to its port. + * osm db guid2lid domain : a hash from guid to lid (min lid). + * p_subn->port_guid_tbl : a map from guid to discovered port obj. + * + * ALGORITHM: + * + * 0. we define a function to obtain the correct port lid: + * __osm_lid_mgr_get_port_lid( p_mgr, port, &min_lid ): + * 0.1 if the port info lid matches the guid2lid return 0 + * 0.2 if the port info has a lid and that range is empty in + * port_lid_tbl, return 0 and update the port_lid_tbl and + * guid2lid + * 0.3 else find an empty space in port_lid_tbl, update the + * port_lid_tbl and guid2lid, return 1 to flag a change required. + * + * 1. During initialization: + * 1.1 initialize the guid2lid database domain. + * 1.2 if reassign_lid is not set: + * 1.2.1 read the persistent data for the domain. + * 1.2.2 validate no duplicate use of lids and lids are 2^(lmc-1) + * + * 2. During SM port lid assignment: + * 2.1 if reassign_lids is set, make it 2^lmc + * 2.2 cleanup all port_lid_tbl and re-fill it according to guid2lid + * 2.3 call __osm_lid_mgr_get_port_lid the SM port + * 2.4 set the port info + * + * 3. During all other ports lid assignment: + * 3.1 go through all ports in the subnet + * 3.1.1 call __osm_lid_mgr_get_port_min_lid + * 3.1.2 if a change required send the port info + * 3.2 if any change send the signal PENDING... + * + * 4. Store the guid2lid + * + * Environment: + * Linux User Mode + * + * $Revision: 1.15 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + lid range item of qlist + **********************************************************************/ +typedef struct _osm_lid_mgr_range { + cl_list_item_t item; + uint16_t min_lid; + uint16_t max_lid; +} osm_lid_mgr_range_t; + +/********************************************************************** + **********************************************************************/ +void +osm_lid_mgr_construct( + IN osm_lid_mgr_t* const p_mgr ) +{ + memset( p_mgr, 0, sizeof(*p_mgr) ); + cl_ptr_vector_construct( &p_mgr->used_lids ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_lid_mgr_destroy( + IN osm_lid_mgr_t* const p_mgr ) +{ + cl_list_item_t *p_item; + + OSM_LOG_ENTER( p_mgr->p_log, osm_lid_mgr_destroy ); + + cl_ptr_vector_destroy( &p_mgr->used_lids ); + p_item = cl_qlist_remove_head( &p_mgr->free_ranges ); + while ( p_item != cl_qlist_end( &p_mgr->free_ranges ) ) + { + free((osm_lid_mgr_range_t *)p_item); + p_item = cl_qlist_remove_head( &p_mgr->free_ranges ); + } + OSM_LOG_EXIT( p_mgr->p_log ); +} + +/********************************************************************** +Validate the guid to lid data by making sure that under the current +LMC we did not get duplicates. If we do flag them as errors and remove +the entry. +**********************************************************************/ +static void +__osm_lid_mgr_validate_db( + IN osm_lid_mgr_t* p_mgr) +{ + cl_qlist_t guids; + osm_db_guid_elem_t *p_item; + uint16_t lid; + uint16_t min_lid; + uint16_t max_lid; + uint16_t lmc_mask; + boolean_t lids_ok; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_lid_mgr_validate_db ); + + if (p_mgr->p_subn->opt.lmc) + lmc_mask = ~((1 << p_mgr->p_subn->opt.lmc) - 1); + else + lmc_mask = 0xffff; + + cl_qlist_init( &guids ); + + if (osm_db_guid2lid_guids( p_mgr->p_g2l, &guids )) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_lid_mgr_validate_db: ERR 0310: " + "could not get guid list\n"); + goto Exit; + } + + p_item = (osm_db_guid_elem_t*)cl_qlist_remove_head(&guids); + while ((cl_list_item_t*)p_item != cl_qlist_end(&guids)) + { + if (osm_db_guid2lid_get( p_mgr->p_g2l, p_item->guid, &min_lid, &max_lid )) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_lid_mgr_validate_db: ERR 0311: " + "could not get lid for guid:0x%016" PRIx64 "\n", + p_item->guid + ); + } + else + { + lids_ok = TRUE; + + if ((min_lid > max_lid) || (min_lid == 0) || (p_item->guid == 0) || + (max_lid > p_mgr->p_subn->max_unicast_lid_ho)) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_lid_mgr_validate_db: ERR 0312: " + "Illegal LID range [0x%x:0x%x] for guid:0x%016" PRIx64 + "\n", + min_lid, max_lid, p_item->guid + ); + lids_ok = FALSE; + } + else if ((min_lid != max_lid) && ((min_lid & lmc_mask) != min_lid)) + { + /* check that if the lids define a range that is valid + for the current LMC mask */ + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_lid_mgr_validate_db: ERR 0313: " + "LID range [0x%x:0x%x] for guid:0x%016" PRIx64 + " is not aligned according to mask:0x%04x\n", + min_lid, max_lid, p_item->guid, lmc_mask + ); + lids_ok = FALSE; + } + else + { + /* check if the lids were not previously assigned */ + for (lid = min_lid; lid <= max_lid; lid++) + { + if (( cl_ptr_vector_get_size( &p_mgr->used_lids ) > lid ) && + ( cl_ptr_vector_get( &p_mgr->used_lids, lid ) ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_lid_mgr_validate_db: ERR 0314: " + "0x%04x for guid:0x%016" PRIx64 + " was previously used\n", + lid, p_item->guid + ); + lids_ok = FALSE; + } + } + } + + if (!lids_ok) + { + if (osm_db_guid2lid_delete( p_mgr->p_g2l, p_item->guid )) + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_lid_mgr_validate_db: ERR 0315: " + "failed to delete entry for guid:0x%016" PRIx64 + "\n", + p_item->guid + ); + } + else + { + /* mark it was visited */ + for (lid = min_lid; lid <= max_lid; lid++) + cl_ptr_vector_set( &p_mgr->used_lids, lid, (void *)1); + } + } /* got a lid */ + p_item = (osm_db_guid_elem_t*)cl_qlist_remove_head(&guids); + } /* all guids */ + Exit: + OSM_LOG_EXIT( p_mgr->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_lid_mgr_init( + IN osm_lid_mgr_t* const p_mgr, + IN osm_req_t* const p_req, + IN osm_subn_t* const p_subn, + IN osm_db_t* const p_db, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_lid_mgr_init ); + + CL_ASSERT( p_req ); + CL_ASSERT( p_subn ); + CL_ASSERT( p_lock ); + CL_ASSERT( p_db ); + + osm_lid_mgr_construct( p_mgr ); + + p_mgr->p_log = p_log; + p_mgr->p_subn = p_subn; + p_mgr->p_db = p_db; + p_mgr->p_lock = p_lock; + p_mgr->p_req = p_req; + + /* we initialize and restore the db domain of guid to lid map */ + p_mgr->p_g2l = osm_db_domain_init(p_mgr->p_db, "guid2lid"); + if (! p_mgr->p_g2l) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "osm_lid_mgr_init: ERR 0316: " + "Error initializing Guid-to-Lid persistent database\n"); + status = IB_ERROR; + goto Exit; + } + + cl_ptr_vector_init( &p_mgr->used_lids, 100, 40 ); + cl_qlist_init( &p_mgr->free_ranges ); + + /* we use the stored guid to lid table if not forced to reassign */ + if (!p_mgr->p_subn->opt.reassign_lids) + { + if (osm_db_restore(p_mgr->p_g2l)) + { +#ifndef __WIN__ + /* + * When Windows is BSODing, it might corrupt files that were + * previously opened for writing, even if the files are closed. + * This is because of Windows write caching option. + * As a result, we might see corrupted guid2lid file. + */ + if (p_subn->opt.exit_on_fatal) + { + osm_log( p_mgr->p_log, OSM_LOG_SYS, + "FATAL: Error restoring Guid-to-Lid persistent database\n" ); + status = IB_ERROR; + goto Exit; + } + else +#endif + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "osm_lid_mgr_init: ERR 0317: " + "Error restoring Guid-to-Lid persistent database\n"); + } + } + + /* we need to make sure we did not get duplicates with + current lmc */ + __osm_lid_mgr_validate_db(p_mgr); + } + +Exit: + OSM_LOG_EXIT( p_mgr->p_log ); + return( status ); +} + +static uint16_t +__osm_trim_lid( + IN uint16_t lid ) +{ + if ((lid > IB_LID_UCAST_END_HO) || + (lid < IB_LID_UCAST_START_HO)) + return 0; + return lid; +} + +/********************************************************************** + initialize the manager for a new sweep: + scans the known persistent assignment and port_lid_tbl + re-calculate all empty ranges. + cleanup invalid port_lid_tbl entries +**********************************************************************/ +static int +__osm_lid_mgr_init_sweep( + IN osm_lid_mgr_t* const p_mgr ) +{ + cl_ptr_vector_t *p_discovered_vec = &p_mgr->p_subn->port_lid_tbl; + cl_ptr_vector_t *p_persistent_vec = &p_mgr->used_lids; + uint16_t max_defined_lid; + uint16_t max_persistent_lid; + uint16_t max_discovered_lid; + uint16_t lid; + uint16_t disc_min_lid; + uint16_t disc_max_lid; + uint16_t db_min_lid; + uint16_t db_max_lid; + int status = 0; + cl_list_item_t *p_item; + boolean_t is_free; + osm_lid_mgr_range_t *p_range = NULL; + osm_port_t *p_port; + cl_qmap_t *p_port_guid_tbl; + uint8_t lmc_num_lids = (uint8_t)(1 << p_mgr->p_subn->opt.lmc); + uint16_t lmc_mask; + uint16_t req_lid, num_lids; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_lid_mgr_init_sweep ); + + if (p_mgr->p_subn->opt.lmc) + lmc_mask = ~((1 << p_mgr->p_subn->opt.lmc) - 1); + else + lmc_mask = 0xffff; + + /* if we came out of standby we need to discard any previous guid2lid + info we might have. + Do this only if the honor_guid2lid_file option is FALSE. If not, then + need to honor this file. */ + if ( p_mgr->p_subn->coming_out_of_standby == TRUE ) + { + if ( p_mgr->p_subn->opt.honor_guid2lid_file == FALSE ) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_lid_mgr_init_sweep: " + "Ignore guid2lid file when coming out of standby\n"); + osm_db_clear( p_mgr->p_g2l ); + for (lid = 0; lid < cl_ptr_vector_get_size(&p_mgr->used_lids); lid++) + cl_ptr_vector_set(p_persistent_vec, lid, NULL); + } + else + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_lid_mgr_init_sweep: " + "Honor current guid2lid file when coming out of standby\n"); + osm_db_clear( p_mgr->p_g2l ); + if (osm_db_restore(p_mgr->p_g2l)) + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "osm_lid_mgr_init_sweep: ERR 0306: " + "Error restoring Guid-to-Lid persistent database. Ignoring it\n"); + } + } + + /* we need to cleanup the empty ranges list */ + p_item = cl_qlist_remove_head( &p_mgr->free_ranges ); + while ( p_item != cl_qlist_end( &p_mgr->free_ranges ) ) + { + free( (osm_lid_mgr_range_t *)p_item ); + p_item = cl_qlist_remove_head( &p_mgr->free_ranges ); + } + + /* first clean up the port_by_lid_tbl */ + for (lid = 0; lid < cl_ptr_vector_get_size(p_discovered_vec); lid++) + cl_ptr_vector_set(p_discovered_vec, lid, NULL); + + /* we if are in the first sweep and in reassign lids mode + we should ignore all the available info and simply define one + huge empty range */ + if ((p_mgr->p_subn->first_time_master_sweep == TRUE) && + (p_mgr->p_subn->opt.reassign_lids == TRUE )) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_lid_mgr_init_sweep: " + "Skipping all lids as we are reassigning them\n"); + p_range = + (osm_lid_mgr_range_t *)malloc(sizeof(osm_lid_mgr_range_t)); + p_range->min_lid = 1; + goto AfterScanningLids; + } + + /* go over all discovered ports and mark their entries */ + p_port_guid_tbl = &p_mgr->p_subn->port_guid_tbl; + + for( p_port = (osm_port_t*)cl_qmap_head( p_port_guid_tbl ); + p_port != (osm_port_t*)cl_qmap_end( p_port_guid_tbl ); + p_port = (osm_port_t*)cl_qmap_next( &p_port->map_item ) ) + { + osm_port_get_lid_range_ho(p_port, &disc_min_lid, &disc_max_lid); + disc_min_lid = __osm_trim_lid(disc_min_lid); + disc_max_lid = __osm_trim_lid(disc_max_lid); + for (lid = disc_min_lid; lid <= disc_max_lid; lid++) + cl_ptr_vector_set(p_discovered_vec, lid, p_port ); + /* make sure the guid2lid entry is valid. If not, clean it. */ + if (!osm_db_guid2lid_get( p_mgr->p_g2l, + cl_ntoh64(osm_port_get_guid(p_port)), + &db_min_lid, &db_max_lid)) + { + if ( !p_port->p_node->sw || + osm_switch_sp0_is_lmc_capable(p_port->p_node->sw, p_mgr->p_subn)) + num_lids = lmc_num_lids; + else + num_lids = 1; + + if ((num_lids != 1) && + (((db_min_lid & lmc_mask) != db_min_lid) || + (db_max_lid - db_min_lid + 1 < num_lids)) ) + { + /* Not aligned, or not wide enough, then remove the entry */ + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_lid_mgr_init_sweep: " + "Cleaning persistent entry for guid:0x%016" PRIx64 + " illegal range:[0x%x:0x%x]\n", + cl_ntoh64(osm_port_get_guid(p_port)), db_min_lid, + db_max_lid ); + osm_db_guid2lid_delete( p_mgr->p_g2l, + cl_ntoh64(osm_port_get_guid(p_port))); + for ( lid = db_min_lid ; lid <= db_max_lid ; lid++ ) + cl_ptr_vector_set(p_persistent_vec, lid, NULL); + } + } + } + + /* + Our task is to find free lid ranges. + A lid can be used if + 1. a persistent assignment exists + 2. the lid is used by a discovered port that does not have a persistent + assignment. + + scan through all lid values of both the persistent table and + discovered table. + If the lid has an assigned port in the discovered table: + * make sure the lid matches the persistent table, or + * there is no other persistent assignment for that lid. + * else cleanup the port_by_lid_tbl, mark this as empty range. + Else if the lid does not have an entry in the persistent table + mark it as free. + */ + + /* find the range of lids to scan */ + max_discovered_lid = (uint16_t)cl_ptr_vector_get_size(p_discovered_vec); + max_persistent_lid = (uint16_t)cl_ptr_vector_get_size(p_persistent_vec); + + /* but the vectors have one extra entry for lid=0 */ + if (max_discovered_lid) max_discovered_lid--; + if (max_persistent_lid) max_persistent_lid--; + + if (max_persistent_lid > max_discovered_lid) + max_defined_lid = max_persistent_lid; + else + max_defined_lid = max_discovered_lid; + + for (lid = 1; lid <= max_defined_lid ; lid++) + { + is_free = TRUE; + /* first check to see if the lid is used by a persistent assignment */ + if ((lid <= max_persistent_lid) && cl_ptr_vector_get(p_persistent_vec, lid)) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_lid_mgr_init_sweep: " + "0x%04x is not free as its mapped by the persistent db\n", + lid); + is_free = FALSE; + } + else + { + /* check this is a discovered port */ + if (lid <= max_discovered_lid && (p_port = (osm_port_t *)cl_ptr_vector_get(p_discovered_vec, lid))) + { + /* we have a port. Now lets see if we can preserve its lid range. */ + /* For that, we need to make sure: + 1. The port has a (legal) persistency entry. Then the local lid + is free (we will use the persistency value). + 2. Can the port keep its local assignment? + a. Make sure the lid a aligned. + b. Make sure all needed lids (for the lmc) are free according + to persistency table. + */ + /* qualify the guid of the port is not persistently mapped to + another range */ + if (!osm_db_guid2lid_get( p_mgr->p_g2l, + cl_ntoh64(osm_port_get_guid(p_port)), + &db_min_lid, &db_max_lid)) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_lid_mgr_init_sweep: " + "0x%04x is free as it was discovered " + "but mapped by the persistent db to [0x%04x:0x%04x]\n", + lid, db_min_lid, db_max_lid); + } + else + { + /* can the port keep its assignment ? */ + /* get the lid range of that port, and the required number + of lids we are about to assign to it */ + osm_port_get_lid_range_ho(p_port, &disc_min_lid, &disc_max_lid); + if ( !p_port->p_node->sw || + osm_switch_sp0_is_lmc_capable(p_port->p_node->sw, p_mgr->p_subn)) + { + disc_max_lid = disc_min_lid + lmc_num_lids - 1; + num_lids = lmc_num_lids; + } + else + num_lids = 1; + + /* Make sure the lid is aligned */ + if ((num_lids != 1) && ((disc_min_lid & lmc_mask) != disc_min_lid)) + { + /* The lid cannot be used */ + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_lid_mgr_init_sweep: " + "0x%04x is free as it was discovered " + "but not aligned\n", + lid ); + } + else + { + /* check that all needed lids are not persistently mapped */ + is_free = FALSE; + for ( req_lid = disc_min_lid + 1 ; req_lid <= disc_max_lid ; req_lid++ ) + { + if ((req_lid <= max_persistent_lid) && cl_ptr_vector_get(p_persistent_vec, req_lid)) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_lid_mgr_init_sweep: " + "0x%04x is free as it was discovered " + "but mapped\n", + lid ); + is_free = TRUE; + break; + } + } + + if (is_free == FALSE) + { + /* This port will use its local lid, and consume the entire required lid range. + Thus we can skip that range. */ + /* If the disc_max_lid is greater then lid, we can skip right to it, + since we've done all neccessary checks on the lids in between. */ + if (disc_max_lid > lid) + lid = disc_max_lid; + } + } + } + } + } + + if (is_free) + { + if (p_range) + { + p_range->max_lid = lid; + } + else + { + p_range = + (osm_lid_mgr_range_t *)malloc(sizeof(osm_lid_mgr_range_t)); + p_range->min_lid = lid; + p_range->max_lid = lid; + } + } + else + { + /* this lid is used so we need to finalize the previous free range */ + if (p_range) + { + cl_qlist_insert_tail( &p_mgr->free_ranges, &p_range->item ); + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_lid_mgr_init_sweep: " + "new free lid range [0x%x:0x%x]\n", + p_range->min_lid, p_range->max_lid); + p_range = NULL; + } + } + } + + AfterScanningLids: + /* after scanning all known lids we need to extend the last range + to the max allowed lid */ + if (!p_range) + { + p_range = + (osm_lid_mgr_range_t *)malloc(sizeof(osm_lid_mgr_range_t)); + /* + The p_range can be NULL in one of 2 cases: + 1. If max_defined_lid == 0. In this case, we want the entire range. + 2. If all lids discovered in the loop where mapped. In this case, + no free range exists and we want to define it after the last + mapped lid. + */ + p_range->min_lid = lid; + } + p_range->max_lid = p_mgr->p_subn->max_unicast_lid_ho - 1; + cl_qlist_insert_tail( &p_mgr->free_ranges, &p_range->item ); + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_lid_mgr_init_sweep: " + "final free lid range [0x%x:0x%x]\n", + p_range->min_lid, p_range->max_lid ); + + OSM_LOG_EXIT( p_mgr->p_log ); + return status; +} + +/********************************************************************** + check if the given range of lids is free +**********************************************************************/ +static boolean_t +__osm_lid_mgr_is_range_not_persistent( + IN osm_lid_mgr_t* const p_mgr, + IN const uint16_t lid, + IN const uint16_t num_lids ) +{ + uint16_t i; + cl_status_t status; + osm_port_t *p_port; + const uint8_t start_lid = (uint8_t)(1 << p_mgr->p_subn->opt.lmc); + const cl_ptr_vector_t* const p_tbl = &p_mgr->used_lids; + + if( lid < start_lid ) + return( FALSE ); + + for( i = lid; i < lid + num_lids; i++ ) + { + status = cl_ptr_vector_at( p_tbl, i, (void*)&p_port ); + if( status == CL_SUCCESS ) + { + if(p_port != NULL) + return( FALSE ); + } + else + { + /* + We are out of range in the array. + Consider all further entries "free". + */ + return( TRUE ); + } + } + + return( TRUE ); +} + +/********************************************************************** +find a free lid range +**********************************************************************/ +static void +__osm_lid_mgr_find_free_lid_range( + IN osm_lid_mgr_t* const p_mgr, + IN const uint8_t num_lids, + OUT uint16_t* const p_min_lid, + OUT uint16_t* const p_max_lid ) +{ + uint16_t lid; + cl_list_item_t *p_item; + cl_list_item_t *p_next_item; + osm_lid_mgr_range_t *p_range = NULL; + uint8_t lmc_num_lids; + uint16_t lmc_mask; + + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_lid_mgr_find_free_lid_range: " + "LMC = %u, number LIDs = %u\n", + p_mgr->p_subn->opt.lmc, num_lids ); + + lmc_num_lids = (1 << p_mgr->p_subn->opt.lmc ); + if (p_mgr->p_subn->opt.lmc) + lmc_mask = ~((1 << p_mgr->p_subn->opt.lmc) - 1); + else + lmc_mask = 0xffff; + + /* + Search the list of free lid ranges for a range which is big enough + */ + p_item = cl_qlist_head( &p_mgr->free_ranges ); + while( p_item != cl_qlist_end( &p_mgr->free_ranges ) ) + { + p_next_item = cl_qlist_next( p_item ); + p_range = (osm_lid_mgr_range_t *)p_item; + + lid = p_range->min_lid; + + /* if we require more then one lid we must align to LMC */ + if (num_lids > 1) + { + if ((lid & lmc_mask) != lid) + lid = (lid + lmc_num_lids) & lmc_mask; + } + + /* but we can be out of the range */ + if (lid + num_lids - 1 <= p_range->max_lid) + { + /* ok let us use that range */ + if (lid + num_lids - 1 == p_range->max_lid) + { + /* we consumed the entire range */ + cl_qlist_remove_item( &p_mgr->free_ranges, p_item ); + } + else + { + /* only update the available range */ + p_range->min_lid = lid + num_lids; + } + + *p_min_lid = lid; + *p_max_lid = (uint16_t)(lid + num_lids - 1); + return; + } + p_item = p_next_item; + } + + /* + Couldn't find a free range of lids. + */ + *p_min_lid = *p_max_lid = 0; + /* if we run out of lids, give an error and abort! */ + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_lid_mgr_find_free_lid_range: ERR 0307: " + "OPENSM RAN OUT OF LIDS!!!\n" ); + CL_ASSERT( 0 ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_lid_mgr_cleanup_discovered_port_lid_range( + IN osm_lid_mgr_t* p_mgr, + IN osm_port_t *p_port ) +{ + cl_ptr_vector_t *p_discovered_vec = &p_mgr->p_subn->port_lid_tbl; + uint16_t lid, min_lid, max_lid; + uint16_t max_tbl_lid = (uint16_t)(cl_ptr_vector_get_size( p_discovered_vec )); + + osm_port_get_lid_range_ho(p_port, &min_lid, &max_lid); + min_lid = __osm_trim_lid(min_lid); + max_lid = __osm_trim_lid(max_lid); + for (lid = min_lid; lid <= max_lid; lid++) + { + if ((lid < max_tbl_lid ) && + (p_port == (osm_port_t*)cl_ptr_vector_get(p_discovered_vec, lid))) + cl_ptr_vector_set(p_discovered_vec, lid, NULL ); + } +} + +/********************************************************************** + 0.1 if the port info lid matches the guid2lid return 0 + 0.2 if the port info has a lid and that range is empty in + port_lid_tbl, return 0 and update the port_lid_tbl and + guid2lid + 0.3 else find an empty space in port_lid_tbl, update the + port_lid_tbl and guid2lid, return 1 to flag a change required. +**********************************************************************/ +static int +__osm_lid_mgr_get_port_lid( + IN osm_lid_mgr_t* const p_mgr, + IN osm_port_t * const p_port, + OUT uint16_t* const p_min_lid, + OUT uint16_t* const p_max_lid) +{ + uint16_t lid, min_lid, max_lid; + uint64_t guid; + uint8_t num_lids = (1 << p_mgr->p_subn->opt.lmc); + int lid_changed = 0; + uint16_t lmc_mask; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_lid_mgr_get_port_lid ); + + if (p_mgr->p_subn->opt.lmc) + lmc_mask = ~((1 << p_mgr->p_subn->opt.lmc) - 1); + else + lmc_mask = 0xffff; + + /* get the lid from the guid2lid */ + guid = cl_ntoh64( osm_port_get_guid( p_port ) ); + + /* if the port is a base switch port 0 then we only need one lid */ + if( p_port->p_node->sw && + !osm_switch_sp0_is_lmc_capable(p_port->p_node->sw, p_mgr->p_subn)) + num_lids = 1; + + /* if the port matches the guid2lid */ + if (!osm_db_guid2lid_get( p_mgr->p_g2l, guid, &min_lid, &max_lid)) + { + *p_min_lid = min_lid; + *p_max_lid = min_lid + num_lids - 1; + if (min_lid == cl_ntoh16(osm_port_get_base_lid(p_port))) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_lid_mgr_get_port_lid: " + "0x%016" PRIx64" matches its known lid:0x%04x\n", + guid, min_lid ); + goto Exit; + } + else + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_lid_mgr_get_port_lid: " + "0x%016" PRIx64 + " with lid:0x%04x does not match its known lid:0x%04x\n", + guid, cl_ntoh16(osm_port_get_base_lid(p_port)), min_lid); + __osm_lid_mgr_cleanup_discovered_port_lid_range( p_mgr, p_port ); + /* we still need to send the setting to the target port */ + lid_changed = 1; + goto Exit; + } + } + else + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_lid_mgr_get_port_lid: " + "0x%016" PRIx64" has no persistent lid assigned\n", + guid ); + } + + /* if the port info carries a lid it must be lmc aligned and not mapped + by the pesistent storage */ + min_lid = cl_ntoh16(osm_port_get_base_lid(p_port)); + + /* we want to ignore the discovered lid if we are also on first sweep of + reassign lids flow */ + if (min_lid && + ! ((p_mgr->p_subn->first_time_master_sweep == TRUE) && + (p_mgr->p_subn->opt.reassign_lids == TRUE ))) + { + /* make sure lid is valid */ + if ((num_lids == 1) || ((min_lid & lmc_mask) == min_lid)) + { + /* is it free */ + if (__osm_lid_mgr_is_range_not_persistent(p_mgr, min_lid, num_lids)) + { + *p_min_lid = min_lid; + *p_max_lid = min_lid + num_lids - 1; + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_lid_mgr_get_port_lid: " + "0x%016" PRIx64" lid range:[0x%x-0x%x] is free\n", + guid, *p_min_lid, *p_max_lid ); + goto NewLidSet; + } + else + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_lid_mgr_get_port_lid: " + "0x%016" PRIx64 + " existing lid range:[0x%x:0x%x] is not free\n", + guid, min_lid, min_lid + num_lids - 1 ); + } + } + else + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_lid_mgr_get_port_lid: " + "0x%016" PRIx64 + " existing lid range:[0x%x:0x%x] is not lmc aligned\n", + guid, min_lid, min_lid + num_lids - 1 ); + } + } + + /* first cleanup the existing discovered lid range */ + __osm_lid_mgr_cleanup_discovered_port_lid_range( p_mgr, p_port ); + + /* find an empty space */ + __osm_lid_mgr_find_free_lid_range(p_mgr, num_lids, p_min_lid, p_max_lid); + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_lid_mgr_get_port_lid: " + "0x%016" PRIx64" assigned a new lid range:[0x%x-0x%x]\n", + guid, *p_min_lid, *p_max_lid ); + lid_changed = 1; + + NewLidSet: + /* update the guid2lid db and used_lids */ + osm_db_guid2lid_set(p_mgr->p_g2l, guid, *p_min_lid, *p_max_lid); + for (lid = *p_min_lid; lid <= *p_max_lid; lid++) + cl_ptr_vector_set(&p_mgr->used_lids, lid, (void*)1); + + Exit: + /* make sure the assigned lids are marked in port_lid_tbl */ + for (lid = *p_min_lid; lid <= *p_max_lid; lid++) + cl_ptr_vector_set(&p_mgr->p_subn->port_lid_tbl, lid, p_port); + + OSM_LOG_EXIT( p_mgr->p_log ); + return lid_changed; +} + +/********************************************************************** + Set to INIT the remote port of the given physical port + **********************************************************************/ +static void +__osm_lid_mgr_set_remote_pi_state_to_init( + IN osm_lid_mgr_t * const p_mgr, + IN osm_physp_t* const p_physp) +{ + ib_port_info_t *p_pi; + osm_physp_t *p_rem_physp = osm_physp_get_remote(p_physp); + + if ( p_rem_physp == NULL ) + return; + + if (osm_physp_is_valid( p_rem_physp )) + { + p_pi = osm_physp_get_port_info_ptr( p_rem_physp ); + /* but in some rare cases the remote side might be irresponsive */ + if (p_pi) + ib_port_info_set_port_state( p_pi, IB_LINK_INIT ); + } +} + +/********************************************************************** + **********************************************************************/ +static boolean_t +__osm_lid_mgr_set_physp_pi( + IN osm_lid_mgr_t * const p_mgr, + IN osm_port_t* const p_port, + IN osm_physp_t* const p_physp, + IN ib_net16_t const lid ) +{ + uint8_t payload[IB_SMP_DATA_SIZE]; + ib_port_info_t* p_pi = (ib_port_info_t*)payload; + const ib_port_info_t* p_old_pi; + osm_madw_context_t context; + osm_node_t* p_node; + ib_api_status_t status; + uint8_t mtu; + uint8_t op_vls; + uint8_t port_num; + boolean_t send_set = FALSE; + boolean_t new_port = FALSE; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_lid_mgr_set_physp_pi ); + + /* + Don't bother doing anything if this Physical Port is not valid. + This allows simplified code in the caller. + */ + if( p_physp == NULL ) + goto Exit; + + if( !osm_physp_is_valid( p_physp ) ) + goto Exit; + + port_num = osm_physp_get_port_num( p_physp ); + p_node = osm_physp_get_node_ptr( p_physp ); + + if( (osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH ) && + (port_num != 0) ) + { + /* + Switch ports that are not numbered 0 should not be set with the + following attributes as they are set later (during NO_CHANGE state + in link mgr). + */ + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_lid_mgr_set_physp_pi: " + "Skipping switch port %u, GUID 0x%016" PRIx64 "\n", + port_num, + cl_ntoh64( osm_physp_get_port_guid( p_physp ) ) ); + } + goto Exit; + } + + p_old_pi = osm_physp_get_port_info_ptr( p_physp ); + + /* + First, copy existing parameters from the PortInfo attribute we + already have for this node. + + Second, update with default values that we know must be set for + every Physical Port and the LID and set the neighbor MTU field + appropriately. + + Third, send the SMP to this physical port. + */ + + memset( payload, 0, IB_SMP_DATA_SIZE ); + + /* Correction by FUJITSU */ + if( port_num != 0 ) + { + memcpy( payload, p_old_pi, sizeof(ib_port_info_t) ); + } + + /* + Correction following a bug injected by the previous + FUJITSU line: + + Should never write back a value that is bigger then 3 in + the PortPhysicalState field, so cannot simply copy! + + Actually we want to write there: + port physical state - no change + link down default state = polling + port state - no change + */ + /* these values can be set only for hca ports, so if we are + on a switch node, set these values to zero */ + if ( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH ) + p_pi->state_info2 = 0x0; + else + { + p_pi->state_info2 = 0x02; + /* Check to see if the value we are setting is different than + the value in the port_info. If it is, turn on send_set flag */ + if ( ib_port_info_get_link_down_def_state(p_pi) != + ib_port_info_get_link_down_def_state(p_old_pi) ) + send_set = TRUE; + } + + ib_port_info_set_port_state( p_pi, IB_LINK_NO_CHANGE ); + + p_pi->m_key = p_mgr->p_subn->opt.m_key; + /* Check to see if the value we are setting is different than + the value in the port_info. If it is, turn on send_set flag */ + if (memcmp( &p_pi->m_key, &p_old_pi->m_key, sizeof(p_pi->m_key) )) + send_set = TRUE; + + p_pi->subnet_prefix = p_mgr->p_subn->opt.subnet_prefix; + /* Check to see if the value we are setting is different than + the value in the port_info. If it is, turn on send_set flag */ + if (memcmp( &p_pi->subnet_prefix, &p_old_pi->subnet_prefix, + sizeof(p_pi->subnet_prefix) )) + send_set = TRUE; + + p_pi->base_lid = lid; + /* Check to see if the value we are setting is different than + the value in the port_info. If it is, turn on send_set flag */ + if (memcmp( &p_pi->base_lid, &p_old_pi->base_lid, + sizeof(p_pi->base_lid) )) + send_set = TRUE; + + /* we are updating the ports with our local sm_base_lid */ + p_pi->master_sm_base_lid = p_mgr->p_subn->sm_base_lid; + /* Check to see if the value we are setting is different than + the value in the port_info. If it is, turn on send_set flag */ + if (memcmp( &p_pi->master_sm_base_lid, &p_old_pi->master_sm_base_lid, + sizeof(p_pi->master_sm_base_lid) )) + send_set = TRUE; + + p_pi->m_key_lease_period = p_mgr->p_subn->opt.m_key_lease_period; + /* Check to see if the value we are setting is different than + the value in the port_info. If it is, turn on send_set flag */ + if (memcmp( &p_pi->m_key_lease_period, &p_old_pi->m_key_lease_period, + sizeof(p_pi->m_key_lease_period) )) + send_set = TRUE; + + /* + we want to set the timeout for both the switch port 0 + and the HCA ports + */ + ib_port_info_set_timeout( p_pi, p_mgr->p_subn->opt.subnet_timeout ); + /* Check to see if the value we are setting is different than + the value in the port_info. If it is, turn on send_set flag */ + if (ib_port_info_get_timeout( p_pi ) != ib_port_info_get_timeout( p_old_pi )) + send_set = TRUE; + + if( port_num != 0 ) + { + /* + HCA's don't have a port 0, and for switch port 0, + the state bits are ignored. + This is not the switch management port + */ + p_pi->link_width_enabled = p_old_pi->link_width_supported; + /* Check to see if the value we are setting is different than + the value in the port_info. If it is, turn on send_set flag */ + if (memcmp( &p_pi->link_width_enabled, &p_old_pi->link_width_enabled, + sizeof(p_pi->link_width_enabled) )) + send_set = TRUE; + + if ( p_mgr->p_subn->opt.force_link_speed ) + ib_port_info_set_link_speed_enabled( p_pi, IB_LINK_SPEED_ACTIVE_2_5 ); + else if (ib_port_info_get_link_speed_enabled( p_old_pi ) != ib_port_info_get_link_speed_sup( p_pi )) + ib_port_info_set_link_speed_enabled( p_pi, IB_PORT_LINK_SPEED_ENABLED_MASK ); + else + ib_port_info_set_link_speed_enabled( p_pi, ib_port_info_get_link_speed_enabled( p_old_pi )); + if (memcmp( &p_pi->link_speed, &p_old_pi->link_speed, + sizeof(p_pi->link_speed) )) + send_set = TRUE; + + /* M_KeyProtectBits are always zero */ + p_pi->mkey_lmc = p_mgr->p_subn->opt.lmc; + /* Check to see if the value we are setting is different than + the value in the port_info. If it is, turn on send_set flag */ + if (memcmp( &p_pi->mkey_lmc, &p_old_pi->mkey_lmc, sizeof(p_pi->mkey_lmc) )) + send_set = TRUE; + + /* calc new op_vls and mtu */ + op_vls = osm_physp_calc_link_op_vls( + p_mgr->p_log, p_mgr->p_subn, p_physp ); + mtu = osm_physp_calc_link_mtu( p_mgr->p_log, p_physp ); + + ib_port_info_set_neighbor_mtu( p_pi, mtu ); + + if ( ib_port_info_get_neighbor_mtu(p_pi) != + ib_port_info_get_neighbor_mtu(p_old_pi) ) + send_set = TRUE; + + ib_port_info_set_op_vls( p_pi, op_vls ); + if ( ib_port_info_get_op_vls(p_pi) != + ib_port_info_get_op_vls(p_old_pi) ) + send_set = TRUE; + + /* + Several timeout mechanisms: + */ + ib_port_info_set_phy_and_overrun_err_thd( + p_pi, + p_mgr->p_subn->opt.local_phy_errors_threshold, + p_mgr->p_subn->opt.overrun_errors_threshold); + + if (memcmp( &p_pi->error_threshold, &p_old_pi->error_threshold, + sizeof(p_pi->error_threshold) )) + send_set = TRUE; + + /* + To reset the port state machine we can send PortInfo.State = DOWN. + (see: 7.2.7 p171 lines:10-19) + */ + if ( (mtu != ib_port_info_get_neighbor_mtu(p_old_pi)) || + (op_vls != ib_port_info_get_op_vls(p_old_pi))) + { + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_lid_mgr_set_physp_pi: " + "Sending Link Down due to op_vls or mtu change. MTU:%u,%u VL_CAP:%u,%u\n", + mtu, ib_port_info_get_neighbor_mtu(p_old_pi), + op_vls, ib_port_info_get_op_vls(p_old_pi) + ); + } + + /* + we need to make sure the internal DB will follow the fact the remote + port is also going through "down" state into "init"... + */ + __osm_lid_mgr_set_remote_pi_state_to_init(p_mgr, p_physp); + + ib_port_info_set_port_state( p_pi, IB_LINK_DOWN ); + if ( ib_port_info_get_port_state(p_pi) != + ib_port_info_get_port_state(p_old_pi) ) + send_set = TRUE; + } + } + else + { + /* + For Port 0, NeighborMTU is relevant only for Enh. SP0. + In this case, we'll set the MTU according to the mtu_cap + */ + ib_port_info_set_neighbor_mtu( p_pi, ib_port_info_get_mtu_cap( p_old_pi ) ); + if ( ib_port_info_get_neighbor_mtu(p_pi) != + ib_port_info_get_neighbor_mtu(p_old_pi) ) + send_set = TRUE; + + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_lid_mgr_set_physp_pi: " + "Updating neighbor_mtu on switch port 0 to:%u\n", + ib_port_info_get_neighbor_mtu( p_pi ) ); + + /* Determine if enhanced switch port 0 and if so set LMC */ + if (osm_switch_sp0_is_lmc_capable(p_node->sw, p_mgr->p_subn)) + { + /* M_KeyProtectBits are always zero */ + p_pi->mkey_lmc = p_mgr->p_subn->opt.lmc; + /* Check to see if the value we are setting is different than + the value in the port_info. If it is, turn on send_set flag */ + if (memcmp( &p_pi->mkey_lmc, &p_old_pi->mkey_lmc, sizeof(p_pi->mkey_lmc) )) + send_set = TRUE; + } + } + + context.pi_context.node_guid = osm_node_get_node_guid( p_node ); + context.pi_context.port_guid = osm_physp_get_port_guid( p_physp ); + context.pi_context.set_method = TRUE; + context.pi_context.update_master_sm_base_lid = FALSE; + context.pi_context.ignore_errors = FALSE; + context.pi_context.light_sweep = FALSE; + context.pi_context.active_transition = FALSE; + + /* + We need to set the cli_rereg bit when we are in first_time_master_sweep for + ports supporting the ClientReregistration Vol1 (v1.2) p811 14.4.11 + Also, if this port was just now discovered, then we should also set the + cli_rereg bit. We know that the port was just discovered if it is in + the p_subn->new_ports_list list. + */ + if ( cl_is_object_in_list(&p_mgr->p_subn->new_ports_list, p_port) ) + { + /* p_port is in new_ports_list, mark new_port as TRUE */ + new_port = TRUE; + } + + if ( ( p_mgr->p_subn->first_time_master_sweep == TRUE || + new_port == TRUE ) && + !p_mgr->p_subn->opt.no_clients_rereg && + ( (p_old_pi->capability_mask & IB_PORT_CAP_HAS_CLIENT_REREG) != 0 ) ) + ib_port_info_set_client_rereg( p_pi, 1 ); + else + ib_port_info_set_client_rereg( p_pi, 0 ); + + /* We need to send the PortInfo Set request with the new sm_lid + in the following cases: + 1. There is a change in the values (send_set == TRUE) + 2. first_time_master_sweep flag on the subnet is TRUE. This means the + SM just became master, and it then needs to send a PortInfo Set to + every port. + 3. got_set_resp on the physical port is FALSE. This means we haven't seen + this port before and we need to send Set of PortInfo to it. + */ + if (send_set || p_mgr->p_subn->first_time_master_sweep == TRUE || + p_physp->got_set_resp == FALSE) + { + + p_mgr->send_set_reqs = TRUE; + status = osm_req_set( p_mgr->p_req, + osm_physp_get_dr_path_ptr( p_physp ), + payload, + sizeof(payload), + IB_MAD_ATTR_PORT_INFO, + cl_hton32(osm_physp_get_port_num( p_physp )), + CL_DISP_MSGID_NONE, + &context ); + } + + Exit: + OSM_LOG_EXIT( p_mgr->p_log ); + return (send_set || p_mgr->p_subn->first_time_master_sweep == TRUE || + p_physp->got_set_resp == FALSE); +} + +/********************************************************************** + Processes our own node + Lock must already be held. +**********************************************************************/ +static boolean_t +__osm_lid_mgr_process_our_sm_node( + IN osm_lid_mgr_t* const p_mgr ) +{ + osm_port_t *p_port; + uint16_t min_lid_ho; + uint16_t max_lid_ho; + osm_physp_t *p_physp; + boolean_t res = TRUE; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_lid_mgr_process_our_sm_node ); + + /* + Acquire our own port object. + */ + p_port = (osm_port_t*)cl_qmap_get( &p_mgr->p_subn->port_guid_tbl, + p_mgr->p_subn->sm_port_guid ); + + if( p_port == (osm_port_t*)cl_qmap_end( &p_mgr->p_subn->port_guid_tbl ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_lid_mgr_process_our_sm_node: ERR 0308: " + "Can't acquire SM's port object, GUID 0x%016" PRIx64 "\n", + cl_ntoh64( p_mgr->p_subn->sm_port_guid ) ); + res = FALSE; + goto Exit; + } + + /* + Determine the LID this SM will use for its own port. + Be careful. With an LMC > 0, the bottom of the LID range becomes + unusable, since port hardware will mask off least significant bits, + leaving a LID of 0 (invalid). Therefore, make sure that we always + configure the SM with a LID that has non-zero bits, even after + LMC masking by hardware. + */ + __osm_lid_mgr_get_port_lid(p_mgr, p_port, &min_lid_ho, &max_lid_ho); + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_lid_mgr_process_our_sm_node: " + "Current base LID is 0x%X\n", min_lid_ho ); + /* + Update subnet object. + */ + p_mgr->p_subn->master_sm_base_lid = cl_hton16( min_lid_ho ); + p_mgr->p_subn->sm_base_lid = cl_hton16( min_lid_ho ); + + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_lid_mgr_process_our_sm_node: " + "Assigning SM's port 0x%016" PRIx64 + "\n\t\t\t\tto LID range [0x%X,0x%X]\n", + cl_ntoh64( osm_port_get_guid( p_port ) ), + min_lid_ho, max_lid_ho ); + } + + /* + Set the PortInfo the Physical Port associated + with this Port. + */ + p_physp = osm_port_get_default_phys_ptr( p_port ); + + __osm_lid_mgr_set_physp_pi( p_mgr, p_port, p_physp, cl_hton16( min_lid_ho ) ); + + Exit: + OSM_LOG_EXIT( p_mgr->p_log ); + return res; +} + +/********************************************************************** + **********************************************************************/ +osm_signal_t +osm_lid_mgr_process_sm( + IN osm_lid_mgr_t* const p_mgr ) +{ + osm_signal_t signal = OSM_SIGNAL_DONE_PENDING; + + OSM_LOG_ENTER( p_mgr->p_log, osm_lid_mgr_process_sm ); + + CL_ASSERT( p_mgr->p_subn->sm_port_guid ); + + CL_PLOCK_EXCL_ACQUIRE( p_mgr->p_lock ); + + /* initialize the port_lid_tbl and empty ranges list following the + persistent db */ + __osm_lid_mgr_init_sweep( p_mgr ); + + if (p_mgr->p_subn->opt.pfn_ui_pre_lid_assign) + { + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "osm_lid_mgr_process_sm: " + "Invoking UI function pfn_ui_pre_lid_assign\n" ); + p_mgr->p_subn->opt.pfn_ui_pre_lid_assign( + p_mgr->p_subn->opt.ui_pre_lid_assign_ctx ); + } + + /* Set the send_set_reqs of the p_mgr to FALSE, and + we'll see if any set requests were sent. If not - + can signal OSM_SIGNAL_DONE */ + p_mgr->send_set_reqs = FALSE; + if ( __osm_lid_mgr_process_our_sm_node( p_mgr ) == FALSE ) + /* The initialization failed */ + signal = OSM_SIGNAL_DONE; + + if ( p_mgr->send_set_reqs == FALSE ) + signal = OSM_SIGNAL_DONE; + + CL_PLOCK_RELEASE( p_mgr->p_lock ); + + OSM_LOG_EXIT( p_mgr->p_log ); + return( signal ); +} + +/********************************************************************** + 1 go through all ports in the subnet. + 1.1 call __osm_lid_mgr_get_port_min_lid + 1.2 if a change is required send the port info + 2 if any change send the signal PENDING... +**********************************************************************/ +osm_signal_t +osm_lid_mgr_process_subnet( + IN osm_lid_mgr_t* const p_mgr ) +{ + osm_signal_t signal; + cl_qmap_t *p_port_guid_tbl; + osm_port_t *p_port; + ib_net64_t port_guid; + uint16_t min_lid_ho, max_lid_ho; + osm_physp_t *p_physp; + int lid_changed; + + CL_ASSERT( p_mgr ); + + OSM_LOG_ENTER( p_mgr->p_log, osm_lid_mgr_process_subnet ); + + CL_PLOCK_EXCL_ACQUIRE( p_mgr->p_lock ); + + CL_ASSERT( p_mgr->p_subn->sm_port_guid ); + + /* Set the send_set_reqs of the p_mgr to FALSE, and + we'll see if any set requests were sent. If not - + can signal OSM_SIGNAL_DONE */ + p_mgr->send_set_reqs = FALSE; + + p_port_guid_tbl = &p_mgr->p_subn->port_guid_tbl; + + for( p_port = (osm_port_t*)cl_qmap_head( p_port_guid_tbl ); + p_port != (osm_port_t*)cl_qmap_end( p_port_guid_tbl ); + p_port = (osm_port_t*)cl_qmap_next( &p_port->map_item ) ) + { + port_guid = osm_port_get_guid( p_port ); + + /* + Our own port is a special case in that we want to + assign a LID to ourselves first, since we have to + advertise that LID value to the other ports. + + For that reason, our node is treated separately and + we will not add it to any of these lists. + */ + if( port_guid == p_mgr->p_subn->sm_port_guid ) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "osm_lid_mgr_process_subnet: " + "Skipping our own port 0x%016" PRIx64 "\n", + cl_ntoh64( port_guid ) ); + } + else + { + /* + get the port lid range - we need to send it on first active sweep or + if there was a change (the result of the __osm_lid_mgr_get_port_lid) + */ + lid_changed = + __osm_lid_mgr_get_port_lid(p_mgr, p_port, &min_lid_ho, &max_lid_ho); + + /* we can call the function to update the port info as it known to + look for any field change and will only send an updated if required */ + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "osm_lid_mgr_process_subnet: " + "Assigned port 0x%016" PRIx64 + ", LID [0x%X,0x%X]\n", cl_ntoh64( port_guid ), + min_lid_ho, max_lid_ho ); + + p_physp = osm_port_get_default_phys_ptr( p_port ); + /* the proc returns the fact it sent a set port info */ + if (__osm_lid_mgr_set_physp_pi( p_mgr, p_port, p_physp, cl_hton16( min_lid_ho ))) + p_mgr->send_set_reqs = TRUE; + } + } /* all ports */ + + /* store the guid to lid table in persistent db */ + osm_db_store( p_mgr->p_g2l ); + + if ( p_mgr->send_set_reqs == FALSE ) + signal = OSM_SIGNAL_DONE; + else + signal = OSM_SIGNAL_DONE_PENDING; + + CL_PLOCK_RELEASE( p_mgr->p_lock ); + + OSM_LOG_EXIT( p_mgr->p_log ); + return( signal ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_lin_fwd_rcv.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_lin_fwd_rcv.c new file mode 100644 index 00000000..928cf842 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_lin_fwd_rcv.c @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_lin_fwd_rcv.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_lft_rcv_t. + * This object represents the NodeDescription Receiver object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +osm_lft_rcv_construct( + IN osm_lft_rcv_t* const p_rcv ) +{ + memset( p_rcv, 0, sizeof(*p_rcv) ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_lft_rcv_destroy( + IN osm_lft_rcv_t* const p_rcv ) +{ + CL_ASSERT( p_rcv ); + + OSM_LOG_ENTER( p_rcv->p_log, osm_lft_rcv_destroy ); + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_lft_rcv_init( + IN osm_lft_rcv_t* const p_rcv, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_lft_rcv_init ); + + osm_lft_rcv_construct( p_rcv ); + + p_rcv->p_log = p_log; + p_rcv->p_subn = p_subn; + p_rcv->p_lock = p_lock; + + OSM_LOG_EXIT( p_rcv->p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_lft_rcv_process( + IN const osm_lft_rcv_t* const p_rcv, + IN osm_madw_t* const p_madw ) +{ + ib_smp_t *p_smp; + uint32_t block_num; + osm_switch_t *p_sw; + osm_lft_context_t *p_lft_context; + uint8_t *p_block; + ib_net64_t node_guid; + ib_api_status_t status; + + CL_ASSERT( p_rcv ); + + OSM_LOG_ENTER( p_rcv->p_log, osm_lft_rcv_process ); + + CL_ASSERT( p_madw ); + + p_smp = osm_madw_get_smp_ptr( p_madw ); + p_block = (uint8_t*)ib_smp_get_payload_ptr( p_smp ); + block_num = cl_ntoh32( p_smp->attr_mod ); + + /* + Acquire the switch object for this switch. + */ + p_lft_context = osm_madw_get_lft_context_ptr( p_madw ); + node_guid = p_lft_context->node_guid; + + CL_PLOCK_EXCL_ACQUIRE( p_rcv->p_lock ); + p_sw = osm_get_switch_by_guid( p_rcv->p_subn, node_guid ); + + if( !p_sw ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_lft_rcv_process: ERR 0401: " + "LFT received for nonexistent node " + "0x%" PRIx64 "\n", cl_ntoh64( node_guid ) ); + } + else + { + status = osm_switch_set_ft_block( p_sw, p_block, block_num ); + if( status != IB_SUCCESS ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_lft_rcv_process: ERR 0402: " + "Setting forwarding table block failed (%s)" + "\n\t\t\t\tSwitch 0x%" PRIx64 "\n", + ib_get_err_str( status ), + cl_ntoh64( node_guid ) ); + } + } + + CL_PLOCK_RELEASE( p_rcv->p_lock ); + OSM_LOG_EXIT( p_rcv->p_log ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_lin_fwd_rcv_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_lin_fwd_rcv_ctrl.c new file mode 100644 index 00000000..d84328d3 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_lin_fwd_rcv_ctrl.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_lin_fwd_rcv_ctrl.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_lft_rcv_ctrl_t. + * This object represents the LFT Receive controller object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +__osm_lft_rcv_ctrl_disp_callback( + IN void *context, + IN void *p_data ) +{ + /* ignore return status when invoked via the dispatcher */ + osm_lft_rcv_process( ((osm_lft_rcv_ctrl_t*)context)->p_rcv, + (osm_madw_t*)p_data ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_lft_rcv_ctrl_construct( + IN osm_lft_rcv_ctrl_t* const p_ctrl ) +{ + memset( p_ctrl, 0, sizeof(*p_ctrl) ); + p_ctrl->h_disp = CL_DISP_INVALID_HANDLE; +} + +/********************************************************************** + **********************************************************************/ +void +osm_lft_rcv_ctrl_destroy( + IN osm_lft_rcv_ctrl_t* const p_ctrl ) +{ + CL_ASSERT( p_ctrl ); + cl_disp_unregister( p_ctrl->h_disp ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_lft_rcv_ctrl_init( + IN osm_lft_rcv_ctrl_t* const p_ctrl, + IN osm_lft_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_lft_rcv_ctrl_init ); + + osm_lft_rcv_ctrl_construct( p_ctrl ); + p_ctrl->p_log = p_log; + p_ctrl->p_rcv = p_rcv; + p_ctrl->p_disp = p_disp; + + p_ctrl->h_disp = cl_disp_register( + p_disp, + OSM_MSG_MAD_LFT, + __osm_lft_rcv_ctrl_disp_callback, + p_ctrl ); + + if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_lft_rcv_ctrl_init: ERR 1601: " + "Dispatcher registration failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return( status ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_lin_fwd_tbl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_lin_fwd_tbl.c new file mode 100644 index 00000000..fe0bfbd5 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_lin_fwd_tbl.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_lin_fwd_tbl.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_lin_fwd_tbl_t. + * This object represents an linear forwarding table. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include + + +inline size_t +__osm_lin_tbl_compute_obj_size( + IN const uint32_t num_ports ) +{ + return( sizeof(osm_lin_fwd_tbl_t) + (num_ports - 1) ); +} + +/********************************************************************** + **********************************************************************/ +osm_lin_fwd_tbl_t* +osm_lin_tbl_new( + IN uint16_t const size ) +{ + osm_lin_fwd_tbl_t* p_tbl; + + /* + The capacity reported by the switch includes LID 0, + so add 1 to the end of the range here for this assert. + */ + CL_ASSERT( size <= IB_LID_UCAST_END_HO + 1 ); + p_tbl = (osm_lin_fwd_tbl_t*)malloc( + __osm_lin_tbl_compute_obj_size( size ) ); + + /* + Initialize the table to OSM_NO_PATH, which means "invalid port" + */ + memset( p_tbl, OSM_NO_PATH, __osm_lin_tbl_compute_obj_size( size ) ); + if( p_tbl != NULL ) + { + p_tbl->size = (uint16_t)size; + } + return( p_tbl ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_lin_tbl_delete( + IN osm_lin_fwd_tbl_t** const pp_tbl ) +{ + free( *pp_tbl ); + *pp_tbl = NULL; +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_link_mgr.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_link_mgr.c new file mode 100644 index 00000000..60de51d1 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_link_mgr.c @@ -0,0 +1,514 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_link_mgr.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_link_mgr_t. + * This file implements the Link Manager object. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.15 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include + + +/********************************************************************** + **********************************************************************/ +void +osm_link_mgr_construct( + IN osm_link_mgr_t* const p_mgr ) +{ + memset( p_mgr, 0, sizeof(*p_mgr) ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_link_mgr_destroy( + IN osm_link_mgr_t* const p_mgr ) +{ + OSM_LOG_ENTER( p_mgr->p_log, osm_link_mgr_destroy ); + + OSM_LOG_EXIT( p_mgr->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_link_mgr_init( + IN osm_link_mgr_t* const p_mgr, + IN osm_req_t* const p_req, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_link_mgr_init ); + + CL_ASSERT( p_req ); + CL_ASSERT( p_subn ); + CL_ASSERT( p_lock ); + + osm_link_mgr_construct( p_mgr ); + + p_mgr->p_log = p_log; + p_mgr->p_subn = p_subn; + p_mgr->p_lock = p_lock; + p_mgr->p_req = p_req; + + OSM_LOG_EXIT( p_mgr->p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_link_mgr_set_physp_pi( + IN osm_link_mgr_t* const p_mgr, + IN osm_physp_t* const p_physp, + IN uint8_t const port_state ) +{ + uint8_t payload[IB_SMP_DATA_SIZE]; + ib_port_info_t* const p_pi = (ib_port_info_t*)payload; + const ib_port_info_t* p_old_pi; + osm_madw_context_t context; + osm_node_t* p_node; + ib_api_status_t status; + uint8_t port_num; + uint8_t mtu; + uint8_t op_vls; + boolean_t esp0 = FALSE; + boolean_t send_set = FALSE; + osm_physp_t *p_remote_physp; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_link_mgr_set_physp_pi ); + + CL_ASSERT( p_physp ); + CL_ASSERT( osm_physp_is_valid( p_physp ) ); + + p_node = osm_physp_get_node_ptr( p_physp ); + + port_num = osm_physp_get_port_num( p_physp ); + + if( port_num == 0 ) + { + ib_switch_info_t* p_sw_info; + + /* + HCA's don't have a port 0, and for switch port 0, + we need to check if this is enhanced port 0 or base port 0. + For base port 0 the following parameters are not valid. (p824, table 145) + */ + if (!p_node->sw) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_link_mgr_set_physp_pi: ERR 4201: " + "Cannot find switch by guid: 0x%" PRIx64 "\n", + cl_ntoh64( p_node->node_info.node_guid ) ); + goto Exit; + } + + p_sw_info = osm_switch_get_si_ptr(p_node->sw); + if (ib_switch_info_is_enhanced_port0( p_sw_info ) == FALSE) + { + /* This means the switch doesn't support enhanced port zero. + Can skip it. */ + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_link_mgr_set_physp_pi: " + "Skipping port 0, GUID 0x%016" PRIx64 "\n", + cl_ntoh64( osm_physp_get_port_guid( p_physp ) ) ); + } + goto Exit; + } + esp0 = TRUE; + } + + /* + PAST THIS POINT WE ARE HANDLING EITHER A NON PORT 0 OR ENHANCED PORT 0 + */ + + p_old_pi = osm_physp_get_port_info_ptr( p_physp ); + + memset( payload, 0, IB_SMP_DATA_SIZE ); + + /* Correction by FUJITSU */ + memcpy( payload, p_old_pi, sizeof(ib_port_info_t) ); + + /* + Correction following a bug injected by the previous + FUJITSU line: + + Should never write back a value that is bigger then 3 in + the PortPhysicalState field - so can not simply copy! + + Actually we want to write there: + port physical state - no change, + link down default state = polling + port state - no change + */ + p_pi->state_info2 = 0x02; + ib_port_info_set_port_state( p_pi, IB_LINK_NO_CHANGE ); + if ( ib_port_info_get_link_down_def_state(p_pi) != + ib_port_info_get_link_down_def_state(p_old_pi) ) + send_set = TRUE; + + /* we only change port fields if we do not change state */ + if (port_state == IB_LINK_NO_CHANGE) + { + /* The following fields are relevant only for CA port or Enh. SP0 */ + if( osm_node_get_type( p_node ) != IB_NODE_TYPE_SWITCH || + port_num == 0 ) + { + p_pi->m_key = p_mgr->p_subn->opt.m_key; + if (memcmp( &p_pi->m_key, &p_old_pi->m_key, sizeof(p_pi->m_key) )) + send_set = TRUE; + + p_pi->subnet_prefix = p_mgr->p_subn->opt.subnet_prefix; + if (memcmp( &p_pi->subnet_prefix, &p_old_pi->subnet_prefix, + sizeof(p_pi->subnet_prefix) )) + send_set = TRUE; + + p_pi->base_lid = osm_physp_get_base_lid( p_physp ); + if (memcmp( &p_pi->base_lid, &p_old_pi->base_lid, + sizeof(p_pi->base_lid) )) + send_set = TRUE; + + /* we are initializing the ports with our local sm_base_lid */ + p_pi->master_sm_base_lid = p_mgr->p_subn->sm_base_lid; + if (memcmp( &p_pi->master_sm_base_lid, &p_old_pi->master_sm_base_lid, + sizeof(p_pi->master_sm_base_lid) )) + send_set = TRUE; + + p_pi->m_key_lease_period = p_mgr->p_subn->opt.m_key_lease_period; + if (memcmp( &p_pi->m_key_lease_period, &p_old_pi->m_key_lease_period, + sizeof(p_pi->m_key_lease_period) )) + send_set = TRUE; + + if (esp0 == FALSE) + p_pi->mkey_lmc = p_mgr->p_subn->opt.lmc; + else + { + if (p_mgr->p_subn->opt.lmc_esp0) + p_pi->mkey_lmc = p_mgr->p_subn->opt.lmc; + else + p_pi->mkey_lmc = 0; + } + if (memcmp( &p_pi->mkey_lmc, &p_old_pi->mkey_lmc, sizeof(p_pi->mkey_lmc) )) + send_set = TRUE; + + ib_port_info_set_timeout( p_pi, p_mgr->p_subn->opt.subnet_timeout ); + if (ib_port_info_get_timeout( p_pi ) != ib_port_info_get_timeout( p_old_pi )) + send_set = TRUE; + } + + /* + Several timeout mechanisms: + */ + p_remote_physp = osm_physp_get_remote( p_physp ); + if (port_num != 0 && p_remote_physp && + osm_physp_is_valid(p_remote_physp)) { + if (osm_node_get_type(osm_physp_get_node_ptr(p_physp)) == + IB_NODE_TYPE_ROUTER) + { + ib_port_info_set_hoq_lifetime( + p_pi, p_mgr->p_subn->opt.leaf_head_of_queue_lifetime); + } + else if (osm_node_get_type(osm_physp_get_node_ptr(p_physp)) == + IB_NODE_TYPE_SWITCH) + { + /* Is remote end CA or router (a leaf port) ? */ + if (osm_node_get_type(osm_physp_get_node_ptr(p_remote_physp)) != + IB_NODE_TYPE_SWITCH) + { + ib_port_info_set_hoq_lifetime( + p_pi, p_mgr->p_subn->opt.leaf_head_of_queue_lifetime); + ib_port_info_set_vl_stall_count( + p_pi, p_mgr->p_subn->opt.leaf_vl_stall_count); + } + else + { + ib_port_info_set_hoq_lifetime( + p_pi, p_mgr->p_subn->opt.head_of_queue_lifetime); + ib_port_info_set_vl_stall_count( + p_pi, p_mgr->p_subn->opt.vl_stall_count); + } + } + if ( ib_port_info_get_hoq_lifetime(p_pi) != + ib_port_info_get_hoq_lifetime(p_old_pi) || + ib_port_info_get_vl_stall_count(p_pi) != + ib_port_info_get_vl_stall_count(p_old_pi) ) + send_set = TRUE; + } + + ib_port_info_set_phy_and_overrun_err_thd( + p_pi, + p_mgr->p_subn->opt.local_phy_errors_threshold, + p_mgr->p_subn->opt.overrun_errors_threshold); + if (memcmp( &p_pi->error_threshold, &p_old_pi->error_threshold, + sizeof(p_pi->error_threshold) )) + send_set = TRUE; + + /* + Set the easy common parameters for all port types, + then determine the neighbor MTU. + */ + p_pi->link_width_enabled = p_old_pi->link_width_supported; + if (memcmp( &p_pi->link_width_enabled, &p_old_pi->link_width_enabled, + sizeof(p_pi->link_width_enabled) )) + send_set = TRUE; + + if ( p_mgr->p_subn->opt.force_link_speed ) + ib_port_info_set_link_speed_enabled( p_pi, IB_LINK_SPEED_ACTIVE_2_5 ); + else if (ib_port_info_get_link_speed_enabled( p_old_pi ) != ib_port_info_get_link_speed_sup( p_pi )) + ib_port_info_set_link_speed_enabled( p_pi, IB_PORT_LINK_SPEED_ENABLED_MASK ); + else + ib_port_info_set_link_speed_enabled( p_pi, ib_port_info_get_link_speed_enabled( p_old_pi )); + if (memcmp( &p_pi->link_speed, &p_old_pi->link_speed, + sizeof(p_pi->link_speed) )) + send_set = TRUE; + + /* calc new op_vls and mtu */ + op_vls = + osm_physp_calc_link_op_vls( p_mgr->p_log, p_mgr->p_subn, p_physp ); + mtu = osm_physp_calc_link_mtu( p_mgr->p_log, p_physp ); + + ib_port_info_set_neighbor_mtu( p_pi, mtu ); + if ( ib_port_info_get_neighbor_mtu(p_pi) != + ib_port_info_get_neighbor_mtu(p_old_pi) ) + send_set = TRUE; + + ib_port_info_set_op_vls( p_pi, op_vls ); + if ( ib_port_info_get_op_vls(p_pi) != + ib_port_info_get_op_vls(p_old_pi) ) + send_set = TRUE; + + /* also the context can flag the need to check for errors. */ + context.pi_context.ignore_errors = FALSE; + } + else + { + /* + Since the only change we try to do is to modify the port + state we can ignore the errors that might be caused by a + race in setting the state and the actual state the port is + in. + */ + context.pi_context.ignore_errors = FALSE; + } + + ib_port_info_set_port_state( p_pi, port_state ); + if (port_state != IB_LINK_NO_CHANGE && + ib_port_info_get_port_state(p_pi) != + ib_port_info_get_port_state(p_old_pi) ) + { + send_set = TRUE; + if (port_state == IB_LINK_ACTIVE) + context.pi_context.active_transition = TRUE; + else + context.pi_context.active_transition = FALSE; + } + + context.pi_context.node_guid = osm_node_get_node_guid( p_node ); + context.pi_context.port_guid = osm_physp_get_port_guid( p_physp ); + context.pi_context.set_method = TRUE; + context.pi_context.update_master_sm_base_lid = FALSE; + context.pi_context.light_sweep = FALSE; + + /* We need to send the PortInfoSet request with the new sm_lid + in the following cases: + 1. There is a change in the values (send_set == TRUE) + 2. This is an hca port or a switch port zero and got_set_resp is FALSE + (in this case we sent a PortInfoSet in the osm_lid_mgr, but for some + reason we didn't get a response) - try and re-send. + 3. This is a switch port and: + a. first_time_master_sweep flag on the subnet is TRUE. This means the + SM just became master, and it then needs to send at PortInfoSet to + every port (and this is the first time we can send a PortInfoSet to + switch external ports). + b. got_set_resp on the physical port is FALSE. This means we haven't + seen this port before - need to send PortInfoSet to it. + */ + if (send_set || + (osm_node_get_type(p_node) != IB_NODE_TYPE_SWITCH && p_physp->got_set_resp == FALSE) || + (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH && port_num == 0 && + p_physp->got_set_resp == FALSE) || + (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH && port_num != 0 && + (p_mgr->p_subn->first_time_master_sweep == TRUE || p_physp->got_set_resp == FALSE))) + { + p_mgr->send_set_reqs = TRUE; + status = osm_req_set( p_mgr->p_req, + osm_physp_get_dr_path_ptr( p_physp ), + payload, + sizeof(payload), + IB_MAD_ATTR_PORT_INFO, + cl_hton32(port_num), + CL_DISP_MSGID_NONE, + &context ); + } + + Exit: + OSM_LOG_EXIT( p_mgr->p_log ); +} + +/********************************************************************** + **********************************************************************/ +static osm_signal_t +__osm_link_mgr_process_port( + IN osm_link_mgr_t* const p_mgr, + IN osm_port_t* const p_port, + IN const uint8_t link_state ) +{ + uint32_t i; + uint32_t num_physp; + osm_physp_t *p_physp; + uint8_t current_state; + osm_signal_t signal = OSM_SIGNAL_DONE; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_link_mgr_process_port ); + + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_link_mgr_process_port: " + "Port 0x%" PRIx64 " going to %s\n", + cl_ntoh64( osm_port_get_guid( p_port ) ), + ib_get_port_state_str( link_state ) ); + } + + /* + Set the PortInfo for every Physical Port associated + with this Port. Start iterating with port 1, since the linkstate + is not applicable to the management port on switches. + */ + num_physp = osm_port_get_num_physp( p_port ); + for( i = 0; i < num_physp; i ++ ) + { + /* + Don't bother doing anything if this Physical Port is not valid. + or if the state of the port is already better then the + specified state. + */ + p_physp = osm_port_get_phys_ptr( p_port, (uint8_t)i ); + if( p_physp && osm_physp_is_valid( p_physp ) ) + { + current_state = osm_physp_get_port_state( p_physp ); + + if( current_state == IB_LINK_DOWN ) + continue; + + /* + Normally we only send state update if state is lower + then required state. However, we need to send update if + no state change required. + */ + if( (link_state == IB_LINK_NO_CHANGE) || + (current_state < link_state) ) + { + p_mgr->send_set_reqs = FALSE; + __osm_link_mgr_set_physp_pi( + p_mgr, + p_physp, + link_state ); + + if ( p_mgr->send_set_reqs == TRUE ) + signal = OSM_SIGNAL_DONE_PENDING; + } + else + { + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_link_mgr_process_port: " + "Physical port 0x%X already %s. Skipping\n", + osm_physp_get_port_num( p_physp ), + ib_get_port_state_str( current_state ) ); + } + } + } + } + + OSM_LOG_EXIT( p_mgr->p_log ); + return( signal ); +} + +/********************************************************************** + **********************************************************************/ +osm_signal_t +osm_link_mgr_process( + IN osm_link_mgr_t* const p_mgr, + IN const uint8_t link_state ) +{ + cl_qmap_t *p_port_guid_tbl; + osm_port_t *p_port; + osm_signal_t signal = OSM_SIGNAL_DONE; + + OSM_LOG_ENTER( p_mgr->p_log, osm_link_mgr_process ); + + p_port_guid_tbl = &p_mgr->p_subn->port_guid_tbl; + + CL_PLOCK_EXCL_ACQUIRE( p_mgr->p_lock ); + + for( p_port = (osm_port_t*)cl_qmap_head( p_port_guid_tbl ); + p_port != (osm_port_t*)cl_qmap_end( p_port_guid_tbl ); + p_port = (osm_port_t*)cl_qmap_next( &p_port->map_item ) ) + { + if( __osm_link_mgr_process_port( p_mgr, p_port, link_state ) == + OSM_SIGNAL_DONE_PENDING ) + signal = OSM_SIGNAL_DONE_PENDING; + } + + CL_PLOCK_RELEASE( p_mgr->p_lock ); + + OSM_LOG_EXIT( p_mgr->p_log ); + return( signal ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_matrix.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_matrix.c new file mode 100644 index 00000000..f655ad61 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_matrix.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_matrix.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Implementation of osm_lid_matrix_t. + * This file implements the LID Matrix object. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.7 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include + +/********************************************************************** + **********************************************************************/ +void +osm_lid_matrix_destroy( + IN osm_lid_matrix_t* const p_lmx ) +{ + cl_vector_destroy( &p_lmx->lid_vec ); +} + +/********************************************************************** + Initializer function called by cl_vector +**********************************************************************/ +cl_status_t +__osm_lid_matrix_vec_init( + IN void* const p_elem, + IN void* context ) +{ + osm_lid_matrix_t* const p_lmx = (osm_lid_matrix_t*)context; + + memset( p_elem, OSM_NO_PATH, p_lmx->num_ports + 1); + return( CL_SUCCESS ); +} + +/********************************************************************** + Initializer function called by cl_vector +**********************************************************************/ +void +__osm_lid_matrix_vec_clear( + IN const size_t index, + IN void* const p_elem, + IN void* context ) +{ + osm_lid_matrix_t* const p_lmx = (osm_lid_matrix_t*)context; + + UNUSED_PARAM( index ); + memset( p_elem, OSM_NO_PATH, p_lmx->num_ports + 1); +} + +/********************************************************************** + **********************************************************************/ +void +osm_lid_matrix_clear( + IN osm_lid_matrix_t* const p_lmx ) +{ + cl_vector_apply_func( &p_lmx->lid_vec, + __osm_lid_matrix_vec_clear, p_lmx ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_lid_matrix_init( + IN osm_lid_matrix_t* const p_lmx, + IN const uint8_t num_ports ) +{ + cl_vector_t *p_vec; + cl_status_t status; + + CL_ASSERT( p_lmx ); + CL_ASSERT( num_ports ); + + p_lmx->num_ports = num_ports; + + p_vec = &p_lmx->lid_vec; + /* + Initialize the vector for the number of ports plus an + extra entry to hold the "least-hops" count for that LID. + */ + status = cl_vector_init( p_vec, + 0, /* min_size, */ + 1, /* grow_size */ + sizeof(uint8_t)*(num_ports + 1), /* element size */ + __osm_lid_matrix_vec_init, /* init function */ + NULL, /* destory func */ + p_lmx /* context */ + ); + + return( status ); +} + +/********************************************************************** + **********************************************************************/ +cl_status_t +osm_lid_matrix_set( + IN osm_lid_matrix_t* const p_lmx, + IN const uint16_t lid_ho, + IN const uint8_t port_num, + IN const uint8_t val ) +{ + uint8_t *p_port_array; + cl_status_t status; + + CL_ASSERT( port_num < p_lmx->num_ports ); + status = cl_vector_set_min_size( &p_lmx->lid_vec, lid_ho + 1 ); + if( status == CL_SUCCESS ) + { + p_port_array = (uint8_t *)cl_vector_get_ptr( &p_lmx->lid_vec, lid_ho ); + p_port_array[port_num] = val; + if( p_port_array[p_lmx->num_ports] > val ) + p_port_array[p_lmx->num_ports] = val; + } + return( status ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcast_fwd_rcv.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcast_fwd_rcv.c new file mode 100644 index 00000000..570a5bb7 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcast_fwd_rcv.c @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_mcast_fwd_rcv.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Implementation of osm_mft_rcv_t. + * This object represents the Multicast Forwarding Table Receiver object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +osm_mft_rcv_construct( + IN osm_mft_rcv_t* const p_rcv ) +{ + memset( p_rcv, 0, sizeof(*p_rcv) ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_mft_rcv_destroy( + IN osm_mft_rcv_t* const p_rcv ) +{ + CL_ASSERT( p_rcv ); + + OSM_LOG_ENTER( p_rcv->p_log, osm_mft_rcv_destroy ); + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_mft_rcv_init( + IN osm_mft_rcv_t* const p_rcv, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_mft_rcv_init ); + + osm_mft_rcv_construct( p_rcv ); + + p_rcv->p_log = p_log; + p_rcv->p_subn = p_subn; + p_rcv->p_lock = p_lock; + + OSM_LOG_EXIT( p_rcv->p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_mft_rcv_process( + IN const osm_mft_rcv_t* const p_rcv, + IN osm_madw_t* const p_madw ) +{ + ib_smp_t *p_smp; + uint32_t block_num; + uint8_t position; + osm_switch_t *p_sw; + osm_mft_context_t *p_mft_context; + uint16_t *p_block; + ib_net64_t node_guid; + ib_api_status_t status; + + CL_ASSERT( p_rcv ); + + OSM_LOG_ENTER( p_rcv->p_log, osm_mft_rcv_process ); + + CL_ASSERT( p_madw ); + + p_smp = osm_madw_get_smp_ptr( p_madw ); + p_block = (uint16_t*)ib_smp_get_payload_ptr( p_smp ); + block_num = cl_ntoh32( p_smp->attr_mod ) & IB_MCAST_BLOCK_ID_MASK_HO; + position = (uint8_t)((cl_ntoh32( p_smp->attr_mod ) & + IB_MCAST_POSITION_MASK_HO) >> IB_MCAST_POSITION_SHIFT); + + /* + Acquire the switch object for this switch. + */ + p_mft_context = osm_madw_get_mft_context_ptr( p_madw ); + node_guid = p_mft_context->node_guid; + + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "osm_mft_rcv_process: " + "Setting MFT block %u, position %u" + "\n\t\t\t\tSwitch 0x%016" PRIx64 ", TID 0x%" PRIx64 "\n", + block_num, position, cl_ntoh64( node_guid ), + cl_ntoh64( p_smp->trans_id ) ); + } + + CL_PLOCK_EXCL_ACQUIRE( p_rcv->p_lock ); + p_sw = osm_get_switch_by_guid( p_rcv->p_subn, node_guid ); + + if( !p_sw ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_mft_rcv_process: ERR 0801: " + "MFT received for nonexistent node " + "0x%016" PRIx64 "\n", cl_ntoh64( node_guid ) ); + } + else + { + status = osm_switch_set_mft_block( p_sw, p_block, + (uint16_t)block_num, position ); + if( status != IB_SUCCESS ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_mft_rcv_process: ERR 0802: " + "Setting MFT block failed (%s)" + "\n\t\t\t\tSwitch 0x%016" PRIx64 + ", block %u, position %u\n", + ib_get_err_str( status ), + cl_ntoh64( node_guid ), + block_num, position ); + } + } + + CL_PLOCK_RELEASE( p_rcv->p_lock ); + OSM_LOG_EXIT( p_rcv->p_log ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcast_fwd_rcv_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcast_fwd_rcv_ctrl.c new file mode 100644 index 00000000..f28ac9b9 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcast_fwd_rcv_ctrl.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_mcast_fwd_rcv_ctrl.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Implementation of osm_mft_rcv_ctrl_t. + * This object represents the LFT Receive controller object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +__osm_mft_rcv_ctrl_disp_callback( + IN void *context, + IN void *p_data ) +{ + /* ignore return status when invoked via the dispatcher */ + osm_mft_rcv_process( ((osm_mft_rcv_ctrl_t*)context)->p_rcv, + (osm_madw_t*)p_data ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_mft_rcv_ctrl_construct( + IN osm_mft_rcv_ctrl_t* const p_ctrl ) +{ + memset( p_ctrl, 0, sizeof(*p_ctrl) ); + p_ctrl->h_disp = CL_DISP_INVALID_HANDLE; +} + +/********************************************************************** + **********************************************************************/ +void +osm_mft_rcv_ctrl_destroy( + IN osm_mft_rcv_ctrl_t* const p_ctrl ) +{ + CL_ASSERT( p_ctrl ); + cl_disp_unregister( p_ctrl->h_disp ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_mft_rcv_ctrl_init( + IN osm_mft_rcv_ctrl_t* const p_ctrl, + IN osm_mft_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_mft_rcv_ctrl_init ); + + osm_mft_rcv_ctrl_construct( p_ctrl ); + p_ctrl->p_log = p_log; + p_ctrl->p_rcv = p_rcv; + p_ctrl->p_disp = p_disp; + + p_ctrl->h_disp = cl_disp_register( + p_disp, + OSM_MSG_MAD_MFT, + __osm_mft_rcv_ctrl_disp_callback, + p_ctrl ); + + if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_mft_rcv_ctrl_init: ERR 0901: " + "Dispatcher registration failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return( status ); +} + + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcast_mgr.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcast_mgr.c new file mode 100644 index 00000000..a3b3882f --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcast_mgr.c @@ -0,0 +1,1726 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_mcast_mgr.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_mcast_mgr_t. + * This file implements the Multicast Manager object. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.9 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LINE_LENGTH 256 + +/********************************************************************** + **********************************************************************/ +typedef struct _osm_mcast_work_obj +{ + cl_list_item_t list_item; + osm_port_t* p_port; +} osm_mcast_work_obj_t; + +/********************************************************************** + **********************************************************************/ +static osm_mcast_work_obj_t* +__osm_mcast_work_obj_new( + IN const osm_port_t* const p_port ) +{ + /* + TO DO - get these objects from a lockpool. + */ + osm_mcast_work_obj_t* p_obj; + + /* + clean allocated memory to avoid assertion when trying to insert to + qlist. + see cl_qlist_insert_tail(): CL_ASSERT(p_list_item->p_list != p_list) + */ + p_obj = malloc( sizeof( *p_obj ) ); + if( p_obj ) + { + memset( p_obj, 0, sizeof( *p_obj ) ); + p_obj->p_port = (osm_port_t*)p_port; + } + + return( p_obj ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_mcast_work_obj_delete( + IN osm_mcast_work_obj_t* p_wobj ) +{ + free( p_wobj ); +} + +/********************************************************************** + Recursively remove nodes from the tree +**********************************************************************/ +static void +__osm_mcast_mgr_purge_tree_node( + IN osm_mtree_node_t* p_mtn ) +{ + uint8_t i; + + for( i = 0; i < p_mtn->max_children; i++ ) + { + if( p_mtn->child_array[i] && + (p_mtn->child_array[i] != OSM_MTREE_LEAF) ) + __osm_mcast_mgr_purge_tree_node( p_mtn->child_array[i] ); + + p_mtn->child_array[i] = NULL; + + } + + free( p_mtn ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_mcast_mgr_purge_tree( + IN osm_mcast_mgr_t* const p_mgr, + IN osm_mgrp_t* const p_mgrp ) +{ + OSM_LOG_ENTER( p_mgr->p_log, __osm_mcast_mgr_purge_tree ); + + if( p_mgrp->p_root ) + __osm_mcast_mgr_purge_tree_node( p_mgrp->p_root ); + + p_mgrp->p_root = NULL; + + OSM_LOG_EXIT( p_mgr->p_log ); +} + +/********************************************************************** + **********************************************************************/ +static float +osm_mcast_mgr_compute_avg_hops( + osm_mcast_mgr_t* const p_mgr, + const osm_mgrp_t* const p_mgrp, + const osm_switch_t* const p_sw ) +{ + float avg_hops = 0; + uint32_t hops = 0; + uint32_t num_ports = 0; + uint16_t base_lid_ho; + const osm_port_t* p_port; + const osm_mcm_port_t* p_mcm_port; + const cl_qmap_t* p_mcm_tbl; + const cl_qmap_t* p_port_tbl; + + OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_compute_avg_hops ); + + p_mcm_tbl = &p_mgrp->mcm_port_tbl; + p_port_tbl = &p_mgr->p_subn->port_guid_tbl; + + /* + For each member of the multicast group, compute the + number of hops to its base LID. + */ + for( p_mcm_port = (osm_mcm_port_t*)cl_qmap_head( p_mcm_tbl ); + p_mcm_port != (osm_mcm_port_t*)cl_qmap_end( p_mcm_tbl ); + p_mcm_port = (osm_mcm_port_t*)cl_qmap_next(&p_mcm_port->map_item)) + { + /* + Acquire the port object for this port guid, then create + the new worker object to build the list. + */ + p_port = (osm_port_t*)cl_qmap_get( p_port_tbl, + ib_gid_get_guid( &p_mcm_port->port_gid ) ); + + if( p_port == (osm_port_t*)cl_qmap_end( p_port_tbl ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "osm_mcast_mgr_compute_avg_hops: ERR 0A18: " + "No port object for port 0x%016" PRIx64 "\n", + cl_ntoh64( ib_gid_get_guid( &p_mcm_port->port_gid ) ) ); + continue; + } + + base_lid_ho = cl_ntoh16( osm_port_get_base_lid( p_port ) ); + hops += osm_switch_get_least_hops( p_sw, base_lid_ho ); + num_ports++; + } + + /* + We should be here if there aren't any ports in the group. + */ + CL_ASSERT( num_ports ); + + if( num_ports != 0 ) + { + avg_hops = (float)(hops / num_ports); + } + + OSM_LOG_EXIT( p_mgr->p_log ); + return( avg_hops ); +} + +/********************************************************************** + Calculate the maximal "min hops" from the given switch to any + of the group HCAs + **********************************************************************/ +static float +osm_mcast_mgr_compute_max_hops( + osm_mcast_mgr_t* const p_mgr, + const osm_mgrp_t* const p_mgrp, + const osm_switch_t* const p_sw ) +{ + uint32_t max_hops = 0; + uint32_t hops = 0; + uint16_t base_lid_ho; + const osm_port_t* p_port; + const osm_mcm_port_t* p_mcm_port; + const cl_qmap_t* p_mcm_tbl; + const cl_qmap_t* p_port_tbl; + + OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_compute_max_hops ); + + p_mcm_tbl = &p_mgrp->mcm_port_tbl; + p_port_tbl = &p_mgr->p_subn->port_guid_tbl; + + /* + For each member of the multicast group, compute the + number of hops to its base LID. + */ + for( p_mcm_port = (osm_mcm_port_t*)cl_qmap_head( p_mcm_tbl ); + p_mcm_port != (osm_mcm_port_t*)cl_qmap_end( p_mcm_tbl ); + p_mcm_port = (osm_mcm_port_t*)cl_qmap_next(&p_mcm_port->map_item)) + { + /* + Acquire the port object for this port guid, then create + the new worker object to build the list. + */ + p_port = (osm_port_t*)cl_qmap_get( + p_port_tbl, + ib_gid_get_guid( &p_mcm_port->port_gid ) ); + + if( p_port == (osm_port_t*)cl_qmap_end( p_port_tbl ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "osm_mcast_mgr_compute_max_hops: ERR 0A1A: " + "No port object for port 0x%016" PRIx64 "\n", + cl_ntoh64( ib_gid_get_guid( &p_mcm_port->port_gid ) ) ); + continue; + } + + base_lid_ho = cl_ntoh16( osm_port_get_base_lid( p_port ) ); + hops = osm_switch_get_least_hops( p_sw, base_lid_ho ); + if (hops > max_hops) max_hops = hops; + } + + if( max_hops == 0 ) + { + /* + We should be here if there aren't any ports in the group. + */ + max_hops = 10001; /* see later - we use it to realize no hops */ + } + + OSM_LOG_EXIT( p_mgr->p_log ); + return(float)(max_hops); +} + +/********************************************************************** + This function attempts to locate the optimal switch for the + center of the spanning tree. The current algorithm chooses + a switch with the lowest average hop count to the members + of the multicast group. +**********************************************************************/ +static osm_switch_t* +__osm_mcast_mgr_find_optimal_switch( + osm_mcast_mgr_t* const p_mgr, + const osm_mgrp_t* const p_mgrp ) +{ + cl_qmap_t* p_sw_tbl; + const osm_switch_t* p_sw; + const osm_switch_t* p_best_sw = NULL; + float hops = 0; + float best_hops = 10000; /* any big # will do */ + uint64_t sw_guid_ho; +#ifdef OSM_VENDOR_INTF_ANAFA + boolean_t use_avg_hops = TRUE; /* anafa2 - bug hca on switch */ /* use max hops for root */ +#else + boolean_t use_avg_hops = FALSE; /* use max hops for root */ +#endif + + OSM_LOG_ENTER( p_mgr->p_log, __osm_mcast_mgr_find_optimal_switch ); + + p_sw_tbl = &p_mgr->p_subn->sw_guid_tbl; + + CL_ASSERT( !osm_mgrp_is_empty( p_mgrp ) ); + + for( p_sw = (osm_switch_t*)cl_qmap_head( p_sw_tbl ); + p_sw != (osm_switch_t*)cl_qmap_end( p_sw_tbl ); + p_sw = (osm_switch_t*)cl_qmap_next( &p_sw->map_item ) ) + { + if( !osm_switch_supports_mcast( p_sw ) ) + continue; + + if (use_avg_hops) + hops = osm_mcast_mgr_compute_avg_hops( p_mgr, p_mgrp, p_sw ); + else + hops = osm_mcast_mgr_compute_max_hops( p_mgr, p_mgrp, p_sw ); + + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) ) + { + sw_guid_ho = cl_ntoh64( osm_node_get_node_guid( + osm_switch_get_node_ptr( p_sw ) ) ); + + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_mcast_mgr_find_optimal_switch: " + "Switch 0x%016" PRIx64 ", hops = %f\n", + sw_guid_ho, hops ); + } + + if( hops < best_hops ) + { + p_best_sw = p_sw; + best_hops = hops; + } + } + + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) ) + { + if( p_best_sw ) + { + sw_guid_ho = cl_ntoh64( osm_node_get_node_guid( + osm_switch_get_node_ptr( p_best_sw ) ) ); + + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_mcast_mgr_find_optimal_switch: " + "Best switch is 0x%" PRIx64 ", hops = %f\n", + sw_guid_ho, best_hops ); + } + else + { + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_mcast_mgr_find_optimal_switch: " + "No multicast capable switches detected\n" ); + } + } + + OSM_LOG_EXIT( p_mgr->p_log ); + return( (osm_switch_t*)p_best_sw ); +} + +/********************************************************************** + This function returns the existing or optimal root swtich for the tree. +**********************************************************************/ +static osm_switch_t* +__osm_mcast_mgr_find_root_switch( + osm_mcast_mgr_t* const p_mgr, + const osm_mgrp_t* const p_mgrp ) +{ + const osm_switch_t* p_sw = NULL; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_mcast_mgr_find_root_switch ); + + /* + We always look for the best multicast tree root switch. + Otherwise since we always start with a a single join + the root will be always on the first switch attached to it. + - Very bad ... + */ + p_sw = __osm_mcast_mgr_find_optimal_switch( p_mgr, p_mgrp ); + + OSM_LOG_EXIT( p_mgr->p_log ); + return( (osm_switch_t*)p_sw ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_mcast_mgr_construct( + IN osm_mcast_mgr_t* const p_mgr ) +{ + memset( p_mgr, 0, sizeof(*p_mgr) ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_mcast_mgr_destroy( + IN osm_mcast_mgr_t* const p_mgr ) +{ + CL_ASSERT( p_mgr ); + + OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_destroy ); + + OSM_LOG_EXIT( p_mgr->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_mcast_mgr_init( + IN osm_mcast_mgr_t* const p_mgr, + IN osm_req_t* const p_req, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_mcast_mgr_init ); + + CL_ASSERT( p_req ); + CL_ASSERT( p_subn ); + CL_ASSERT( p_lock ); + + osm_mcast_mgr_construct( p_mgr ); + + p_mgr->p_log = p_log; + p_mgr->p_subn = p_subn; + p_mgr->p_lock = p_lock; + p_mgr->p_req = p_req; + + OSM_LOG_EXIT( p_mgr->p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +static osm_signal_t +__osm_mcast_mgr_set_tbl( + IN osm_mcast_mgr_t* const p_mgr, + IN osm_switch_t* const p_sw ) +{ + osm_node_t* p_node; + osm_dr_path_t* p_path; + osm_madw_context_t mad_context; + ib_api_status_t status; + uint32_t block_id_ho = 0; + int16_t block_num = 0; + uint32_t position = 0; + uint32_t max_position; + osm_mcast_tbl_t* p_tbl; + ib_net16_t block[IB_MCAST_BLOCK_SIZE]; + osm_signal_t signal = OSM_SIGNAL_DONE; + + CL_ASSERT( p_mgr ); + + OSM_LOG_ENTER( p_mgr->p_log, __osm_mcast_mgr_set_tbl ); + + CL_ASSERT( p_sw ); + + p_node = osm_switch_get_node_ptr( p_sw ); + + CL_ASSERT( p_node ); + + p_path = osm_node_get_any_dr_path_ptr( p_node ); + + CL_ASSERT( p_path ); + + /* + Send multicast forwarding table blocks to the switch + as long as the switch indicates it has blocks needing + configuration. + */ + + mad_context.mft_context.node_guid = osm_node_get_node_guid( p_node ); + mad_context.mft_context.set_method = TRUE; + + p_tbl = osm_switch_get_mcast_tbl_ptr( p_sw ); + max_position = p_tbl->max_position; + + while( osm_mcast_tbl_get_block( p_tbl, block_num, + (uint8_t)position, block ) ) + { + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_mcast_mgr_set_tbl: " + "Writing MFT block 0x%X\n", block_id_ho ); + } + + block_id_ho = block_num + (position << 28); + + status = osm_req_set( p_mgr->p_req, + p_path, + (void*)block, + sizeof(block), + IB_MAD_ATTR_MCAST_FWD_TBL, + cl_hton32( block_id_ho ), + CL_DISP_MSGID_NONE, + &mad_context ); + + if( status != IB_SUCCESS ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_mcast_mgr_set_tbl: ERR 0A02: " + "Sending multicast fwd. tbl. block failed (%s)\n", + ib_get_err_str( status ) ); + } + + signal = OSM_SIGNAL_DONE_PENDING; + + if( ++position > max_position ) + { + position = 0; + block_num++; + } + } + + OSM_LOG_EXIT( p_mgr->p_log ); + return( signal ); +} + +/********************************************************************** + This is part of the recursive function to compute the paths in the + spanning tree that eminate from this switch. On input, the p_list + contains the group members that must be routed from this switch. +**********************************************************************/ +static void +__osm_mcast_mgr_subdivide( + osm_mcast_mgr_t* const p_mgr, + osm_mgrp_t* const p_mgrp, + osm_switch_t* const p_sw, + cl_qlist_t* const p_list, + cl_qlist_t* const list_array, + uint8_t const array_size ) +{ + uint8_t port_num; + uint16_t mlid_ho; + uint16_t lid_ho; + boolean_t ignore_existing; + osm_mcast_work_obj_t* p_wobj; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_mcast_mgr_subdivide ); + + mlid_ho = cl_ntoh16( osm_mgrp_get_mlid( p_mgrp ) ); + + /* + For Multicast Groups, we want not to count on previous + configurations - since we can easily generate a storm + by loops. + */ + ignore_existing = TRUE; + + /* + Subdivide the set of ports into non-overlapping subsets + that will be routed to other switches. + */ + while( (p_wobj = (osm_mcast_work_obj_t*)cl_qlist_remove_head( p_list )) != + (osm_mcast_work_obj_t*)cl_qlist_end( p_list ) ) + { + lid_ho = cl_ntoh16( osm_port_get_base_lid( p_wobj->p_port ) ); + + port_num = osm_switch_recommend_mcast_path( + p_sw, lid_ho, mlid_ho, ignore_existing ); + + if( port_num == OSM_NO_PATH ) + { + /* + This typically occurs if the switch does not support + multicast and the multicast tree must branch at this + switch. + */ + uint64_t node_guid_ho = cl_ntoh64( osm_node_get_node_guid( + osm_switch_get_node_ptr( p_sw ) ) ); + + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_mcast_mgr_subdivide: ERR 0A03: " + "Error routing MLID 0x%X through switch 0x%" PRIx64 "\n" + "\t\t\t\tNo multicast paths from this switch for port " + "with LID 0x%X\n", + mlid_ho, node_guid_ho, lid_ho ); + + __osm_mcast_work_obj_delete( p_wobj ); + continue; + } + + if( port_num > array_size ) + { + uint64_t node_guid_ho = cl_ntoh64( osm_node_get_node_guid( + osm_switch_get_node_ptr( p_sw ) ) ); + + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_mcast_mgr_subdivide: ERR 0A04: " + "Error routing MLID 0x%X through switch 0x%" PRIx64 "\n" + "\t\t\t\tNo multicast paths from this switch to port " + "with LID 0x%X\n", + mlid_ho, node_guid_ho, lid_ho ); + + __osm_mcast_work_obj_delete( p_wobj ); + + /* This is means OpenSM has a bug. */ + CL_ASSERT( FALSE ); + continue; + } + + cl_qlist_insert_tail( &list_array[port_num], &p_wobj->list_item ); + } + + OSM_LOG_EXIT( p_mgr->p_log ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_mcast_mgr_purge_list( + osm_mcast_mgr_t* const p_mgr, + cl_qlist_t* const p_list ) +{ + osm_mcast_work_obj_t* p_wobj; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_mcast_mgr_purge_list ); + + while( (p_wobj = (osm_mcast_work_obj_t*)cl_qlist_remove_head( p_list ) ) + != (osm_mcast_work_obj_t*)cl_qlist_end( p_list ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_mcast_mgr_purge_list: ERR 0A06: " + "Unable to route for port 0x%" PRIx64 "\n", + osm_port_get_guid( p_wobj->p_port ) ); + __osm_mcast_work_obj_delete( p_wobj ); + } + + OSM_LOG_EXIT( p_mgr->p_log ); +} + +/********************************************************************** + This is the recursive function to compute the paths in the spanning + tree that emanate from this switch. On input, the p_list contains + the group members that must be routed from this switch. + + The function returns the newly created mtree node element. +**********************************************************************/ +static osm_mtree_node_t* +__osm_mcast_mgr_branch( + osm_mcast_mgr_t* const p_mgr, + osm_mgrp_t* const p_mgrp, + osm_switch_t* const p_sw, + cl_qlist_t* const p_list, + uint8_t depth, + uint8_t const upstream_port, + uint8_t* const p_max_depth ) +{ + uint8_t max_children; + osm_mtree_node_t* p_mtn = NULL; + cl_qlist_t* list_array = NULL; + uint8_t i; + ib_net64_t node_guid; + uint64_t node_guid_ho; + osm_mcast_work_obj_t* p_wobj; + cl_qlist_t* p_port_list; + size_t count; + uint16_t mlid_ho; + osm_mcast_tbl_t* p_tbl; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_mcast_mgr_branch ); + + CL_ASSERT( p_sw ); + CL_ASSERT( p_list ); + CL_ASSERT( p_max_depth ); + + node_guid = osm_node_get_node_guid( osm_switch_get_node_ptr( p_sw ) ); + node_guid_ho = cl_ntoh64( node_guid ); + mlid_ho = cl_ntoh16( osm_mgrp_get_mlid( p_mgrp ) ); + + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_mcast_mgr_branch: " + "Routing MLID 0x%X through switch 0x%" PRIx64 "\n" + "\t\t\t\t%u nodes at depth %u\n", + mlid_ho, + node_guid_ho, + cl_qlist_count( p_list ), depth ); + } + + CL_ASSERT( cl_qlist_count( p_list ) > 0 ); + + depth++; + + if( depth > *p_max_depth ) + { + CL_ASSERT( depth == *p_max_depth + 1 ); + *p_max_depth = depth; + } + + if( osm_switch_supports_mcast( p_sw ) == FALSE ) + { + /* + This switch doesn't do multicast. Clean-up. + */ + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_mcast_mgr_branch: ERR 0A14: " + "Switch 0x%" PRIx64 " does not support multicast\n", + node_guid_ho ); + + /* + Deallocate all the work objects on this branch of the tree. + */ + __osm_mcast_mgr_purge_list( p_mgr, p_list ); + goto Exit; + } + + p_mtn = osm_mtree_node_new( p_sw ); + if( p_mtn == NULL ) + { + /* + We are unable to continue routing down this + leg of the tree. Clean-up. + */ + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_mcast_mgr_branch: ERR 0A15: " + "Insufficient memory to build multicast tree\n" ); + + /* + Deallocate all the work objects on this branch of the tree. + */ + __osm_mcast_mgr_purge_list( p_mgr, p_list ); + goto Exit; + } + + max_children = osm_mtree_node_get_max_children( p_mtn ); + + CL_ASSERT( max_children > 1 ); + + /* + Prepare an empty list for each port in the switch. + TO DO - this list array could probably be moved + inside the switch element to save on malloc thrashing. + */ + list_array = malloc( sizeof(cl_qlist_t) * max_children ); + if( list_array == NULL ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_mcast_mgr_branch: ERR 0A16: " + "Unable to allocate list array\n" ); + __osm_mcast_mgr_purge_list( p_mgr, p_list ); + goto Exit; + } + + memset( list_array, 0, sizeof(cl_qlist_t) * max_children ); + + for( i = 0; i < max_children; i++ ) + cl_qlist_init( &list_array[i] ); + + __osm_mcast_mgr_subdivide( p_mgr, p_mgrp, p_sw, p_list, list_array, + max_children ); + + p_tbl = osm_switch_get_mcast_tbl_ptr( p_sw ); + + /* + Add the upstream port to the forwarding table unless + we're at the root of the spanning tree. + */ + if( depth > 1 ) + { + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_mcast_mgr_branch: " + "Adding upstream port 0x%X\n", upstream_port ); + } + + CL_ASSERT( upstream_port ); + osm_mcast_tbl_set( p_tbl, mlid_ho, upstream_port ); + } + + /* + For each port that was allocated some routes, + recurse into this function to continue building the tree + if the node on the other end of that port is another switch. + Otherwise, the node is an endpoint, and we've found a leaf + of the tree. Mark leaves with our special pointer value. + */ + + for( i = 0; i < max_children; i++ ) + { + const osm_physp_t *p_physp; + const osm_physp_t *p_remote_physp; + const osm_node_t *p_node; + const osm_node_t *p_remote_node; + + p_port_list = &list_array[i]; + + count = cl_qlist_count( p_port_list ); + + /* + There should be no children routed through the upstream port! + */ + CL_ASSERT( ( upstream_port == 0 ) || ( i != upstream_port) || + ( (i == upstream_port) && (count == 0)) ); + + if( count == 0) + continue; /* No routes down this port. */ + + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_mcast_mgr_branch: " + "Routing %zu destination(s) via switch port 0x%X\n", + count, i ); + } + + /* + This port routes frames for this mcast group. Therefore, + set the appropriate bit in the multicast forwarding + table for this switch. + */ + osm_mcast_tbl_set( p_tbl, mlid_ho, i ); + if (i == 0) + /* This means we are adding the switch to the MC group. + We do not need to continue looking at the remote port, just + needed to add the port to the table */ + continue; + + p_node = osm_switch_get_node_ptr( p_sw ); + p_remote_node = osm_node_get_remote_node( p_node, i, NULL ); + + if( osm_node_get_type( p_remote_node ) == IB_NODE_TYPE_SWITCH ) + { + /* + Acquire a pointer to the remote switch then recurse. + */ + CL_ASSERT( p_remote_node->sw ); + + p_physp = osm_node_get_physp_ptr( p_node, i ); + CL_ASSERT( p_physp ); + CL_ASSERT( osm_physp_is_valid( p_physp ) ); + + p_remote_physp = osm_physp_get_remote( p_physp ); + CL_ASSERT( p_remote_physp ); + CL_ASSERT( osm_physp_is_valid( p_remote_physp ) ); + + p_mtn->child_array[i] = __osm_mcast_mgr_branch( + p_mgr, p_mgrp, p_remote_node->sw, + p_port_list, depth, + osm_physp_get_port_num( p_remote_physp), + p_max_depth ); + } + else + { + /* + The neighbor node is not a switch, so this + must be a leaf. + */ + CL_ASSERT( count == 1 ); + + p_mtn->child_array[i] = OSM_MTREE_LEAF; + p_wobj = (osm_mcast_work_obj_t*)cl_qlist_remove_head( + p_port_list ); + + CL_ASSERT( cl_is_qlist_empty( p_port_list ) ); + + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_mcast_mgr_branch: " + "Found leaf for port 0x%016" PRIx64 "\n" + "\t\t\t\ton switch port 0x%X\n", + cl_ntoh64( osm_port_get_guid( p_wobj->p_port ) ), i ); + } + + __osm_mcast_work_obj_delete( p_wobj ); + } + } + + free( list_array ); + Exit: + OSM_LOG_EXIT( p_mgr->p_log ); + return( p_mtn ); +} + +/********************************************************************** + **********************************************************************/ +static ib_api_status_t +__osm_mcast_mgr_build_spanning_tree( + osm_mcast_mgr_t* const p_mgr, + osm_mgrp_t* const p_mgrp ) +{ + const cl_qmap_t* p_mcm_tbl; + const cl_qmap_t* p_port_tbl; + const osm_port_t* p_port; + const osm_mcm_port_t* p_mcm_port; + uint32_t num_ports; + cl_qlist_t port_list; + osm_switch_t* p_sw; + osm_mcast_work_obj_t* p_wobj; + ib_api_status_t status = IB_SUCCESS; + uint8_t max_depth = 0; + uint32_t count; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_mcast_mgr_build_spanning_tree ); + + cl_qlist_init( &port_list ); + + /* + TO DO - for now, just blow away the old tree. + In the future we'll need to construct the tree based + on multicast forwarding table information if the user wants to + preserve existing multicast routes. + */ + __osm_mcast_mgr_purge_tree( p_mgr, p_mgrp ); + + p_mcm_tbl = &p_mgrp->mcm_port_tbl; + p_port_tbl = &p_mgr->p_subn->port_guid_tbl; + num_ports = cl_qmap_count( p_mcm_tbl ); + if( num_ports == 0 ) + { + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_mcast_mgr_build_spanning_tree: " + "MLID 0x%X has no members--nothing to do\n", + cl_ntoh16( osm_mgrp_get_mlid( p_mgrp ) ) ); + } + goto Exit; + } + + /* + This function builds the single spanning tree recursively. + At each stage, the ports to be reached are divided into + non-overlapping subsets of member ports that can be reached through + a given switch port. Construction then moves down each + branch, and the process starts again with each branch computing + for its own subset of the member ports. + + The maximum recursion depth is at worst the maximum hop count in the + subnet, which is spec limited to 64. + */ + + /* + Locate the switch around which to create the spanning + tree for this multicast group. + */ + p_sw = __osm_mcast_mgr_find_root_switch( p_mgr, p_mgrp ); + if( p_sw == NULL ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_mcast_mgr_build_spanning_tree: ERR 0A08: " + "Unable to locate a suitable switch for group 0x%X\n", + cl_ntoh16( osm_mgrp_get_mlid( p_mgrp ) )); + status = IB_ERROR; + goto Exit; + } + + /* + Build the first "subset" containing all member ports. + */ + for( p_mcm_port = (osm_mcm_port_t*)cl_qmap_head( p_mcm_tbl ); + p_mcm_port != (osm_mcm_port_t*)cl_qmap_end( p_mcm_tbl ); + p_mcm_port = (osm_mcm_port_t*)cl_qmap_next(&p_mcm_port->map_item)) + { + /* + Acquire the port object for this port guid, then create + the new worker object to build the list. + */ + p_port = (osm_port_t*)cl_qmap_get( p_port_tbl, + ib_gid_get_guid( &p_mcm_port->port_gid ) ); + + if( p_port == (osm_port_t*)cl_qmap_end( p_port_tbl ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_mcast_mgr_build_spanning_tree: ERR 0A09: " + "No port object for port 0x%016" PRIx64 "\n", + cl_ntoh64( ib_gid_get_guid( &p_mcm_port->port_gid ) ) ); + continue; + } + + p_wobj = __osm_mcast_work_obj_new( p_port ); + if( p_wobj == NULL ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_mcast_mgr_build_spanning_tree: ERR 0A10: " + "Insufficient memory to route port 0x%016" PRIx64 "\n", + cl_ntoh64( osm_port_get_guid( p_port ) ) ); + continue; + } + + cl_qlist_insert_tail( &port_list, &p_wobj->list_item ); + } + + count = cl_qlist_count( &port_list ); + p_mgrp->p_root = __osm_mcast_mgr_branch( p_mgr, p_mgrp, p_sw, + &port_list, 0, 0, &max_depth ); + + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_mcast_mgr_build_spanning_tree: " + "Configured MLID 0x%X for %u ports, max tree depth = %u\n", + cl_ntoh16( osm_mgrp_get_mlid( p_mgrp ) ), + count, max_depth ); + + Exit: + OSM_LOG_EXIT( p_mgr->p_log ); + return( status ); +} + +#if 0 +/* unused */ +/********************************************************************** + **********************************************************************/ +void +osm_mcast_mgr_set_table( + IN osm_mcast_mgr_t* const p_mgr, + IN const osm_mgrp_t* const p_mgrp, + IN const osm_mtree_node_t* const p_mtn ) +{ + uint8_t i; + uint8_t max_children; + osm_mtree_node_t* p_child_mtn; + uint16_t mlid_ho; + osm_mcast_tbl_t* p_tbl; + osm_switch_t* p_sw; + + OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_set_table ); + + mlid_ho = cl_ntoh16( osm_mgrp_get_mlid( p_mgrp ) ); + p_sw = osm_mtree_node_get_switch_ptr( p_mtn ); + + CL_ASSERT( p_sw ); + + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "osm_mcast_mgr_set_table: " + "Configuring MLID 0x%X on switch 0x%" PRIx64 "\n", + mlid_ho, osm_node_get_node_guid( + osm_switch_get_node_ptr( p_sw ) ) ); + } + + /* + For every child of this tree node, set the corresponding + bit in the switch's mcast table. + */ + p_tbl = osm_switch_get_mcast_tbl_ptr( p_sw ); + max_children = osm_mtree_node_get_max_children( p_mtn ); + + CL_ASSERT( max_children <= osm_switch_get_num_ports( p_sw ) ); + + osm_mcast_tbl_clear_mlid( p_tbl, mlid_ho ); + + for( i = 0; i < max_children; i++ ) + { + p_child_mtn = osm_mtree_node_get_child( p_mtn, i ); + if( p_child_mtn == NULL ) + continue; + + osm_mcast_tbl_set( p_tbl, mlid_ho, i ); + } + + OSM_LOG_EXIT( p_mgr->p_log ); +} +#endif + +/********************************************************************** + **********************************************************************/ +static void +__osm_mcast_mgr_clear( + IN osm_mcast_mgr_t* const p_mgr, + IN osm_mgrp_t* const p_mgrp ) +{ + osm_switch_t* p_sw; + cl_qmap_t* p_sw_tbl; + osm_mcast_tbl_t* p_mcast_tbl; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_mcast_mgr_clear ); + + /* + Walk the switches and clear the routing entries for + this MLID. + */ + p_sw_tbl = &p_mgr->p_subn->sw_guid_tbl; + p_sw = (osm_switch_t*)cl_qmap_head( p_sw_tbl ); + while( p_sw != (osm_switch_t*)cl_qmap_end( p_sw_tbl ) ) + { + p_mcast_tbl = osm_switch_get_mcast_tbl_ptr( p_sw ); + osm_mcast_tbl_clear_mlid( p_mcast_tbl, cl_ntoh16(p_mgrp->mlid) ); + p_sw = (osm_switch_t*)cl_qmap_next( &p_sw->map_item ); + } + + OSM_LOG_EXIT( p_mgr->p_log ); +} + +#if 0 +/* TO DO - make this real -- at least update spanning tree */ +/********************************************************************** + Lock must be held on entry. +**********************************************************************/ +ib_api_status_t +osm_mcast_mgr_process_single( + IN osm_mcast_mgr_t* const p_mgr, + IN ib_net16_t const mlid, + IN ib_net64_t const port_guid, + IN uint8_t const join_state ) +{ + uint8_t port_num; + uint16_t mlid_ho; + osm_switch_t* p_sw; + ib_net64_t sw_guid; + osm_port_t* p_port; + osm_physp_t* p_physp; + osm_physp_t* p_remote_physp; + osm_node_t* p_remote_node; + cl_qmap_t* p_port_tbl; + osm_mcast_tbl_t* p_mcast_tbl; + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_process_single ); + + CL_ASSERT( mlid ); + CL_ASSERT( port_guid ); + + p_port_tbl = &p_mgr->p_subn->port_guid_tbl; + mlid_ho = cl_ntoh16( mlid ); + + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "osm_mcast_mgr_process_single: " + "Attempting to add port 0x%" PRIx64 " to MLID 0x%X, " + "\n\t\t\t\tjoin state = 0x%X\n", + cl_ntoh64( port_guid ), mlid_ho, join_state ); + } + + /* + Acquire the Port object. + */ + p_port = (osm_port_t*)cl_qmap_get( p_port_tbl, port_guid ); + if( p_port == (osm_port_t*)cl_qmap_end( p_port_tbl ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "osm_mcast_mgr_process_single: ERR 0A01: " + "Unable to acquire port object for 0x%" PRIx64 "\n", + cl_ntoh64( port_guid ) ); + status = IB_ERROR; + goto Exit; + } + + p_physp = osm_port_get_default_phys_ptr( p_port ); + if( p_physp == NULL ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "osm_mcast_mgr_process_single: ERR 0A05: " + "Unable to acquire phsyical port object for 0x%" PRIx64 "\n", + cl_ntoh64( port_guid ) ); + status = IB_ERROR; + goto Exit; + } + + if( !osm_physp_is_valid( p_physp ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "osm_mcast_mgr_process_single: ERR 0A07: " + "Unable to acquire valid physical port object " + "for 0x%" PRIx64 "\n", + cl_ntoh64( port_guid ) ); + status = IB_ERROR; + goto Exit; + } + + p_remote_physp = osm_physp_get_remote( p_physp ); + if( p_remote_physp == NULL ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "osm_mcast_mgr_process_single: ERR 0A11: " + "Unable to acquire remote phsyical port object " + "for 0x%" PRIx64 "\n", + cl_ntoh64( port_guid ) ); + status = IB_ERROR; + goto Exit; + } + + if( !osm_physp_is_valid( p_remote_physp ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "osm_mcast_mgr_process_single: ERR 0A21: " + "Unable to acquire valid remote physical port object " + "for 0x%" PRIx64 "\n", + cl_ntoh64( port_guid ) ); + status = IB_ERROR; + goto Exit; + } + + p_remote_node = osm_physp_get_node_ptr( p_remote_physp ); + + CL_ASSERT( p_remote_node ); + + sw_guid = osm_node_get_node_guid( p_remote_node ); + + if( osm_node_get_type( p_remote_node ) != IB_NODE_TYPE_SWITCH ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "osm_mcast_mgr_process_single: ERR 0A22: " + "Remote node not a switch node 0x%" PRIx64 "\n", + cl_ntoh64( sw_guid ) ); + status = IB_ERROR; + goto Exit; + } + + p_sw = p_remote_node->sw; + if( !p_sw ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "osm_mcast_mgr_process_single: ERR 0A12: " + "No switch object 0x%" PRIx64 "\n", + cl_ntoh64( sw_guid ) ); + status = IB_ERROR; + goto Exit; + } + + if( osm_switch_is_in_mcast_tree( p_sw, mlid_ho ) ) + { + /* + We're in luck. The switch attached to this port + is already in the multicast group, so we can just + add the specified port as a new leaf of the tree. + */ + if( join_state & (IB_JOIN_STATE_FULL | IB_JOIN_STATE_NON ) ) + { + /* + This node wants to receive multicast frames. + Get the switch port number to which the new member port + is attached, then configure this single mcast table. + */ + port_num = osm_physp_get_port_num( p_remote_physp ); + CL_ASSERT( port_num ); + + p_mcast_tbl = osm_switch_get_mcast_tbl_ptr( p_sw ); + osm_mcast_tbl_set( p_mcast_tbl, mlid_ho, port_num ); + } + else + { + if( join_state & IB_JOIN_STATE_SEND_ONLY ) + { + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "osm_mcast_mgr_process_single: " + "Success. Nothing to do for send" + "only member\n" ); + } + } + else + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "osm_mcast_mgr_process_single: ERR 0A13: " + "Unknown join state 0x%X\n", join_state ); + status = IB_ERROR; + goto Exit; + } + } + } + else + { + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "osm_mcast_mgr_process_single: " + "Unable to add port\n" ); + } + } + + Exit: + OSM_LOG_EXIT( p_mgr->p_log ); + return( status ); +} +#endif + +/********************************************************************** + lock must already be held on entry +**********************************************************************/ +static ib_api_status_t +osm_mcast_mgr_process_tree( + IN osm_mcast_mgr_t* const p_mgr, + IN osm_mgrp_t* const p_mgrp, + IN osm_mcast_req_type_t req_type, + ib_net64_t port_guid ) +{ + ib_api_status_t status = IB_SUCCESS; + ib_net16_t mlid; + boolean_t ui_mcast_fdb_assign_func_defined; + + OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_process_tree ); + + mlid = osm_mgrp_get_mlid( p_mgrp ); + + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "osm_mcast_mgr_process_tree: " + "Processing multicast group 0x%X\n", cl_ntoh16( mlid )); + } + + /* + If there are no switches in the subnet, then we have nothing to do. + */ + if( cl_qmap_count( &p_mgr->p_subn->sw_guid_tbl ) == 0 ) + { + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "osm_mcast_mgr_process_tree: " + "No switches in subnet. Nothing to do\n" ); + } + goto Exit; + } + + if (p_mgr->p_subn->opt.pfn_ui_mcast_fdb_assign) + ui_mcast_fdb_assign_func_defined = TRUE; + else + ui_mcast_fdb_assign_func_defined = FALSE; + + /* + Clear the multicast tables to start clean, then build + the spanning tree which sets the mcast table bits for each + port in the group. + We will clean the multicast tables if a ui_mcast function isn't + defined, or if such function is defined, but we got here + through a MC_CREATE request - this means we are creating a new + multicast group - clean all old data. + */ + if ( ui_mcast_fdb_assign_func_defined == FALSE || + req_type == OSM_MCAST_REQ_TYPE_CREATE ) + __osm_mcast_mgr_clear( p_mgr, p_mgrp ); + + /* If a UI function is defined, then we will call it here. + If not - the use the regular build spanning tree function */ + if ( ui_mcast_fdb_assign_func_defined == FALSE ) + { + status = __osm_mcast_mgr_build_spanning_tree( p_mgr, p_mgrp ); + if( status != IB_SUCCESS ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "osm_mcast_mgr_process_tree: ERR 0A17: " + "Unable to create spanning tree (%s)\n", + ib_get_err_str( status ) ); + goto Exit; + } + } + else + { + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "osm_mcast_mgr_process_tree: " + "Invoking UI function pfn_ui_mcast_fdb_assign\n"); + } + + p_mgr->p_subn->opt.pfn_ui_mcast_fdb_assign( + p_mgr->p_subn->opt.ui_mcast_fdb_assign_ctx, + mlid, req_type, port_guid ); + } + + Exit: + OSM_LOG_EXIT( p_mgr->p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +static void +mcast_mgr_dump_sw_routes( + IN const osm_mcast_mgr_t* const p_mgr, + IN const osm_switch_t* const p_sw, + IN FILE *file ) +{ + osm_mcast_tbl_t* p_tbl; + int16_t mlid_ho = 0; + int16_t mlid_start_ho; + uint8_t position = 0; + int16_t block_num = 0; + boolean_t first_mlid; + boolean_t first_port; + const osm_node_t* p_node; + uint16_t i, j; + uint16_t mask_entry; + char sw_hdr[256]; + char mlid_hdr[32]; + + OSM_LOG_ENTER( p_mgr->p_log, mcast_mgr_dump_sw_routes ); + + if( !osm_log_is_active( p_mgr->p_log, OSM_LOG_ROUTING ) ) + goto Exit; + + p_node = osm_switch_get_node_ptr( p_sw ); + + p_tbl = osm_switch_get_mcast_tbl_ptr( p_sw ); + + sprintf( sw_hdr, "\nSwitch 0x%016" PRIx64 "\n" + "LID : Out Port(s)\n", + cl_ntoh64( osm_node_get_node_guid( p_node ) ) ); + first_mlid = TRUE; + while ( block_num <= p_tbl->max_block_in_use ) + { + mlid_start_ho = (uint16_t)(block_num * IB_MCAST_BLOCK_SIZE); + for (i = 0 ; i < IB_MCAST_BLOCK_SIZE ; i++) + { + mlid_ho = mlid_start_ho + i; + position = 0; + first_port = TRUE; + sprintf( mlid_hdr, "0x%04X :", mlid_ho + IB_LID_MCAST_START_HO ); + while ( position <= p_tbl->max_position ) + { + mask_entry = cl_ntoh16((*p_tbl->p_mask_tbl)[mlid_ho][position]); + if (mask_entry == 0) + { + position++; + continue; + } + for (j = 0 ; j < 16 ; j++) + { + if ( (1 << j) & mask_entry ) + { + if (first_mlid) + { + fprintf( file,"%s", sw_hdr ); + first_mlid = FALSE; + } + if (first_port) + { + fprintf( file,"%s", mlid_hdr ); + first_port = FALSE; + } + fprintf( file, " 0x%03X ", j+(position*16) ); + } + } + position++; + } + if (first_port == FALSE) + { + fprintf( file, "\n" ); + } + } + block_num++; + } + + Exit: + OSM_LOG_EXIT( p_mgr->p_log ); +} + +/********************************************************************** + **********************************************************************/ +struct mcast_mgr_dump_context { + osm_mcast_mgr_t *p_mgr; + FILE *file; +}; + +static void +mcast_mgr_dump_table(cl_map_item_t *p_map_item, void *context) +{ + osm_switch_t *p_sw = (osm_switch_t *)p_map_item; + struct mcast_mgr_dump_context *cxt = context; + + mcast_mgr_dump_sw_routes(cxt->p_mgr, p_sw, cxt->file); +} + +static void +mcast_mgr_dump_mcast_routes(osm_mcast_mgr_t *p_mgr) +{ + char file_name[1024]; + struct mcast_mgr_dump_context dump_context; + FILE *file; + + if (!osm_log_is_active(p_mgr->p_log, OSM_LOG_ROUTING)) + return; + + snprintf(file_name, sizeof(file_name), "%s/%s", + p_mgr->p_subn->opt.dump_files_dir, "osm.mcfdbs"); + + file = fopen(file_name, "w"); + if (!file) { + osm_log(p_mgr->p_log, OSM_LOG_ERROR, + "mcast_dump_mcast_routes: ERR 0A18: " + "cannot create mcfdb file \'%s\': %s\n", + file_name, strerror(errno)); + return; + } + + dump_context.p_mgr = p_mgr; + dump_context.file = file; + + cl_qmap_apply_func(&p_mgr->p_subn->sw_guid_tbl, + mcast_mgr_dump_table, &dump_context); + + fclose(file); +} + +/********************************************************************** + Process the entire group. + + NOTE : The lock should be held externally! + **********************************************************************/ +static osm_signal_t +osm_mcast_mgr_process_mgrp( + IN osm_mcast_mgr_t* const p_mgr, + IN osm_mgrp_t* const p_mgrp, + IN osm_mcast_req_type_t req_type, + IN ib_net64_t port_guid ) +{ + osm_signal_t signal = OSM_SIGNAL_DONE; + ib_api_status_t status; + osm_switch_t* p_sw; + cl_qmap_t* p_sw_tbl; + boolean_t pending_transactions = FALSE; + + OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_process_mgrp ); + + p_sw_tbl = &p_mgr->p_subn->sw_guid_tbl; + + status = osm_mcast_mgr_process_tree( p_mgr, p_mgrp, req_type, port_guid ); + if( status != IB_SUCCESS ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "osm_mcast_mgr_process_mgrp: ERR 0A19: " + "Unable to create spanning tree (%s)\n", + ib_get_err_str( status ) ); + + goto Exit; + } + + /* + Walk the switches and download the tables for each. + */ + p_sw = (osm_switch_t*)cl_qmap_head( p_sw_tbl ); + while( p_sw != (osm_switch_t*)cl_qmap_end( p_sw_tbl ) ) + { + signal = __osm_mcast_mgr_set_tbl( p_mgr, p_sw ); + if( signal == OSM_SIGNAL_DONE_PENDING ) + pending_transactions = TRUE; + + p_sw = (osm_switch_t*)cl_qmap_next( &p_sw->map_item ); + } + + mcast_mgr_dump_mcast_routes( p_mgr ); + + Exit: + OSM_LOG_EXIT( p_mgr->p_log ); + + if( pending_transactions == TRUE ) + return( OSM_SIGNAL_DONE_PENDING ); + else + return( OSM_SIGNAL_DONE ); +} + +/********************************************************************** + **********************************************************************/ +osm_signal_t +osm_mcast_mgr_process( + IN osm_mcast_mgr_t* const p_mgr ) +{ + osm_signal_t signal; + osm_switch_t* p_sw; + cl_qmap_t* p_sw_tbl; + cl_qmap_t* p_mcast_tbl; + osm_mgrp_t* p_mgrp; + ib_api_status_t status; + boolean_t pending_transactions = FALSE; + + OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_process ); + + p_sw_tbl = &p_mgr->p_subn->sw_guid_tbl; + + p_mcast_tbl = &p_mgr->p_subn->mgrp_mlid_tbl; + /* + While holding the lock, iterate over all the established + multicast groups, servicing each in turn. + + Then, download the multicast tables to the switches. + */ + CL_PLOCK_EXCL_ACQUIRE( p_mgr->p_lock ); + + p_mgrp = (osm_mgrp_t*)cl_qmap_head( p_mcast_tbl ); + while( p_mgrp != (osm_mgrp_t*)cl_qmap_end( p_mcast_tbl ) ) + { + /* We reached here due to some change that caused a heavy sweep + of the subnet. Not due to a specific multicast request. + So the request type is subnet_change and the port guid is 0. */ + status = osm_mcast_mgr_process_tree( p_mgr, p_mgrp, + OSM_MCAST_REQ_TYPE_SUBNET_CHANGE, 0); + if( status != IB_SUCCESS ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "osm_mcast_mgr_process: ERR 0A20: " + "Unable to create spanning tree (%s)\n", + ib_get_err_str( status ) ); + } + + p_mgrp = (osm_mgrp_t*)cl_qmap_next( &p_mgrp->map_item ); + } + + /* + Walk the switches and download the tables for each. + */ + p_sw = (osm_switch_t*)cl_qmap_head( p_sw_tbl ); + while( p_sw != (osm_switch_t*)cl_qmap_end( p_sw_tbl ) ) + { + signal = __osm_mcast_mgr_set_tbl( p_mgr, p_sw ); + if( signal == OSM_SIGNAL_DONE_PENDING ) + pending_transactions = TRUE; + + p_sw = (osm_switch_t*)cl_qmap_next( &p_sw->map_item ); + } + + mcast_mgr_dump_mcast_routes( p_mgr ); + + CL_PLOCK_RELEASE( p_mgr->p_lock ); + + OSM_LOG_EXIT( p_mgr->p_log ); + + if( pending_transactions == TRUE ) + return( OSM_SIGNAL_DONE_PENDING ); + else + return( OSM_SIGNAL_DONE ); +} + +/********************************************************************** + **********************************************************************/ +static +osm_mgrp_t * +__get_mgrp_by_mlid( + IN osm_mcast_mgr_t* const p_mgr, + IN ib_net16_t const mlid) +{ + cl_map_item_t *map_item; + + map_item = cl_qmap_get(&p_mgr->p_subn->mgrp_mlid_tbl, mlid); + if(map_item == cl_qmap_end(&p_mgr->p_subn->mgrp_mlid_tbl)) + { + return NULL; + } + return (osm_mgrp_t *)map_item; +} + +/********************************************************************** + This is the function that is invoked during idle time to handle the + process request. Context1 is simply the osm_mcast_mgr_t*, Context2 + hold the mlid, port guid and action (join/leave/delete) required. + **********************************************************************/ +osm_signal_t +osm_mcast_mgr_process_mgrp_cb( + IN void* const Context1, + IN void* const Context2 ) +{ + osm_mcast_mgr_t* p_mgr = (osm_mcast_mgr_t*)Context1; + osm_mgrp_t* p_mgrp; + ib_net16_t mlid; + osm_signal_t signal = OSM_SIGNAL_DONE; + osm_mcast_mgr_ctxt_t* p_ctxt = (osm_mcast_mgr_ctxt_t*)Context2; + osm_mcast_req_type_t req_type = p_ctxt->req_type; + ib_net64_t port_guid = p_ctxt->port_guid; + + OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_process_mgrp_cb ); + + /* nice copy no warning on size diff */ + memcpy(&mlid, &p_ctxt->mlid, sizeof(mlid)); + + /* we can destroy the context now */ + free(p_ctxt); + + /* we need a lock to make sure the p_mgrp is not change other ways */ + CL_PLOCK_EXCL_ACQUIRE( p_mgr->p_lock ); + p_mgrp = __get_mgrp_by_mlid( p_mgr, mlid); + + /* since we delayed the execution we prefer to pass the + mlid as the mgrp identifier and then find it or abort */ + + if (p_mgrp) + { + + /* if there was no change from the last time we processed the group + we can skip doing anything + */ + if ( p_mgrp->last_change_id == p_mgrp->last_tree_id) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "osm_mcast_mgr_process_mgrp_cb: " + "Skip processing mgrp with lid:0x%X change id:%u\n", + cl_ntoh16(mlid), p_mgrp->last_change_id ); + } + else + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "osm_mcast_mgr_process_mgrp_cb: " + "Processing mgrp with lid:0x%X change id:%u\n", + cl_ntoh16(mlid), p_mgrp->last_change_id ); + + signal = + osm_mcast_mgr_process_mgrp( p_mgr, p_mgrp, req_type, port_guid ); + p_mgrp->last_tree_id = p_mgrp->last_change_id; + } + + /* Remove MGRP only if osm_mcm_port_t count is 0 and + * Not a well known group + */ + if((0x0 == cl_qmap_count(&p_mgrp->mcm_port_tbl)) && + (p_mgrp->well_known == FALSE)) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "osm_mcast_mgr_process_mgrp_cb: " + "Destroying mgrp with lid:0x%X\n", + cl_ntoh16(mlid) ); + + /* Send a Report to any InformInfo registered for + Trap 67 : MCGroup delete */ + osm_mgrp_send_delete_notice( p_mgr->p_subn, p_mgr->p_log, p_mgrp ); + + cl_qmap_remove_item(&p_mgr->p_subn->mgrp_mlid_tbl, + (cl_map_item_t *)p_mgrp ); + + osm_mgrp_destroy(p_mgrp); + } + } + + CL_PLOCK_RELEASE( p_mgr->p_lock ); + OSM_LOG_EXIT( p_mgr->p_log ); + return signal; +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcast_tbl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcast_tbl.c new file mode 100644 index 00000000..e60229ca --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcast_tbl.c @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_mcast_tbl.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Implementation of osm_mcast_tbl_t. + * This object represents an multicast forwarding table. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include + + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_mcast_tbl_init( + IN osm_mcast_tbl_t* const p_tbl, + IN uint8_t const num_ports, + IN uint16_t const capacity ) +{ + CL_ASSERT( p_tbl ); + CL_ASSERT( num_ports ); + + memset( p_tbl, 0, sizeof(*p_tbl) ); + + p_tbl->max_block_in_use = -1; + + if( capacity == 0 ) + { + /* + This switch apparently doesn't support multicast. + Everything is initialized to zero already, so return. + */ + return( IB_SUCCESS ); + } + + p_tbl->num_entries = capacity; + p_tbl->num_ports = num_ports; + p_tbl->max_position = (uint8_t)((ROUNDUP( num_ports, IB_MCAST_MASK_SIZE) / + IB_MCAST_MASK_SIZE) - 1); + + p_tbl->max_block = (uint16_t)((ROUNDUP( p_tbl->num_entries, + IB_MCAST_BLOCK_SIZE ) / IB_MCAST_BLOCK_SIZE) - 1); + + p_tbl->max_mlid_ho = (uint16_t)(IB_LID_MCAST_START_HO + capacity); + + /* + The number of bytes needed in the mask table is: + The (maximum bit mask 'position' + 1) times the + number of bytes in each bit mask times the + number of MLIDs supported by the table. + + We must always allocate the array with the maximum position + since it is (and must be) defined that way the table structure + in order to create a pointer to a two dimensional array. + */ + p_tbl->p_mask_tbl = malloc( p_tbl->num_entries * + (IB_MCAST_POSITION_MAX + 1) * IB_MCAST_MASK_SIZE / 8 ); + + if( p_tbl->p_mask_tbl == NULL ) + return( IB_INSUFFICIENT_MEMORY ); + + memset(p_tbl->p_mask_tbl, 0, + p_tbl->num_entries * (IB_MCAST_POSITION_MAX + 1) * IB_MCAST_MASK_SIZE / 8 ); + return( IB_SUCCESS ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_mcast_tbl_destroy( + IN osm_mcast_tbl_t* const p_tbl ) +{ + free( p_tbl->p_mask_tbl ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_mcast_tbl_set( + IN osm_mcast_tbl_t* const p_tbl, + IN const uint16_t mlid_ho, + IN const uint8_t port ) +{ + uintn_t mlid_offset; + uintn_t mask_offset; + uintn_t bit_mask; + int16_t block_num; + + CL_ASSERT( p_tbl ); + CL_ASSERT( mlid_ho >= IB_LID_MCAST_START_HO ); + CL_ASSERT( mlid_ho <= p_tbl->max_mlid_ho ); + CL_ASSERT( p_tbl->p_mask_tbl ); + + mlid_offset = mlid_ho - IB_LID_MCAST_START_HO; + mask_offset = port / IB_MCAST_MASK_SIZE; + bit_mask = cl_ntoh16( (uint16_t)( 1 << (port % IB_MCAST_MASK_SIZE) ) ); + (*p_tbl->p_mask_tbl)[mlid_offset][mask_offset] |= bit_mask; + + block_num = (int16_t)(mlid_offset / IB_MCAST_BLOCK_SIZE); + + if( block_num > p_tbl->max_block_in_use ) + p_tbl->max_block_in_use = (uint16_t)block_num; +} + +/********************************************************************** + **********************************************************************/ +boolean_t +osm_mcast_tbl_is_port( + IN const osm_mcast_tbl_t* const p_tbl, + IN const uint16_t mlid_ho, + IN const uint8_t port_num ) +{ + uintn_t mlid_offset; + uintn_t mask_offset; + uintn_t bit_mask; + + CL_ASSERT( p_tbl ); + + if( p_tbl->p_mask_tbl ) + { + CL_ASSERT( port_num <= (p_tbl->max_position + 1) * IB_MCAST_MASK_SIZE ); + CL_ASSERT( mlid_ho >= IB_LID_MCAST_START_HO ); + CL_ASSERT( mlid_ho <= p_tbl->max_mlid_ho ); + + mlid_offset = mlid_ho - IB_LID_MCAST_START_HO; + mask_offset = port_num / IB_MCAST_MASK_SIZE; + bit_mask = cl_ntoh16( + (uint16_t)( 1 << (port_num % IB_MCAST_MASK_SIZE) ) ); + return( ((*p_tbl->p_mask_tbl)[mlid_offset][mask_offset] & bit_mask) == + bit_mask ); + } + + return( FALSE ); +} + +/********************************************************************** + **********************************************************************/ +boolean_t +osm_mcast_tbl_is_any_port( + IN const osm_mcast_tbl_t* const p_tbl, + IN const uint16_t mlid_ho ) +{ + uintn_t mlid_offset; + uint8_t position; + uint16_t result = 0; + + CL_ASSERT( p_tbl ); + + if( p_tbl->p_mask_tbl ) + { + CL_ASSERT( mlid_ho >= IB_LID_MCAST_START_HO ); + CL_ASSERT( mlid_ho <= p_tbl->max_mlid_ho ); + + mlid_offset = mlid_ho - IB_LID_MCAST_START_HO; + + for( position = 0; position <= p_tbl->max_position; position++ ) + result |= (*p_tbl->p_mask_tbl)[mlid_offset][position]; + } + + return( result != 0 ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_mcast_tbl_set_block( + IN osm_mcast_tbl_t* const p_tbl, + IN const ib_net16_t* const p_block, + IN const int16_t block_num, + IN const uint8_t position ) +{ + uint32_t i; + uint16_t mlid_start_ho; + + CL_ASSERT( p_tbl ); + CL_ASSERT( p_block ); + + if( block_num > p_tbl->max_block ) + return( IB_INVALID_PARAMETER ); + + if( position > p_tbl->max_position ) + return( IB_INVALID_PARAMETER ); + + mlid_start_ho = (uint16_t)(block_num * IB_MCAST_BLOCK_SIZE); + + if( mlid_start_ho + IB_MCAST_BLOCK_SIZE > p_tbl->max_mlid_ho ) + return( IB_INVALID_PARAMETER ); + + for( i = 0; i < IB_MCAST_BLOCK_SIZE; i++ ) + (*p_tbl->p_mask_tbl)[mlid_start_ho + i][position] = p_block[i]; + + if( block_num > p_tbl->max_block_in_use ) + p_tbl->max_block_in_use = (uint16_t)block_num; + + return( IB_SUCCESS ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_mcast_tbl_clear_mlid( + IN osm_mcast_tbl_t* const p_tbl, + IN const uint16_t mlid_ho ) +{ + uint8_t i; + uintn_t mlid_offset; + + CL_ASSERT( p_tbl ); + CL_ASSERT( mlid_ho >= IB_LID_MCAST_START_HO ); + + if( p_tbl->p_mask_tbl && (mlid_ho <= p_tbl->max_mlid_ho) ) + { + mlid_offset = mlid_ho - IB_LID_MCAST_START_HO; + for( i = 0; i <= p_tbl->max_position; i++ ) + (*p_tbl->p_mask_tbl)[mlid_offset][i] = 0; + } +} + +/********************************************************************** + **********************************************************************/ +boolean_t +osm_mcast_tbl_get_block( + IN osm_mcast_tbl_t* const p_tbl, + IN int16_t const block_num, + IN uint8_t const position, + OUT ib_net16_t* const p_block ) +{ + uint32_t i; + uint16_t mlid_start_ho; + + CL_ASSERT( p_tbl ); + CL_ASSERT( p_block ); + + if( block_num > p_tbl->max_block_in_use ) + return( FALSE ); + + if( position > p_tbl->max_position ) + { + /* + Caller shouldn't do this for efficiency's sake... + */ + memset( p_block, 0, IB_SMP_DATA_SIZE ); + return( TRUE ); + } + + mlid_start_ho = (uint16_t)(block_num * IB_MCAST_BLOCK_SIZE); + + if( mlid_start_ho + IB_MCAST_BLOCK_SIZE > p_tbl->max_mlid_ho ) + return( IB_INVALID_PARAMETER ); + + for( i = 0; i < IB_MCAST_BLOCK_SIZE; i++ ) + p_block[i] = (*p_tbl->p_mask_tbl)[mlid_start_ho + i][position]; + + return( TRUE ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcm_info.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcm_info.c new file mode 100644 index 00000000..770aa040 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcm_info.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_mcm_info.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Declaration of osm_mcm_info_t. + * This object represents a Multicast Forwarding Information object. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include + +/********************************************************************** + **********************************************************************/ +void +osm_mcm_info_destroy( + IN osm_mcm_info_t* const p_mcm ) +{ + CL_ASSERT( p_mcm ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_mcm_info_init( + IN osm_mcm_info_t* const p_mcm, + IN const ib_net16_t mlid ) +{ + CL_ASSERT( p_mcm ); + p_mcm->mlid = mlid; +} + +/********************************************************************** + **********************************************************************/ +osm_mcm_info_t* +osm_mcm_info_new( + IN const ib_net16_t mlid ) +{ + osm_mcm_info_t* p_mcm; + + p_mcm = (osm_mcm_info_t*)malloc( sizeof(*p_mcm) ); + if( p_mcm ) + { + memset(p_mcm, 0, sizeof(*p_mcm) ); + osm_mcm_info_init( p_mcm, mlid ); + } + + return( p_mcm ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_mcm_info_delete( + IN osm_mcm_info_t* const p_mcm ) +{ + osm_mcm_info_destroy( p_mcm ); + free( p_mcm ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcm_port.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcm_port.c new file mode 100644 index 00000000..5996ac96 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcm_port.c @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_mcm_port.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_mcm_port_t. + * This object represents the membership of a port in a multicast group. + * This object is part of the OpenSM family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +osm_mcm_port_construct( + IN osm_mcm_port_t* const p_mcm ) +{ + memset( p_mcm, 0, sizeof(*p_mcm) ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_mcm_port_destroy( + IN osm_mcm_port_t* const p_mcm ) +{ + /* + Nothing to do? + */ + UNUSED_PARAM( p_mcm ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_mcm_port_init( + IN osm_mcm_port_t* const p_mcm, + IN const ib_gid_t* const p_port_gid, + IN const uint8_t scope_state, + IN const boolean_t proxy_join ) +{ + CL_ASSERT( p_mcm ); + CL_ASSERT( p_port_gid ); + CL_ASSERT( scope_state ); + + osm_mcm_port_construct( p_mcm ); + p_mcm->port_gid = *p_port_gid; + p_mcm->scope_state = scope_state; + p_mcm->proxy_join = proxy_join; +} + +/********************************************************************** + **********************************************************************/ +osm_mcm_port_t* +osm_mcm_port_new( + IN const ib_gid_t* const p_port_gid, + IN const uint8_t scope_state, + IN const boolean_t proxy_join ) +{ + osm_mcm_port_t* p_mcm; + + p_mcm = malloc( sizeof(*p_mcm) ); + if( p_mcm ) + { + osm_mcm_port_init( p_mcm, p_port_gid, + scope_state, proxy_join ); + } + + return( p_mcm ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_mcm_port_delete( + IN osm_mcm_port_t* const p_mcm ) +{ + CL_ASSERT( p_mcm ); + + osm_mcm_port_destroy( p_mcm ); + free( p_mcm ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mtree.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mtree.c new file mode 100644 index 00000000..16283a09 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mtree.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_mtree.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_mtree_node_t. + * This file implements the Multicast Tree object. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +osm_mtree_node_init( + IN osm_mtree_node_t* const p_mtn, + IN const osm_switch_t* const p_sw ) +{ + uint32_t i; + + CL_ASSERT( p_mtn ); + CL_ASSERT( p_sw ); + + osm_mtree_node_construct( p_mtn ); + + p_mtn->p_sw = (osm_switch_t*)p_sw; + p_mtn->max_children = osm_switch_get_num_ports( p_sw ); + + for( i = 0; i < p_mtn->max_children; i++ ) + p_mtn->child_array[i] = NULL; +} + +/********************************************************************** + **********************************************************************/ +osm_mtree_node_t* +osm_mtree_node_new( + IN const osm_switch_t* const p_sw ) +{ + osm_mtree_node_t *p_mtn; + + p_mtn = malloc( sizeof(osm_mtree_node_t) + + sizeof(void*) * (osm_switch_get_num_ports( p_sw ) - 1) ); + + if( p_mtn != NULL ) + osm_mtree_node_init( p_mtn, p_sw ); + + return( p_mtn ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_mtree_destroy( + IN osm_mtree_node_t *p_mtn ) +{ + uint32_t i; + + if (p_mtn == NULL) + return; + + if ( p_mtn->child_array != NULL ) + for (i = 0 ; i< p_mtn->max_children; i++ ) + if ( (p_mtn->child_array[i] != NULL) && + (p_mtn->child_array[i] != OSM_MTREE_LEAF) ) + osm_mtree_destroy(p_mtn->child_array[i]); + + free( p_mtn ); +} + +/********************************************************************** + **********************************************************************/ +void +__osm_mtree_dump( + IN osm_mtree_node_t *p_mtn ) +{ + uint32_t i; + + if (p_mtn == NULL) + return; + + printf("GUID:0x%016" PRIx64 " max_children:%u\n", + cl_ntoh64(p_mtn->p_sw->p_node->node_info.node_guid), + p_mtn->max_children ); + if ( p_mtn->child_array != NULL ) + { + for (i = 0 ; i< p_mtn->max_children; i++ ) + { + printf("i=%d\n", i); + if ( (p_mtn->child_array[i] != NULL) && (p_mtn->child_array[i] != OSM_MTREE_LEAF) ) + __osm_mtree_dump(p_mtn->child_array[i]); + } + } +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_multicast.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_multicast.c new file mode 100644 index 00000000..858685d4 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_multicast.c @@ -0,0 +1,403 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_multicast.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Implementation of multicast functions. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +/* osm_mcast_req_type_t values converted to test for easier printing. */ +const char* osm_mcast_req_type_str[] = +{ + "OSM_MCAST_REQ_TYPE_CREATE", + "OSM_MCAST_REQ_TYPE_JOIN", + "OSM_MCAST_REQ_TYPE_LEAVE", + "OSM_MCAST_REQ_TYPE_SUBNET_CHANGE" +}; + +const char* +osm_get_mcast_req_type_str( + IN osm_mcast_req_type_t req_type ) +{ + if ( req_type > OSM_MCAST_REQ_TYPE_SUBNET_CHANGE ) + req_type = OSM_MCAST_REQ_TYPE_SUBNET_CHANGE; + return( osm_mcast_req_type_str[req_type] ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_mgrp_construct( + IN osm_mgrp_t* const p_mgrp ) +{ + memset( p_mgrp, 0, sizeof(*p_mgrp) ); + cl_qmap_init( &p_mgrp->mcm_port_tbl ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_mgrp_destroy( + IN osm_mgrp_t* const p_mgrp ) +{ + osm_mcm_port_t *p_mcm_port; + osm_mcm_port_t *p_next_mcm_port; + + CL_ASSERT(p_mgrp); + + p_next_mcm_port = (osm_mcm_port_t*)cl_qmap_head( &p_mgrp->mcm_port_tbl ); + while( p_next_mcm_port != (osm_mcm_port_t*)cl_qmap_end( &p_mgrp->mcm_port_tbl ) ) + { + p_mcm_port = p_next_mcm_port; + p_next_mcm_port = (osm_mcm_port_t*)cl_qmap_next( &p_mcm_port->map_item ); + osm_mcm_port_delete( p_mcm_port ); + } + /* destroy the mtree_node structure */ + osm_mtree_destroy(p_mgrp->p_root); + + free(p_mgrp); +} + +/********************************************************************** + **********************************************************************/ +void +osm_mgrp_init( + IN osm_mgrp_t* const p_mgrp, + IN const ib_net16_t mlid ) +{ + CL_ASSERT( p_mgrp ); + CL_ASSERT( cl_ntoh16( mlid ) >= IB_LID_MCAST_START_HO ); + + osm_mgrp_construct( p_mgrp ); + p_mgrp->mlid = mlid; + p_mgrp->last_change_id = 0; + p_mgrp->last_tree_id = 0; + p_mgrp->to_be_deleted = FALSE; +} + +/********************************************************************** + **********************************************************************/ +osm_mgrp_t* +osm_mgrp_new( + IN const ib_net16_t mlid ) +{ + osm_mgrp_t* p_mgrp; + + p_mgrp = (osm_mgrp_t*)malloc( sizeof(*p_mgrp) ); + if( p_mgrp ) + osm_mgrp_init( p_mgrp, mlid ); + + return( p_mgrp ); +} + +/********************************************************************** + **********************************************************************/ +osm_mcm_port_t* +osm_mgrp_add_port( + IN osm_mgrp_t* const p_mgrp, + IN const ib_gid_t* const p_port_gid, + IN const uint8_t join_state, + IN boolean_t proxy_join ) +{ + ib_net64_t port_guid; + osm_mcm_port_t *p_mcm_port; + cl_map_item_t *prev_item; + uint8_t prev_join_state; + uint8_t prev_scope; + + p_mcm_port = osm_mcm_port_new( p_port_gid, join_state, proxy_join ); + if( p_mcm_port ) + { + port_guid = p_port_gid->unicast.interface_id; + + /* + prev_item = cl_qmap_insert(...) + Pointer to the item in the map with the specified key. If insertion + was successful, this is the pointer to the item. If an item with the + specified key already exists in the map, the pointer to that item is + returned. + */ + prev_item = cl_qmap_insert( &p_mgrp->mcm_port_tbl, + port_guid, &p_mcm_port->map_item ); + + /* if already exists - revert the insertion and only update join state */ + if( prev_item != &p_mcm_port->map_item ) + { + + osm_mcm_port_delete( p_mcm_port ); + p_mcm_port =(osm_mcm_port_t *) prev_item; + + /* + o15.0.1.11 + Join state of the end port should be the or of the + previous setting with the current one + */ + ib_member_get_scope_state(p_mcm_port->scope_state, &prev_scope, &prev_join_state); + p_mcm_port->scope_state = + ib_member_set_scope_state(prev_scope, prev_join_state | join_state); + + } + else + { + /* track the fact we modified the group ports */ + p_mgrp->last_change_id++; + } + } + + return( p_mcm_port ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_mgrp_remove_port( + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN osm_mgrp_t* const p_mgrp, + IN const ib_net64_t port_guid ) +{ + cl_map_item_t *p_map_item; + + CL_ASSERT(p_mgrp); + + p_map_item = cl_qmap_get( &p_mgrp->mcm_port_tbl, port_guid ); + + if( p_map_item != cl_qmap_end( &p_mgrp->mcm_port_tbl ) ) + { + cl_qmap_remove_item( &p_mgrp->mcm_port_tbl, + p_map_item ); + osm_mcm_port_delete((osm_mcm_port_t*)p_map_item); + + /* track the fact we modified the group */ + p_mgrp->last_change_id++; + } + + /* + no more ports so the group will be deleted after re-route + but only if it is not a well known group and not already deleted + */ + if ((cl_is_qmap_empty( &p_mgrp->mcm_port_tbl )) && + (p_mgrp->well_known == FALSE) && + (p_mgrp->to_be_deleted == FALSE)) + { + p_mgrp->to_be_deleted = TRUE; + + /* Send a Report to any InformInfo registered for + Trap 67 : MCGroup delete */ + osm_mgrp_send_delete_notice( p_subn, p_log, p_mgrp ); + } +} + +/********************************************************************** + **********************************************************************/ +boolean_t +osm_mgrp_is_port_present( + IN const osm_mgrp_t* const p_mgrp, + IN const ib_net64_t port_guid, + OUT osm_mcm_port_t ** const pp_mcm_port ) +{ + cl_map_item_t *p_map_item; + + CL_ASSERT(p_mgrp); + + p_map_item = cl_qmap_get(&p_mgrp->mcm_port_tbl, + port_guid); + + if (p_map_item != cl_qmap_end(&p_mgrp->mcm_port_tbl)) + { + if (pp_mcm_port) + *pp_mcm_port = (osm_mcm_port_t *)p_map_item; + return TRUE; + } + if (pp_mcm_port) + *pp_mcm_port = NULL; + return FALSE; +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_mgrp_apply_func_sub( + const osm_mgrp_t* const p_mgrp, + const osm_mtree_node_t* const p_mtn, + osm_mgrp_func_t p_func, + void* context ) +{ + uint8_t i = 0; + uint8_t max_children; + osm_mtree_node_t* p_child_mtn; + + /* + Call the user, then recurse. + */ + p_func( p_mgrp, p_mtn, context ); + + max_children = osm_mtree_node_get_max_children( p_mtn ); + for( i = 0; i < max_children; i++ ) + { + p_child_mtn = osm_mtree_node_get_child( p_mtn, i ); + if( p_child_mtn ) + __osm_mgrp_apply_func_sub( p_mgrp, p_child_mtn, p_func, context ); + } +} + +/********************************************************************** + **********************************************************************/ +void +osm_mgrp_apply_func( + const osm_mgrp_t* const p_mgrp, + osm_mgrp_func_t p_func, + void* context ) +{ + osm_mtree_node_t* p_mtn; + + CL_ASSERT( p_mgrp ); + CL_ASSERT( p_func ); + + p_mtn = p_mgrp->p_root; + + if( p_mtn ) + __osm_mgrp_apply_func_sub( p_mgrp, p_mtn, p_func, context ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_mgrp_send_delete_notice( + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN osm_mgrp_t *p_mgrp ) +{ + ib_mad_notice_attr_t notice; + ib_api_status_t status; + + OSM_LOG_ENTER( p_log, osm_mgrp_send_delete_notice ); + + /* prepare the needed info */ + + /* details of the notice */ + notice.generic_type = 0x83; /* is generic subn mgt type */ + ib_notice_set_prod_type_ho(¬ice, 4); /* A Class Manager generator */ + notice.g_or_v.generic.trap_num = CL_HTON16(67); /* delete of mcg */ + /* The sm_base_lid is saved in network order already. */ + notice.issuer_lid = p_subn->sm_base_lid; + /* following o14-12.1.11 and table 120 p726 */ + /* we need to provide the MGID */ + memcpy(&(notice.data_details.ntc_64_67.gid), + &(p_mgrp->mcmember_rec.mgid), + sizeof(ib_gid_t)); + + /* According to page 653 - the issuer gid in this case of trap + is the SM gid, since the SM is the initiator of this trap. */ + notice.issuer_gid.unicast.prefix = p_subn->opt.subnet_prefix; + notice.issuer_gid.unicast.interface_id = p_subn->sm_port_guid; + + status = osm_report_notice(p_log, p_subn, ¬ice); + if( status != IB_SUCCESS ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_mgrp_send_delete_notice: ERR 7601: " + "Error sending trap reports (%s)\n", + ib_get_err_str( status ) ); + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_mgrp_send_create_notice( + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN osm_mgrp_t *p_mgrp ) +{ + ib_mad_notice_attr_t notice; + ib_api_status_t status; + + OSM_LOG_ENTER( p_log, osm_mgrp_send_create_notice ); + + /* prepare the needed info */ + + /* details of the notice */ + notice.generic_type = 0x83; /* Generic SubnMgt type */ + ib_notice_set_prod_type_ho(¬ice, 4); /* A Class Manager generator */ + notice.g_or_v.generic.trap_num = CL_HTON16(66); /* create of mcg */ + /* The sm_base_lid is saved in network order already. */ + notice.issuer_lid = p_subn->sm_base_lid; + /* following o14-12.1.11 and table 120 p726 */ + /* we need to provide the MGID */ + memcpy(&(notice.data_details.ntc_64_67.gid), + &(p_mgrp->mcmember_rec.mgid), + sizeof(ib_gid_t)); + + /* According to page 653 - the issuer gid in this case of trap + is the SM gid, since the SM is the initiator of this trap. */ + notice.issuer_gid.unicast.prefix = p_subn->opt.subnet_prefix; + notice.issuer_gid.unicast.interface_id = p_subn->sm_port_guid; + + status = osm_report_notice(p_log, p_subn, ¬ice); + if( status != IB_SUCCESS ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_mgrp_send_create_notice: ERR 7602: " + "Error sending trap reports (%s)\n", + ib_get_err_str( status ) ); + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_node.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_node.c new file mode 100644 index 00000000..72a77c77 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_node.c @@ -0,0 +1,335 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_node.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_node_t. + * This object represents an Infiniband Node. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +osm_node_init_physp( + IN osm_node_t* const p_node, + IN const osm_madw_t* const p_madw ) +{ + osm_physp_t *p_physp; + ib_net64_t port_guid; + ib_smp_t *p_smp; + ib_node_info_t *p_ni; + uint8_t port_num; + + CL_ASSERT( p_node ); + CL_ASSERT( p_madw ); + + p_smp = osm_madw_get_smp_ptr( p_madw ); + + CL_ASSERT( p_smp->attr_id == IB_MAD_ATTR_NODE_INFO ); + + p_ni = (ib_node_info_t*)ib_smp_get_payload_ptr( p_smp ); + port_guid = p_ni->port_guid; + port_num = ib_node_info_get_local_port_num( p_ni ); + + CL_ASSERT( port_num < p_node->physp_tbl_size ); + + p_physp = osm_node_get_physp_ptr( p_node, port_num ); + + osm_physp_init( p_physp, port_guid, port_num, p_node, + osm_madw_get_bind_handle( p_madw ), + p_smp->hop_count, p_smp->initial_path ); +} + +/********************************************************************** + **********************************************************************/ +osm_node_t* +osm_node_new( + IN const osm_madw_t* const p_madw ) +{ + osm_node_t *p_node; + ib_smp_t *p_smp; + ib_node_info_t *p_ni; + uint8_t i; + uint32_t size; + + CL_ASSERT( p_madw ); + + p_smp = osm_madw_get_smp_ptr( p_madw ); + + CL_ASSERT( p_smp->attr_id == IB_MAD_ATTR_NODE_INFO ); + + p_ni = (ib_node_info_t*)ib_smp_get_payload_ptr( p_smp ); + + /* + The node object already contains one physical port object. + Therefore, subtract 1 from the number of physical ports + used by the switch. This is not done for CA's since they + need to occupy 1 more physp than they physically have since + we still reserve room for a "port 0". + */ + size = p_ni->num_ports; + + p_node = malloc( sizeof(*p_node) + sizeof(osm_physp_t) * size ); + if( p_node != NULL ) + { + memset( p_node, 0, sizeof(*p_node) + sizeof(osm_physp_t) * size ); + p_node->node_info = *p_ni; + p_node->physp_tbl_size = size + 1; + + /* + Construct Physical Port objects owned by this Node. + Then, initialize the Physical Port through with we + discovered this port. + For switches, all ports have the same GUID. + For HCA's each port has a different GUID, so we only + know the GUID for the port that responded to our + Get(NodeInfo). + */ + for( i = 0; i < p_node->physp_tbl_size; i++ ) + osm_physp_construct( osm_node_get_physp_ptr( p_node, i ) ); + + osm_node_init_physp( p_node, p_madw ); + } + + return( p_node ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_node_destroy( + IN osm_node_t *p_node ) +{ + uint16_t i; + + /* Cleanup all PhysPorts */ + if( p_node != NULL ) + { + /* + Cleanup all physports + */ + for( i = 0; i < p_node->physp_tbl_size; i++ ) + { + osm_physp_t *p_physp = osm_node_get_physp_ptr( p_node, i ); + if (p_physp) + osm_physp_destroy( p_physp ); + } + } +} + +/********************************************************************** + **********************************************************************/ +void +osm_node_delete( + IN OUT osm_node_t** const p_node ) +{ + osm_node_destroy( *p_node ); + free( *p_node ); + *p_node = NULL; +} + +/********************************************************************** + **********************************************************************/ +void +osm_node_link( + IN osm_node_t* const p_node, + IN const uint8_t port_num, + IN osm_node_t* const p_remote_node, + IN const uint8_t remote_port_num ) +{ + osm_physp_t *p_physp; + osm_physp_t *p_remote_physp; + + CL_ASSERT( port_num < p_node->physp_tbl_size ); + CL_ASSERT( remote_port_num < p_remote_node->physp_tbl_size ); + + p_physp = osm_node_get_physp_ptr( p_node, port_num ); + p_remote_physp = osm_node_get_physp_ptr( p_remote_node, + remote_port_num ); + + if (p_physp->p_remote_physp) + p_physp->p_remote_physp->p_remote_physp = NULL; + if (p_remote_physp->p_remote_physp) + p_remote_physp->p_remote_physp->p_remote_physp = NULL; + + osm_physp_link( p_physp, p_remote_physp ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_node_unlink( + IN osm_node_t* const p_node, + IN const uint8_t port_num, + IN osm_node_t* const p_remote_node, + IN const uint8_t remote_port_num ) +{ + osm_physp_t *p_physp; + osm_physp_t *p_remote_physp; + + CL_ASSERT( port_num < p_node->physp_tbl_size ); + CL_ASSERT( remote_port_num < p_remote_node->physp_tbl_size ); + + if( osm_node_link_exists( p_node, port_num, + p_remote_node, remote_port_num ) ) + { + + p_physp = osm_node_get_physp_ptr( p_node, port_num ); + p_remote_physp = osm_node_get_physp_ptr( p_remote_node, + remote_port_num ); + + osm_physp_unlink( p_physp, p_remote_physp ); + } +} + +/********************************************************************** + **********************************************************************/ +boolean_t +osm_node_link_exists( + IN osm_node_t* const p_node, + IN const uint8_t port_num, + IN osm_node_t* const p_remote_node, + IN const uint8_t remote_port_num ) +{ + osm_physp_t *p_physp; + osm_physp_t *p_remote_physp; + + CL_ASSERT( port_num < p_node->physp_tbl_size ); + CL_ASSERT( remote_port_num < p_remote_node->physp_tbl_size ); + + p_physp = osm_node_get_physp_ptr( p_node, port_num ); + p_remote_physp = osm_node_get_physp_ptr( p_remote_node, + remote_port_num ); + + return( osm_physp_link_exists( p_physp, p_remote_physp ) ); +} + +/********************************************************************** + **********************************************************************/ +boolean_t +osm_node_link_has_valid_ports( + IN osm_node_t* const p_node, + IN const uint8_t port_num, + IN osm_node_t* const p_remote_node, + IN const uint8_t remote_port_num ) +{ + osm_physp_t *p_physp; + osm_physp_t *p_remote_physp; + + CL_ASSERT( port_num < p_node->physp_tbl_size ); + CL_ASSERT( remote_port_num < p_remote_node->physp_tbl_size ); + + p_physp = osm_node_get_physp_ptr( p_node, port_num ); + p_remote_physp = osm_node_get_physp_ptr( p_remote_node, + remote_port_num ); + + return( osm_physp_is_valid( p_physp ) && + osm_physp_is_valid( p_remote_physp ) ); +} + +/********************************************************************** + **********************************************************************/ +boolean_t +osm_node_has_any_link( + IN osm_node_t* const p_node, + IN const uint8_t port_num ) +{ + osm_physp_t *p_physp; + CL_ASSERT( port_num < p_node->physp_tbl_size ); + p_physp = osm_node_get_physp_ptr( p_node, port_num ); + return( osm_physp_has_any_link( p_physp ) ); +} + +/********************************************************************** + **********************************************************************/ +osm_node_t* +osm_node_get_remote_node( + IN const osm_node_t* const p_node, + IN const uint8_t port_num, + OUT uint8_t *p_remote_port_num ) +{ + osm_physp_t *p_physp; + osm_physp_t *p_remote_physp; + + p_physp = osm_node_get_physp_ptr( p_node, port_num ); + + if( !osm_physp_has_any_link( p_physp ) ) + return( NULL ); + + p_remote_physp = osm_physp_get_remote( p_physp ); + if( p_remote_port_num ) + *p_remote_port_num = osm_physp_get_port_num( p_remote_physp ); + + return( osm_physp_get_node_ptr( p_remote_physp ) ); +} + +/********************************************************************** + The lock must be held before calling this function. +**********************************************************************/ +ib_net16_t +osm_node_get_remote_base_lid( + IN const osm_node_t* const p_node, + IN const uint32_t port_num ) +{ + osm_physp_t *p_physp; + osm_physp_t *p_remote_physp; + CL_ASSERT( port_num < p_node->physp_tbl_size ); + + p_physp = osm_node_get_physp_ptr( p_node, port_num ); + if( osm_physp_is_valid( p_physp ) ) + { + p_remote_physp = osm_physp_get_remote( p_physp ); + return( osm_physp_get_base_lid( p_remote_physp ) ); + } + + return( 0 ); +} + + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_node_desc_rcv.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_node_desc_rcv.c new file mode 100644 index 00000000..f21c481b --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_node_desc_rcv.c @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_node_desc_rcv.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_nd_rcv_t. + * This object represents the NodeDescription Receiver object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +__osm_nd_rcv_process_nd( + IN const osm_nd_rcv_t* const p_rcv, + IN osm_node_t* const p_node, + IN const ib_node_desc_t* const p_nd ) +{ + char desc[IB_NODE_DESCRIPTION_SIZE + 1]; + OSM_LOG_ENTER( p_rcv->p_log, __osm_nd_rcv_process_nd ); + + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) ) + { + memcpy( desc, p_nd, sizeof(*p_nd) ); + /* Guarantee null termination before printing. */ + desc[IB_NODE_DESCRIPTION_SIZE] = '\0'; + + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "__osm_nd_rcv_process_nd: " + "Node 0x%" PRIx64 "\n\t\t\t\tDescription = %s\n", + cl_ntoh64( osm_node_get_node_guid( p_node )), desc ); + } + + memcpy( &p_node->node_desc.description, p_nd, sizeof(*p_nd) ); + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_nd_rcv_construct( + IN osm_nd_rcv_t* const p_rcv ) +{ + memset( p_rcv, 0, sizeof(*p_rcv) ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_nd_rcv_destroy( + IN osm_nd_rcv_t* const p_rcv ) +{ + CL_ASSERT( p_rcv ); + + OSM_LOG_ENTER( p_rcv->p_log, osm_nd_rcv_destroy ); + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_nd_rcv_init( + IN osm_nd_rcv_t* const p_rcv, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_nd_rcv_init ); + + osm_nd_rcv_construct( p_rcv ); + + p_rcv->p_log = p_log; + p_rcv->p_subn = p_subn; + p_rcv->p_lock = p_lock; + + OSM_LOG_EXIT( p_rcv->p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_nd_rcv_process( + IN const osm_nd_rcv_t* const p_rcv, + IN osm_madw_t* const p_madw ) +{ + cl_qmap_t *p_guid_tbl; + ib_node_desc_t *p_nd; + ib_smp_t *p_smp; + osm_node_t *p_node; + ib_net64_t node_guid; + + CL_ASSERT( p_rcv ); + + OSM_LOG_ENTER( p_rcv->p_log, osm_nd_rcv_process ); + + CL_ASSERT( p_madw ); + + p_guid_tbl = &p_rcv->p_subn->node_guid_tbl; + p_smp = osm_madw_get_smp_ptr( p_madw ); + p_nd = (ib_node_desc_t*)ib_smp_get_payload_ptr( p_smp ); + + /* + Acquire the node object and add the node description. + */ + + node_guid = osm_madw_get_nd_context_ptr( p_madw )->node_guid; + CL_PLOCK_EXCL_ACQUIRE( p_rcv->p_lock ); + p_node = (osm_node_t*)cl_qmap_get( p_guid_tbl, node_guid ); + + if( p_node == (osm_node_t*)cl_qmap_end( p_guid_tbl) ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_nd_rcv_process: ERR 0B01: " + "NodeDescription received for nonexistent node " + "0x%" PRIx64 "\n", cl_ntoh64(node_guid) ); + } + else + { + __osm_nd_rcv_process_nd( p_rcv, p_node, p_nd ); + } + + CL_PLOCK_RELEASE( p_rcv->p_lock ); + OSM_LOG_EXIT( p_rcv->p_log ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_node_desc_rcv_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_node_desc_rcv_ctrl.c new file mode 100644 index 00000000..1a185c7c --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_node_desc_rcv_ctrl.c @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_node_desc_rcv_ctrl.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_nd_rcv_ctrl_t. + * This object represents the NodeDescription request controller object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +__osm_nd_rcv_ctrl_disp_callback( + IN void *context, + IN void *p_data ) +{ + /* ignore return status when invoked via the dispatcher */ + osm_nd_rcv_process( ((osm_nd_rcv_ctrl_t*)context)->p_rcv, + (osm_madw_t*)p_data ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_nd_rcv_ctrl_construct( + IN osm_nd_rcv_ctrl_t* const p_ctrl ) +{ + memset( p_ctrl, 0, sizeof(*p_ctrl) ); + p_ctrl->h_disp = CL_DISP_INVALID_HANDLE; +} + +/********************************************************************** + **********************************************************************/ +void +osm_nd_rcv_ctrl_destroy( + IN osm_nd_rcv_ctrl_t* const p_ctrl ) +{ + CL_ASSERT( p_ctrl ); + cl_disp_unregister( p_ctrl->h_disp ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_nd_rcv_ctrl_init( + IN osm_nd_rcv_ctrl_t* const p_ctrl, + IN osm_nd_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_nd_rcv_ctrl_init ); + + osm_nd_rcv_ctrl_construct( p_ctrl ); + p_ctrl->p_log = p_log; + + p_ctrl->p_rcv = p_rcv; + p_ctrl->p_disp = p_disp; + + p_ctrl->h_disp = cl_disp_register( + p_disp, + OSM_MSG_MAD_NODE_DESC, + __osm_nd_rcv_ctrl_disp_callback, + p_ctrl ); + + if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_nd_rcv_ctrl_init: ERR 0C01: " + "Dispatcher registration failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return( status ); +} + + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_node_info_rcv.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_node_info_rcv.c new file mode 100644 index 00000000..038f5198 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_node_info_rcv.c @@ -0,0 +1,1090 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_node_info_rcv.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Implementation of osm_ni_rcv_t. + * This object represents the NodeInfo Receiver object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.9 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + The plock must be held before calling this function. +**********************************************************************/ +static void +__osm_ni_rcv_set_links( + IN const osm_ni_rcv_t* const p_rcv, + osm_node_t* p_node, + const uint8_t port_num, + const osm_ni_context_t* const p_ni_context ) +{ + cl_qmap_t *p_guid_tbl; + osm_node_t *p_neighbor_node; + osm_node_t *p_old_neighbor_node; + uint8_t old_neighbor_port_num; + osm_physp_t *p_physp, *p_old_physp; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_set_links ); + + /* + A special case exists in which the node we're trying to + link is our own node. In this case, the guid value in + the ni_context will be zero. + */ + if( p_ni_context->node_guid != 0 ) + { + p_guid_tbl = &p_rcv->p_subn->node_guid_tbl; + p_neighbor_node = (osm_node_t*)cl_qmap_get( p_guid_tbl, + p_ni_context->node_guid ); + if( p_neighbor_node == (osm_node_t*)cl_qmap_end( p_guid_tbl ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_ni_rcv_set_links: ERR 0D10: " + "Unexpected removal of neighbor node " + "0x%" PRIx64 "\n", + cl_ntoh64( p_ni_context->node_guid ) ); + } + else + { + /* + We have seen this neighbor node before, but we might + not have seen this port on the neighbor node before. + We should not set links to an uninitialized port on the + neighbor, so check validity up front. If it's not + valid, do nothing, since we'll see this link again + when we probe the neighbor. + */ + if( osm_node_link_has_valid_ports( p_node, port_num, + p_neighbor_node, p_ni_context->port_num ) ) + { + if( osm_node_link_exists( p_node, port_num, + p_neighbor_node, p_ni_context->port_num ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_ni_rcv_set_links: " + "Link already exists\n" ); + } + else + { + if( osm_node_has_any_link( p_node, port_num ) && + p_rcv->p_subn->force_immediate_heavy_sweep == FALSE ) + { + /* + Uh oh... + This means that we found 2 nodes with the same guid, + or a 12x link with lane reversal that is not configured correctly. + If the force_immediate_heavy_sweep == TRUE, then this might be a case + of port being moved (causing trap 128), and thus rediscovered. + In this case, just continue. There will be another heavy sweep + immediately after, when the subnet is stable again. + */ + char line[BUF_SIZE]; + char dr_new_path[BUF_SIZE]; + char dr_old_path[BUF_SIZE]; + uint32_t i; + osm_dr_path_t *p_path = NULL, *p_old_path = NULL; + + p_physp = osm_node_get_physp_ptr( p_node, port_num ); + sprintf( dr_new_path, "no_path_available" ); + if (p_physp) + { + p_path = osm_physp_get_dr_path_ptr( p_physp ); + if ( p_path ) + { + sprintf( dr_new_path, "new path:" ); + for (i = 0; i <= p_path->hop_count; i++ ) + { + sprintf( line, "[%X]", p_path->path[i] ); + strcat( dr_new_path, line ); + } + } + } + + p_old_neighbor_node = osm_node_get_remote_node( + p_node, port_num, &old_neighbor_port_num ); + p_old_physp = osm_node_get_physp_ptr( + p_old_neighbor_node, + old_neighbor_port_num); + sprintf( dr_old_path, "no_path_available" ); + if (p_old_physp) + { + p_old_path = osm_physp_get_dr_path_ptr( p_old_physp ); + if ( p_old_path ) + { + sprintf( dr_old_path, "old_path:" ); + for (i = 0; i <= p_old_path->hop_count; i++ ) + { + sprintf( line, "[%X]", p_old_path->path[i] ); + strcat( dr_old_path, line ); + } + } + } + + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_ni_rcv_set_links: ERR 0D01: " + "Found duplicated guids or 12x link " + "with lane reversal badly configured.\n" + "Overriding existing link to:" + "node 0x%" PRIx64 ", port number 0x%X connected to:\n" + "\t\t\t\told node 0x%" PRIx64 ", " + "port number 0x%X %s\n" + "\t\t\t\tnew node 0x%" PRIx64 ", " + "port number 0x%X %s\n", + cl_ntoh64( osm_node_get_node_guid( p_node ) ), + port_num, + cl_ntoh64( osm_node_get_node_guid( + p_old_neighbor_node ) ), + old_neighbor_port_num , + dr_old_path, + cl_ntoh64( p_ni_context->node_guid ), + p_ni_context->port_num, + dr_new_path + ); + + osm_log( p_rcv->p_log, OSM_LOG_SYS, + "FATAL: duplicated guids or 12x lane reversal\n"); + + if ( p_rcv->p_subn->opt.exit_on_fatal == TRUE ) + { + osm_log( p_rcv->p_log, OSM_LOG_SYS, "Exiting\n"); + exit( 1 ); + } + } + + /* + When there are only two nodes with exact same guids (connected back + to back) - the previous check for duplicated guid will not catch + them. But the link will be from the port to itself... + Enhanced Port 0 is an exception to this + */ + if ((osm_node_get_node_guid( p_node ) == p_ni_context->node_guid) && + (port_num == p_ni_context->port_num) && + (port_num != 0)) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_ni_rcv_set_links: ERR 0D18: " + "Duplicate GUID found by link from a port to itself:" + "node 0x%" PRIx64 ", port number 0x%X\n", + cl_ntoh64( osm_node_get_node_guid( p_node ) ), + port_num ); + p_physp = osm_node_get_physp_ptr( p_node, port_num ); + if (p_physp) + osm_dump_dr_path(p_rcv->p_log, + osm_physp_get_dr_path_ptr(p_physp), + OSM_LOG_ERROR); + + osm_log( p_rcv->p_log, OSM_LOG_SYS, + "Errors on subnet. Duplicate GUID found " + "by link from a port to itself. " + "See osm log for more details\n"); + + if ( p_rcv->p_subn->opt.exit_on_fatal == TRUE ) + exit( 1 ); + } + else + { + + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_ni_rcv_set_links: " + "Creating new link between: " + "\n\t\t\t\tnode 0x%" PRIx64 ", " + "port number 0x%X and" + "\n\t\t\t\tnode 0x%" PRIx64 ", " + "port number 0x%X\n", + cl_ntoh64( osm_node_get_node_guid( p_node ) ), + port_num, + cl_ntoh64( p_ni_context->node_guid ), + p_ni_context->port_num ); + } + + CL_ASSERT( osm_node_get_node_guid( p_neighbor_node ) == + p_ni_context->node_guid ); + + osm_node_link( p_node, port_num, p_neighbor_node, + p_ni_context->port_num ); + } + } + } + } + } + else + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_ni_rcv_set_links: " + "Nothing to link for our own node 0x%" PRIx64 "\n", + cl_ntoh64( osm_node_get_node_guid( p_node ) ) ); + } + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + The plock must be held before calling this function. +**********************************************************************/ +static void +__osm_ni_rcv_process_new_node( + IN const osm_ni_rcv_t* const p_rcv, + IN osm_node_t* const p_node, + IN const osm_madw_t* const p_madw ) +{ + ib_api_status_t status = IB_SUCCESS; + osm_madw_context_t context; + osm_physp_t *p_physp; + ib_node_info_t *p_ni; + ib_smp_t *p_smp; + uint8_t port_num; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_process_new_node ); + + CL_ASSERT( p_node ); + CL_ASSERT( p_madw ); + + p_smp = osm_madw_get_smp_ptr( p_madw ); + p_ni = (ib_node_info_t*)ib_smp_get_payload_ptr( p_smp ); + port_num = ib_node_info_get_local_port_num( p_ni ); + + /* + Request PortInfo & NodeDescription attributes for the port + that responded to the NodeInfo attribute. + Because this is a channel adapter or router, we are + not allowed to request PortInfo for the other ports. + Set the context union properly, so the recipient + knows which node & port are relevant. + */ + p_physp = osm_node_get_physp_ptr( p_node, port_num ); + + CL_ASSERT( p_physp ); + CL_ASSERT( osm_physp_is_valid( p_physp ) ); + CL_ASSERT( osm_madw_get_bind_handle( p_madw ) == + osm_dr_path_get_bind_handle( + osm_physp_get_dr_path_ptr( p_physp ) ) ); + + context.pi_context.node_guid = p_ni->node_guid; + context.pi_context.port_guid = p_ni->port_guid; + context.pi_context.set_method = FALSE; + context.pi_context.update_master_sm_base_lid = FALSE; + context.pi_context.ignore_errors = FALSE; + context.pi_context.light_sweep = FALSE; + context.pi_context.active_transition = FALSE; + + status = osm_req_get( p_rcv->p_gen_req, + osm_physp_get_dr_path_ptr( p_physp ), + IB_MAD_ATTR_PORT_INFO, + cl_hton32( port_num ), + CL_DISP_MSGID_NONE, + &context ); + if( status != IB_SUCCESS ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_ni_rcv_process_new_node: ERR 0D02: " + "Failure initiating PortInfo request (%s)\n", + ib_get_err_str(status)); + } + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + The plock must be held before calling this function. +**********************************************************************/ +static void +__osm_ni_rcv_get_node_desc( + IN const osm_ni_rcv_t* const p_rcv, + IN osm_node_t* const p_node, + IN const osm_madw_t* const p_madw ) +{ + ib_api_status_t status = IB_SUCCESS; + osm_madw_context_t context; + osm_physp_t *p_physp; + ib_node_info_t *p_ni; + ib_smp_t *p_smp; + uint8_t port_num; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_get_node_desc ); + + CL_ASSERT( p_node ); + CL_ASSERT( p_madw ); + + p_smp = osm_madw_get_smp_ptr( p_madw ); + p_ni = (ib_node_info_t*)ib_smp_get_payload_ptr( p_smp ); + port_num = ib_node_info_get_local_port_num( p_ni ); + + /* + Request PortInfo & NodeDescription attributes for the port + that responded to the NodeInfo attribute. + Because this is a channel adapter or router, we are + not allowed to request PortInfo for the other ports. + Set the context union properly, so the recipient + knows which node & port are relevant. + */ + p_physp = osm_node_get_physp_ptr( p_node, port_num ); + + CL_ASSERT( p_physp ); + CL_ASSERT( osm_physp_is_valid( p_physp ) ); + CL_ASSERT( osm_madw_get_bind_handle( p_madw ) == + osm_dr_path_get_bind_handle( + osm_physp_get_dr_path_ptr( p_physp ) ) ); + + context.nd_context.node_guid = osm_node_get_node_guid( p_node ); + + status = osm_req_get( p_rcv->p_gen_req, + osm_physp_get_dr_path_ptr( p_physp ), + IB_MAD_ATTR_NODE_DESC, + 0, + CL_DISP_MSGID_NONE, + &context ); + if( status != IB_SUCCESS ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_ni_rcv_get_node_desc: ERR 0D03: " + "Failure initiating NodeDescription request (%s)\n", + ib_get_err_str(status)); + } + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + The plock must be held before calling this function. +**********************************************************************/ +static void +__osm_ni_rcv_process_new_ca_or_router( + IN const osm_ni_rcv_t* const p_rcv, + IN osm_node_t* const p_node, + IN const osm_madw_t* const p_madw ) +{ + OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_process_new_ca_or_router ); + + __osm_ni_rcv_process_new_node( p_rcv, p_node, p_madw ); + + /* + A node guid of 0 is the corner case that indicates + we discovered our own node. Initialize the subnet + object with the SM's own port guid. + */ + if( osm_madw_get_ni_context_ptr( p_madw )->node_guid == 0 ) + { + p_rcv->p_subn->sm_port_guid = p_node->node_info.port_guid; + } + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + The plock must be held before calling this function. +**********************************************************************/ +static void +__osm_ni_rcv_process_existing_ca_or_router( + IN const osm_ni_rcv_t* const p_rcv, + IN osm_node_t* const p_node, + IN const osm_madw_t* const p_madw ) +{ + ib_node_info_t *p_ni; + ib_smp_t *p_smp; + osm_port_t *p_port; + osm_port_t *p_port_check; + cl_qmap_t *p_guid_tbl; + osm_madw_context_t context; + uint8_t port_num; + osm_physp_t *p_physp; + ib_api_status_t status; + osm_dr_path_t *p_dr_path; + osm_bind_handle_t h_bind; + cl_status_t cl_status; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_process_existing_ca_or_router ); + + p_smp = osm_madw_get_smp_ptr( p_madw ); + p_ni = (ib_node_info_t*)ib_smp_get_payload_ptr( p_smp ); + port_num = ib_node_info_get_local_port_num( p_ni ); + p_guid_tbl = &p_rcv->p_subn->port_guid_tbl; + h_bind = osm_madw_get_bind_handle( p_madw ); + + /* + Determine if we have encountered this node through a + previously undiscovered port. If so, build the new + port object. + */ + p_port = (osm_port_t*)cl_qmap_get( p_guid_tbl, p_ni->port_guid ); + + if( p_port == (osm_port_t*)cl_qmap_end( p_guid_tbl ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "__osm_ni_rcv_process_existing_ca_or_router: " + "Creating new port object with GUID 0x%" PRIx64 "\n", + cl_ntoh64( p_ni->port_guid ) ); + + osm_node_init_physp( p_node, p_madw ); + + p_port = osm_port_new( p_ni, p_node ); + if( p_port == NULL ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_ni_rcv_process_existing_ca_or_router: ERR 0D04: " + "Unable to create new port object\n" ); + goto Exit; + } + + /* + Add the new port object to the database. + */ + p_port_check = (osm_port_t*)cl_qmap_insert( p_guid_tbl, + p_ni->port_guid, &p_port->map_item ); + if( p_port_check != p_port ) + { + /* + We should never be here! + Somehow, this port GUID already exists in the table. + */ + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_ni_rcv_process_existing_ca_or_router: ERR 0D12: " + "Port 0x%" PRIx64 " already in the database!\n", + cl_ntoh64( p_ni->port_guid ) ); + + osm_port_delete( &p_port ); + goto Exit; + } + + /* If we are a master, then this means the port is new on the subnet. + Add it to the new_ports_list - need to send trap 64 on these ports. + The condition that we are master is true, since if we are in discovering + state (meaning we woke up from standby or we are just initializing), + then these ports may be new to us, but are not new on the subnet. + If we are master, then the subnet as we know it is the updated one, + and any new ports we encounter should cause trap 64. C14-72.1.1 */ + if ( p_rcv->p_subn->sm_state == IB_SMINFO_STATE_MASTER ) + { + cl_status = cl_list_insert_tail( &p_rcv->p_subn->new_ports_list, p_port ); + if( cl_status != CL_SUCCESS ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_ni_rcv_process_existing_ca_or_router: ERR 0D08: " + "Error %s adding to list\n", + CL_STATUS_MSG( cl_status ) ); + osm_port_delete( &p_port ); + goto Exit; + } + else + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_ni_rcv_process_existing_ca_or_router: " + "Adding port GUID:0x%016" PRIx64 " to new_ports_list\n", + cl_ntoh64(osm_node_get_node_guid( p_port->p_node )) ); + } + } + + p_physp = osm_node_get_physp_ptr( p_node, port_num ); + } + else + { + p_physp = osm_node_get_physp_ptr( p_node, port_num ); + + CL_ASSERT( p_physp ); + + if ( !osm_physp_is_valid( p_physp ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_ni_rcv_process_existing_ca_or_router: ERR 0D19: " + "Invalid physical port. Aborting discovery\n"); + goto Exit; + } + + /* + Update the DR Path to the port, + in case the old one is no longer available. + */ + p_dr_path = osm_physp_get_dr_path_ptr( p_physp ); + + osm_dr_path_init( p_dr_path, h_bind, p_smp->hop_count, + p_smp->initial_path ); + } + + context.pi_context.node_guid = p_ni->node_guid; + context.pi_context.port_guid = p_ni->port_guid; + context.pi_context.set_method = FALSE; + context.pi_context.update_master_sm_base_lid = FALSE; + context.pi_context.ignore_errors = FALSE; + context.pi_context.light_sweep = FALSE; + + status = osm_req_get( p_rcv->p_gen_req, + osm_physp_get_dr_path_ptr( p_physp ), + IB_MAD_ATTR_PORT_INFO, + cl_hton32( port_num ), + CL_DISP_MSGID_NONE, + &context ); + + if( status != IB_SUCCESS ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_ni_rcv_process_existing_ca_or_router: ERR 0D13: " + "Failure initiating PortInfo request (%s)\n", + ib_get_err_str(status)); + } + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_ni_rcv_process_switch( + IN const osm_ni_rcv_t* const p_rcv, + IN osm_node_t* const p_node, + IN const osm_madw_t* const p_madw ) +{ + ib_api_status_t status = IB_SUCCESS; + osm_madw_context_t context; + osm_dr_path_t dr_path; + ib_smp_t *p_smp; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_process_switch ); + + CL_ASSERT( p_node ); + CL_ASSERT( p_madw ); + + p_smp = osm_madw_get_smp_ptr( p_madw ); + + osm_dr_path_init( &dr_path, + osm_madw_get_bind_handle( p_madw ), + p_smp->hop_count, + p_smp->initial_path ); + + context.si_context.node_guid = osm_node_get_node_guid( p_node ); + context.si_context.set_method = FALSE; + context.si_context.light_sweep = FALSE; + + /* Request a SwitchInfo attribute */ + status = osm_req_get( p_rcv->p_gen_req, + &dr_path, + IB_MAD_ATTR_SWITCH_INFO, + 0, + CL_DISP_MSGID_NONE, + &context ); + if( status != IB_SUCCESS ) + { + /* continue despite error */ + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_ni_rcv_process_switch: ERR 0D06: " + "Failure initiating SwitchInfo request (%s)\n", + ib_get_err_str( status ) ); + } + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + The plock must be held before calling this function. +**********************************************************************/ +static void +__osm_ni_rcv_process_existing_switch( + IN const osm_ni_rcv_t* const p_rcv, + IN osm_node_t* const p_node, + IN const osm_madw_t* const p_madw ) +{ + OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_process_existing_switch ); + + /* + If this switch has already been probed during this sweep, + then don't bother reprobing it. + There is one exception - if the node has been visited, but + for some reason we don't have the switch object (this can happen + if the SwitchInfo mad didn't reach the SM) then we want + to retry to probe the switch. + */ + if( osm_node_discovery_count_get( p_node ) == 1 ) + __osm_ni_rcv_process_switch( p_rcv, p_node, p_madw ); + else + { + /* Make sure we have SwitchInfo on this node */ + if( !p_node->sw || osm_switch_discovery_count_get( p_node->sw ) == 0 ) + { + /* we don't have the SwitchInfo - retry to get it */ + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_ni_rcv_process_existing_switch: " + "Retry to get SwitchInfo on node GUID:0x%" + PRIx64 "\n", cl_ntoh64(osm_node_get_node_guid(p_node)) ); + __osm_ni_rcv_process_switch( p_rcv, p_node, p_madw ); + } + } + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + The plock must be held before calling this function. +**********************************************************************/ +static void +__osm_ni_rcv_process_new_switch( + IN const osm_ni_rcv_t* const p_rcv, + IN osm_node_t* const p_node, + IN const osm_madw_t* const p_madw ) +{ + OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_process_new_switch ); + + __osm_ni_rcv_process_switch( p_rcv, p_node, p_madw ); + + /* + A node guid of 0 is the corner case that indicates + we discovered our own node. Initialize the subnet + object with the SM's own port guid. + */ + if( osm_madw_get_ni_context_ptr( p_madw )->node_guid == 0 ) + { + p_rcv->p_subn->sm_port_guid = p_node->node_info.port_guid; + } + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + The plock must NOT be held before calling this function. +**********************************************************************/ +static void +__osm_ni_rcv_process_new( + IN const osm_ni_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ) +{ + osm_node_t *p_node; + osm_node_t *p_node_check; + osm_port_t *p_port; + osm_port_t *p_port_check; + osm_router_t *p_rtr = NULL; + osm_router_t *p_rtr_check; + cl_qmap_t *p_node_guid_tbl; + cl_qmap_t *p_port_guid_tbl; + cl_qmap_t *p_rtr_guid_tbl; + ib_node_info_t *p_ni; + ib_smp_t *p_smp; + osm_ni_context_t *p_ni_context; + uint8_t port_num; + cl_status_t status; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_process_new ); + + p_smp = osm_madw_get_smp_ptr( p_madw ); + p_ni = (ib_node_info_t*)ib_smp_get_payload_ptr( p_smp ); + p_ni_context = osm_madw_get_ni_context_ptr( p_madw ); + port_num = ib_node_info_get_local_port_num( p_ni ); + + osm_dump_smp_dr_path( p_rcv->p_log, p_smp, OSM_LOG_VERBOSE ); + + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "__osm_ni_rcv_process_new: " + "Discovered new %s node," + "\n\t\t\t\tGUID 0x%" PRIx64 ", TID 0x%" PRIx64 "\n", + ib_get_node_type_str( p_ni->node_type ), + cl_ntoh64( p_ni->node_guid ), + cl_ntoh64( p_smp->trans_id ) ); + + p_node = osm_node_new( p_madw ); + if( p_node == NULL ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_ni_rcv_process_new: ERR 0D07: " + "Unable to create new node object\n" ); + goto Exit; + } + + /* + Create a new port object to represent this node's physical + ports in the port table. + */ + p_port = osm_port_new( p_ni, p_node ); + if( p_port == NULL ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_ni_rcv_process_new: ERR 0D14: " + "Unable to create new port object\n" ); + osm_node_delete( &p_node ); + goto Exit; + } + + /* If there were RouterInfo or other router attribute, + this would be elsewhere */ + if ( p_ni->node_type == IB_NODE_TYPE_ROUTER ) + { + p_rtr = osm_router_new( p_port ); + if ( p_rtr == NULL ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_ni_rcv_process_new: ERR 0D1A: " + "Unable to create new router object\n" ); + } + } + + /* + Add the new port object to the database. + */ + p_port_guid_tbl = &p_rcv->p_subn->port_guid_tbl; + p_port_check = (osm_port_t*)cl_qmap_insert( p_port_guid_tbl, + p_ni->port_guid, + &p_port->map_item ); + if( p_port_check != p_port ) + { + /* + We should never be here! + Somehow, this port GUID already exists in the table. + */ + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_ni_rcv_process_new: ERR 0D15: " + "Duplicate Port GUID 0x%" PRIx64 "! Found by the two directed routes:\n", + cl_ntoh64( p_ni->port_guid ) ); + osm_dump_dr_path(p_rcv->p_log, + osm_physp_get_dr_path_ptr( + osm_port_get_default_phys_ptr ( p_port) ), + OSM_LOG_ERROR); + osm_dump_dr_path(p_rcv->p_log, + osm_physp_get_dr_path_ptr( + osm_port_get_default_phys_ptr ( p_port_check) ), + OSM_LOG_ERROR); + if ( p_rtr ) + osm_router_delete( &p_rtr ); + osm_port_delete( &p_port ); + osm_node_delete( &p_node ); + goto Exit; + } + + /* If we are a master, then this means the port is new on the subnet. + Add it to the new_ports_list - need to send trap 64 on these ports. + The condition that we are master is true, since if we are in discovering + state (meaning we woke up from standby or we are just initializing), + then these ports may be new to us, but are not new on the subnet. + If we are master, then the subnet as we know it is the updated one, + and any new ports we encounter should cause trap 64. C14-72.1.1 */ + if ( p_rcv->p_subn->sm_state == IB_SMINFO_STATE_MASTER ) + { + status = cl_list_insert_tail( &p_rcv->p_subn->new_ports_list, p_port ); + if( status != CL_SUCCESS ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_ni_rcv_process_new: ERR 0D05: " + "Error %s adding to new_ports_list\n", + CL_STATUS_MSG( status ) ); + if ( p_rtr ) + osm_router_delete( &p_rtr ); + osm_port_delete( &p_port ); + osm_node_delete( &p_node ); + goto Exit; + } + else + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_ni_rcv_process_new: " + "Adding port GUID:0x%016" PRIx64 " to new_ports_list\n", + cl_ntoh64( osm_node_get_node_guid( p_port->p_node ) ) ); + } + } + + if ( p_rtr && p_ni->node_type == IB_NODE_TYPE_ROUTER ) + { + p_rtr_guid_tbl = &p_rcv->p_subn->rtr_guid_tbl; + p_rtr_check = (osm_router_t*)cl_qmap_insert( p_rtr_guid_tbl, + p_ni->port_guid, + &p_rtr->map_item ); + if( p_rtr_check != p_rtr ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_ni_rcv_process_new: ERR 0D1B: " + "Unable to add port GUID:0x%016" PRIx64 " to router table\n", + cl_ntoh64( p_ni->port_guid ) ); + } + } + + p_node_guid_tbl = &p_rcv->p_subn->node_guid_tbl; + p_node_check = (osm_node_t*)cl_qmap_insert( p_node_guid_tbl, + p_ni->node_guid, + &p_node->map_item ); + if( p_node_check != p_node ) + { + /* + This node must have been inserted by another thread. + This is unexpected, but is not an error. + We can simply clean-up, since the other thread will + see this processing through to completion. + */ + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "__osm_ni_rcv_process_new: " + "Discovery race detected at node 0x%" PRIx64 "\n", + cl_ntoh64( p_ni->node_guid ) ); + osm_node_delete( &p_node ); + p_node = p_node_check; + __osm_ni_rcv_set_links( p_rcv, p_node, port_num, p_ni_context ); + goto Exit; + } + else + __osm_ni_rcv_set_links( p_rcv, p_node, port_num, p_ni_context ); + + osm_node_discovery_count_inc( p_node ); + __osm_ni_rcv_get_node_desc( p_rcv, p_node, p_madw ); + + switch( p_ni->node_type ) + { + case IB_NODE_TYPE_CA: + case IB_NODE_TYPE_ROUTER: + __osm_ni_rcv_process_new_ca_or_router( p_rcv, p_node, p_madw ); + break; + case IB_NODE_TYPE_SWITCH: + __osm_ni_rcv_process_new_switch( p_rcv, p_node, p_madw ); + break; + default: + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_ni_rcv_process_new: ERR 0D16: " + "Unknown node type %u with GUID 0x%" PRIx64 "\n", + p_ni->node_type, cl_ntoh64( p_ni->node_guid ) ); + break; + } + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + The plock must be held before calling this function. +**********************************************************************/ +static void +__osm_ni_rcv_process_existing( + IN const osm_ni_rcv_t* const p_rcv, + IN osm_node_t* const p_node, + IN const osm_madw_t* const p_madw ) +{ + ib_node_info_t *p_ni; + ib_smp_t *p_smp; + osm_ni_context_t *p_ni_context; + uint8_t port_num; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_process_existing ); + + p_smp = osm_madw_get_smp_ptr( p_madw ); + p_ni = (ib_node_info_t*)ib_smp_get_payload_ptr( p_smp ); + p_ni_context = osm_madw_get_ni_context_ptr( p_madw ); + port_num = ib_node_info_get_local_port_num( p_ni ); + + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "__osm_ni_rcv_process_existing: " + "Rediscovered %s node 0x%" PRIx64 + "\n\t\t\t\tTID 0x%" PRIx64 + ", discovered %u times already\n", + ib_get_node_type_str(p_ni->node_type), + cl_ntoh64( p_ni->node_guid ), + cl_ntoh64( p_smp->trans_id ), + osm_node_discovery_count_get( p_node ) ); + } + + /* + If we haven't already encountered this existing node + on this particular sweep, then process further. + */ + osm_node_discovery_count_inc( p_node ); + + switch( p_ni->node_type ) + { + case IB_NODE_TYPE_CA: + case IB_NODE_TYPE_ROUTER: + __osm_ni_rcv_process_existing_ca_or_router( p_rcv, p_node, p_madw ); + break; + + case IB_NODE_TYPE_SWITCH: + __osm_ni_rcv_process_existing_switch( p_rcv, p_node, p_madw ); + break; + + default: + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_ni_rcv_process_existing: ERR 0D09: " + "Unknown node type %u with GUID 0x%" PRIx64 "\n", + p_ni->node_type, cl_ntoh64( p_ni->node_guid ) ); + break; + } + + __osm_ni_rcv_set_links( p_rcv, p_node, port_num, p_ni_context ); + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_ni_rcv_construct( + IN osm_ni_rcv_t* const p_rcv ) +{ + memset( p_rcv, 0, sizeof(*p_rcv) ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_ni_rcv_destroy( + IN osm_ni_rcv_t* const p_rcv ) +{ + CL_ASSERT( p_rcv ); + + OSM_LOG_ENTER( p_rcv->p_log, osm_ni_rcv_destroy ); + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_ni_rcv_init( + IN osm_ni_rcv_t* const p_rcv, + IN osm_req_t* const p_req, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN osm_state_mgr_t* const p_state_mgr, + IN cl_plock_t* const p_lock ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_ni_rcv_init ); + + osm_ni_rcv_construct( p_rcv ); + + p_rcv->p_log = p_log; + p_rcv->p_subn = p_subn; + p_rcv->p_lock = p_lock; + p_rcv->p_gen_req = p_req; + p_rcv->p_state_mgr = p_state_mgr; + + OSM_LOG_EXIT( p_rcv->p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_ni_rcv_process( + IN const osm_ni_rcv_t* const p_rcv, + IN osm_madw_t* const p_madw ) +{ + cl_qmap_t *p_guid_tbl; + ib_node_info_t *p_ni; + ib_smp_t *p_smp; + osm_node_t *p_node; + boolean_t process_new_flag = FALSE; + + CL_ASSERT( p_rcv ); + + OSM_LOG_ENTER( p_rcv->p_log, osm_ni_rcv_process ); + + CL_ASSERT( p_madw ); + + p_smp = osm_madw_get_smp_ptr( p_madw ); + p_ni = (ib_node_info_t*)ib_smp_get_payload_ptr( p_smp ); + + CL_ASSERT( p_smp->attr_id == IB_MAD_ATTR_NODE_INFO ); + + if (p_ni->node_guid == 0) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_ni_rcv_process: ERR 0D16: " + "Got Zero Node GUID! Found on the directed route:\n"); + osm_dump_smp_dr_path(p_rcv->p_log, p_smp, OSM_LOG_ERROR); + goto Exit; + } + + if (p_ni->port_guid == 0) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_ni_rcv_process: ERR 0D17: " + "Got Zero Port GUID! Found on the directed route:\n"); + osm_dump_smp_dr_path(p_rcv->p_log, p_smp, OSM_LOG_ERROR); + goto Exit; + } + + p_guid_tbl = &p_rcv->p_subn->node_guid_tbl; + + /* + Determine if this node has already been discovered, + and process accordingly. + During processing of this node, hold the shared lock. + */ + + CL_PLOCK_EXCL_ACQUIRE( p_rcv->p_lock ); + p_node = (osm_node_t*)cl_qmap_get( p_guid_tbl, p_ni->node_guid ); + + osm_dump_node_info( p_rcv->p_log, p_ni, OSM_LOG_DEBUG ); + + if( p_node == (osm_node_t*)cl_qmap_end(p_guid_tbl) ) + { + __osm_ni_rcv_process_new( p_rcv, p_madw ); + process_new_flag = TRUE; + } + else + __osm_ni_rcv_process_existing( p_rcv, p_node, p_madw ); + + CL_PLOCK_RELEASE( p_rcv->p_lock ); + + /* + * If we processed a new node - need to signal to the state_mgr that + * change detected. BUT - we cannot call the osm_state_mgr_process + * from within the lock of p_rcv->p_lock (can cause a deadlock). + */ + if ( process_new_flag ) + osm_state_mgr_process( p_rcv->p_state_mgr, OSM_SIGNAL_CHANGE_DETECTED ); + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_node_info_rcv_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_node_info_rcv_ctrl.c new file mode 100644 index 00000000..bf478131 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_node_info_rcv_ctrl.c @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_node_info_rcv_ctrl.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_ni_rcv_ctrl_t. + * This object represents the NodeInfo request controller object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +__osm_ni_rcv_ctrl_disp_callback( + IN void *context, + IN void *p_data ) +{ + /* ignore return status when invoked via the dispatcher */ + osm_ni_rcv_process( ((osm_ni_rcv_ctrl_t*)context)->p_rcv, + (osm_madw_t*)p_data ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_ni_rcv_ctrl_construct( + IN osm_ni_rcv_ctrl_t* const p_ctrl ) +{ + memset( p_ctrl, 0, sizeof(*p_ctrl) ); + p_ctrl->h_disp = CL_DISP_INVALID_HANDLE; +} + +/********************************************************************** + **********************************************************************/ +void +osm_ni_rcv_ctrl_destroy( + IN osm_ni_rcv_ctrl_t* const p_ctrl ) +{ + CL_ASSERT( p_ctrl ); + cl_disp_unregister( p_ctrl->h_disp ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_ni_rcv_ctrl_init( + IN osm_ni_rcv_ctrl_t* const p_ctrl, + IN osm_ni_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_ni_rcv_ctrl_init ); + + osm_ni_rcv_ctrl_construct( p_ctrl ); + p_ctrl->p_log = p_log; + + p_ctrl->p_rcv = p_rcv; + p_ctrl->p_disp = p_disp; + + p_ctrl->h_disp = cl_disp_register( + p_disp, + OSM_MSG_MAD_NODE_INFO, + __osm_ni_rcv_ctrl_disp_callback, + p_ctrl ); + + if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_ni_rcv_ctrl_init: ERR 0E01: " + "Dispatcher registration failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return( status ); +} + + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_opensm.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_opensm.c new file mode 100644 index 00000000..4f0019fd --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_opensm.c @@ -0,0 +1,320 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_opensm.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_opensm_t. + * This object represents the opensm super object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.7 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct routing_engine_module { + const char *name; + int (*setup)(osm_opensm_t *p_osm); +}; + +extern int osm_ucast_updn_setup(osm_opensm_t *p_osm); +extern int osm_ucast_file_setup(osm_opensm_t *p_osm); +extern int osm_ucast_ftree_setup(osm_opensm_t *p_osm); + +static int osm_ucast_null_setup(osm_opensm_t *p_osm); + +const static struct routing_engine_module routing_modules[] = { + { "null", osm_ucast_null_setup }, + { "updn", osm_ucast_updn_setup }, + { "file", osm_ucast_file_setup }, + { "ftree", osm_ucast_ftree_setup }, + { NULL, NULL } +}; + +static int setup_routing_engine(osm_opensm_t *p_osm, const char *name) +{ + const struct routing_engine_module *r; + + for (r = routing_modules; r->name && *r->name; r++) { + if(!strcmp(r->name, name)) { + p_osm->routing_engine.name = r->name; + if (r->setup(p_osm)) { + osm_log(&p_osm->log, OSM_LOG_VERBOSE, + "setup_routing_engine: setup of routing" + " engine \'%s\' failed\n", name); + return -2; + } + osm_log (&p_osm->log, OSM_LOG_DEBUG, + "setup_routing_engine: " + "\'%s\' routing engine set up\n", + p_osm->routing_engine.name); + return 0; + } + } + return -1; +} + +static int osm_ucast_null_setup(osm_opensm_t *p_osm) +{ + osm_log(&p_osm->log, OSM_LOG_VERBOSE, + "osm_ucast_null_setup: nothing yet - " + "will use default routing engine\n"); + return 0; +} + +/********************************************************************** + **********************************************************************/ +void +osm_opensm_construct( + IN osm_opensm_t * const p_osm ) +{ + memset( p_osm, 0, sizeof( *p_osm ) ); + osm_subn_construct( &p_osm->subn ); + osm_sm_construct( &p_osm->sm ); + osm_sa_construct( &p_osm->sa ); + osm_db_construct( &p_osm->db ); + osm_mad_pool_construct( &p_osm->mad_pool ); + osm_vl15_construct( &p_osm->vl15 ); + osm_log_construct( &p_osm->log ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_opensm_destroy( + IN osm_opensm_t * const p_osm ) +{ + + /* in case of shutdown through exit proc - no ^C */ + osm_exit_flag = TRUE; + + /* + * First of all - Clear the is_sm bit. + */ + if( p_osm->sm.mad_ctrl.h_bind ) + osm_vendor_set_sm( p_osm->sm.mad_ctrl.h_bind, FALSE ); + + /* shut down the SA + * - unbind from QP1 messages + */ + osm_sa_shutdown( &p_osm->sa ); + + /* shut down the SM + * - make sure the SM sweeper thread exited + * - unbind from QP0 messages + */ + osm_sm_shutdown( &p_osm->sm ); + + /* cleanup all messages on VL15 fifo that were not sent yet */ + osm_vl15_shutdown( &p_osm->vl15, &p_osm->mad_pool ); + + /* shut down the dispatcher - so no new messages cross */ + cl_disp_shutdown( &p_osm->disp ); + + /* dump SA DB */ + osm_sa_db_file_dump(p_osm); + + /* do the destruction in reverse order as init */ + if (p_osm->routing_engine.delete) + p_osm->routing_engine.delete(p_osm->routing_engine.context); + osm_sa_destroy( &p_osm->sa ); + osm_sm_destroy( &p_osm->sm ); + osm_db_destroy( &p_osm->db ); + osm_vl15_destroy( &p_osm->vl15, &p_osm->mad_pool ); + osm_mad_pool_destroy( &p_osm->mad_pool ); + osm_vendor_delete( &p_osm->p_vendor ); + osm_subn_destroy( &p_osm->subn ); + cl_disp_destroy( &p_osm->disp ); + + cl_plock_destroy( &p_osm->lock ); + + osm_log_destroy( &p_osm->log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_opensm_init( + IN osm_opensm_t * const p_osm, + IN const osm_subn_opt_t * const p_opt ) +{ + ib_api_status_t status; + + /* Can't use log macros here, since we're initializing the log. */ + osm_opensm_construct( p_osm ); + + status = osm_log_init_v2( &p_osm->log, p_opt->force_log_flush, + p_opt->log_flags, p_opt->log_file, + p_opt->log_max_size, p_opt->accum_log_file ); + if( status != IB_SUCCESS ) + return ( status ); + + /* If there is a log level defined - add the OSM_VERSION to it. */ + osm_log( &p_osm->log, + osm_log_get_level( &p_osm->log ) & ( OSM_LOG_SYS ^ 0xFF ), "%s\n", + OSM_VERSION ); + /* Write the OSM_VERSION to the SYS_LOG */ + osm_log( &p_osm->log, OSM_LOG_SYS, "%s\n", OSM_VERSION ); /* Format Waived */ + + osm_log( &p_osm->log, OSM_LOG_FUNCS, "osm_opensm_init: [\n" ); /* Format Waived */ + + status = cl_plock_init( &p_osm->lock ); + if( status != IB_SUCCESS ) + goto Exit; + + if( p_opt->single_thread ) + { + osm_log( &p_osm->log, OSM_LOG_INFO, + "osm_opensm_init: Forcing single threaded dispatcher.\n" ); + status = cl_disp_init( &p_osm->disp, 1, "opensm" ); + } + else + { + /* + * Normal behavior is to initialize the dispatcher with + * one thread per CPU, as specified by a thread count of '0'. + */ + status = cl_disp_init( &p_osm->disp, 0, "opensm" ); + } + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_subn_init( &p_osm->subn, p_osm, p_opt ); + if( status != IB_SUCCESS ) + goto Exit; + + p_osm->p_vendor = + osm_vendor_new( &p_osm->log, p_opt->transaction_timeout ); + if( p_osm->p_vendor == NULL ) + { + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + status = osm_mad_pool_init( &p_osm->mad_pool, &p_osm->log ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_vl15_init( &p_osm->vl15, + p_osm->p_vendor, + &p_osm->log, &p_osm->stats, p_opt->max_wire_smps, + &p_osm->subn, &p_osm->disp, &p_osm->lock ); + if( status != IB_SUCCESS ) + goto Exit; + + /* the DB is in use by the SM and SA so init before */ + status = osm_db_init( &p_osm->db, &p_osm->log ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_sm_init( &p_osm->sm, + &p_osm->subn, + &p_osm->db, + p_osm->p_vendor, + &p_osm->mad_pool, + &p_osm->vl15, + &p_osm->log, + &p_osm->stats, &p_osm->disp, &p_osm->lock ); + + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_sa_init( &p_osm->sm, + &p_osm->sa, + &p_osm->subn, + p_osm->p_vendor, + &p_osm->mad_pool, + &p_osm->log, + &p_osm->stats, &p_osm->disp, &p_osm->lock ); + + if( status != IB_SUCCESS ) + goto Exit; + + if( p_opt->routing_engine_name && + setup_routing_engine(p_osm, p_opt->routing_engine_name)) { + osm_log( &p_osm->log, OSM_LOG_VERBOSE, + "osm_opensm_init: cannot find or setup routing engine" + " \'%s\'. Default will be used instead\n", + p_opt->routing_engine_name); + goto Exit; + } + + Exit: + osm_log( &p_osm->log, OSM_LOG_FUNCS, "osm_opensm_init: ]\n" ); /* Format Waived */ + return ( status ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_opensm_bind( + IN osm_opensm_t * const p_osm, + IN const ib_net64_t guid ) +{ + ib_api_status_t status; + + OSM_LOG_ENTER( &p_osm->log, osm_opensm_bind ); + + status = osm_sm_bind( &p_osm->sm, guid ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_sa_bind( &p_osm->sa, guid ); + if( status != IB_SUCCESS ) + goto Exit; + Exit: + OSM_LOG_EXIT( &p_osm->log ); + return ( status ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_pkey.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_pkey.c new file mode 100644 index 00000000..f649c802 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_pkey.c @@ -0,0 +1,547 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_pkey.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of opensm pkey manipulation functions. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.1 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void osm_pkey_tbl_construct( + IN osm_pkey_tbl_t *p_pkey_tbl) +{ + cl_ptr_vector_construct( &p_pkey_tbl->blocks ); + cl_ptr_vector_construct( &p_pkey_tbl->new_blocks ); + cl_map_construct( &p_pkey_tbl->keys ); +} + +/********************************************************************** + **********************************************************************/ +void osm_pkey_tbl_destroy( + IN osm_pkey_tbl_t *p_pkey_tbl) +{ + ib_pkey_table_t *p_block; + uint16_t num_blocks, i; + + num_blocks = (uint16_t)(cl_ptr_vector_get_size( &p_pkey_tbl->blocks )); + for (i = 0; i < num_blocks; i++) + if ((p_block = cl_ptr_vector_get( &p_pkey_tbl->blocks, i ))) + free(p_block); + cl_ptr_vector_destroy( &p_pkey_tbl->blocks ); + + num_blocks = (uint16_t)(cl_ptr_vector_get_size( &p_pkey_tbl->new_blocks )); + for (i = 0; i < num_blocks; i++) + if ((p_block = cl_ptr_vector_get( &p_pkey_tbl->new_blocks, i ))) + free(p_block); + cl_ptr_vector_destroy( &p_pkey_tbl->new_blocks ); + + cl_map_remove_all( &p_pkey_tbl->keys ); + cl_map_destroy( &p_pkey_tbl->keys ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_pkey_tbl_init( + IN osm_pkey_tbl_t *p_pkey_tbl) +{ + cl_ptr_vector_init(&p_pkey_tbl->blocks, 0, 1); + cl_ptr_vector_init(&p_pkey_tbl->new_blocks, 0, 1); + cl_map_init(&p_pkey_tbl->keys, 1); + cl_qlist_init(&p_pkey_tbl->pending); + p_pkey_tbl->used_blocks = 0; + p_pkey_tbl->max_blocks = 0; + return(IB_SUCCESS); +} + +/********************************************************************** + **********************************************************************/ +void osm_pkey_tbl_init_new_blocks( + IN const osm_pkey_tbl_t *p_pkey_tbl) +{ + ib_pkey_table_t *p_block; + size_t b, num_blocks = cl_ptr_vector_get_size(&p_pkey_tbl->new_blocks); + + for (b = 0; b < num_blocks; b++) + if ((p_block = cl_ptr_vector_get(&p_pkey_tbl->new_blocks, b))) + memset(p_block, 0, sizeof(*p_block)); +} + +/********************************************************************** + **********************************************************************/ +void osm_pkey_tbl_cleanup_pending( + IN osm_pkey_tbl_t *p_pkey_tbl) +{ + cl_list_item_t *p_item; + + p_item = cl_qlist_remove_head(&p_pkey_tbl->pending); + while (p_item != cl_qlist_end(&p_pkey_tbl->pending)) + { + free((osm_pending_pkey_t *)p_item); + } +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_pkey_tbl_set( + IN osm_pkey_tbl_t *p_pkey_tbl, + IN uint16_t block, + IN ib_pkey_table_t *p_tbl) +{ + uint16_t b, i; + ib_pkey_table_t *p_pkey_block; + uint16_t *p_prev_pkey; + ib_net16_t pkey; + + /* make sure the block is allocated */ + if (cl_ptr_vector_get_size( &p_pkey_tbl->blocks ) > block) + p_pkey_block = + (ib_pkey_table_t *)cl_ptr_vector_get( &p_pkey_tbl->blocks, block ); + else + p_pkey_block = NULL; + + if ( !p_pkey_block ) + { + p_pkey_block = (ib_pkey_table_t *)malloc(sizeof(ib_pkey_table_t)); + if (p_pkey_block) + memset(p_pkey_block, 0, sizeof(ib_pkey_table_t)); + cl_ptr_vector_set( &p_pkey_tbl->blocks, block, p_pkey_block ); + } + + /* sets the block values */ + memcpy( p_pkey_block, p_tbl, sizeof(ib_pkey_table_t) ); + + /* + NOTE: as the spec does not require uniqueness of PKeys in + tables there is no other way but to refresh the entire keys map. + + Moreover, if the same key exists but with full membership it should have + precedence on the key with limited membership ! + */ + cl_map_remove_all( &p_pkey_tbl->keys ); + + for (b = 0; b < cl_ptr_vector_get_size( &p_pkey_tbl->blocks ); b++) + { + + p_pkey_block = cl_ptr_vector_get( &p_pkey_tbl->blocks, b ); + if (! p_pkey_block) + continue; + + for (i = 0; i < IB_NUM_PKEY_ELEMENTS_IN_BLOCK; i++) + { + pkey = p_pkey_block->pkey_entry[i]; + if (ib_pkey_is_invalid(pkey)) + continue; + + /* + ignore the PKey Full Member bit in the key but store + the pointer to the table element as the map value + */ + p_prev_pkey = + cl_map_get( &p_pkey_tbl->keys, ib_pkey_get_base(pkey)); + + /* we only insert if no previous or it is not full member */ + if ((p_prev_pkey == NULL) || + (cl_ntoh16(*p_prev_pkey) < cl_ntoh16(pkey))) + cl_map_insert( &p_pkey_tbl->keys, + ib_pkey_get_base(pkey), + &(p_pkey_block->pkey_entry[i]) + ); + } + } + return(IB_SUCCESS); +} + +/********************************************************************** + **********************************************************************/ +/* + Store the given pkey in the "new" blocks array. + Also, make sure the regular block exists. +*/ +ib_api_status_t +osm_pkey_tbl_set_new_entry( + IN osm_pkey_tbl_t *p_pkey_tbl, + IN uint16_t block_idx, + IN uint8_t pkey_idx, + IN uint16_t pkey) +{ + ib_pkey_table_t *p_block; + + if (!(p_block = osm_pkey_tbl_new_block_get(p_pkey_tbl, block_idx))) { + p_block = (ib_pkey_table_t *)malloc(sizeof(ib_pkey_table_t)); + if (!p_block) + return(IB_ERROR); + memset(p_block, 0, sizeof(ib_pkey_table_t)); + cl_ptr_vector_set(&p_pkey_tbl->new_blocks, block_idx, p_block); + } + + p_block->pkey_entry[pkey_idx] = pkey; + if (p_pkey_tbl->used_blocks <= block_idx) + p_pkey_tbl->used_blocks = block_idx + 1; + + return(IB_SUCCESS); +} + +/********************************************************************** + **********************************************************************/ +boolean_t +osm_pkey_find_next_free_entry( + IN osm_pkey_tbl_t *p_pkey_tbl, + OUT uint16_t *p_block_idx, + OUT uint8_t *p_pkey_idx) +{ + ib_pkey_table_t *p_new_block; + + CL_ASSERT(p_block_idx); + CL_ASSERT(p_pkey_idx); + + while (*p_block_idx < p_pkey_tbl->max_blocks) + { + if (*p_pkey_idx > IB_NUM_PKEY_ELEMENTS_IN_BLOCK - 1) + { + *p_pkey_idx = 0; + (*p_block_idx)++; + if (*p_block_idx >= p_pkey_tbl->max_blocks) + return FALSE; + } + + p_new_block = osm_pkey_tbl_new_block_get(p_pkey_tbl, *p_block_idx); + + if (!p_new_block || + ib_pkey_is_invalid(p_new_block->pkey_entry[*p_pkey_idx])) + return TRUE; + else + (*p_pkey_idx)++; + } + return FALSE; +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_pkey_tbl_get_block_and_idx( + IN osm_pkey_tbl_t *p_pkey_tbl, + IN uint16_t *p_pkey, + OUT uint16_t *p_block_idx, + OUT uint8_t *p_pkey_idx) +{ + uint16_t num_of_blocks; + uint16_t block_index; + ib_pkey_table_t *block; + + CL_ASSERT( p_block_idx != NULL ); + CL_ASSERT( p_pkey_idx != NULL ); + + num_of_blocks = (uint16_t)cl_ptr_vector_get_size( &p_pkey_tbl->blocks ); + for (block_index = 0; block_index < num_of_blocks; block_index++) + { + block = osm_pkey_tbl_block_get(p_pkey_tbl, block_index); + if ((block->pkey_entry <= p_pkey) && + (p_pkey < block->pkey_entry + IB_NUM_PKEY_ELEMENTS_IN_BLOCK)) + { + *p_block_idx = block_index; + *p_pkey_idx = (uint8_t)(p_pkey - block->pkey_entry); + return(IB_SUCCESS); + } + } + return(IB_NOT_FOUND); +} + +/********************************************************************** + **********************************************************************/ +static boolean_t +__osm_match_pkey ( + IN const ib_net16_t *pkey1, + IN const ib_net16_t *pkey2 ) +{ + + /* if both pkeys are not full member - this is not a match */ + if (!(ib_pkey_is_full_member(*pkey1) || ib_pkey_is_full_member(*pkey2))) + return(FALSE); + + /* compare if the bases are the same. if they are - then + this is a match */ + if (ib_pkey_get_base(*pkey1) != ib_pkey_get_base(*pkey2)) + return(FALSE); + + return(TRUE); +} + +/********************************************************************** + **********************************************************************/ +boolean_t +osm_physp_share_this_pkey( + IN const osm_physp_t* const p_physp1, + IN const osm_physp_t* const p_physp2, + IN const ib_net16_t pkey ) +{ + ib_net16_t *pkey1, *pkey2; + + pkey1 = cl_map_get( &(osm_physp_get_pkey_tbl(p_physp1))->keys, + ib_pkey_get_base(pkey)); + pkey2 = cl_map_get( &(osm_physp_get_pkey_tbl(p_physp2))->keys, + ib_pkey_get_base(pkey)); + return (pkey1 && pkey2 && __osm_match_pkey(pkey1, pkey2)); +} + +/********************************************************************** + **********************************************************************/ +ib_net16_t +osm_physp_find_common_pkey( + IN const osm_physp_t* const p_physp1, + IN const osm_physp_t* const p_physp2 ) +{ + ib_net16_t *pkey1, *pkey2; + uint64_t pkey1_base, pkey2_base; + const osm_pkey_tbl_t *pkey_tbl1, *pkey_tbl2; + cl_map_iterator_t map_iter1, map_iter2; + + pkey_tbl1 = osm_physp_get_pkey_tbl(p_physp1); + pkey_tbl2 = osm_physp_get_pkey_tbl(p_physp2); + + map_iter1 = cl_map_head(&pkey_tbl1->keys); + map_iter2 = cl_map_head(&pkey_tbl2->keys); + + /* we rely on the fact the map are sorted by pkey */ + while ( (map_iter1 != cl_map_end( &pkey_tbl1->keys )) && + (map_iter2 != cl_map_end( &pkey_tbl2->keys ))) + { + pkey1 = (ib_net16_t *)cl_map_obj( map_iter1 ); + pkey2 = (ib_net16_t *)cl_map_obj( map_iter2 ); + + if (__osm_match_pkey(pkey1, pkey2)) + return *pkey1; + + /* advance the lower value if they are not equal */ + pkey1_base = cl_map_key( map_iter1 ); + pkey2_base = cl_map_key( map_iter2 ); + if (pkey2_base == pkey1_base) + { + map_iter1 = cl_map_next( map_iter1 ); + map_iter2 = cl_map_next( map_iter2 ); + } + else if (pkey2_base < pkey1_base) + map_iter2 = cl_map_next( map_iter2 ); + else + map_iter1 = cl_map_next( map_iter1 ); + } + + return 0; +} + +/********************************************************************** + **********************************************************************/ +boolean_t +osm_physp_share_pkey( + IN osm_log_t* p_log, + IN const osm_physp_t* const p_physp_1, + IN const osm_physp_t* const p_physp_2 ) +{ + const osm_pkey_tbl_t *pkey_tbl1, *pkey_tbl2; + + if (p_physp_1 == p_physp_2) + return TRUE; + + pkey_tbl1 = osm_physp_get_pkey_tbl(p_physp_1); + pkey_tbl2 = osm_physp_get_pkey_tbl(p_physp_2); + + /* + The spec: 10.9.2 does not require each phys port to have PKey Table. + So actually if it does not, we need to use the default port instead. + + HACK: meanwhile we will ignore the check + */ + if (cl_is_map_empty(&pkey_tbl1->keys) || cl_is_map_empty(&pkey_tbl2->keys)) + return TRUE; + + return !ib_pkey_is_invalid(osm_physp_find_common_pkey(p_physp_1, p_physp_2)); +} + +/********************************************************************** + **********************************************************************/ +boolean_t +osm_port_share_pkey( + IN osm_log_t* p_log, + IN const osm_port_t* const p_port_1, + IN const osm_port_t* const p_port_2 ) { + + osm_physp_t *p_physp1, *p_physp2; + boolean_t ret; + + OSM_LOG_ENTER( p_log, osm_port_share_pkey ); + + if (!p_port_1 || !p_port_2) + { + ret = FALSE; + goto Exit; + } + + p_physp1 = osm_port_get_default_phys_ptr(p_port_1); + p_physp2 = osm_port_get_default_phys_ptr(p_port_2); + + if (!p_physp1 || !p_physp2) + { + ret = FALSE; + goto Exit; + } + + ret = osm_physp_share_pkey(p_log, p_physp1, p_physp2); + +Exit: + OSM_LOG_EXIT(p_log); + return ret; +} + +/********************************************************************** + **********************************************************************/ +boolean_t +osm_lid_share_pkey( + IN osm_log_t* p_log, + IN const osm_subn_t * const p_subn, + IN const ib_net16_t lid1, + IN const uint8_t port_num1, + IN const ib_net16_t lid2, + IN const uint8_t port_num2 ) { + + osm_physp_t *p_physp1, *p_physp2; + osm_port_t *p_port1, *p_port2; + osm_node_t *p_node1, *p_node2; + const cl_ptr_vector_t* const p_port_lid_tbl = &(p_subn->port_lid_tbl); + + OSM_LOG_ENTER( p_log, osm_lid_share_pkey ); + + p_port1 = cl_ptr_vector_get(p_port_lid_tbl, lid1); + p_port2 = cl_ptr_vector_get(p_port_lid_tbl, lid2); + + p_node1 = p_port1->p_node; + p_node2 = p_port2->p_node; + + if (osm_node_get_type( p_node1 ) == IB_NODE_TYPE_SWITCH) + { + p_physp1 = osm_node_get_physp_ptr( p_node1, port_num1 ); + } + else + { + p_physp1 = osm_port_get_default_phys_ptr(p_port1); + } + + if (osm_node_get_type( p_node2 ) == IB_NODE_TYPE_SWITCH) + { + p_physp2 = osm_node_get_physp_ptr( p_node2, port_num2 ); + } + else + { + p_physp2 = osm_port_get_default_phys_ptr(p_port2); + } + + return(osm_physp_share_pkey(p_log, p_physp1, p_physp2)); +} + +/********************************************************************** + **********************************************************************/ +boolean_t +osm_physp_has_pkey( + IN osm_log_t* p_log, + IN const ib_net16_t pkey, + IN const osm_physp_t* const p_physp ) { + + ib_net16_t *p_pkey, pkey_base; + const osm_pkey_tbl_t *pkey_tbl; + boolean_t res = FALSE; + + OSM_LOG_ENTER( p_log, osm_physp_has_pkey ); + + osm_log( p_log, OSM_LOG_DEBUG, + "osm_physp_has_pkey: " + "Search for PKey: 0x%4x\n", + cl_ntoh16(pkey) ); + + /* if the pkey given is an invalid pkey - return TRUE. */ + if(ib_pkey_is_invalid(pkey)) + { + osm_log( p_log, OSM_LOG_DEBUG, + "osm_physp_has_pkey: " + "Given invalid PKey - we treat it loosely and allow it\n"); + res = TRUE; + goto Exit; + } + + pkey_base = ib_pkey_get_base(pkey); + + pkey_tbl = osm_physp_get_pkey_tbl(p_physp); + + p_pkey = cl_map_get( &pkey_tbl->keys, pkey_base); + if (p_pkey) + { + res = TRUE; + osm_log( p_log, OSM_LOG_DEBUG, + "osm_physp_has_pkey: " + "PKey 0x%04x was found\n", cl_ntoh16(pkey)); + } + else + { + osm_log( p_log, OSM_LOG_DEBUG, + "osm_physp_has_pkey: " + "PKey 0x%04x was not found\n", cl_ntoh16(pkey)); + } + + Exit: + OSM_LOG_EXIT( p_log ); + return res; +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_pkey_mgr.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_pkey_mgr.c new file mode 100644 index 00000000..fb44de8c --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_pkey_mgr.c @@ -0,0 +1,596 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_pkey_mgr.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of the P_Key Manager (Partititon Manager). + * This is part of the OpenSM. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.7 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +/* + The max number of pkey blocks for a physical port is located in + a different place for switch external ports (SwitchInfo) and the + rest of the ports (NodeInfo). +*/ +static uint16_t +pkey_mgr_get_physp_max_blocks( + IN const osm_subn_t *p_subn, + IN const osm_physp_t *p_physp ) +{ + osm_node_t *p_node = osm_physp_get_node_ptr( p_physp ); + uint16_t num_pkeys = 0; + + if ( !p_node->sw || + ( osm_physp_get_port_num( p_physp ) == 0 ) ) + num_pkeys = cl_ntoh16( p_node->node_info.partition_cap ); + else + num_pkeys = cl_ntoh16( p_node->sw->switch_info.enforce_cap ); + return((num_pkeys + 31) / 32); +} + +/********************************************************************** + **********************************************************************/ +/* + * Insert new pending pkey entry to the specific port pkey table + * pending pkeys. New entries are inserted at the back. + */ +static void +pkey_mgr_process_physical_port( + IN osm_log_t *p_log, + IN const osm_req_t *p_req, + IN const ib_net16_t pkey, + IN osm_physp_t *p_physp ) +{ + osm_node_t *p_node = osm_physp_get_node_ptr( p_physp ); + osm_pkey_tbl_t *p_pkey_tbl; + ib_net16_t *p_orig_pkey; + char *stat = NULL; + osm_pending_pkey_t *p_pending; + + p_pkey_tbl = osm_physp_get_mod_pkey_tbl( p_physp ); + p_pending = (osm_pending_pkey_t *)malloc( sizeof( osm_pending_pkey_t ) ); + if (!p_pending) + { + osm_log( p_log, OSM_LOG_ERROR, + "pkey_mgr_process_physical_port: ERR 0502: " + "Failed to allocate new pending pkey entry for node " + "0x%016" PRIx64 " port %u\n", + cl_ntoh64( osm_node_get_node_guid( p_node ) ), + osm_physp_get_port_num( p_physp ) ); + return; + } + p_pending->pkey = pkey; + p_orig_pkey = cl_map_get( &p_pkey_tbl->keys, ib_pkey_get_base( pkey ) ); + if (!p_orig_pkey) + { + p_pending->is_new = TRUE; + cl_qlist_insert_tail( &p_pkey_tbl->pending, (cl_list_item_t*)p_pending ); + stat = "inserted"; + } + else + { + CL_ASSERT( ib_pkey_get_base( *p_orig_pkey ) == ib_pkey_get_base( pkey ) ); + p_pending->is_new = FALSE; + if (osm_pkey_tbl_get_block_and_idx( + p_pkey_tbl, p_orig_pkey, + &p_pending->block, &p_pending->index ) != IB_SUCCESS) + { + osm_log( p_log, OSM_LOG_ERROR, + "pkey_mgr_process_physical_port: ERR 0503: " + "Failed to obtain P_Key 0x%04x block and index for node " + "0x%016" PRIx64 " port %u\n", + ib_pkey_get_base( pkey ), + cl_ntoh64( osm_node_get_node_guid( p_node ) ), + osm_physp_get_port_num( p_physp ) ); + return; + } + cl_qlist_insert_head( &p_pkey_tbl->pending, (cl_list_item_t*)p_pending ); + stat = "updated"; + } + + osm_log( p_log, OSM_LOG_DEBUG, + "pkey_mgr_process_physical_port: " + "pkey 0x%04x was %s for node 0x%016" PRIx64 + " port %u\n", + cl_ntoh16( pkey ), stat, + cl_ntoh64( osm_node_get_node_guid( p_node ) ), + osm_physp_get_port_num( p_physp ) ); +} + +/********************************************************************** + **********************************************************************/ +static void +pkey_mgr_process_partition_table( + osm_log_t *p_log, + const osm_req_t *p_req, + const osm_prtn_t *p_prtn, + const boolean_t full ) +{ + const cl_map_t *p_tbl = + full ? &p_prtn->full_guid_tbl : &p_prtn->part_guid_tbl; + cl_map_iterator_t i, i_next; + ib_net16_t pkey = p_prtn->pkey; + osm_physp_t *p_physp; + + if (full) + pkey |= cl_hton16( 0x8000 ); + + i_next = cl_map_head( p_tbl ); + while ( i_next != cl_map_end( p_tbl ) ) + { + i = i_next; + i_next = cl_map_next( i ); + p_physp = cl_map_obj( i ); + if ( p_physp && osm_physp_is_valid( p_physp ) ) + pkey_mgr_process_physical_port( p_log, p_req, pkey, p_physp ); + } +} + +/********************************************************************** + **********************************************************************/ +static ib_api_status_t +pkey_mgr_update_pkey_entry( + IN const osm_req_t *p_req, + IN const osm_physp_t *p_physp, + IN const ib_pkey_table_t *block, + IN const uint16_t block_index ) +{ + osm_madw_context_t context; + osm_node_t *p_node = osm_physp_get_node_ptr( p_physp ); + uint32_t attr_mod; + + context.pkey_context.node_guid = osm_node_get_node_guid( p_node ); + context.pkey_context.port_guid = osm_physp_get_port_guid( p_physp ); + context.pkey_context.set_method = TRUE; + attr_mod = block_index; + if ( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH ) + attr_mod |= osm_physp_get_port_num( p_physp ) << 16; + return osm_req_set( p_req, osm_physp_get_dr_path_ptr( p_physp ), + ( uint8_t * ) block, sizeof( *block ), + IB_MAD_ATTR_P_KEY_TABLE, + cl_hton32( attr_mod ), CL_DISP_MSGID_NONE, &context ); +} + +/********************************************************************** + **********************************************************************/ +static boolean_t +pkey_mgr_enforce_partition( + IN osm_log_t *p_log, + IN const osm_req_t *p_req, + IN const osm_physp_t *p_physp, + IN const boolean_t enforce) +{ + osm_madw_context_t context; + uint8_t payload[IB_SMP_DATA_SIZE]; + ib_port_info_t *p_pi; + ib_api_status_t status; + + if (!(p_pi = osm_physp_get_port_info_ptr( p_physp ))) + { + osm_log( p_log, OSM_LOG_ERROR, + "pkey_mgr_enforce_partition: ERR 0507: " + "No port info for " + "node 0x%016" PRIx64 " port %u\n", + cl_ntoh64( + osm_node_get_node_guid( + osm_physp_get_node_ptr( p_physp ))), + osm_physp_get_port_num( p_physp ) ); + return FALSE; + } + + if ((p_pi->vl_enforce & 0xc) == (0xc)*(enforce == TRUE)) + { + osm_log( p_log, OSM_LOG_DEBUG, + "pkey_mgr_enforce_partition: " + "No need to update PortInfo for " + "node 0x%016" PRIx64 " port %u\n", + cl_ntoh64( + osm_node_get_node_guid( + osm_physp_get_node_ptr( p_physp ))), + osm_physp_get_port_num( p_physp ) ); + return FALSE; + } + + memset( payload, 0, IB_SMP_DATA_SIZE ); + memcpy( payload, p_pi, sizeof(ib_port_info_t) ); + + p_pi = (ib_port_info_t*)payload; + if (enforce == TRUE) + p_pi->vl_enforce |= 0xc; + else + p_pi->vl_enforce &= ~0xc; + p_pi->state_info2 = 0; + ib_port_info_set_port_state( p_pi, IB_LINK_NO_CHANGE ); + + context.pi_context.node_guid = + osm_node_get_node_guid( osm_physp_get_node_ptr( p_physp ) ); + context.pi_context.port_guid = osm_physp_get_port_guid( p_physp ); + context.pi_context.set_method = TRUE; + context.pi_context.update_master_sm_base_lid = FALSE; + context.pi_context.ignore_errors = FALSE; + context.pi_context.light_sweep = FALSE; + context.pi_context.active_transition = FALSE; + + status = osm_req_set( p_req, osm_physp_get_dr_path_ptr( p_physp ), + payload, sizeof(payload), + IB_MAD_ATTR_PORT_INFO, + cl_hton32( osm_physp_get_port_num( p_physp ) ), + CL_DISP_MSGID_NONE, &context ); + if (status != IB_SUCCESS) + { + osm_log( p_log, OSM_LOG_ERROR, + "pkey_mgr_enforce_partition: ERR 0511: " + "Failed to set PortInfo for " + "node 0x%016" PRIx64 " port %u\n", + cl_ntoh64( + osm_node_get_node_guid( + osm_physp_get_node_ptr( p_physp ))), + osm_physp_get_port_num( p_physp ) ); + return FALSE; + } + else + { + osm_log( p_log, OSM_LOG_DEBUG, + "pkey_mgr_enforce_partition: " + "Set PortInfo for " + "node 0x%016" PRIx64 " port %u\n", + cl_ntoh64( + osm_node_get_node_guid( + osm_physp_get_node_ptr( p_physp ))), + osm_physp_get_port_num( p_physp ) ); + return TRUE; + } +} + +/********************************************************************** + **********************************************************************/ +static boolean_t pkey_mgr_update_port( + osm_log_t *p_log, + osm_req_t *p_req, + const osm_port_t * const p_port ) +{ + osm_physp_t *p_physp; + osm_node_t *p_node; + ib_pkey_table_t *block, *new_block; + osm_pkey_tbl_t *p_pkey_tbl; + uint16_t block_index; + uint8_t pkey_index; + uint16_t last_free_block_index = 0; + uint8_t last_free_pkey_index = 0; + uint16_t num_of_blocks; + uint16_t max_num_of_blocks; + ib_api_status_t status; + boolean_t ret_val = FALSE; + osm_pending_pkey_t *p_pending; + boolean_t found; + ib_pkey_table_t empty_block; + + memset(&empty_block, 0, sizeof(ib_pkey_table_t)); + + p_physp = osm_port_get_default_phys_ptr( p_port ); + if ( !osm_physp_is_valid( p_physp ) ) + return FALSE; + + p_node = osm_physp_get_node_ptr( p_physp ); + p_pkey_tbl = osm_physp_get_mod_pkey_tbl( p_physp ); + num_of_blocks = osm_pkey_tbl_get_num_blocks( p_pkey_tbl ); + max_num_of_blocks = pkey_mgr_get_physp_max_blocks( p_req->p_subn, p_physp ); + if ( p_pkey_tbl->max_blocks > max_num_of_blocks ) + { + osm_log( p_log, OSM_LOG_INFO, + "pkey_mgr_update_port: " + "Max number of blocks reduced from %u to %u " + "for node 0x%016" PRIx64 " port %u\n", + p_pkey_tbl->max_blocks, max_num_of_blocks, + cl_ntoh64( osm_node_get_node_guid( p_node ) ), + osm_physp_get_port_num( p_physp ) ); + } + p_pkey_tbl->max_blocks = max_num_of_blocks; + + osm_pkey_tbl_init_new_blocks( p_pkey_tbl ); + p_pkey_tbl->used_blocks = 0; + + /* + process every pending pkey in order - + first must be "updated" last are "new" + */ + p_pending = (osm_pending_pkey_t *)cl_qlist_remove_head( &p_pkey_tbl->pending ); + while ( p_pending != (osm_pending_pkey_t *)cl_qlist_end( &p_pkey_tbl->pending )) + { + if (p_pending->is_new == FALSE) + { + block_index = p_pending->block; + pkey_index = p_pending->index; + found = TRUE; + } + else + { + found = osm_pkey_find_next_free_entry( p_pkey_tbl, + &last_free_block_index, + &last_free_pkey_index ); + if (!found) + { + osm_log( p_log, OSM_LOG_ERROR, + "pkey_mgr_update_port: ERR 0504: " + "Failed to find empty space for new pkey 0x%04x " + "for node 0x%016" PRIx64 " port %u\n", + cl_ntoh16( p_pending->pkey ), + cl_ntoh64( osm_node_get_node_guid( p_node )), + osm_physp_get_port_num( p_physp ) ); + } + else + { + block_index = last_free_block_index; + pkey_index = last_free_pkey_index++; + } + } + + if (found) + { + if (IB_SUCCESS != osm_pkey_tbl_set_new_entry( p_pkey_tbl, block_index, + pkey_index, p_pending->pkey )) + { + osm_log( p_log, OSM_LOG_ERROR, + "pkey_mgr_update_port: ERR 0505: " + "Failed to set PKey 0x%04x in block %u idx %u " + "for node 0x%016" PRIx64 " port %u\n", + p_pending->pkey, block_index, pkey_index, + cl_ntoh64( osm_node_get_node_guid( p_node ) ), + osm_physp_get_port_num( p_physp ) ); + } + } + + free(p_pending); + p_pending = (osm_pending_pkey_t *)cl_qlist_remove_head( &p_pkey_tbl->pending ); + } + + /* now look for changes and store */ + for (block_index = 0; block_index < num_of_blocks; block_index++) + { + block = osm_pkey_tbl_block_get( p_pkey_tbl, block_index ); + new_block = osm_pkey_tbl_new_block_get( p_pkey_tbl, block_index ); + if (!new_block) + new_block = &empty_block; + if (block && !memcmp( new_block, block, sizeof( *block ) )) + continue; + + status = pkey_mgr_update_pkey_entry( p_req, p_physp, new_block, block_index ); + if (status == IB_SUCCESS) + { + osm_log( p_log, OSM_LOG_DEBUG, + "pkey_mgr_update_port: " + "Updated " + "pkey table block %d for node 0x%016" PRIx64 " port %u\n", + block_index, + cl_ntoh64( osm_node_get_node_guid( p_node ) ), + osm_physp_get_port_num( p_physp ) ); + ret_val = TRUE; + } + else + { + osm_log( p_log, OSM_LOG_ERROR, + "pkey_mgr_update_port: ERR 0506: " + "pkey_mgr_update_pkey_entry() failed to update " + "pkey table block %d for node 0x%016" PRIx64 " port %u\n", + block_index, + cl_ntoh64( osm_node_get_node_guid( p_node ) ), + osm_physp_get_port_num( p_physp ) ); + } + } + + return ret_val; +} + +/********************************************************************** + **********************************************************************/ +static boolean_t +pkey_mgr_update_peer_port( + osm_log_t *p_log, + const osm_req_t *p_req, + const osm_subn_t *p_subn, + const osm_port_t * const p_port, + boolean_t enforce ) +{ + osm_physp_t *p_physp, *peer; + osm_node_t *p_node; + ib_pkey_table_t *block, *peer_block; + const osm_pkey_tbl_t *p_pkey_tbl; + osm_pkey_tbl_t *p_peer_pkey_tbl; + uint16_t block_index; + uint16_t num_of_blocks; + uint16_t peer_max_blocks; + ib_api_status_t status = IB_SUCCESS; + boolean_t ret_val = FALSE; + boolean_t port_info_set = FALSE; + ib_pkey_table_t empty_block; + + memset(&empty_block, 0, sizeof(ib_pkey_table_t)); + + p_physp = osm_port_get_default_phys_ptr( p_port ); + if (!osm_physp_is_valid( p_physp )) + return FALSE; + peer = osm_physp_get_remote( p_physp ); + if ( !peer || !osm_physp_is_valid( peer ) ) + return FALSE; + p_node = osm_physp_get_node_ptr( peer ); + if ( !p_node->sw || !p_node->sw->switch_info.enforce_cap ) + return FALSE; + + p_pkey_tbl = osm_physp_get_pkey_tbl( p_physp ); + p_peer_pkey_tbl = osm_physp_get_mod_pkey_tbl( peer ); + num_of_blocks = osm_pkey_tbl_get_num_blocks( p_pkey_tbl ); + peer_max_blocks = pkey_mgr_get_physp_max_blocks( p_subn, peer ); + if (peer_max_blocks < p_pkey_tbl->used_blocks) + { + osm_log( p_log, OSM_LOG_ERROR, + "pkey_mgr_update_peer_port: ERR 0508: " + "Not enough pkey entries (%u < %u) on switch 0x%016" PRIx64 + " port %u. Clearing Enforcement bit\n", + peer_max_blocks, num_of_blocks, + cl_ntoh64( osm_node_get_node_guid( p_node ) ), + osm_physp_get_port_num( peer ) ); + enforce = FALSE; + } + + if ( pkey_mgr_enforce_partition( p_log, p_req, peer, enforce ) ) + port_info_set = TRUE; + + if (enforce == FALSE) + return port_info_set; + + p_peer_pkey_tbl->used_blocks = p_pkey_tbl->used_blocks; + for (block_index = 0; block_index < p_pkey_tbl->used_blocks; block_index++) + { + block = osm_pkey_tbl_new_block_get( p_pkey_tbl, block_index ); + if (!block) + block = &empty_block; + + peer_block = osm_pkey_tbl_block_get( p_peer_pkey_tbl, block_index ); + if ( !peer_block || memcmp( peer_block, block, sizeof( *peer_block ) ) ) + { + status = pkey_mgr_update_pkey_entry( p_req, peer, block, block_index ); + if ( status == IB_SUCCESS ) + ret_val = TRUE; + else + osm_log( p_log, OSM_LOG_ERROR, + "pkey_mgr_update_peer_port: ERR 0509: " + "pkey_mgr_update_pkey_entry() failed to update " + "pkey table block %d for node 0x%016" PRIx64 + " port %u\n", + block_index, + cl_ntoh64( osm_node_get_node_guid( p_node ) ), + osm_physp_get_port_num( peer ) ); + } + } + + if ( (ret_val == TRUE) && osm_log_is_active( p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_log, OSM_LOG_DEBUG, + "pkey_mgr_update_peer_port: " + "Pkey table was updated for node 0x%016" PRIx64 + " port %u\n", + cl_ntoh64( osm_node_get_node_guid( p_node ) ), + osm_physp_get_port_num( peer ) ); + } + + if (port_info_set) + return TRUE; + return ret_val; +} + +/********************************************************************** + **********************************************************************/ +osm_signal_t +osm_pkey_mgr_process( + IN osm_opensm_t *p_osm ) +{ + cl_qmap_t *p_tbl; + cl_map_item_t *p_next; + osm_prtn_t *p_prtn; + osm_port_t *p_port; + osm_signal_t signal = OSM_SIGNAL_DONE; + osm_node_t *p_node; + + CL_ASSERT( p_osm ); + + OSM_LOG_ENTER( &p_osm->log, osm_pkey_mgr_process ); + + CL_PLOCK_EXCL_ACQUIRE( &p_osm->lock ); + + if ( osm_prtn_make_partitions( &p_osm->log, &p_osm->subn ) != IB_SUCCESS ) + { + osm_log( &p_osm->log, OSM_LOG_ERROR, + "osm_pkey_mgr_process: ERR 0510: " + "osm_prtn_make_partitions() failed\n" ); + goto _err; + } + + /* populate the pending pkey entries by scanning all partitions */ + p_tbl = &p_osm->subn.prtn_pkey_tbl; + p_next = cl_qmap_head( p_tbl ); + while ( p_next != cl_qmap_end( p_tbl ) ) + { + p_prtn = ( osm_prtn_t * ) p_next; + p_next = cl_qmap_next( p_next ); + pkey_mgr_process_partition_table( &p_osm->log, &p_osm->sm.req, + p_prtn, FALSE ); + pkey_mgr_process_partition_table( &p_osm->log, &p_osm->sm.req, + p_prtn, TRUE ); + } + + /* calculate and set new pkey tables */ + p_tbl = &p_osm->subn.port_guid_tbl; + p_next = cl_qmap_head( p_tbl ); + while ( p_next != cl_qmap_end( p_tbl ) ) + { + p_port = ( osm_port_t * ) p_next; + p_next = cl_qmap_next( p_next ); + if ( pkey_mgr_update_port( &p_osm->log, &p_osm->sm.req, p_port ) ) + signal = OSM_SIGNAL_DONE_PENDING; + p_node = osm_port_get_parent_node( p_port ); + if ( ( osm_node_get_type( p_node ) != IB_NODE_TYPE_SWITCH ) && + pkey_mgr_update_peer_port( &p_osm->log, &p_osm->sm.req, + &p_osm->subn, p_port, + !p_osm->subn.opt.no_partition_enforcement ) ) + signal = OSM_SIGNAL_DONE_PENDING; + } + + _err: + CL_PLOCK_RELEASE( &p_osm->lock ); + OSM_LOG_EXIT( &p_osm->log ); + return ( signal ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_pkey_rcv.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_pkey_rcv.c new file mode 100644 index 00000000..1e982114 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_pkey_rcv.c @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_pkey_rcv.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +osm_pkey_rcv_construct( + IN osm_pkey_rcv_t* const p_rcv ) +{ + memset( p_rcv, 0, sizeof(*p_rcv) ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_pkey_rcv_destroy( + IN osm_pkey_rcv_t* const p_rcv ) +{ + CL_ASSERT( p_rcv ); + + OSM_LOG_ENTER( p_rcv->p_log, osm_pkey_rcv_destroy ); + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_pkey_rcv_init( + IN osm_pkey_rcv_t* const p_rcv, + IN osm_req_t* const p_req, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_pkey_rcv_init ); + + osm_pkey_rcv_construct( p_rcv ); + + p_rcv->p_log = p_log; + p_rcv->p_subn = p_subn; + p_rcv->p_lock = p_lock; + p_rcv->p_req = p_req; + + OSM_LOG_EXIT( p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +/* + * WE MIGHT ONLY RECEIVE GET or SET responses + */ +void +osm_pkey_rcv_process( + IN const osm_pkey_rcv_t* const p_rcv, + IN osm_madw_t* const p_madw ) +{ + cl_qmap_t *p_guid_tbl; + ib_pkey_table_t *p_pkey_tbl; + ib_smp_t *p_smp; + osm_port_t *p_port; + osm_physp_t *p_physp; + osm_node_t *p_node; + osm_pkey_context_t *p_context; + ib_net64_t port_guid; + ib_net64_t node_guid; + uint8_t port_num; + uint16_t block_num; + + CL_ASSERT( p_rcv ); + + OSM_LOG_ENTER( p_rcv->p_log, osm_pkey_rcv_process ); + + CL_ASSERT( p_madw ); + + p_smp = osm_madw_get_smp_ptr( p_madw ); + + p_context = osm_madw_get_pkey_context_ptr( p_madw ); + p_pkey_tbl = (ib_pkey_table_t*)ib_smp_get_payload_ptr( p_smp ); + + port_guid = p_context->port_guid; + node_guid = p_context->node_guid; + + CL_ASSERT( p_smp->attr_id == IB_MAD_ATTR_P_KEY_TABLE ); + + p_guid_tbl = &p_rcv->p_subn->port_guid_tbl; + cl_plock_excl_acquire( p_rcv->p_lock ); + p_port = (osm_port_t*)cl_qmap_get( p_guid_tbl, port_guid ); + + if( p_port == (osm_port_t*)cl_qmap_end( p_guid_tbl) ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_pkey_rcv_process: ERR 4806: " + "No port object for port with GUID 0x%" PRIx64 + "\n\t\t\t\tfor parent node GUID 0x%" PRIx64 + ", TID 0x%" PRIx64 "\n", + cl_ntoh64( port_guid ), + cl_ntoh64( node_guid ), + cl_ntoh64( p_smp->trans_id ) ); + goto Exit; + } + + p_node = osm_port_get_parent_node( p_port ); + CL_ASSERT( p_node ); + + block_num = (uint16_t)((cl_ntoh32(p_smp->attr_mod)) & 0x0000FFFF); + /* in case of a non switch node the attr modifier should be ignored */ + if (osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH) + { + port_num = (uint8_t)(((cl_ntoh32( p_smp->attr_mod)) & 0x00FF0000) >> 16 ); + p_physp = osm_node_get_physp_ptr( p_node, port_num ); + } + else + { + p_physp = osm_port_get_default_phys_ptr(p_port); + port_num = p_port->default_port_num; + } + + CL_ASSERT( p_physp ); + + /* + We do not mind if this is a result of a set or get - all we want is to + update the subnet. + */ + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "osm_pkey_rcv_process: " + "Got GetResp(PKey) block:%u port_num %u with GUID 0x%" PRIx64 + " for parent node GUID 0x%" PRIx64 + ", TID 0x%" PRIx64 "\n", + block_num, port_num, + cl_ntoh64( port_guid ), + cl_ntoh64( node_guid ), + cl_ntoh64( p_smp->trans_id ) ); + } + + /* + Determine if we encountered a new Physical Port. + If so, ignore it. + */ + if( !osm_physp_is_valid( p_physp ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_pkey_rcv_process: ERR 4807: " + "Got invalid port number 0x%X\n", + port_num ); + goto Exit; + } + + osm_dump_pkey_block( p_rcv->p_log, + port_guid, block_num, + port_num, p_pkey_tbl, + OSM_LOG_DEBUG ); + + osm_physp_set_pkey_tbl( p_rcv->p_log, p_rcv->p_subn, + p_physp, p_pkey_tbl, block_num ); + + Exit: + cl_plock_release( p_rcv->p_lock ); + + OSM_LOG_EXIT( p_rcv->p_log ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_pkey_rcv_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_pkey_rcv_ctrl.c new file mode 100644 index 00000000..17eb0351 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_pkey_rcv_ctrl.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_pkey_rcv_ctrl.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +static void +__osm_pkey_rcv_ctrl_disp_callback( + IN void *context, + IN void *p_data ) +{ + /* ignore return status when invoked via the dispatcher */ + osm_pkey_rcv_process( ((osm_pkey_rcv_ctrl_t*)context)->p_rcv, + (osm_madw_t*)p_data ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_pkey_rcv_ctrl_construct( + IN osm_pkey_rcv_ctrl_t* const p_ctrl ) +{ + memset( p_ctrl, 0, sizeof(*p_ctrl) ); + p_ctrl->h_disp = CL_DISP_INVALID_HANDLE; +} + +/********************************************************************** + **********************************************************************/ +void +osm_pkey_rcv_ctrl_destroy( + IN osm_pkey_rcv_ctrl_t* const p_ctrl ) +{ + CL_ASSERT( p_ctrl ); + cl_disp_unregister( p_ctrl->h_disp ); +} + + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_pkey_rcv_ctrl_init( + IN osm_pkey_rcv_ctrl_t* const p_ctrl, + IN osm_pkey_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_pkey_rcv_ctrl_init ); + + osm_pkey_rcv_ctrl_construct( p_ctrl ); + p_ctrl->p_log = p_log; + + + p_ctrl->p_rcv = p_rcv; + p_ctrl->p_disp = p_disp; + + p_ctrl->h_disp = cl_disp_register( + p_disp, + OSM_MSG_MAD_PKEY, + __osm_pkey_rcv_ctrl_disp_callback, + p_ctrl ); + + if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_pkey_rcv_ctrl_init: ERR 4901: " + "Dispatcher registration failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return( status ); +} + + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_port.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_port.c new file mode 100644 index 00000000..2ab02d2a --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_port.c @@ -0,0 +1,936 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_port.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_physp_t. + * This object represents an Infiniband Port. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.7 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +osm_physp_construct( + IN osm_physp_t* const p_physp ) +{ + memset( p_physp, 0, sizeof(*p_physp) ); + osm_dr_path_construct( &p_physp->dr_path ); + cl_ptr_vector_construct( &p_physp->slvl_by_port ); + osm_pkey_tbl_construct( &p_physp->pkeys ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_physp_destroy( + IN osm_physp_t* const p_physp ) +{ + size_t num_slvl, i; + + /* the physp might be un-initialized */ + if (p_physp->port_guid) + { + /* free the SL2VL Tables */ + num_slvl = cl_ptr_vector_get_size(&p_physp->slvl_by_port); + for (i = 0; i < num_slvl; i++) + free(cl_ptr_vector_get(&p_physp->slvl_by_port, i)); + cl_ptr_vector_destroy(&p_physp->slvl_by_port); + + /* free the P_Key Tables */ + osm_pkey_tbl_destroy( &p_physp->pkeys ); + + memset( p_physp, 0, sizeof(*p_physp) ); + osm_dr_path_construct( &p_physp->dr_path ); /* clear dr_path */ + } +} + +/********************************************************************** + **********************************************************************/ +void +osm_physp_init( + IN osm_physp_t* const p_physp, + IN const ib_net64_t port_guid, + IN const uint8_t port_num, + IN const struct _osm_node* const p_node, + IN const osm_bind_handle_t h_bind, + IN const uint8_t hop_count, + IN const uint8_t* const p_initial_path ) +{ + uint16_t num_slvl, i; + ib_slvl_table_t *p_slvl; + + CL_ASSERT( p_node ); + + osm_physp_construct( p_physp ); + p_physp->port_guid = port_guid; + p_physp->port_num = port_num; + p_physp->healthy = TRUE; + p_physp->p_node = (struct _osm_node*)p_node; + + osm_dr_path_init( + &p_physp->dr_path, + h_bind, + hop_count, + p_initial_path ); + + /* allocate enough SL2VL tables */ + if (osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH) + { + /* we need node num ports + 1 SL2VL tables */ + num_slvl = osm_node_get_num_physp( p_node ) + 1; + } + else + { + /* An end node - we need only one SL2VL */ + num_slvl = 1; + } + + cl_ptr_vector_init( &p_physp->slvl_by_port, num_slvl, 1); + for (i = 0; i < num_slvl; i++) + { + p_slvl = (ib_slvl_table_t *)malloc(sizeof(ib_slvl_table_t)); + if (p_slvl) + memset(p_slvl, 0, sizeof(ib_slvl_table_t)); + cl_ptr_vector_set(&p_physp->slvl_by_port, i, p_slvl); + } + + /* initialize the pkey table */ + osm_pkey_tbl_init( &p_physp->pkeys ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_port_destroy( + IN osm_port_t* const p_port ) +{ + /* cleanup all mcm recs attached */ + osm_port_remove_all_mgrp( p_port ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_port_init( + IN osm_port_t* const p_port, + IN const ib_node_info_t* p_ni, + IN const osm_node_t* const p_parent_node ) +{ + uint32_t port_index; + ib_net64_t port_guid; + osm_physp_t *p_physp; + uint32_t size; + + CL_ASSERT( p_port ); + CL_ASSERT( p_ni ); + CL_ASSERT( p_parent_node ); + + osm_port_construct( p_port ); + + p_port->p_node = (struct _osm_node *)p_parent_node; + port_guid = p_ni->port_guid; + p_port->guid = port_guid; + + /* + See comment in port_new for info about this... + */ + size = p_ni->num_ports; + + p_port->physp_tbl_size = (uint8_t)(size + 1); + + /* + Get the pointers to the physical node objects "owned" by this + logical port GUID. + For switches, all the ports are owned; for HCA's and routers, + only the singular part that has this GUID is owned. + */ + p_port->default_port_num = 0xFF; + for( port_index = 0; port_index < p_port->physp_tbl_size; port_index++ ) + { + p_physp = osm_node_get_physp_ptr( p_parent_node, port_index ); + if( osm_physp_is_valid( p_physp ) && + port_guid == osm_physp_get_port_guid( p_physp ) ) + { + p_port->tbl[port_index] = p_physp; + /* + Because much of the PortInfo data is only valid + for port 0 on switches, try to keep the lowest + possible value of default_port_num. + */ + if( port_index < p_port->default_port_num ) + p_port->default_port_num = (uint8_t)port_index; + } + else + p_port->tbl[port_index] = NULL; + } + + CL_ASSERT( p_port->default_port_num < 0xFF ); +} + +/********************************************************************** + **********************************************************************/ +osm_port_t* +osm_port_new( + IN const ib_node_info_t* p_ni, + IN const osm_node_t* const p_parent_node ) +{ + osm_port_t* p_port; + uint32_t size; + + /* + The port object already contains one physical port object pointer. + Therefore, subtract 1 from the number of physical ports + used by the switch. This is not done for CA's since they + need to occupy 1 more physp pointer than they physically have since + we still reserve room for a "port 0". + */ + size = p_ni->num_ports; + + p_port = malloc( sizeof(*p_port) + sizeof(void *) * size ); + if( p_port != NULL ) + { + memset( p_port, 0, sizeof(*p_port) + sizeof(void *) * size ); + osm_port_init( p_port, p_ni, p_parent_node ); + } + + return( p_port ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_port_get_lid_range_ho( + IN const osm_port_t* const p_port, + IN uint16_t* const p_min_lid, + IN uint16_t* const p_max_lid ) +{ + uint8_t lmc; + + *p_min_lid = cl_ntoh16( osm_port_get_base_lid( p_port ) ); + lmc = osm_port_get_lmc( p_port ); + *p_max_lid = (uint16_t)(*p_min_lid + (1 << lmc) - 1); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_get_port_by_base_lid( + IN const osm_subn_t* const p_subn, + IN const ib_net16_t lid, + IN OUT const osm_port_t** const pp_port ) +{ + ib_api_status_t status; + uint16_t base_lid; + uint8_t lmc; + + *pp_port = NULL; + + /* Loop on lmc from 0 up through max LMC possible */ + for (lmc = 0; lmc <= IB_PORT_LMC_MAX; lmc++) + { + /* Calculate a base LID assuming this is the real LMC */ + base_lid = cl_ntoh16(lid) & ~((1 << lmc) - 1); + + /* Look for a match */ + status = cl_ptr_vector_at( &p_subn->port_lid_tbl, + base_lid, + (void**)pp_port ); + if ((status == CL_SUCCESS) && (*pp_port != NULL)) + { + /* Determine if base LID "tested" is the real base LID */ + /* This is true if the LMC "tested" is the port's actual LMC */ + if (lmc == osm_port_get_lmc( *pp_port ) ) + { + status = IB_SUCCESS; + goto Found; + } + } + } + *pp_port = NULL; + status = IB_NOT_FOUND; + + Found: + return status; +} + +/********************************************************************** + **********************************************************************/ +void +osm_port_add_new_physp( + IN osm_port_t* const p_port, + IN const uint8_t port_num ) +{ + osm_node_t *p_node; + osm_physp_t *p_physp; + + CL_ASSERT( port_num < p_port->physp_tbl_size ); + + p_node = p_port->p_node; + CL_ASSERT( p_node ); + + p_physp = osm_node_get_physp_ptr( p_node, port_num ); + CL_ASSERT( osm_physp_is_valid( p_physp ) ); + CL_ASSERT( osm_physp_get_port_guid( p_physp ) == p_port->guid ); + p_port->tbl[port_num] = p_physp; + + /* + For switches, we generally want to use Port 0, which is + the management port as the default Physical Port. + The LID value in the PortInfo for example, is only valid + for port 0 on switches. + */ + if( !osm_physp_is_valid( p_port->tbl[p_port->default_port_num] ) ) + { + p_port->default_port_num = port_num; + } + else + { + if( port_num < p_port->default_port_num ) + { + p_port->default_port_num = port_num; + } + } +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_port_add_mgrp( + IN osm_port_t* const p_port, + IN const ib_net16_t mlid ) +{ + ib_api_status_t status = IB_SUCCESS; + osm_mcm_info_t *p_mcm; + + p_mcm = osm_mcm_info_new( mlid ); + if( p_mcm ) + cl_qlist_insert_tail( &p_port->mcm_list, (cl_list_item_t*)p_mcm ); + else + status = IB_INSUFFICIENT_MEMORY; + + return( status ); +} + +/********************************************************************** + **********************************************************************/ +static cl_status_t +__osm_port_mgrp_find_func( + IN const cl_list_item_t* const p_list_item, + IN void* context ) +{ + if( *((ib_net16_t*)context) == ((osm_mcm_info_t*)p_list_item)->mlid ) + return( CL_SUCCESS ); + else + return( CL_NOT_FOUND ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_port_remove_mgrp( + IN osm_port_t* const p_port, + IN const ib_net16_t mlid ) +{ + cl_list_item_t *p_mcm; + + p_mcm = cl_qlist_find_from_head( &p_port->mcm_list, + __osm_port_mgrp_find_func, &mlid ); + + if( p_mcm != cl_qlist_end( &p_port->mcm_list ) ) + { + cl_qlist_remove_item( &p_port->mcm_list, p_mcm ); + osm_mcm_info_delete( (osm_mcm_info_t*)p_mcm ); + } +} + +/********************************************************************** + **********************************************************************/ +void +osm_port_remove_all_mgrp( + IN osm_port_t* const p_port ) +{ + cl_list_item_t *p_mcm; + + p_mcm = cl_qlist_remove_head( &p_port->mcm_list ); + while( p_mcm != cl_qlist_end( &p_port->mcm_list ) ) + { + osm_mcm_info_delete( (osm_mcm_info_t*)p_mcm ); + p_mcm = cl_qlist_remove_head( &p_port->mcm_list ); + } +} + +/********************************************************************** + **********************************************************************/ +uint8_t +osm_physp_calc_link_mtu( + IN osm_log_t* p_log, + IN const osm_physp_t* p_physp ) +{ + const ib_port_info_t* p_old_pi; + const ib_port_info_t* p_remote_pi; + const osm_physp_t* p_remote_physp; + uint8_t mtu; + uint8_t remote_mtu; + + OSM_LOG_ENTER( p_log, osm_physp_calc_link_mtu ); + p_old_pi = osm_physp_get_port_info_ptr( p_physp ); + + /* use the available MTU */ + mtu = ib_port_info_get_mtu_cap( p_old_pi ); + + p_remote_physp = osm_physp_get_remote( p_physp ); + if( p_remote_physp && osm_physp_is_valid( p_remote_physp ) ) + { + p_remote_pi = osm_physp_get_port_info_ptr( p_remote_physp ); + remote_mtu = ib_port_info_get_mtu_cap( p_remote_pi ); + + if( osm_log_is_active( p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_log, OSM_LOG_DEBUG, + "osm_physp_calc_link_mtu: " + "Remote port 0x%016" PRIx64 " port# = 0x%X : " + "MTU = %u. This Port MTU: %u\n", + cl_ntoh64( osm_physp_get_port_guid( p_remote_physp ) ), + osm_physp_get_port_num( p_remote_physp ), + remote_mtu, mtu ); + } + + if( mtu != remote_mtu ) + { + if( mtu > remote_mtu ) + mtu = remote_mtu; + + if( osm_log_is_active( p_log, OSM_LOG_VERBOSE ) ) + { + osm_log( p_log, OSM_LOG_VERBOSE, + "osm_physp_calc_link_mtu: " + "MTU mismatch between ports." + "\n\t\t\t\tPort 0x%016" PRIx64 ", port# 0x%X" + " and port 0x%016" PRIx64 ", port# 0x%X." + "\n\t\t\t\tUsing lower MTU of %u\n", + cl_ntoh64( osm_physp_get_port_guid( p_physp ) ), + osm_physp_get_port_num( p_physp ), + cl_ntoh64( osm_physp_get_port_guid( p_remote_physp ) ), + osm_physp_get_port_num( p_remote_physp ), + mtu ); + } + } + } + + if( mtu == 0 ) + { + osm_log( p_log, OSM_LOG_DEBUG, + "osm_physp_calc_link_mtu: ERR 4101: " + "Invalid MTU = 0. Forcing correction to 256\n" ); + mtu = 1; + } + + OSM_LOG_EXIT( p_log ); + return(mtu); +} + +/********************************************************************** + **********************************************************************/ +uint8_t +osm_physp_calc_link_op_vls( + IN osm_log_t* p_log, + IN const osm_subn_t* p_subn, + IN const osm_physp_t* p_physp ) +{ + const ib_port_info_t* p_old_pi; + const ib_port_info_t* p_remote_pi; + const osm_physp_t* p_remote_physp; + uint8_t op_vls; + uint8_t remote_op_vls; + + OSM_LOG_ENTER( p_log, osm_physp_calc_link_op_vls ); + p_old_pi = osm_physp_get_port_info_ptr( p_physp ); + + /* use the available VL CAP */ + op_vls = ib_port_info_get_vl_cap(p_old_pi); + + p_remote_physp = osm_physp_get_remote( p_physp ); + if( p_remote_physp && osm_physp_is_valid( p_remote_physp ) ) + { + p_remote_pi = osm_physp_get_port_info_ptr( p_remote_physp ); + remote_op_vls = ib_port_info_get_vl_cap(p_remote_pi); + + if( osm_log_is_active( p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_log, OSM_LOG_DEBUG, + "osm_physp_calc_link_op_vls: " + "Remote port 0x%016" PRIx64 " port# = 0x%X : " + "VL_CAP = %u. This port VL_CAP:%u\n", + cl_ntoh64( osm_physp_get_port_guid( p_remote_physp ) ), + osm_physp_get_port_num( p_remote_physp ), + remote_op_vls, + op_vls + ); + } + + if( op_vls != remote_op_vls ) + { + if( op_vls > remote_op_vls ) + op_vls = remote_op_vls; + + if( osm_log_is_active( p_log, OSM_LOG_VERBOSE ) ) + { + osm_log( p_log, OSM_LOG_VERBOSE, + "osm_physp_calc_link_op_vls: " + "OP_VLS mismatch between ports." + "\n\t\t\t\tPort 0x%016" PRIx64 ", port# 0x%X" + " and port 0x%016" PRIx64 ", port# 0x%X." + "\n\t\t\t\tUsing lower OP_VLS of %u\n", + cl_ntoh64( osm_physp_get_port_guid( p_physp ) ), + osm_physp_get_port_num( p_physp ), + cl_ntoh64( osm_physp_get_port_guid( p_remote_physp ) ), + osm_physp_get_port_num( p_remote_physp ), + op_vls ); + } + } + } + + /* support user limitation of max_op_vls */ + if (op_vls > p_subn->opt.max_op_vls) + op_vls = p_subn->opt.max_op_vls; + + if( op_vls == 0 ) + { + osm_log( p_log, OSM_LOG_DEBUG, + "osm_physp_calc_link_op_vls: ERR 4102: " + "Invalid OP_VLS = 0. Forcing correction to 1 (VL0)\n" ); + op_vls = 1; + } + + OSM_LOG_EXIT( p_log ); + return(op_vls); +} + +inline +uint64_t +__osm_ptr_to_key(void const *p) +{ + uint64_t k = 0; + + memcpy(&k, p, sizeof(void *)); + return k; +} + +inline +void * +__osm_key_to_ptr(uint64_t k) +{ + void *p = 0; + + memcpy(&p, &k, sizeof(void *)); + return p; +} + +/********************************************************************** + Traverse the fabric from the SM node following the DR path given and + add every phys port traversed to the map. Avoid tracking the first and + last phys ports (going into the first switch and into the target port). + **********************************************************************/ +cl_status_t +__osm_physp_get_dr_physp_set( + IN osm_log_t* p_log, + IN osm_subn_t const *p_subn, + IN osm_dr_path_t const *p_path, + OUT cl_map_t* p_physp_map) +{ + osm_port_t *p_port; + osm_physp_t *p_physp; + osm_node_t *p_node; + uint8_t hop; + cl_status_t status = CL_SUCCESS; + + OSM_LOG_ENTER( p_log, __osm_physp_get_dr_physp_set ); + + /* find the OSM node */ + p_port = osm_get_port_by_guid(p_subn, p_subn->sm_port_guid); + if (! p_port) + { + osm_log( p_log, OSM_LOG_ERROR, + "__osm_physp_get_dr_nodes_set: ERR 4103: " + "Failed to find the SM own port by guid\n"); + status = CL_ERROR; + goto Exit; + } + + /* get the node of the SM */ + p_node = osm_port_get_parent_node(p_port); + + /* + traverse the path adding the nodes to the table + start after the first dummy hop and stop just before the + last one + */ + for (hop = 1; hop < p_path->hop_count - 1; hop++) + { + /* go out using the phys port of the path */ + p_physp = osm_node_get_physp_ptr(p_node, p_path->path[hop]); + + /* we track the ports we go out along the path */ + if (hop > 1) + cl_map_insert(p_physp_map, __osm_ptr_to_key(p_physp), NULL); + + osm_log( p_log, OSM_LOG_DEBUG, + "__osm_physp_get_dr_nodes_set: " + "Traversed through node: 0x%016" PRIx64 + " port:%u\n", + cl_ntoh64(p_node->node_info.node_guid), + p_path->path[hop]); + + /* make sure we got a valid port and it has a remote port */ + if (!(p_physp && osm_physp_is_valid( p_physp ))) + { + osm_log( p_log, OSM_LOG_ERROR, + "__osm_physp_get_dr_nodes_set: ERR 4104: " + "DR Traversal stopped on invalid port at hop:%u\n", + hop); + status = CL_ERROR; + goto Exit; + } + + if (! (p_physp = osm_physp_get_remote(p_physp))) + { + osm_log( p_log, OSM_LOG_ERROR, + "__osm_physp_get_dr_nodes_set: ERR 4106: " + "DR Traversal stopped on missing remote physp at hop:%u\n", + hop); + status = CL_ERROR; + goto Exit; + } + + p_node = osm_physp_get_node_ptr(p_physp); + } + + Exit: + OSM_LOG_EXIT( p_log ); + return status; +} + +/********************************************************************** + **********************************************************************/ +void +__osm_physp_update_new_dr_path( + IN osm_physp_t const *p_dest_physp, + IN cl_map_t *p_visited_map, + IN osm_bind_handle_t *h_bind ) +{ + cl_list_t tmpPortsList; + osm_physp_t *p_physp, *p_src_physp = NULL; + uint8_t path_array[IB_SUBNET_PATH_HOPS_MAX]; + uint8_t i = 0; + osm_dr_path_t *p_dr_path; + + cl_list_construct( &tmpPortsList ); + cl_list_init( &tmpPortsList, 10 ); + + cl_list_insert_head( &tmpPortsList, p_dest_physp ); + /* get the output port where we need to come from */ + p_physp = (osm_physp_t*)cl_map_get( p_visited_map, + __osm_ptr_to_key(p_dest_physp) ); + while ( p_physp != NULL ) + { + cl_list_insert_head( &tmpPortsList, p_physp ); + /* get the input port through where we reached the output port */ + p_src_physp = p_physp; + p_physp = (osm_physp_t*)cl_map_get( p_visited_map, + __osm_ptr_to_key(p_physp) ); + /* if we reached a null p_physp - this means we are at the begining + of the path. Break. */ + if ( p_physp == NULL ) + break; + /* get the output port */ + p_physp = (osm_physp_t*)cl_map_get( p_visited_map, + __osm_ptr_to_key(p_physp) ); + } + + memset( path_array, 0, sizeof(path_array) ); + p_physp = (osm_physp_t*)cl_list_remove_head( &tmpPortsList ); + while ( p_physp != NULL ) + { + i++; + path_array[i] = p_physp->port_num; + p_physp = (osm_physp_t*)cl_list_remove_head( &tmpPortsList ); + } + if (p_src_physp) + { + p_dr_path = osm_physp_get_dr_path_ptr( p_src_physp ); + osm_dr_path_init( p_dr_path, h_bind, i, path_array ); + } + + cl_list_destroy( &tmpPortsList ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_physp_replace_dr_path_with_alternate_dr_path( + IN osm_log_t *p_log, + IN osm_subn_t const *p_subn, + IN osm_physp_t const *p_dest_physp, + IN osm_bind_handle_t *h_bind + ) +{ + cl_map_t physp_map; + cl_map_t visited_map; + osm_dr_path_t * p_dr_path; + cl_list_t *p_currPortsList; + cl_list_t *p_nextPortsList; + cl_qmap_t const *p_port_tbl; + osm_port_t *p_port; + osm_physp_t *p_physp, *p_remote_physp; + ib_net64_t port_guid; + boolean_t next_list_is_full = TRUE, reached_dest = FALSE; + uint8_t num_ports, port_num; + + /* + initialize the map of all port participating in current dr path + not including first and last switches + */ + cl_map_construct( &physp_map ); + cl_map_init( &physp_map, 4 ); + cl_map_construct( &visited_map ); + cl_map_init( &visited_map, 4 ); + p_dr_path = osm_physp_get_dr_path_ptr( p_dest_physp ); + __osm_physp_get_dr_physp_set(p_log, p_subn, p_dr_path, &physp_map); + + /* + BFS from OSM port until we find the target physp but avoid + going through mapped ports + */ + p_nextPortsList = (cl_list_t*)malloc(sizeof(cl_list_t)); + cl_list_construct( p_nextPortsList ); + cl_list_init( p_nextPortsList, 10 ); + + p_port_tbl = &p_subn->port_guid_tbl; + port_guid = p_subn->sm_port_guid; + + CL_ASSERT( port_guid ); + + p_port = (osm_port_t*)cl_qmap_get( p_port_tbl, port_guid ); + + if( p_port == (osm_port_t*)cl_qmap_end( p_port_tbl ) ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_physp_replace_dr_path_with_alternate_dr_path: ERR 4105: " + "No SM port object\n" ); + goto Exit; + } + + /* + HACK: We are assuming SM is running on HCA, so when getting the default + port we'll get the port connected to the rest of the subnet. If SM is + running on SWITCH - we should try to get a dr path from all switch ports. + */ + p_physp = osm_port_get_default_phys_ptr( p_port ); + + CL_ASSERT( p_physp ); + CL_ASSERT( osm_physp_is_valid( p_physp ) ); + + cl_list_insert_tail( p_nextPortsList, p_physp ); + + while (next_list_is_full == TRUE) + { + next_list_is_full = FALSE; + p_currPortsList = p_nextPortsList; + p_nextPortsList = (cl_list_t*)malloc(sizeof(cl_list_t)); + cl_list_construct( p_nextPortsList ); + cl_list_init( p_nextPortsList, 10 ); + p_physp = (osm_physp_t*)cl_list_remove_head( p_currPortsList ); + while ( p_physp != NULL ) + { + /* If we are in a switch - need to go out through all the other + physical ports of the switch */ + num_ports = osm_node_get_num_physp( p_physp->p_node ); + + for (port_num = 1 ; port_num < num_ports ; port_num++) + { + if (osm_node_get_type( p_physp->p_node ) == IB_NODE_TYPE_SWITCH) + p_remote_physp = osm_node_get_physp_ptr( p_physp->p_node, port_num ); + else + /* this is HCA or router - the remote port is just the port connected + on the other side */ + p_remote_physp = p_physp->p_remote_physp; + + /* + make sure that all of the following occurred: + 1. The port isn't NULL + 2. The port is a valid port + 3. This is not the port we came from + 4. The port is not in the physp_map + 5. This port haven't been visited before + */ + if ( p_remote_physp && + osm_physp_is_valid ( p_remote_physp ) && + p_remote_physp != p_physp && + cl_map_get( &physp_map, __osm_ptr_to_key(p_remote_physp)) == NULL && + cl_map_get( &visited_map, __osm_ptr_to_key(p_remote_physp)) == NULL ) + { + /* Insert the port into the visited_map, and save its source port */ + cl_map_insert( &visited_map, __osm_ptr_to_key(p_remote_physp), p_physp ); + + /* Is this the p_dest_physp? */ + if ( p_remote_physp == p_dest_physp ) + { + /* update the new dr path */ + __osm_physp_update_new_dr_path( p_dest_physp, &visited_map, h_bind ); + reached_dest = TRUE; + break; + } + + /* add the p_remote_physp to the nextPortsList */ + cl_list_insert_tail( p_nextPortsList, p_remote_physp ); + next_list_is_full = TRUE; + } + } + + p_physp = (osm_physp_t*)cl_list_remove_head( p_currPortsList ); + if ( reached_dest == TRUE ) + { + /* free the rest of the currPortsList */ + while ( p_physp != NULL ) + p_physp = (osm_physp_t*)cl_list_remove_head( p_currPortsList ); + /* free the nextPortsList, if items were added to it */ + p_physp = (osm_physp_t*)cl_list_remove_head( p_nextPortsList ); + while ( p_physp != NULL ) + p_physp = (osm_physp_t*)cl_list_remove_head( p_nextPortsList ); + next_list_is_full = FALSE; + } + } + cl_list_destroy( p_currPortsList ); + free(p_currPortsList); + } + + /* cleanup */ + Exit: + cl_list_destroy( p_nextPortsList ); + free( p_nextPortsList ); + cl_map_destroy( &physp_map ); + cl_map_destroy( &visited_map ); +} + +/********************************************************************** + **********************************************************************/ +boolean_t +osm_link_is_healthy( + IN const osm_physp_t* const p_physp ) +{ + osm_physp_t* p_remote_physp; + CL_ASSERT( p_physp ); + p_remote_physp = p_physp->p_remote_physp; + if (p_remote_physp != NULL && osm_physp_is_valid(p_remote_physp) ) + return( (p_physp->healthy)&(p_remote_physp->healthy) ); + /* the other side is not known - consider the link as healthy */ + return(TRUE); +} + +/********************************************************************** + **********************************************************************/ +void +osm_physp_set_pkey_tbl( + IN osm_log_t* p_log, + IN const osm_subn_t* p_subn, + IN osm_physp_t* const p_physp, + IN ib_pkey_table_t *p_pkey_tbl, + IN uint16_t block_num ) +{ + uint16_t max_blocks; + + CL_ASSERT( p_pkey_tbl ); + CL_ASSERT( osm_physp_is_valid( p_physp ) ); + /* + (14.2.5.7) - the block number valid values are 0-2047, and are further + limited by the size of the P_Key table specified by the PartitionCap on the + node. + */ + if (!p_physp->p_node->sw || p_physp->port_num == 0 ) + { + /* + The maximum blocks is defined in the node info: partition cap for CA, + routers and switch management ports. + */ + max_blocks = (cl_ntoh16(p_physp->p_node->node_info.partition_cap) + + IB_NUM_PKEY_ELEMENTS_IN_BLOCK - 1) + / IB_NUM_PKEY_ELEMENTS_IN_BLOCK; + } + else + { + /* + This is a switch, and not a management port. The maximum blocks is defined + in the switch info: partition enforcement cap. + */ + max_blocks = + (cl_ntoh16(p_physp->p_node->sw->switch_info.enforce_cap) + + IB_NUM_PKEY_ELEMENTS_IN_BLOCK - 1) / IB_NUM_PKEY_ELEMENTS_IN_BLOCK; + } + + if ( block_num >= max_blocks ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_physp_set_pkey_tbl: ERR 4108: " + "Got illegal set for block number:%u " + "For GUID: %" PRIx64 " port number:0x%X\n", + block_num, + cl_ntoh64(p_physp->p_node->node_info.node_guid), + p_physp->port_num ); + return; + } + + osm_pkey_tbl_set( &p_physp->pkeys, block_num, p_pkey_tbl); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_port_info_rcv.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_port_info_rcv.c new file mode 100644 index 00000000..bdf1b613 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_port_info_rcv.c @@ -0,0 +1,870 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_port_info_rcv.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_pi_rcv_t. + * This object represents the PortInfo Receiver object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.8 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +static void +__osm_pi_rcv_set_sm( + IN const osm_pi_rcv_t* const p_rcv, + IN osm_physp_t* const p_physp ) +{ + osm_bind_handle_t h_bind; + osm_dr_path_t *p_dr_path; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_pi_rcv_set_sm ); + + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_pi_rcv_set_sm: " + "Setting 'IS_SM' bit in port attributes\n" ); + } + + p_dr_path = osm_physp_get_dr_path_ptr( p_physp ); + h_bind = osm_dr_path_get_bind_handle( p_dr_path ); + /* + The 'IS_SM' bit isn't already set, so set it. + */ + osm_vendor_set_sm( h_bind, TRUE ); + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_pi_rcv_process_endport( + IN const osm_pi_rcv_t* const p_rcv, + IN osm_physp_t* const p_physp, + IN const ib_port_info_t* const p_pi ) +{ + osm_madw_context_t context; + ib_api_status_t status; + ib_net64_t port_guid; + uint8_t rate, mtu; + cl_qmap_t* p_sm_tbl; + osm_remote_sm_t* p_sm; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_pi_rcv_process_endport ); + + port_guid = osm_physp_get_port_guid( p_physp ); + + /* HACK extended port 0 should be handled too! */ + if (osm_physp_get_port_num( p_physp ) != 0) + { + /* track the minimal endport MTU and rate */ + mtu = ib_port_info_get_mtu_cap(p_pi); + if (mtu < p_rcv->p_subn->min_ca_mtu) + { + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "__osm_pi_rcv_process_endport: " + "Setting endport minimal MTU to:%u defined by port:0x%" + PRIx64 "\n", + mtu, + cl_ntoh64( port_guid ) ); + p_rcv->p_subn->min_ca_mtu = mtu; + } + + rate = ib_port_info_compute_rate( p_pi ); + if (rate < p_rcv->p_subn->min_ca_rate) + { + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "__osm_pi_rcv_process_endport: " + "Setting endport minimal rate to:%u defined by port:0x%" + PRIx64 "\n", + rate, + cl_ntoh64( port_guid ) ); + p_rcv->p_subn->min_ca_rate = rate; + } + } + + if( port_guid == p_rcv->p_subn->sm_port_guid ) + { + /* + We received the PortInfo for our own port. + */ + if( !(p_pi->capability_mask & IB_PORT_CAP_IS_SM ) ) + { + /* + Set the IS_SM bit to indicate our port hosts an SM. + */ + __osm_pi_rcv_set_sm( p_rcv, p_physp ); + } + } + else + { + /* + Before querying the SM - we want to make sure we clean its state, so + if the querying fails we recognize that this SM is not active. + */ + p_sm_tbl = &p_rcv->p_subn->sm_guid_tbl; + p_sm = (osm_remote_sm_t*)cl_qmap_get( p_sm_tbl, port_guid ); + if( p_sm != (osm_remote_sm_t*)cl_qmap_end( p_sm_tbl ) ) + { + /* clean it up */ + p_sm->smi.pri_state = 0xF0 & p_sm->smi.pri_state; + } + + if( p_pi->capability_mask & IB_PORT_CAP_IS_SM ) + { + if( p_rcv->p_subn->opt.ignore_other_sm ) + { + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "__osm_pi_rcv_process_endport: " + "Ignoring SM on port 0x%" PRIx64 "\n", + cl_ntoh64( port_guid ) ); + } + else + { + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "__osm_pi_rcv_process_endport: " + "Detected another SM. Requesting SMInfo" + "\n\t\t\t\tPort 0x%" PRIx64 "\n", + cl_ntoh64( port_guid ) ); + } + + /* + This port indicates it's an SM and it's not our own port. + Acquire the SMInfo Attribute. + */ + memset( &context, 0, sizeof(context) ); + context.smi_context.set_method = FALSE; + status = osm_req_get( p_rcv->p_req, + osm_physp_get_dr_path_ptr( p_physp ), + IB_MAD_ATTR_SM_INFO, + 0, + CL_DISP_MSGID_NONE, + &context ); + + if( status != IB_SUCCESS ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_pi_rcv_process_endport: ERR 0F05: " + "Failure requesting SMInfo (%s)\n", + ib_get_err_str( status ) ); + } + } + } + } + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + The plock must be held before calling this function. +**********************************************************************/ +static void +__osm_pi_rcv_process_switch_port( + IN const osm_pi_rcv_t* const p_rcv, + IN osm_node_t* const p_node, + IN osm_physp_t* const p_physp, + IN const ib_port_info_t* const p_pi ) +{ + ib_api_status_t status = IB_SUCCESS; + osm_madw_context_t context; + osm_physp_t *p_remote_physp; + osm_node_t *p_remote_node; + ib_net16_t orig_lid; + uint8_t port_num; + uint8_t remote_port_num; + osm_dr_path_t path; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_pi_rcv_process_switch_port ); + + /* + Check the state of the physical port. + If there appears to be something on the other end of the wire, + then ask for NodeInfo. Ignore the switch management port. + */ + port_num = osm_physp_get_port_num( p_physp ); + /* if in_sweep_hop_0 is TRUE, then this means the SM in on the switch, + and we got switchInfo of our local switch. Do not continue + probing through the switch. */ + if( port_num != 0 && p_rcv->p_subn->in_sweep_hop_0 == FALSE) + { + switch( ib_port_info_get_port_state( p_pi ) ) + { + case IB_LINK_DOWN: + p_remote_physp = osm_physp_get_remote( p_physp ); + if( p_remote_physp && osm_physp_is_valid( p_remote_physp ) ) + { + p_remote_node = osm_physp_get_node_ptr( p_remote_physp ); + remote_port_num = osm_physp_get_port_num( p_remote_physp ); + + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "__osm_pi_rcv_process_switch_port: " + "Unlinking local node 0x%" PRIx64 ", port 0x%X" + "\n\t\t\t\tand remote node 0x%" PRIx64 + ", port 0x%X\n", + cl_ntoh64( osm_node_get_node_guid( p_node ) ), + port_num, + cl_ntoh64( osm_node_get_node_guid( p_remote_node ) ), + remote_port_num ); + + osm_node_unlink( p_node, (uint8_t)port_num, + p_remote_node, (uint8_t)remote_port_num ); + + } + break; + + case IB_LINK_INIT: + case IB_LINK_ARMED: + case IB_LINK_ACTIVE: + /* + To avoid looping forever, only probe the port if it + is NOT the port that responded to the SMP. + + Request node info from the other end of this link: + 1) Copy the current path from the parent node. + 2) Extend the path to the next hop thru this port. + 3) Request node info with the new path + + */ + if( p_pi->local_port_num != osm_physp_get_port_num( p_physp ) ) + { + path = *osm_physp_get_dr_path_ptr( p_physp ); + + osm_dr_path_extend( &path, osm_physp_get_port_num( p_physp ) ); + + context.ni_context.node_guid = osm_node_get_node_guid( p_node ); + context.ni_context.port_num = osm_physp_get_port_num( p_physp ); + + status = osm_req_get( p_rcv->p_req, + &path, + IB_MAD_ATTR_NODE_INFO, + 0, + CL_DISP_MSGID_NONE, + &context ); + + if( status != IB_SUCCESS ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_pi_rcv_process_switch_port: ERR 0F02: " + "Failure initiating NodeInfo request (%s)\n", + ib_get_err_str(status) ); + } + } + else + { + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_pi_rcv_process_switch_port: " + "Skipping SMP responder port 0x%X\n", + p_pi->local_port_num ); + } + } + break; + + default: + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_pi_rcv_process_switch_port: ERR 0F03: " + "Unknown link state = %u, port = 0x%X\n", + ib_port_info_get_port_state( p_pi ), + p_pi->local_port_num ); + break; + } + } + + /* + Update the PortInfo attribute. + */ + osm_physp_set_port_info( p_physp, p_pi ); + + if (port_num == 0) + { + /* This is switch management port 0 */ + if ( ( orig_lid = osm_physp_trim_base_lid_to_valid_range( p_physp ) ) ) + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_pi_rcv_process_switch_port: ERR 0F04: " + "Invalid base LID 0x%x corrected\n", + cl_ntoh16( orig_lid ) ); + /* Determine if base switch port 0 */ + if (p_node->sw && + !ib_switch_info_is_enhanced_port0(&p_node->sw->switch_info)) + { + /* PortState is not used on BSP0 but just in case it is DOWN */ + p_physp->port_info = *p_pi; + } + __osm_pi_rcv_process_endport(p_rcv, p_physp, p_pi); + } + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_pi_rcv_process_ca_port( + IN const osm_pi_rcv_t* const p_rcv, + IN osm_node_t* const p_node, + IN osm_physp_t* const p_physp, + IN const ib_port_info_t* const p_pi ) +{ + ib_net16_t orig_lid; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_pi_rcv_process_ca_port ); + + UNUSED_PARAM( p_node ); + + osm_physp_set_port_info( p_physp, p_pi ); + + if ( (orig_lid = osm_physp_trim_base_lid_to_valid_range( p_physp ) ) ) + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_pi_rcv_process_ca_port: ERR 0F08: " + "Invalid base LID 0x%x corrected\n", + cl_ntoh16 ( orig_lid ) ); + + __osm_pi_rcv_process_endport(p_rcv, p_physp, p_pi); + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_pi_rcv_process_router_port( + IN const osm_pi_rcv_t* const p_rcv, + IN osm_node_t* const p_node, + IN osm_physp_t* const p_physp, + IN const ib_port_info_t* const p_pi ) +{ + ib_net16_t orig_lid; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_pi_rcv_process_router_port ); + + UNUSED_PARAM( p_node ); + + /* + Update the PortInfo attribute. + */ + osm_physp_set_port_info( p_physp, p_pi ); + + if ( (orig_lid = osm_physp_trim_base_lid_to_valid_range( p_physp ) ) ) + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_pi_rcv_process_router_port: ERR 0F09: " + "Invalid base LID 0x%x corrected\n", + cl_ntoh16 ( orig_lid) ); + + __osm_pi_rcv_process_endport(p_rcv, p_physp, p_pi); + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +#define IBM_VENDOR_ID (0x5076) +/********************************************************************** + **********************************************************************/ +void osm_pkey_get_tables( + IN osm_log_t *p_log, + IN osm_req_t *p_req, + IN osm_subn_t* const p_subn, + IN osm_node_t* const p_node, + IN osm_physp_t* const p_physp ) { + + osm_madw_context_t context; + ib_api_status_t status; + osm_dr_path_t path; + uint8_t port_num; + uint16_t block_num, max_blocks; + uint32_t attr_mod_ho; + + OSM_LOG_ENTER( p_log, osm_pkey_get_tables ); + + path = *osm_physp_get_dr_path_ptr( p_physp ); + + context.pkey_context.node_guid = + osm_node_get_node_guid( p_node ); + context.pkey_context.port_guid = + osm_physp_get_port_guid( p_physp ); + context.pkey_context.set_method = FALSE; + + port_num = p_physp->port_num; + + if (!p_node->sw || port_num == 0) + { + /* The maximum blocks is defined by the node info partition cap for CA, + router, and switch management ports. */ + max_blocks = (cl_ntoh16(p_node->node_info.partition_cap)+IB_NUM_PKEY_ELEMENTS_IN_BLOCK -1) + / IB_NUM_PKEY_ELEMENTS_IN_BLOCK ; + } + else + { + /* This is a switch, and not a management port. The maximum blocks + is defined in the switch info partition enforcement cap. */ + + /* Check for IBM eHCA firmware defect in reporting partition enforcement cap */ + if (cl_ntoh32(ib_node_info_get_vendor_id(&p_node->node_info)) == IBM_VENDOR_ID) + p_node->sw->switch_info.enforce_cap = 0; + + /* Bail out if this is a switch with no partition enforcement capability */ + if (cl_ntoh16(p_node->sw->switch_info.enforce_cap) == 0) + goto Exit; + + max_blocks = (cl_ntoh16(p_node->sw->switch_info.enforce_cap) + + IB_NUM_PKEY_ELEMENTS_IN_BLOCK -1) / IB_NUM_PKEY_ELEMENTS_IN_BLOCK ; + } + + for (block_num = 0 ; block_num < max_blocks ; block_num++) + { + if (osm_node_get_type( p_node ) != IB_NODE_TYPE_SWITCH) + attr_mod_ho = block_num; + else + attr_mod_ho = block_num | (port_num << 16); + status = osm_req_get( p_req, + &path, + IB_MAD_ATTR_P_KEY_TABLE, + cl_hton32(attr_mod_ho), + CL_DISP_MSGID_NONE, + &context ); + + if( status != IB_SUCCESS ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_physp_has_pkey: ERR 0F12: " + "Failure initiating PKeyTable request (%s)\n", + ib_get_err_str(status)); + goto Exit; + } + } + + Exit: + OSM_LOG_EXIT( p_log ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_pi_rcv_get_pkey_slvl_vla_tables( + IN const osm_pi_rcv_t* const p_rcv, + IN osm_node_t* const p_node, + IN osm_physp_t* const p_physp ) +{ + OSM_LOG_ENTER( p_rcv->p_log, __osm_pi_rcv_get_pkey_slvl_vla_tables ); + + osm_pkey_get_tables( p_rcv->p_log, p_rcv->p_req, p_rcv->p_subn, + p_node, p_physp ); + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_pi_rcv_construct( + IN osm_pi_rcv_t* const p_rcv ) +{ + memset( p_rcv, 0, sizeof(*p_rcv) ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_pi_rcv_destroy( + IN osm_pi_rcv_t* const p_rcv ) +{ + OSM_LOG_ENTER( p_rcv->p_log, osm_pi_rcv_destroy ); + + CL_ASSERT( p_rcv ); + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_pi_rcv_init( + IN osm_pi_rcv_t* const p_rcv, + IN osm_req_t* const p_req, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN osm_state_mgr_t* const p_state_mgr, + IN cl_plock_t* const p_lock ) +{ + ib_api_status_t status = IB_SUCCESS; + OSM_LOG_ENTER( p_log, osm_pi_rcv_init ); + + osm_pi_rcv_construct( p_rcv ); + + p_rcv->p_log = p_log; + p_rcv->p_subn = p_subn; + p_rcv->p_lock = p_lock; + p_rcv->p_req = p_req; + p_rcv->p_state_mgr = p_state_mgr; + + OSM_LOG_EXIT( p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_pi_rcv_process_set( + IN const osm_pi_rcv_t* const p_rcv, + IN osm_port_t* const p_port, + IN const uint8_t port_num, + IN osm_madw_t* const p_madw ) +{ + osm_physp_t *p_physp; + osm_node_t *p_node; + ib_net64_t port_guid; + ib_smp_t *p_smp; + ib_port_info_t *p_pi; + osm_pi_context_t *p_context; + osm_log_level_t level; + + OSM_LOG_ENTER( p_rcv->p_log, osm_pi_rcv_process_set ); + + p_context = osm_madw_get_pi_context_ptr( p_madw ); + + p_physp = osm_port_get_phys_ptr( p_port, port_num ); + CL_ASSERT( p_physp ); + CL_ASSERT( osm_physp_is_valid( p_physp ) ); + + port_guid = osm_physp_get_port_guid( p_physp ); + p_node = osm_port_get_parent_node( p_port ); + CL_ASSERT( p_node ); + + p_smp = osm_madw_get_smp_ptr( p_madw ); + p_pi = (ib_port_info_t*)ib_smp_get_payload_ptr( p_smp ); + + /* check for error */ + if (!p_context->ignore_errors && (cl_ntoh16(p_smp->status) & 0x7fff)) + { + /* If port already ACTIVE, don't treat status 7 as error */ + if (p_context->active_transition && + (cl_ntoh16(p_smp->status) & 0x7fff) == 0x1c) + { + level = OSM_LOG_INFO; + osm_log( p_rcv->p_log, OSM_LOG_INFO, + "osm_pi_rcv_process_set: " + "Received error status 0x%x for SetResp() during ACTIVE transition\n", + cl_ntoh16(p_smp->status) & 0x7fff); + /* Should there be a subsequent Get to validate that port is ACTIVE ? */ + } + else + { + level = OSM_LOG_ERROR; + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_pi_rcv_process_set: ERR 0F10: " + "Received error status for SetResp()\n"); + } + osm_dump_port_info( + p_rcv->p_log, + osm_node_get_node_guid( p_node ), + port_guid, + port_num, + p_pi, + level); + } + + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "osm_pi_rcv_process_set: " + "Received logical SetResp() for GUID 0x%" PRIx64 + ", port num 0x%X" + "\n\t\t\t\tfor parent node GUID 0x%" PRIx64 + " TID 0x%" PRIx64 "\n", + cl_ntoh64( port_guid ), + port_num, + cl_ntoh64( osm_node_get_node_guid( p_node ) ), + cl_ntoh64( p_smp->trans_id ) ); + } + + osm_physp_set_port_info( p_physp, p_pi ); + + /* We got a PortInfoSetResp - set the got_set_resp flag to TRUE */ + p_physp->got_set_resp = TRUE; + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_pi_rcv_process( + IN const osm_pi_rcv_t* const p_rcv, + IN osm_madw_t* const p_madw ) +{ + cl_qmap_t *p_guid_tbl; + ib_port_info_t *p_pi; + ib_smp_t *p_smp; + osm_port_t *p_port; + osm_physp_t *p_physp; + osm_dr_path_t *p_dr_path; + osm_node_t *p_node; + osm_pi_context_t *p_context; + ib_net64_t port_guid; + ib_net64_t node_guid; + uint8_t port_num; + + OSM_LOG_ENTER( p_rcv->p_log, osm_pi_rcv_process ); + + CL_ASSERT( p_rcv ); + CL_ASSERT( p_madw ); + + p_smp = osm_madw_get_smp_ptr( p_madw ); + p_context = osm_madw_get_pi_context_ptr( p_madw ); + p_pi = (ib_port_info_t*)ib_smp_get_payload_ptr( p_smp ); + + CL_ASSERT( p_smp->attr_id == IB_MAD_ATTR_PORT_INFO ); + + /* On receipt of client reregister, clear the reregister bit so + reregistering won't be sent again and again */ + if ( ib_port_info_get_client_rereg( p_pi ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "osm_pi_rcv_process: " + "Client reregister received on response\n"); + ib_port_info_set_client_rereg( p_pi, 0 ); + } + + port_num = (uint8_t)cl_ntoh32( p_smp->attr_mod ); + + port_guid = p_context->port_guid; + node_guid = p_context->node_guid; + + osm_dump_port_info( p_rcv->p_log, + node_guid, port_guid, port_num, p_pi, + OSM_LOG_DEBUG ); + + /* + we might get a response during a light sweep looking for a change in + the status of a remote port that did not respond in earlier sweeps. + So if the context of the Get was light_sweep - we do not need to + do anything with the response - just flag that we need a heavy sweep + */ + if (p_context->light_sweep == TRUE) + { + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "osm_pi_rcv_process: " + "Got light sweep response from remote port of parent node " + "GUID 0x%" PRIx64 " port 0x%016" PRIx64 + ", Commencing heavy sweep\n", + cl_ntoh64( node_guid ), + cl_ntoh64( port_guid ) ); + osm_state_mgr_process( p_rcv->p_state_mgr, + OSM_SIGNAL_CHANGE_DETECTED ); + goto Exit; + } + + p_guid_tbl = &p_rcv->p_subn->port_guid_tbl; + CL_PLOCK_EXCL_ACQUIRE( p_rcv->p_lock ); + p_port = (osm_port_t*)cl_qmap_get( p_guid_tbl, port_guid ); + + if( p_port == (osm_port_t*)cl_qmap_end( p_guid_tbl) ) + { + CL_PLOCK_RELEASE( p_rcv->p_lock ); + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_pi_rcv_process: ERR 0F06: " + "No port object for port with GUID 0x%" PRIx64 + "\n\t\t\t\tfor parent node GUID 0x%" PRIx64 + ", TID 0x%" PRIx64 "\n", + cl_ntoh64( port_guid ), + cl_ntoh64( node_guid ), + cl_ntoh64( p_smp->trans_id ) ); + goto Exit; + } + + /* + If we were setting the PortInfo, then receiving + this attribute was not part of sweeping the subnet. + In this case, just update the PortInfo attribute. + + In an unfortunate blunder, the IB spec defines the + return method for Set() as a GetResp(). Thus, we can't + use the method (what would have been SetResp()) to determine + our course of action. So, we have to carry this extra + boolean around to determine if we were doing Get() or Set(). + */ + if( p_context->set_method ) + { + osm_pi_rcv_process_set( p_rcv, p_port, port_num, p_madw ); + } + else + { + osm_port_discovery_count_inc( p_port ); + + /* + This PortInfo arrived because we did a Get() method, + most likely due to a subnet sweep in progress. + */ + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "osm_pi_rcv_process: " + "Discovered port num 0x%X with GUID 0x%" PRIx64 + " for parent node GUID 0x%" PRIx64 + ", TID 0x%" PRIx64 "\n", + port_num, + cl_ntoh64( port_guid ), + cl_ntoh64( node_guid ), + cl_ntoh64( p_smp->trans_id ) ); + } + + p_node = osm_port_get_parent_node( p_port ); + p_physp = osm_node_get_physp_ptr( p_node, port_num ); + + CL_ASSERT( p_node ); + CL_ASSERT( p_physp ); + + /* + Determine if we encountered a new Physical Port. + If so, initialize the new Physical Port then + continue processing as normal. + */ + if( !osm_physp_is_valid( p_physp ) ) + { + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "osm_pi_rcv_process: " + "Initializing port number 0x%X\n", + port_num ); + } + + osm_physp_init( p_physp, + port_guid, + port_num, + p_node, + osm_madw_get_bind_handle( p_madw ), + p_smp->hop_count, + p_smp->initial_path ); + + osm_port_add_new_physp( p_port, port_num ); + } + else + { + /* + Update the directed route path to this port + in case the old path is no longer usable. + */ + p_dr_path = osm_physp_get_dr_path_ptr( p_physp ); + osm_dr_path_init( p_dr_path, + osm_madw_get_bind_handle( p_madw ), + p_smp->hop_count, p_smp->initial_path ); + } + + /* + Check if the update_sm_base_lid in the context is TRUE. + If it is - then update the master_sm_base_lid of the variable + in the subnet. + */ + if (p_context->update_master_sm_base_lid == TRUE) + { + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "osm_pi_rcv_process: " + "update_master_sm is TRUE. " + "Updating master_sm_base_lid to:%u\n", + p_pi->master_sm_base_lid ); + + p_rcv->p_subn->master_sm_base_lid = p_pi->master_sm_base_lid; + } + + switch( osm_node_get_type( p_node ) ) + { + case IB_NODE_TYPE_CA: + __osm_pi_rcv_process_ca_port( p_rcv, + p_node, p_physp, p_pi ); + break; + case IB_NODE_TYPE_ROUTER: + __osm_pi_rcv_process_router_port( p_rcv, + p_node, p_physp, p_pi ); + break; + case IB_NODE_TYPE_SWITCH: + __osm_pi_rcv_process_switch_port( p_rcv, + p_node, p_physp, p_pi ); + break; + default: + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_pi_rcv_process: ERR 0F07: " + "Unknown node type %u with GUID 0x%" PRIx64 "\n", + osm_node_get_type( p_node ), + cl_ntoh64( node_guid ) ); + break; + } + + /* + Get the tables on the physp. + */ + __osm_pi_rcv_get_pkey_slvl_vla_tables( p_rcv, p_node, p_physp ); + + } + + CL_PLOCK_RELEASE( p_rcv->p_lock ); + + Exit: + /* + Release the lock before jumping here!! + */ + OSM_LOG_EXIT( p_rcv->p_log ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_port_info_rcv_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_port_info_rcv_ctrl.c new file mode 100644 index 00000000..ff609054 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_port_info_rcv_ctrl.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_port_info_rcv_ctrl.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_pi_rcv_ctrl_t. + * This object represents the PortInfo request controller object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +__osm_pi_rcv_ctrl_disp_callback( + IN void *context, + IN void *p_data ) +{ + /* ignore return status when invoked via the dispatcher */ + osm_pi_rcv_process( ((osm_pi_rcv_ctrl_t*)context)->p_rcv, + (osm_madw_t*)p_data ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_pi_rcv_ctrl_construct( + IN osm_pi_rcv_ctrl_t* const p_ctrl ) +{ + memset( p_ctrl, 0, sizeof(*p_ctrl) ); + p_ctrl->h_disp = CL_DISP_INVALID_HANDLE; +} + +/********************************************************************** + **********************************************************************/ +void +osm_pi_rcv_ctrl_destroy( + IN osm_pi_rcv_ctrl_t* const p_ctrl ) +{ + CL_ASSERT( p_ctrl ); + cl_disp_unregister( p_ctrl->h_disp ); +} + + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_pi_rcv_ctrl_init( + IN osm_pi_rcv_ctrl_t* const p_ctrl, + IN osm_pi_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_pi_rcv_ctrl_init ); + + osm_pi_rcv_ctrl_construct( p_ctrl ); + p_ctrl->p_log = p_log; + + p_ctrl->p_rcv = p_rcv; + p_ctrl->p_disp = p_disp; + + p_ctrl->h_disp = cl_disp_register( + p_disp, + OSM_MSG_MAD_PORT_INFO, + __osm_pi_rcv_ctrl_disp_callback, + p_ctrl ); + + if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_pi_rcv_ctrl_init: ERR 1001: " + "Dispatcher registration failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return( status ); +} + + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_prtn.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_prtn.c new file mode 100644 index 00000000..4440553d --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_prtn.c @@ -0,0 +1,399 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ + + +/* + * Abstract: + * Implementation of osm_prtn_t. + * This object represents an IBA partition. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision$ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern int osm_prtn_config_parse_file(osm_log_t * const p_log, + osm_subn_t * const p_subn, + const char *file_name); + +static uint16_t global_pkey_counter; + +osm_prtn_t* osm_prtn_new( + IN const char *name, + IN const uint16_t pkey ) +{ + osm_prtn_t *p = malloc(sizeof(*p)); + if (!p) + return NULL; + + memset(p, 0, sizeof(*p)); + p->pkey = pkey; + p->sl = OSM_DEFAULT_SL; + cl_map_construct(&p->full_guid_tbl); + cl_map_init(&p->full_guid_tbl, 32); + cl_map_construct(&p->part_guid_tbl); + cl_map_init(&p->part_guid_tbl, 32); + + if (name && *name) + strncpy(p->name, name, sizeof(p->name)); + else + snprintf(p->name, sizeof(p->name), "%04x", cl_ntoh16(pkey)); + + return p; +} + +void osm_prtn_delete( + IN OUT osm_prtn_t** const pp_prtn ) +{ + osm_prtn_t *p = *pp_prtn; + + cl_map_remove_all(&p->full_guid_tbl); + cl_map_destroy(&p->full_guid_tbl); + cl_map_remove_all(&p->part_guid_tbl); + cl_map_destroy(&p->part_guid_tbl); + free(p); + *pp_prtn = NULL; +} + +ib_api_status_t osm_prtn_add_port(osm_log_t *p_log, osm_subn_t *p_subn, + osm_prtn_t *p, ib_net64_t guid, boolean_t full) +{ + cl_qmap_t *p_port_tbl = &p_subn->port_guid_tbl; + ib_api_status_t status = IB_SUCCESS; + cl_map_t *p_tbl; + osm_port_t *p_port; + osm_physp_t *p_physp; + + p_port = (osm_port_t *)cl_qmap_get(p_port_tbl, guid); + if (!p_port || p_port == (osm_port_t *)cl_qmap_end(p_port_tbl)) { + osm_log(p_log, OSM_LOG_VERBOSE, "osm_prtn_add_port: " + "port 0x%" PRIx64 " not found\n", + cl_ntoh64(guid)); + return status; + } + + p_physp = osm_port_get_default_phys_ptr(p_port); + if (!p_physp) { + osm_log(p_log, OSM_LOG_VERBOSE, "osm_prtn_add_port: " + "no physical for port 0x%" PRIx64 "\n", + cl_ntoh64(guid)); + return status; + } + + if (cl_map_remove(&p->part_guid_tbl, guid) || + cl_map_remove(&p->full_guid_tbl, guid)) { + osm_log(p_log, OSM_LOG_VERBOSE, "osm_prtn_add_port: " + "port 0x%" PRIx64 " already in " + "partition \'%s\' (0x%04x). Will overwrite\n", + cl_ntoh64(guid), p->name, cl_ntoh16(p->pkey)); + } + + p_tbl = (full == TRUE) ? &p->full_guid_tbl : &p->part_guid_tbl ; + + if (cl_map_insert(p_tbl, guid, p_physp) == NULL) + return IB_INSUFFICIENT_MEMORY; + + return status; +} + +ib_api_status_t osm_prtn_add_all(osm_log_t *p_log, osm_subn_t *p_subn, + osm_prtn_t *p, boolean_t full) +{ + cl_qmap_t *p_port_tbl = &p_subn->port_guid_tbl; + cl_map_item_t *p_item; + osm_port_t *p_port; + ib_api_status_t status = IB_SUCCESS; + + p_item = cl_qmap_head(p_port_tbl); + while (p_item != cl_qmap_end(p_port_tbl)) { + p_port = (osm_port_t *)p_item; + p_item = cl_qmap_next(p_item); + status = osm_prtn_add_port(p_log, p_subn, p, + osm_port_get_guid(p_port), full); + if (status != IB_SUCCESS) + goto _err; + } + + _err: + return status; +} + +static const ib_gid_t osm_ipoib_mgid = { + { + 0xff, /* multicast field */ + 0x12, /* non-permanent bit, link local scope */ + 0x40, 0x1b, /* IPv4 signature */ + 0xff, 0xff, /* 16 bits of P_Key (to be filled in) */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 48 bits of zeros */ + 0xff, 0xff, 0xff, 0xff, /* 32 bit IPv4 broadcast address */ + }, +}; + +/* + * HACK: Until TS resolves their noncompliant join compmask, + * we have to pre-define the MGID + */ +static const ib_gid_t osm_ts_ipoib_mgid = { + { + 0xff, /* multicast field */ + 0x12, /* non-permanent bit, link local scope */ + 0x40, 0x1b, /* IPv4 signature */ + 0xff, 0xff, /* 16 bits of P_Key (to be filled in) */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 48 bits of zeros */ + 0x00, 0x00, 0x00, 0x01, /* 32 bit IPv4 broadcast address */ + }, +}; + +ib_api_status_t osm_prtn_add_mcgroup(osm_log_t *p_log, + osm_subn_t *p_subn, osm_prtn_t *p, + unsigned is_ipoib, uint8_t rate, + uint8_t mtu, uint8_t scope) +{ + ib_member_rec_t mc_rec; + ib_net64_t comp_mask; + ib_net16_t pkey; + osm_mgrp_t *p_mgrp = NULL; + osm_sa_t *p_sa = &p_subn->p_osm->sa; + ib_api_status_t status = IB_SUCCESS; + uint8_t ts_scope; + + pkey = p->pkey | cl_hton16(0x8000); + + memset(&mc_rec, 0, sizeof(mc_rec)); + + mc_rec.mgid = osm_ipoib_mgid; /* ipv4 broadcast group */ + memcpy(&mc_rec.mgid.raw[4], &pkey, sizeof(pkey)); + + mc_rec.qkey = CL_HTON32(0x0b1b); + mc_rec.mtu = (mtu ? mtu : OSM_DEFAULT_MGRP_MTU) | (2 << 6); /* 2048 Bytes */ + mc_rec.tclass = 0; + mc_rec.pkey = pkey; + mc_rec.rate = (rate ? rate : OSM_DEFAULT_MGRP_RATE) | (2 << 6); /* 10Gb/sec */ + mc_rec.pkt_life = OSM_DEFAULT_SUBNET_TIMEOUT; + mc_rec.sl_flow_hop = ib_member_set_sl_flow_hop(p->sl, 0, 0); + /* Scope in MCMemberRecord needs to be consistent with MGID */ + mc_rec.scope_state = ib_member_set_scope_state(scope ? scope : OSM_DEFAULT_MGRP_SCOPE, MC_FULL_MEMBER); + ib_mgid_set_scope(&mc_rec.mgid, scope ? scope : OSM_DEFAULT_MGRP_SCOPE); + + /* don't update rate, mtu, scope */ + comp_mask = IB_MCR_COMPMASK_MTU | IB_MCR_COMPMASK_MTU_SEL + | IB_MCR_COMPMASK_RATE | IB_MCR_COMPMASK_RATE_SEL + | IB_MCR_COMPMASK_SCOPE; + status = osm_mcmr_rcv_find_or_create_new_mgrp(&p_sa->mcmr_rcv, + comp_mask, &mc_rec, &p_mgrp); + if (!p_mgrp || status != IB_SUCCESS) + osm_log( p_log, OSM_LOG_ERROR, + "osm_prtn_add_mcgroup: " + "Failed to create MC group with pkey 0x%04x\n", + cl_ntoh16(pkey)); + if (p_mgrp) + p_mgrp->well_known = TRUE; + + /* workaround for TS */ + /* FIXME: remove this upon TS fixes */ + mc_rec.mgid = osm_ts_ipoib_mgid; + memcpy(&mc_rec.mgid.raw[4], &pkey, sizeof(pkey)); + /* Scope in MCMemberRecord needs to be consistent with MGID */ + ts_scope = ib_mgid_get_scope(&osm_ts_ipoib_mgid); /* get scope from MGID */ + mc_rec.scope_state = ib_member_set_scope_state(ts_scope, MC_FULL_MEMBER); + status = osm_mcmr_rcv_find_or_create_new_mgrp(&p_sa->mcmr_rcv, + comp_mask, &mc_rec, &p_mgrp); + if (p_mgrp) + p_mgrp->well_known = TRUE; + + return status; +} + +static uint16_t __generate_pkey(osm_subn_t *p_subn) +{ + uint16_t pkey; + + cl_qmap_t *m = &p_subn->prtn_pkey_tbl; + while (global_pkey_counter < cl_ntoh16(IB_DEFAULT_PARTIAL_PKEY) - 1) { + pkey = ++global_pkey_counter; + pkey = cl_hton16(pkey); + if (cl_qmap_get(m, pkey) == cl_qmap_end(m)) + return pkey; + } + return 0; +} + +static osm_prtn_t *find_prtn_by_name(osm_subn_t *p_subn, const char *name) +{ + cl_map_item_t *p_next; + osm_prtn_t *p; + + p_next = cl_qmap_head(&p_subn->prtn_pkey_tbl); + while (p_next != cl_qmap_end(&p_subn->prtn_pkey_tbl)) { + p = (osm_prtn_t *)p_next; + p_next = cl_qmap_next(&p->map_item); + if (!strncmp(p->name, name, sizeof(p->name))) + return p; + } + + return NULL; +} + +osm_prtn_t *osm_prtn_make_new(osm_log_t *p_log, osm_subn_t *p_subn, + const char *name, uint16_t pkey) +{ + osm_prtn_t *p = NULL, *p_check; + + pkey &= cl_hton16((uint16_t)~0x8000); + + if (!pkey) { + if (name && (p = find_prtn_by_name(p_subn, name))) + return p; + if(!(pkey = __generate_pkey(p_subn))) + return NULL; + } + + p = osm_prtn_new(name, pkey); + if (!p) { + osm_log(p_log, OSM_LOG_ERROR, + "osm_prtn_make_new: Unable to create" + " partition \'%s\' (0x%04x)\n", + name, cl_ntoh16(pkey)); + return NULL; + } + + p_check = (osm_prtn_t *)cl_qmap_insert(&p_subn->prtn_pkey_tbl, + p->pkey, &p->map_item); + if (p != p_check) { + osm_log(p_log, OSM_LOG_VERBOSE, + "osm_prtn_make_new: Duplicated partition" + " definition: \'%s\' (0x%04x) prev name \'%s\'" + ". Will use it\n", + name, cl_ntoh16(pkey), p_check->name); + osm_prtn_delete(&p); + p = p_check; + } + + return p; +} + +static ib_api_status_t osm_prtn_make_default(osm_log_t * const p_log, + osm_subn_t * const p_subn, + boolean_t no_config) +{ + ib_api_status_t status = IB_UNKNOWN_ERROR; + osm_prtn_t *p; + + p = osm_prtn_make_new(p_log, p_subn, "Default", IB_DEFAULT_PARTIAL_PKEY); + if (!p) + goto _err; + status = osm_prtn_add_all(p_log, p_subn, p, no_config); + if (status != IB_SUCCESS) + goto _err; + cl_map_remove(&p->part_guid_tbl, p_subn->sm_port_guid); + status = osm_prtn_add_port(p_log, p_subn, p, p_subn->sm_port_guid, TRUE); + + if (no_config) + osm_prtn_add_mcgroup(p_log, p_subn, p, 1, 0, 0, 0); + + _err: + return status; +} + +ib_api_status_t osm_prtn_make_partitions(osm_log_t * const p_log, + osm_subn_t * const p_subn) +{ + struct stat statbuf; + const char *file_name; + boolean_t is_config = TRUE; + ib_api_status_t status = IB_SUCCESS; + cl_map_item_t *p_next; + osm_prtn_t *p; + + file_name = p_subn->opt.partition_config_file ? + p_subn->opt.partition_config_file : + "/etc/osm-partitions.conf"; + if (stat(file_name, &statbuf)) + is_config = FALSE; + + /* clean up current port maps */ + p_next = cl_qmap_head(&p_subn->prtn_pkey_tbl); + while (p_next != cl_qmap_end(&p_subn->prtn_pkey_tbl)) { + p = (osm_prtn_t *)p_next; + p_next = cl_qmap_next(&p->map_item); + cl_map_remove_all(&p->part_guid_tbl); + cl_map_remove_all(&p->full_guid_tbl); + } + + global_pkey_counter = 0; + + status = osm_prtn_make_default(p_log, p_subn, !is_config); + if (status != IB_SUCCESS) + goto _err; + + if (is_config && osm_prtn_config_parse_file(p_log, p_subn, file_name)) { + osm_log(p_log, OSM_LOG_VERBOSE, + "osm_prtn_make_partitions: Partition configuration " + "was not fully processed\n"); + } + + /* and now clean up empty partitions */ + p_next = cl_qmap_head(&p_subn->prtn_pkey_tbl); + while (p_next != cl_qmap_end(&p_subn->prtn_pkey_tbl)) { + p = (osm_prtn_t *)p_next; + p_next = cl_qmap_next(&p->map_item); + if (cl_map_count(&p->part_guid_tbl) == 0 && + cl_map_count(&p->full_guid_tbl) == 0) { + cl_qmap_remove_item(&p_subn->prtn_pkey_tbl, + (cl_map_item_t *)p); + osm_prtn_delete(&p); + } + } + + _err: + return status; +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_prtn_config.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_prtn_config.c new file mode 100644 index 00000000..3d4411b2 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_prtn_config.c @@ -0,0 +1,447 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ + + +/* + * Abstract: + * Implementation of opensm partition management configuration + * + * Environment: + * Linux User Mode + * + * $Revision$ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#if __WORDSIZE == 64 +#define STRTO_IB_NET64(str, end, base) strtoul(str, end, base) +#else +#define STRTO_IB_NET64(str, end, base) strtoull(str, end, base) +#endif + +/* + */ +struct part_conf { + osm_log_t *p_log; + osm_subn_t *p_subn; + osm_prtn_t *p_prtn; + unsigned is_ipoib, mtu, rate, sl, scope; +}; + +extern osm_prtn_t *osm_prtn_make_new(osm_log_t *p_log, osm_subn_t *p_subn, + const char *name, uint16_t pkey); +extern ib_api_status_t osm_prtn_add_all(osm_log_t *p_log, + osm_subn_t *p_subn, + osm_prtn_t *p, boolean_t full); +extern ib_api_status_t osm_prtn_add_port(osm_log_t *p_log, + osm_subn_t *p_subn, osm_prtn_t *p, + ib_net64_t guid, boolean_t full); +extern ib_api_status_t osm_prtn_add_mcgroup(osm_log_t *p_log, + osm_subn_t *p_subn, osm_prtn_t *p, + unsigned is_ipoib, uint8_t rate, + uint8_t mtu, uint8_t scope); + +static int partition_create(unsigned lineno, struct part_conf *conf, + char *name, char *id, char *flag, char *flag_val) +{ + uint16_t pkey; + + if (!id && name && isdigit(*name)) { + id = name; + name = NULL; + } + + if (id) { + char *end; + + pkey = (uint16_t)strtoul(id, &end, 0); + if (end == id || *end) + return -1; + } else + pkey = 0; + + conf->p_prtn = osm_prtn_make_new(conf->p_log, conf->p_subn, + name, cl_hton16(pkey)); + if (!conf->p_prtn) + return -1; + + if (conf->p_subn->opt.no_qos) { + if (conf->sl != OSM_DEFAULT_SL) { + osm_log(conf->p_log, OSM_LOG_ERROR, + "partition_create: Overriding SL %d to default SL %d on partition %s as QoS not enabled\n", + conf->sl, OSM_DEFAULT_SL, name); + conf->sl = OSM_DEFAULT_SL; + } + } + conf->p_prtn->sl = (uint8_t)conf->sl; + + if (conf->is_ipoib) + osm_prtn_add_mcgroup(conf->p_log, conf->p_subn, conf->p_prtn, + conf->is_ipoib, (uint8_t)conf->rate, + (uint8_t)conf->mtu, (uint8_t)conf->scope); + + return 0; +} + +static int partition_add_flag(unsigned lineno, struct part_conf *conf, + char *flag, char *val) +{ + int len = strlen(flag); + if (!strncmp(flag, "ipoib", len)) { + conf->is_ipoib = 1; + } else if (!strncmp(flag, "mtu", len)) { + if (!val || (conf->mtu = strtoul(val, NULL, 0)) == 0) + osm_log(conf->p_log, OSM_LOG_VERBOSE, + "PARSE WARN: line %d: " + "flag \'mtu\' requires valid value" + " - skipped\n", lineno); + } else if (!strncmp(flag, "rate", len)) { + if (!val || (conf->rate = strtoul(val, NULL, 0)) == 0) + osm_log(conf->p_log, OSM_LOG_VERBOSE, + "PARSE WARN: line %d: " + "flag \'rate\' requires valid value" + " - skipped\n", lineno); + } else if (!strncmp(flag, "scope", len)) { + if (!val || (conf->scope = strtoul(val, NULL, 0)) == 0) + osm_log(conf->p_log, OSM_LOG_VERBOSE, + "PARSE WARN: line %d: " + "flag \'scope\' requires valid value" + " - skipped\n", lineno); + } else if (!strncmp(flag, "sl", len)) { + unsigned sl; + char *end; + + if (!val || !*val || (sl = strtoul(val, &end, 0)) > 15 || + (*end && !isspace(*end))) + osm_log(conf->p_log, OSM_LOG_VERBOSE, + "PARSE WARN: line %d: " + "flag \'sl\' requires valid value" + " - skipped\n", lineno); + else + conf->sl = sl; + } else { + osm_log(conf->p_log, OSM_LOG_VERBOSE, + "PARSE WARN: line %d: " + "unrecognized partition flag \'%s\'" + " - ignored\n", lineno, flag); + } + return 0; +} + +static int partition_add_port(unsigned lineno, struct part_conf *conf, + char *name, char *flag) +{ + osm_prtn_t *p = conf->p_prtn; + ib_net64_t guid; + boolean_t full = FALSE; + + if (!name || !*name || !strncmp(name, "NONE", strlen(name))) + return 0; + + if (flag) { + if (!strncmp(flag, "full", strlen(flag))) + full = TRUE; + else if (strncmp(flag, "limited", strlen(flag))) { + osm_log(conf->p_log, OSM_LOG_VERBOSE, + "PARSE WARN: line %d: " + "unrecognized port flag \'%s\'." + " Assume \'limited\'\n", lineno, flag); + } + } + + if (!strncmp(name, "ALL", strlen(name))) { + return osm_prtn_add_all(conf->p_log, conf->p_subn, p, + full) == IB_SUCCESS ? 0 : -1; + } else if (!strncmp(name, "SELF", strlen(name))) { + guid = cl_ntoh64(conf->p_subn->sm_port_guid); + } else { + char *end; + guid = STRTO_IB_NET64(name, &end, 0); + if (!guid || *end) + return -1; + } + + if (osm_prtn_add_port(conf->p_log, conf->p_subn, p, + cl_hton64(guid), full) != IB_SUCCESS) + return -1; + + return 0; +} + +/* conf file parser */ + +#define STRIP_HEAD_SPACES(p) while (*(p) == ' ' || *(p) == '\t' || \ + *(p) == '\n') { (p)++; } +#define STRIP_TAIL_SPACES(p) { char *q = (p) + strlen(p); \ + while ( q != (p) && ( *q == '\0' || \ + *q == ' ' || *q == '\t' || \ + *q == '\n')) { *q-- = '\0'; }; } + +static int parse_name_token(char *str, char **name, char **val) +{ + int len = 0; + char *p, *q; + + *name = *val = NULL; + + p = str; + + while (*p == ' ' || *p == '\t' || *p == '\n') + p++; + + q = strchr(p, '='); + if (q) + *q++ = '\0'; + + len = strlen(str) + 1; + str = q; + + q = p + strlen(p); + while ( q != p && + ( *q == '\0' || *q == ' ' || *q == '\t' || *q == '\n')) + *q-- = '\0'; + + *name = p; + + p = str; + if (!p) + return len; + + while (*p == ' ' || *p == '\t' || *p == '\n') + p++; + + q = p + strlen(p); + len += (int)(q - str) + 1; + while ( q != p && + ( *q == '\0' || *q == ' ' || *q == '\t' || *q == '\n')) + *q-- = '\0'; + *val = p; + + return len; +} + +static struct part_conf *new_part_conf(osm_log_t *p_log, osm_subn_t *p_subn) +{ + static struct part_conf part; + struct part_conf *conf = ∂ + + memset(conf, 0, sizeof(*conf)); + conf->p_log = p_log; + conf->p_subn = p_subn; + conf->p_prtn = NULL; + conf->is_ipoib = 0; + conf->sl = OSM_DEFAULT_SL; + return conf; +} + +static int flush_part_conf(struct part_conf *conf) +{ + memset(conf, 0, sizeof(*conf)); + return 0; +} + +static int parse_part_conf(struct part_conf *conf, char *str, int lineno) +{ + int ret, len = 0; + char *name, *id, *flag, *flval; + char *q, *p; + + p = str; + if (*p == '\t' || *p == '\0' || *p == '\n') + p++; + + len += (int)(p - str); + str = p; + + if (conf->p_prtn) + goto skip_header; + + q = strchr(p, ':'); + if (!q) { + osm_log(conf->p_log, OSM_LOG_ERROR, + "PARSE ERROR: line %d: " + "no partition definition found\n", lineno); + fprintf(stderr, "\nPARSE ERROR: line %d: " + "no partition definition found\n", lineno); + return -1; + } + + *q++ = '\0'; + str = q; + + name = id = flag = flval = NULL; + + q = strchr(p, ','); + if (q) + *q = '\0'; + + ret = parse_name_token(p, &name, &id); + p += ret; + len += ret; + + while (q) { + flag = flval = NULL; + q = strchr(p, ','); + if (q) + *q++ = '\0'; + ret = parse_name_token(p, &flag, &flval); + if (!flag) { + osm_log(conf->p_log, OSM_LOG_ERROR, + "PARSE ERROR: line %d: " + "bad partition flags\n",lineno); + fprintf(stderr, "\nPARSE ERROR: line %d: " + "bad partition flags\n",lineno); + return -1; + } + p += ret; + len += ret; + partition_add_flag(lineno, conf, flag, flval); + } + + if (p != str || (partition_create(lineno, conf, + name, id, flag, flval) < 0)) { + osm_log(conf->p_log, OSM_LOG_ERROR, + "PARSE ERROR: line %d: " + "bad partition definition\n", lineno); + fprintf(stderr, "\nPARSE ERROR: line %d: " + "bad partition definition\n", lineno); + return -1; + } + + skip_header: + do { + name = flag = NULL; + q = strchr(p, ','); + if (q) + *q++ = '\0'; + ret = parse_name_token(p, &name, &flag); + if (partition_add_port(lineno, conf, name, flag) < 0) { + osm_log(conf->p_log, OSM_LOG_ERROR, + "PARSE ERROR: line %d: " + "bad PortGUID\n", lineno); + fprintf(stderr, "PARSE ERROR: line %d: " + "bad PortGUID\n", lineno); + return -1; + } + p += ret; + len += ret; + } while (q); + + return len; +} + +int osm_prtn_config_parse_file(osm_log_t *p_log, osm_subn_t *p_subn, + const char *file_name) +{ + char line[1024]; + struct part_conf *conf = NULL; + FILE *file; + int lineno; + + file = fopen(file_name, "r"); + if (!file) { + osm_log(p_log, OSM_LOG_VERBOSE, + "osm_prtn_config_parse_file: " + "Cannot open config file \'%s\': %s\n", + file_name, strerror(errno)); + return -1; + } + + lineno = 0; + + while (fgets(line, sizeof(line) - 1, file) != NULL) { + char *q, *p = line; + + lineno++; + + p = line; + + q = strchr(p, '#'); + if (q) + *q = '\0'; + + do { + int len; + while (*p == ' ' || *p == '\t' || *p == '\n') + p++; + if (*p == '\0') + break; + + if (!conf && + !(conf = new_part_conf(p_log, p_subn))) { + osm_log(conf->p_log, OSM_LOG_ERROR, + "PARSE ERROR: line %d: " + "internal: cannot create config\n", lineno); + fprintf(stderr, "PARSE ERROR: line %d: " + "internal: cannot create config\n", lineno); + break; + } + + q = strchr(p, ';'); + if (q) + *q = '\0'; + + len = parse_part_conf(conf, p, lineno); + if (len < 0) { + break; + } + + p += len; + + if (q) { + flush_part_conf(conf); + conf = NULL; + } + } while (q); + } + + fclose(file); + + return 0; +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_qos.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_qos.c new file mode 100644 index 00000000..fe3b9534 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_qos.c @@ -0,0 +1,451 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ + + +/* + * Abstract: + * Implementation of OpenSM QoS infrastructure primitives + * + * Environment: + * Linux User Mode + * + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include + +#include +#include +#include +#include +#include + +struct qos_config { + uint8_t max_vls; + uint8_t vl_high_limit; + ib_vl_arb_table_t vlarb_high[2]; + ib_vl_arb_table_t vlarb_low[2]; + ib_slvl_table_t sl2vl; +}; + +static void qos_build_config(struct qos_config * cfg, + osm_qos_options_t * opt, osm_qos_options_t * dflt); + +/* + * QoS primitives + */ +static ib_api_status_t vlarb_update_table_block(osm_req_t * p_req, + osm_physp_t * p, + uint8_t port_num, + const ib_vl_arb_table_t *table_block, + unsigned block_length, + unsigned block_num) +{ + ib_vl_arb_table_t block; + osm_madw_context_t context; + uint32_t attr_mod; + ib_port_info_t *p_pi; + unsigned vl_mask, i; + + if (!(p_pi = osm_physp_get_port_info_ptr(p))) + return IB_ERROR; + + vl_mask = (1 << (ib_port_info_get_op_vls(p_pi) - 1)) - 1; + + memset(&block, 0, sizeof(block)); + memcpy(&block, table_block, + block_length * sizeof(block.vl_entry[0])); + for (i = 0; i < block_length; i++) + block.vl_entry[i].vl &= vl_mask; + + if (!memcmp(&p->vl_arb[block_num], &block, + block_length * sizeof(block.vl_entry[0]))) + return IB_SUCCESS; + + context.vla_context.node_guid = + osm_node_get_node_guid(osm_physp_get_node_ptr(p)); + context.vla_context.port_guid = osm_physp_get_port_guid(p); + context.vla_context.set_method = TRUE; + attr_mod = ((block_num + 1) << 16) | port_num; + + return osm_req_set(p_req, osm_physp_get_dr_path_ptr(p), + (uint8_t *) & block, sizeof(block), + IB_MAD_ATTR_VL_ARBITRATION, + cl_hton32(attr_mod), CL_DISP_MSGID_NONE, &context); +} + +static ib_api_status_t vlarb_update(osm_req_t * p_req, + osm_physp_t * p, uint8_t port_num, + const struct qos_config *qcfg) +{ + ib_api_status_t status = IB_SUCCESS; + ib_port_info_t *p_pi; + unsigned len; + + if (!(p_pi = osm_physp_get_port_info_ptr(p))) + return IB_ERROR; + + if (p_pi->vl_arb_low_cap > 0) { + len = p_pi->vl_arb_low_cap < IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK ? + p_pi->vl_arb_low_cap : IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK; + if ((status = vlarb_update_table_block(p_req, p, port_num, + &qcfg->vlarb_low[0], + len, 0)) != IB_SUCCESS) + return status; + } + if (p_pi->vl_arb_low_cap > IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK) { + len = p_pi->vl_arb_low_cap % IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK; + if ((status = vlarb_update_table_block(p_req, p, port_num, + &qcfg->vlarb_low[1], + len, 1)) != IB_SUCCESS) + return status; + } + if (p_pi->vl_arb_high_cap > 0) { + len = p_pi->vl_arb_high_cap < IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK ? + p_pi->vl_arb_high_cap : IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK; + if ((status = vlarb_update_table_block(p_req, p, port_num, + &qcfg->vlarb_high[0], + len, 2)) != IB_SUCCESS) + return status; + } + if (p_pi->vl_arb_high_cap > IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK) { + len = p_pi->vl_arb_high_cap % IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK; + if ((status = vlarb_update_table_block(p_req, p, port_num, + &qcfg->vlarb_high[1], + len, 3)) != IB_SUCCESS) + return status; + } + + return status; +} + +static ib_api_status_t sl2vl_update_table(osm_req_t * p_req, + osm_physp_t * p, uint8_t in_port, + uint8_t out_port, + const ib_slvl_table_t * sl2vl_table) +{ + osm_madw_context_t context; + ib_slvl_table_t tbl, *p_tbl; + osm_node_t *p_node = osm_physp_get_node_ptr(p); + uint32_t attr_mod; + ib_port_info_t *p_pi; + unsigned vl_mask; + uint8_t vl1, vl2; + int i; + + if (!(p_pi = osm_physp_get_port_info_ptr(p))) + return IB_ERROR; + + vl_mask = (1 << (ib_port_info_get_op_vls(p_pi) - 1)) - 1; + + for (i = 0; i < IB_MAX_NUM_VLS / 2; i++) { + vl1 = sl2vl_table->raw_vl_by_sl[i] >> 4; + vl2 = sl2vl_table->raw_vl_by_sl[i] & 0xf; + if (vl1 != 15) + vl1 &= vl_mask; + if (vl2 != 15) + vl2 &= vl_mask; + tbl.raw_vl_by_sl[i] = (vl1 << 4 ) | vl2 ; + } + + p_tbl = osm_physp_get_slvl_tbl(p, in_port); + if (p_tbl && !memcmp(p_tbl, &tbl, sizeof(tbl))) + return IB_SUCCESS; + + context.slvl_context.node_guid = osm_node_get_node_guid(p_node); + context.slvl_context.port_guid = osm_physp_get_port_guid(p); + context.slvl_context.set_method = TRUE; + attr_mod = in_port << 8 | out_port; + return osm_req_set(p_req, osm_physp_get_dr_path_ptr(p), + (uint8_t *) & tbl, sizeof(tbl), + IB_MAD_ATTR_SLVL_TABLE, + cl_hton32(attr_mod), CL_DISP_MSGID_NONE, &context); +} + +static ib_api_status_t sl2vl_update(osm_req_t * p_req, osm_port_t * p_port, + osm_physp_t * p, uint8_t port_num, + const struct qos_config *qcfg) +{ + ib_api_status_t status; + uint8_t i, num_ports; + ib_port_info_t *p_pi = osm_physp_get_port_info_ptr(p); + osm_physp_t *p_physp; + + if (!p_pi) + return IB_ERROR; + + if (osm_node_get_type(osm_physp_get_node_ptr(p)) == IB_NODE_TYPE_SWITCH) { + if (ib_port_info_get_vl_cap(p_pi) == 1) { + /* Check port 0's capability mask */ + p_physp = osm_port_get_default_phys_ptr(p_port); + p_pi = osm_physp_get_port_info_ptr(p_physp); + if (!(p_pi->capability_mask & IB_PORT_CAP_HAS_SL_MAP)) + return IB_SUCCESS; + } + num_ports = osm_node_get_num_physp(osm_physp_get_node_ptr(p)); + } else { + if (!(p_pi->capability_mask & IB_PORT_CAP_HAS_SL_MAP)) + return IB_SUCCESS; + num_ports = 1; + } + + for (i = 0; i < num_ports; i++) { + status = + sl2vl_update_table(p_req, p, i, port_num, &qcfg->sl2vl); + if (status != IB_SUCCESS) + return status; + } + + return IB_SUCCESS; +} + +static ib_api_status_t vl_high_limit_update(osm_req_t * p_req, + osm_physp_t * p, + const struct qos_config *qcfg) +{ + uint8_t payload[IB_SMP_DATA_SIZE]; + osm_madw_context_t context; + ib_port_info_t *p_pi; + + if (!(p_pi = osm_physp_get_port_info_ptr(p))) + return IB_ERROR; + + if (p_pi->vl_high_limit == qcfg->vl_high_limit) + return IB_SUCCESS; + + memset(payload, 0, IB_SMP_DATA_SIZE); + memcpy(payload, p_pi, sizeof(ib_port_info_t)); + + p_pi = (ib_port_info_t *) payload; + ib_port_info_set_state_no_change(p_pi); + + p_pi->vl_high_limit = qcfg->vl_high_limit; + + context.pi_context.node_guid = + osm_node_get_node_guid(osm_physp_get_node_ptr(p)); + context.pi_context.port_guid = osm_physp_get_port_guid(p); + context.pi_context.set_method = TRUE; + context.pi_context.update_master_sm_base_lid = FALSE; + context.pi_context.ignore_errors = FALSE; + context.pi_context.light_sweep = FALSE; + context.pi_context.active_transition = FALSE; + + return osm_req_set(p_req, osm_physp_get_dr_path_ptr(p), + payload, sizeof(payload), IB_MAD_ATTR_PORT_INFO, + cl_hton32(osm_physp_get_port_num(p)), + CL_DISP_MSGID_NONE, &context); +} + +static ib_api_status_t qos_physp_setup(osm_log_t * p_log, osm_req_t * p_req, + osm_port_t * p_port, osm_physp_t * p, + uint8_t port_num, + const struct qos_config *qcfg) +{ + ib_api_status_t status; + + /* OpVLs should be ok at this moment - just use it */ + + /* setup VL high limit */ + status = vl_high_limit_update(p_req, p, qcfg); + if (status != IB_SUCCESS) { + osm_log(p_log, OSM_LOG_ERROR, + "qos_physp_setup: ERR 6201 : " + "failed to update VLHighLimit " + "for port %" PRIx64 " #%d\n", + cl_ntoh64(p->port_guid), port_num); + return status; + } + + /* setup VLArbitration */ + status = vlarb_update(p_req, p, port_num, qcfg); + if (status != IB_SUCCESS) { + osm_log(p_log, OSM_LOG_ERROR, + "qos_physp_setup: ERR 6202 : " + "failed to update VLArbitration tables " + "for port %" PRIx64 " #%d\n", + cl_ntoh64(p->port_guid), port_num); + return status; + } + + /* setup SL2VL tables */ + status = sl2vl_update(p_req, p_port, p, port_num, qcfg); + if (status != IB_SUCCESS) { + osm_log(p_log, OSM_LOG_ERROR, + "qos_physp_setup: ERR 6203 : " + "failed to update SL2VLMapping tables " + "for port %" PRIx64 " #%d\n", + cl_ntoh64(p->port_guid), port_num); + return status; + } + + return IB_SUCCESS; +} + +osm_signal_t osm_qos_setup(osm_opensm_t * p_osm) +{ + struct qos_config ca_config, sw0_config, swe_config, rtr_config; + struct qos_config *cfg; + cl_qmap_t *p_tbl; + cl_map_item_t *p_next; + osm_port_t *p_port; + uint32_t num_physp; + osm_physp_t *p_physp; + osm_node_t *p_node; + ib_api_status_t status; + uint8_t i; + + if (p_osm->subn.opt.no_qos) + return OSM_SIGNAL_DONE; + + OSM_LOG_ENTER(&p_osm->log, osm_qos_setup); + + qos_build_config(&ca_config, &p_osm->subn.opt.qos_ca_options, + &p_osm->subn.opt.qos_options); + qos_build_config(&sw0_config, &p_osm->subn.opt.qos_sw0_options, + &p_osm->subn.opt.qos_options); + qos_build_config(&swe_config, &p_osm->subn.opt.qos_swe_options, + &p_osm->subn.opt.qos_options); + qos_build_config(&rtr_config, &p_osm->subn.opt.qos_rtr_options, + &p_osm->subn.opt.qos_options); + + cl_plock_excl_acquire(&p_osm->lock); + + p_tbl = &p_osm->subn.port_guid_tbl; + p_next = cl_qmap_head(p_tbl); + while (p_next != cl_qmap_end(p_tbl)) { + p_port = (osm_port_t *) p_next; + p_next = cl_qmap_next(p_next); + + p_node = p_port->p_node; + if (p_node->sw) { + num_physp = osm_port_get_num_physp(p_port); + for (i = 1; i < num_physp; i++) { + p_physp = osm_port_get_phys_ptr(p_port, i); + if (!p_physp || !osm_physp_is_valid(p_physp)) + continue; + status = + qos_physp_setup(&p_osm->log, &p_osm->sm.req, + p_port, p_physp, i, &swe_config); + } + /* skip base port 0 */ + if (!ib_switch_info_is_enhanced_port0(&p_node->sw->switch_info)) + continue; + + cfg = &sw0_config; + } else if (osm_node_get_type(p_node) == IB_NODE_TYPE_ROUTER) + cfg = &rtr_config; + else + cfg = &ca_config; + + p_physp = osm_port_get_default_phys_ptr(p_port); + if (!osm_physp_is_valid(p_physp)) + continue; + + status = qos_physp_setup(&p_osm->log, &p_osm->sm.req, + p_port, p_physp, 0, cfg); + } + + cl_plock_release(&p_osm->lock); + OSM_LOG_EXIT(&p_osm->log); + + return OSM_SIGNAL_DONE; +} + +/* + * QoS config stuff + */ +static int parse_one_unsigned(char *str, char delim, unsigned *val) +{ + char *end; + *val = strtoul(str, &end, 0); + if (*end) + end++; + return (int)(end - str); +} + +static int parse_vlarb_entry(char *str, ib_vl_arb_element_t * e) +{ + unsigned val; + char *p = str; + p += parse_one_unsigned(p, ':', &val); + e->vl = val % 15; + p += parse_one_unsigned(p, ',', &val); + e->weight = (uint8_t)val; + return (int)(p - str); +} + +static int parse_sl2vl_entry(char *str, uint8_t * raw) +{ + unsigned val1, val2; + char *p = str; + p += parse_one_unsigned(p, ',', &val1); + p += parse_one_unsigned(p, ',', &val2); + *raw = (val1 << 4) | (val2 & 0xf); + return (int)(p - str); +} + +static void qos_build_config(struct qos_config *cfg, + osm_qos_options_t * opt, osm_qos_options_t * dflt) +{ + int i; + char *p; + + memset(cfg, 0, sizeof(*cfg)); + + cfg->max_vls = opt->max_vls > 0 ? opt->max_vls : dflt->max_vls; + cfg->vl_high_limit = (uint8_t)opt->high_limit; + + p = opt->vlarb_high ? opt->vlarb_high : dflt->vlarb_high; + for (i = 0; i < 2 * IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK; i++) { + p += parse_vlarb_entry(p, + &cfg->vlarb_high[i/IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK]. + vl_entry[i%IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK]); + } + + p = opt->vlarb_low ? opt->vlarb_low : dflt->vlarb_low; + for (i = 0; i < 2 * IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK; i++) { + p += parse_vlarb_entry(p, + &cfg->vlarb_low[i/IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK]. + vl_entry[i%IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK]); + } + + p = opt->sl2vl ? opt->sl2vl : dflt->sl2vl; + for (i = 0; i < IB_MAX_NUM_VLS / 2; i++) + p += parse_sl2vl_entry(p, &cfg->sl2vl.raw_vl_by_sl[i]); + +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_remote_sm.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_remote_sm.c new file mode 100644 index 00000000..22a68de7 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_remote_sm.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_remote_sm.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_sm_t. + * This object represents the remote SM object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include + +/********************************************************************** + **********************************************************************/ +void +osm_remote_sm_construct( + IN osm_remote_sm_t* const p_sm ) +{ + memset( p_sm, 0, sizeof(*p_sm) ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_remote_sm_destroy( + IN osm_remote_sm_t* const p_sm ) +{ + memset( p_sm, 0, sizeof(*p_sm) ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_remote_sm_init( + IN osm_remote_sm_t* const p_sm, + IN const osm_port_t* const p_port, + IN const ib_sm_info_t* const p_smi ) +{ + CL_ASSERT( p_sm ); + CL_ASSERT( p_port ); + + osm_remote_sm_construct( p_sm ); + + p_sm->p_port = p_port; + p_sm->smi = *p_smi; + return; +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_req.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_req.c new file mode 100644 index 00000000..0002e152 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_req.c @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_req.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_req_t. + * This object represents the generic attribute requester. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.6 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +osm_req_construct( + IN osm_req_t* const p_req ) +{ + CL_ASSERT( p_req ); + + memset( p_req, 0, sizeof(*p_req) ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_req_destroy( + IN osm_req_t* const p_req ) +{ + CL_ASSERT( p_req ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_req_init( + IN osm_req_t* const p_req, + IN osm_mad_pool_t* const p_pool, + IN osm_vl15_t* const p_vl15, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN atomic32_t* const p_sm_trans_id ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_req_init ); + + osm_req_construct( p_req ); + p_req->p_log = p_log; + + p_req->p_pool = p_pool; + p_req->p_vl15 = p_vl15; + p_req->p_subn = p_subn; + p_req->p_sm_trans_id = p_sm_trans_id; + + OSM_LOG_EXIT( p_log ); + return( status ); +} + +/********************************************************************** + The plock MAY or MAY NOT be held before calling this function. +**********************************************************************/ +ib_api_status_t +osm_req_get( + IN const osm_req_t* const p_req, + IN const osm_dr_path_t* const p_path, + IN const uint16_t attr_id, + IN const uint32_t attr_mod, + IN const cl_disp_msgid_t err_msg, + IN const osm_madw_context_t* const p_context ) +{ + osm_madw_t *p_madw; + ib_api_status_t status = IB_SUCCESS; + ib_net64_t tid; + + CL_ASSERT( p_req ); + + OSM_LOG_ENTER( p_req->p_log, osm_req_get ); + + CL_ASSERT( p_path ); + CL_ASSERT( attr_id ); + + /* do nothing if we are exiting ... */ + if (osm_exit_flag) + goto Exit; + + /* p_context may be NULL. */ + + p_madw = osm_mad_pool_get( + p_req->p_pool, + p_path->h_bind, + MAD_BLOCK_SIZE, + NULL ); + + if( p_madw == NULL ) + { + osm_log( p_req->p_log, OSM_LOG_ERROR, + "osm_req_get: ERR 1101: " + "Unable to acquire MAD\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + tid = cl_hton64( (uint64_t)cl_atomic_inc( p_req->p_sm_trans_id ) ); + + if( osm_log_is_active( p_req->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_req->p_log, OSM_LOG_DEBUG, + "osm_req_get: " + "Getting %s (0x%X), modifier 0x%X, TID 0x%" PRIx64 "\n", + ib_get_sm_attr_str( attr_id ), + cl_ntoh16( attr_id ), + cl_ntoh32( attr_mod ), + cl_ntoh64( tid ) ); + } + + ib_smp_init_new( + osm_madw_get_smp_ptr( p_madw ), + IB_MAD_METHOD_GET, + tid, + attr_id, + attr_mod, + p_path->hop_count, + p_req->p_subn->opt.m_key, + p_path->path, + IB_LID_PERMISSIVE, + IB_LID_PERMISSIVE ); + + p_madw->mad_addr.dest_lid = IB_LID_PERMISSIVE; + p_madw->mad_addr.addr_type.smi.source_lid = IB_LID_PERMISSIVE; + p_madw->resp_expected = TRUE; + p_madw->fail_msg = err_msg; + + /* + Fill in the mad wrapper context for the recipient. + In this case, the only thing the recipient needs is the + guid value. + */ + + if( p_context ) + p_madw->context = *p_context; + + osm_vl15_post( p_req->p_vl15, p_madw ); + + Exit: + OSM_LOG_EXIT( p_req->p_log ); + return( status ); +} + +/********************************************************************** + The plock MAY or MAY NOT be held before calling this function. +**********************************************************************/ +ib_api_status_t +osm_req_set( + IN const osm_req_t* const p_req, + IN const osm_dr_path_t* const p_path, + IN const uint8_t* const p_payload, + IN const size_t payload_size, + IN const uint16_t attr_id, + IN const uint32_t attr_mod, + IN const cl_disp_msgid_t err_msg, + IN const osm_madw_context_t* const p_context ) +{ + osm_madw_t *p_madw; + ib_api_status_t status = IB_SUCCESS; + ib_net64_t tid; + + CL_ASSERT( p_req ); + + OSM_LOG_ENTER( p_req->p_log, osm_req_set ); + + CL_ASSERT( p_path ); + CL_ASSERT( attr_id ); + CL_ASSERT( p_payload ); + + /* do nothing if we are exiting ... */ + if (osm_exit_flag) + goto Exit; + + /* p_context may be NULL. */ + + p_madw = osm_mad_pool_get( + p_req->p_pool, + p_path->h_bind, + MAD_BLOCK_SIZE, + NULL ); + + if( p_madw == NULL ) + { + osm_log( p_req->p_log, OSM_LOG_ERROR, + "osm_req_set: ERR 1102: " + "Unable to acquire MAD\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + tid = cl_hton64( (uint64_t)cl_atomic_inc( p_req->p_sm_trans_id ) ); + + if( osm_log_is_active( p_req->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_req->p_log, OSM_LOG_DEBUG, + "osm_req_set: " + "Setting %s (0x%X), modifier 0x%X, TID 0x%" PRIx64 "\n", + ib_get_sm_attr_str( attr_id ), + cl_ntoh16( attr_id ), + cl_ntoh32( attr_mod ), + cl_ntoh64( tid ) ); + } + + ib_smp_init_new( + osm_madw_get_smp_ptr( p_madw ), + IB_MAD_METHOD_SET, + tid, + attr_id, + attr_mod, + p_path->hop_count, + p_req->p_subn->opt.m_key, + p_path->path, + IB_LID_PERMISSIVE, + IB_LID_PERMISSIVE ); + + p_madw->mad_addr.dest_lid = IB_LID_PERMISSIVE; + p_madw->mad_addr.addr_type.smi.source_lid = IB_LID_PERMISSIVE; + p_madw->resp_expected = TRUE; + p_madw->fail_msg = err_msg; + + /* + Fill in the mad wrapper context for the recipient. + In this case, the only thing the recipient needs is the + guid value. + */ + + if( p_context ) + p_madw->context = *p_context; + + memcpy( osm_madw_get_smp_ptr( p_madw )->data, + p_payload, payload_size ); + + osm_vl15_post( p_req->p_vl15, p_madw ); + + Exit: + OSM_LOG_EXIT( p_req->p_log ); + return( status ); +} + + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_req_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_req_ctrl.c new file mode 100644 index 00000000..fbec64c9 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_req_ctrl.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_req_ctrl.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_req_ctrl_t. + * This object represents the request controller object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +__osm_req_ctrl_disp_callback( + IN void *context, + IN void *p_data ) +{ + /* ignore return status when invoked via the dispatcher */ + osm_req_get( ((osm_req_ctrl_t*)context)->p_req, + (&((osm_attrib_req_t*)p_data)->path), + ((osm_attrib_req_t*)p_data)->attrib_id, + ((osm_attrib_req_t*)p_data)->attrib_mod, + ((osm_attrib_req_t*)p_data)->err_msg, + (&((osm_attrib_req_t*)p_data)->context) ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_req_ctrl_construct( + IN osm_req_ctrl_t* const p_ctrl ) +{ + memset( p_ctrl, 0, sizeof(*p_ctrl) ); + p_ctrl->h_disp = CL_DISP_INVALID_HANDLE; +} + +/********************************************************************** + **********************************************************************/ +void +osm_req_ctrl_destroy( + IN osm_req_ctrl_t* const p_ctrl ) +{ + CL_ASSERT( p_ctrl ); + cl_disp_unregister( p_ctrl->h_disp ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_req_ctrl_init( + IN osm_req_ctrl_t* const p_ctrl, + IN osm_req_t* const p_req, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_req_ctrl_init ); + + osm_req_ctrl_construct( p_ctrl ); + p_ctrl->p_log = p_log; + + p_ctrl->p_disp = p_disp; + p_ctrl->p_req = p_req; + + p_ctrl->h_disp = cl_disp_register( + p_disp, + OSM_MSG_REQ, + __osm_req_ctrl_disp_callback, + p_ctrl ); + + if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_req_ctrl_init: ERR 1202: " + "Dispatcher registration failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return( status ); +} + + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_resp.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_resp.c new file mode 100644 index 00000000..e12a901d --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_resp.c @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_resp.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_resp_t. + * This object represents the generic attribute responder. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.7 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +osm_resp_construct( + IN osm_resp_t* const p_resp ) +{ + memset( p_resp, 0, sizeof(*p_resp) ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_resp_destroy( + IN osm_resp_t* const p_resp ) +{ + CL_ASSERT( p_resp ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_resp_init( + IN osm_resp_t* const p_resp, + IN osm_mad_pool_t* const p_pool, + IN osm_vl15_t* const p_vl15, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_resp_init ); + + osm_resp_construct( p_resp ); + + p_resp->p_log = p_log; + p_resp->p_pool = p_pool; + p_resp->p_vl15 = p_vl15; + p_resp->p_subn = p_subn; + + OSM_LOG_EXIT( p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_resp_make_resp_smp( + IN const osm_resp_t* const p_resp, + IN const ib_smp_t* const p_src_smp, + IN const ib_net16_t status, + IN const uint8_t* const p_payload, + OUT ib_smp_t* const p_dest_smp ) +{ + OSM_LOG_ENTER( p_resp->p_log, osm_resp_make_resp_smp ); + + CL_ASSERT( p_dest_smp ); + CL_ASSERT( p_src_smp ); + CL_ASSERT( !ib_smp_is_response( p_src_smp ) ); + + *p_dest_smp = *p_src_smp; + if (p_src_smp->method == IB_MAD_METHOD_GET || + p_src_smp->method == IB_MAD_METHOD_SET ) { + p_dest_smp->method = IB_MAD_METHOD_GET_RESP; + p_dest_smp->status = status; + } + else if (p_src_smp->method == IB_MAD_METHOD_TRAP) + { + p_dest_smp->method = IB_MAD_METHOD_TRAP_REPRESS; + p_dest_smp->status = 0; + } + else + { + osm_log( p_resp->p_log, OSM_LOG_ERROR, + "osm_resp_make_resp_smp: ERR 1302: " + "src smp method unsupported 0x%X\n", + p_src_smp->method ); + goto Exit; + } + + if (p_src_smp->mgmt_class == IB_MCLASS_SUBN_DIR) + p_dest_smp->status |= IB_SMP_DIRECTION; + + p_dest_smp->dr_dlid = p_dest_smp->dr_slid; + p_dest_smp->dr_slid = p_dest_smp->dr_dlid; + memcpy( &p_dest_smp->data, p_payload, IB_SMP_DATA_SIZE ); + + Exit: + OSM_LOG_EXIT( p_resp->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_resp_send( + IN const osm_resp_t* const p_resp, + IN const osm_madw_t* const p_req_madw, + IN const ib_net16_t mad_status, + IN const uint8_t* const p_payload ) +{ + const ib_smp_t* p_req_smp; + ib_smp_t* p_smp; + osm_madw_t* p_madw; + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_resp->p_log, osm_resp_send ); + + CL_ASSERT( p_req_madw ); + CL_ASSERT( p_payload ); + + /* do nothing if we are exiting ... */ + if (osm_exit_flag) + goto Exit; + + p_madw = osm_mad_pool_get( + p_resp->p_pool, + osm_madw_get_bind_handle( p_req_madw ), + MAD_BLOCK_SIZE, + NULL ); + + if( p_madw == NULL ) + { + osm_log( p_resp->p_log, OSM_LOG_ERROR, + "osm_resp_send: ERR 1301: " + "Unable to acquire MAD\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + /* + Copy the request smp to the response smp, then just + update the necessary fields. + */ + p_smp = osm_madw_get_smp_ptr( p_madw ); + p_req_smp = osm_madw_get_smp_ptr( p_req_madw ); + osm_resp_make_resp_smp( p_resp, p_req_smp, mad_status, + p_payload, p_smp ); + p_madw->mad_addr.dest_lid = + p_req_madw->mad_addr.addr_type.smi.source_lid; + p_madw->mad_addr.addr_type.smi.source_lid = + p_req_madw->mad_addr.dest_lid; + + p_madw->resp_expected = FALSE; + p_madw->fail_msg = CL_DISP_MSGID_NONE; + + if( osm_log_is_active( p_resp->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_resp->p_log, OSM_LOG_DEBUG, + "osm_resp_send: " + "Responding to %s (0x%X)" + "\n\t\t\t\tattribute modifier 0x%X, TID 0x%" PRIx64 "\n", + ib_get_sm_attr_str( p_smp->attr_id ), + cl_ntoh16( p_smp->attr_id ), + cl_ntoh32( p_smp->attr_mod ), + cl_ntoh64( p_smp->trans_id ) ); + } + + osm_vl15_post( p_resp->p_vl15, p_madw ); + + Exit: + OSM_LOG_EXIT( p_resp->p_log ); + return( status ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_router.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_router.c new file mode 100644 index 00000000..0f478b65 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_router.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ + + +/* + * Abstract: + * Implementation of osm_router_t. + * This object represents an Infiniband router. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +osm_router_construct( + IN osm_router_t* const p_rtr ) +{ + CL_ASSERT( p_rtr ); + memset( p_rtr, 0, sizeof(*p_rtr) ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_router_init( + IN osm_router_t* const p_rtr, + IN osm_port_t* const p_port ) +{ + ib_api_status_t status = IB_SUCCESS; + + CL_ASSERT( p_rtr ); + CL_ASSERT( p_port ); + + osm_router_construct( p_rtr ); + + p_rtr->p_port = p_port; + + return( status ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_router_destroy( + IN osm_router_t* const p_rtr ) +{ +} + +/********************************************************************** + **********************************************************************/ +void +osm_router_delete( + IN OUT osm_router_t** const pp_rtr ) +{ + osm_router_destroy( *pp_rtr ); + free( *pp_rtr ); + *pp_rtr = NULL; +} + +/********************************************************************** + **********************************************************************/ +osm_router_t* +osm_router_new( + IN osm_port_t* const p_port ) +{ + ib_api_status_t status; + osm_router_t *p_rtr; + + p_rtr = (osm_router_t*)malloc( sizeof(*p_rtr) ); + if( p_rtr ) + { + memset( p_rtr, 0, sizeof(*p_rtr) ); + status = osm_router_init( p_rtr, p_port ); + if( status != IB_SUCCESS ) + osm_router_delete( &p_rtr ); + } + + return( p_rtr ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa.c new file mode 100644 index 00000000..3f5dfb77 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa.c @@ -0,0 +1,1207 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Implementation of osm_sa_t. + * This object represents the Subnet Administration object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.14 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define OSM_SA_INITIAL_TID_VALUE 0xabc + +/********************************************************************** + **********************************************************************/ +void +osm_sa_construct( + IN osm_sa_t* const p_sa ) +{ + memset( p_sa, 0, sizeof(*p_sa) ); + p_sa->state = OSM_SA_STATE_INIT; + p_sa->sa_trans_id = OSM_SA_INITIAL_TID_VALUE; + + osm_sa_mad_ctrl_construct( &p_sa->mad_ctrl ); + osm_sa_resp_construct( &p_sa->resp ); + + osm_nr_rcv_construct( &p_sa->nr_rcv); + osm_nr_rcv_ctrl_construct( &p_sa->nr_rcv_ctrl ); + + osm_pir_rcv_construct( &p_sa->pir_rcv ); + osm_pir_rcv_ctrl_construct( &p_sa->pir_rcv_ctrl ); + + osm_gir_rcv_construct( &p_sa->gir_rcv ); + osm_gir_rcv_ctrl_construct( &p_sa->gir_rcv_ctrl ); + + osm_lr_rcv_construct( &p_sa->lr_rcv ); + osm_lr_rcv_ctrl_construct( &p_sa->lr_rcv_ctrl ); + + osm_pr_rcv_construct( &p_sa->pr_rcv ); + osm_pr_rcv_ctrl_construct( &p_sa->pr_rcv_ctrl ); + +#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP) + osm_mpr_rcv_construct( &p_sa->mpr_rcv ); + osm_mpr_rcv_ctrl_construct( &p_sa->mpr_rcv_ctrl ); +#endif + + osm_smir_rcv_construct( &p_sa->smir_rcv ); + osm_smir_ctrl_construct( &p_sa->smir_ctrl ); + + osm_mcmr_rcv_construct(&p_sa->mcmr_rcv ); + osm_mcmr_rcv_ctrl_construct(&p_sa->mcmr_rcv_ctlr); + + osm_sr_rcv_construct( &p_sa->sr_rcv ); + osm_sr_rcv_ctrl_construct( &p_sa->sr_rcv_ctrl ); + + osm_infr_rcv_construct( &p_sa->infr_rcv ); + osm_infr_rcv_ctrl_construct( &p_sa->infr_rcv_ctrl ); + + osm_vlarb_rec_rcv_construct( &p_sa->vlarb_rec_rcv ); + osm_vlarb_rec_rcv_ctrl_construct( &p_sa->vlarb_rec_rcv_ctrl ); + + osm_slvl_rec_rcv_construct( &p_sa->slvl_rec_rcv ); + osm_slvl_rec_rcv_ctrl_construct( &p_sa->slvl_rec_rcv_ctrl ); + + osm_pkey_rec_rcv_construct( &p_sa->pkey_rec_rcv ); + osm_pkey_rec_rcv_ctrl_construct( &p_sa->pkey_rec_rcv_ctrl ); + + osm_lftr_rcv_construct( &p_sa->lftr_rcv ); + osm_lftr_rcv_ctrl_construct( &p_sa->lftr_rcv_ctrl ); + + osm_sir_rcv_construct( &p_sa->sir_rcv ); + osm_sir_rcv_ctrl_construct( &p_sa->sir_rcv_ctrl ); + + osm_mftr_rcv_construct( &p_sa->mftr_rcv ); + osm_mftr_rcv_ctrl_construct( &p_sa->mftr_rcv_ctrl ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_sa_shutdown( + IN osm_sa_t* const p_sa ) +{ + ib_api_status_t status; + OSM_LOG_ENTER( p_sa->p_log, osm_sa_shutdown ); + + /* unbind from the mad service */ + status = osm_sa_mad_ctrl_unbind( &p_sa->mad_ctrl ); + + /* remove any registered dispatcher message */ + osm_nr_rcv_ctrl_destroy( &p_sa->nr_rcv_ctrl ); + osm_pir_rcv_ctrl_destroy( &p_sa->pir_rcv_ctrl ); + osm_gir_rcv_ctrl_destroy( &p_sa->gir_rcv_ctrl ); + osm_lr_rcv_ctrl_destroy( &p_sa->lr_rcv_ctrl ); + osm_pr_rcv_ctrl_destroy( &p_sa->pr_rcv_ctrl ); +#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP) + osm_mpr_rcv_ctrl_destroy( &p_sa->mpr_rcv_ctrl ); +#endif + osm_smir_ctrl_destroy( &p_sa->smir_ctrl ); + osm_mcmr_rcv_ctrl_destroy( &p_sa->mcmr_rcv_ctlr); + osm_sr_rcv_ctrl_destroy( &p_sa->sr_rcv_ctrl ); + osm_infr_rcv_ctrl_destroy( &p_sa->infr_rcv_ctrl ); + osm_vlarb_rec_rcv_ctrl_destroy( &p_sa->vlarb_rec_rcv_ctrl ); + osm_slvl_rec_rcv_ctrl_destroy( &p_sa->slvl_rec_rcv_ctrl ); + osm_pkey_rec_rcv_ctrl_destroy( &p_sa->pkey_rec_rcv_ctrl ); + osm_lftr_rcv_ctrl_destroy( &p_sa->lftr_rcv_ctrl ); + osm_sir_rcv_ctrl_destroy( &p_sa->sir_rcv_ctrl ); + osm_mftr_rcv_ctrl_destroy( &p_sa->mftr_rcv_ctrl ); + osm_sa_mad_ctrl_destroy( &p_sa->mad_ctrl ); + + OSM_LOG_EXIT( p_sa->p_log ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_sa_destroy( + IN osm_sa_t* const p_sa ) +{ + OSM_LOG_ENTER( p_sa->p_log, osm_sa_destroy ); + + p_sa->state = OSM_SA_STATE_INIT; + + osm_nr_rcv_destroy( &p_sa->nr_rcv ); + osm_pir_rcv_destroy( &p_sa->pir_rcv ); + osm_gir_rcv_destroy( &p_sa->gir_rcv ); + osm_lr_rcv_destroy( &p_sa->lr_rcv ); + osm_pr_rcv_destroy( &p_sa->pr_rcv ); +#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP) + osm_mpr_rcv_destroy( &p_sa->mpr_rcv ); +#endif + osm_smir_rcv_destroy( &p_sa->smir_rcv ); + osm_mcmr_rcv_destroy(&p_sa->mcmr_rcv); + osm_sr_rcv_destroy( &p_sa->sr_rcv ); + osm_infr_rcv_destroy( &p_sa->infr_rcv ); + osm_vlarb_rec_rcv_destroy( &p_sa->vlarb_rec_rcv ); + osm_slvl_rec_rcv_destroy( &p_sa->slvl_rec_rcv ); + osm_pkey_rec_rcv_destroy( &p_sa->pkey_rec_rcv ); + osm_lftr_rcv_destroy( &p_sa->lftr_rcv ); + osm_sir_rcv_destroy( &p_sa->sir_rcv ); + osm_mftr_rcv_destroy( &p_sa->mftr_rcv ); + osm_sa_resp_destroy( &p_sa->resp ); + + OSM_LOG_EXIT( p_sa->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_sa_init( + IN osm_sm_t* const p_sm, + IN osm_sa_t* const p_sa, + IN osm_subn_t* const p_subn, + IN osm_vendor_t* const p_vendor, + IN osm_mad_pool_t* const p_mad_pool, + IN osm_log_t* const p_log, + IN osm_stats_t* const p_stats, + IN cl_dispatcher_t* const p_disp, + IN cl_plock_t* const p_lock ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_sa_init ); + + p_sa->p_subn = p_subn; + p_sa->p_vendor = p_vendor; + p_sa->p_mad_pool = p_mad_pool; + p_sa->p_log = p_log; + p_sa->p_disp = p_disp; + p_sa->p_lock = p_lock; + + p_sa->state = OSM_SA_STATE_READY; + + status = osm_sa_resp_init(&p_sa->resp, + p_sa->p_mad_pool, + p_log); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_sa_mad_ctrl_init( + &p_sa->mad_ctrl, + &p_sa->resp, + p_sa->p_mad_pool, + p_sa->p_vendor, + p_subn, + p_log, + p_stats, + p_disp ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_cpi_rcv_init( + &p_sa->cpi_rcv, + &p_sa->resp, + p_sa->p_mad_pool, + p_subn, + p_log, + p_lock ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_cpi_rcv_ctrl_init( + &p_sa->cpi_rcv_ctrl, + &p_sa->cpi_rcv, + p_log, + p_disp ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_nr_rcv_init( + &p_sa->nr_rcv, + &p_sa->resp, + p_sa->p_mad_pool, + p_subn, + p_log, + p_lock ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_nr_rcv_ctrl_init( + &p_sa->nr_rcv_ctrl, + &p_sa->nr_rcv, + p_log, + p_disp ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_pir_rcv_init( + &p_sa->pir_rcv, + &p_sa->resp, + p_sa->p_mad_pool, + p_subn, + p_log, + p_lock ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_pir_rcv_ctrl_init( + &p_sa->pir_rcv_ctrl, + &p_sa->pir_rcv, + p_log, + p_disp ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_gir_rcv_init( + &p_sa->gir_rcv, + &p_sa->resp, + p_sa->p_mad_pool, + p_subn, + p_log, + p_lock ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_gir_rcv_ctrl_init( + &p_sa->gir_rcv_ctrl, + &p_sa->gir_rcv, + p_log, + p_disp ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_lr_rcv_init( + &p_sa->lr_rcv, + &p_sa->resp, + p_sa->p_mad_pool, + p_subn, + p_log, + p_lock ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_lr_rcv_ctrl_init( + &p_sa->lr_rcv_ctrl, + &p_sa->lr_rcv, + p_log, + p_disp ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_pr_rcv_init( + &p_sa->pr_rcv, + &p_sa->resp, + p_sa->p_mad_pool, + p_subn, + p_log, + p_lock ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_pr_rcv_ctrl_init( + &p_sa->pr_rcv_ctrl, + &p_sa->pr_rcv, + p_log, + p_disp ); + if( status != IB_SUCCESS ) + goto Exit; + +#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP) + status = osm_mpr_rcv_init( + &p_sa->mpr_rcv, + &p_sa->resp, + p_sa->p_mad_pool, + p_subn, + p_log, + p_lock ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_mpr_rcv_ctrl_init( + &p_sa->mpr_rcv_ctrl, + &p_sa->mpr_rcv, + p_log, + p_disp ); + if( status != IB_SUCCESS ) + goto Exit; +#endif + + status = osm_smir_rcv_init( + &p_sa->smir_rcv, + &p_sa->resp, + p_sa->p_mad_pool, + p_subn, + p_stats, + p_log, + p_lock ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_smir_ctrl_init( + &p_sa->smir_ctrl, + &p_sa->smir_rcv, + p_log, + p_disp ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_mcmr_rcv_init( + p_sm, + &p_sa->mcmr_rcv, + &p_sa->resp, + p_sa->p_mad_pool, + p_subn, + p_log, + p_lock); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_mcmr_rcv_ctrl_init( + &p_sa->mcmr_rcv_ctlr, + &p_sa->mcmr_rcv, + p_log, + p_disp); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_sr_rcv_init( + &p_sa->sr_rcv, + &p_sa->resp, + p_sa->p_mad_pool, + p_subn, + p_log, + p_lock); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_sr_rcv_ctrl_init( + &p_sa->sr_rcv_ctrl, + &p_sa->sr_rcv, + p_log, + p_disp ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_infr_rcv_init( + &p_sa->infr_rcv, + &p_sa->resp, + p_sa->p_mad_pool, + p_subn, + p_log, + p_lock); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_infr_rcv_ctrl_init( + &p_sa->infr_rcv_ctrl, + &p_sa->infr_rcv, + p_log, + p_disp ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_vlarb_rec_rcv_init( + &p_sa->vlarb_rec_rcv, + &p_sa->resp, + p_sa->p_mad_pool, + p_subn, + p_log, + p_lock); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_vlarb_rec_rcv_ctrl_init( + &p_sa->vlarb_rec_rcv_ctrl, + &p_sa->vlarb_rec_rcv, + p_log, + p_disp ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_slvl_rec_rcv_init( + &p_sa->slvl_rec_rcv, + &p_sa->resp, + p_sa->p_mad_pool, + p_subn, + p_log, + p_lock); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_slvl_rec_rcv_ctrl_init( + &p_sa->slvl_rec_rcv_ctrl, + &p_sa->slvl_rec_rcv, + p_log, + p_disp ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_pkey_rec_rcv_init( + &p_sa->pkey_rec_rcv, + &p_sa->resp, + p_sa->p_mad_pool, + p_subn, + p_log, + p_lock); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_pkey_rec_rcv_ctrl_init( + &p_sa->pkey_rec_rcv_ctrl, + &p_sa->pkey_rec_rcv, + p_log, + p_disp ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_lftr_rcv_init( + &p_sa->lftr_rcv, + &p_sa->resp, + p_sa->p_mad_pool, + p_subn, + p_log, + p_lock); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_lftr_rcv_ctrl_init( + &p_sa->lftr_rcv_ctrl, + &p_sa->lftr_rcv, + p_log, + p_disp ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_sir_rcv_init( + &p_sa->sir_rcv, + &p_sa->resp, + p_sa->p_mad_pool, + p_subn, + p_log, + p_lock); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_sir_rcv_ctrl_init( + &p_sa->sir_rcv_ctrl, + &p_sa->sir_rcv, + p_log, + p_disp ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_mftr_rcv_init( + &p_sa->mftr_rcv, + &p_sa->resp, + p_sa->p_mad_pool, + p_subn, + p_log, + p_lock); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_mftr_rcv_ctrl_init( + &p_sa->mftr_rcv_ctrl, + &p_sa->mftr_rcv, + p_log, + p_disp ); + if( status != IB_SUCCESS ) + goto Exit; + + Exit: + OSM_LOG_EXIT( p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_sa_bind( + IN osm_sa_t* const p_sa, + IN const ib_net64_t port_guid ) +{ + ib_api_status_t status; + + OSM_LOG_ENTER( p_sa->p_log, osm_sa_bind ); + + status = osm_sa_mad_ctrl_bind( + &p_sa->mad_ctrl, port_guid ); + + OSM_LOG_EXIT( p_sa->p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +/* + * SA DB Dumper + * + */ + +struct opensm_dump_context { + osm_opensm_t *p_osm; + FILE *file; +}; + +static int +opensm_dump_to_file(osm_opensm_t *p_osm, const char *file_name, + void (*dump_func)(osm_opensm_t *p_osm, FILE *file)) +{ + char path[1024]; + FILE *file; + + snprintf(path, sizeof(path), "%s/%s", + p_osm->subn.opt.dump_files_dir, file_name); + + file = fopen(path, "w"); + if (!file) { + osm_log(&p_osm->log, OSM_LOG_ERROR, + "opensm_dump_to_file: ERR 0000: " + "cannot open file \'%s\': %s\n", + file_name, strerror(errno)); + return -1; + } + + chmod(path, S_IRUSR|S_IWUSR); + + dump_func(p_osm, file); + + fclose(file); + return 0; +} + +static void +mcast_mgr_dump_one_port(cl_map_item_t *p_map_item, void *cxt) +{ + FILE *file = ((struct opensm_dump_context *)cxt)->file; + osm_mcm_port_t *p_mcm_port = (osm_mcm_port_t *)p_map_item; + + fprintf(file, "mcm_port: " + "port_gid=0x%016" PRIx64 ":0x%016" PRIx64 " " + "scope_state=0x%02x proxy_join=0x%x" "\n\n", + cl_ntoh64(p_mcm_port->port_gid.unicast.prefix), + cl_ntoh64(p_mcm_port->port_gid.unicast.interface_id), + p_mcm_port->scope_state, + p_mcm_port->proxy_join); +} + +static void +sa_dump_one_mgrp(cl_map_item_t *p_map_item, void *cxt) +{ + struct opensm_dump_context dump_context; + osm_opensm_t *p_osm = ((struct opensm_dump_context *)cxt)->p_osm; + FILE *file = ((struct opensm_dump_context *)cxt)->file; + osm_mgrp_t *p_mgrp = (osm_mgrp_t *)p_map_item; + + fprintf(file, "MC Group 0x%04x %s:" + " mgid=0x%016" PRIx64 ":0x%016" PRIx64 + " port_gid=0x%016" PRIx64 ":0x%016" PRIx64 + " qkey=0x%08x mlid=0x%04x mtu=0x%02x tclass=0x%02x" + " pkey=0x%04x rate=0x%02x pkt_life=0x%02x sl_flow_hop=0x%08x" + " scope_state=0x%02x proxy_join=0x%x" "\n\n", + cl_ntoh16(p_mgrp->mlid), + p_mgrp->well_known ? " (well known)" : "", + cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.prefix), + cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.interface_id), + cl_ntoh64(p_mgrp->mcmember_rec.port_gid.unicast.prefix), + cl_ntoh64(p_mgrp->mcmember_rec.port_gid.unicast.interface_id), + cl_ntoh32(p_mgrp->mcmember_rec.qkey), + cl_ntoh16(p_mgrp->mcmember_rec.mlid), + p_mgrp->mcmember_rec.mtu, + p_mgrp->mcmember_rec.tclass, + cl_ntoh16(p_mgrp->mcmember_rec.pkey), + p_mgrp->mcmember_rec.rate, + p_mgrp->mcmember_rec.pkt_life, + cl_ntoh32(p_mgrp->mcmember_rec.sl_flow_hop), + p_mgrp->mcmember_rec.scope_state, + p_mgrp->mcmember_rec.proxy_join + ); + + dump_context.p_osm = p_osm; + dump_context.file = file; + + cl_qmap_apply_func(&p_mgrp->mcm_port_tbl, + mcast_mgr_dump_one_port, &dump_context); +} + +static void +sa_dump_one_inform(cl_list_item_t *p_list_item, void *cxt) +{ + FILE *file = ((struct opensm_dump_context *)cxt)->file; + osm_infr_t *p_infr = (osm_infr_t *)p_list_item; + ib_inform_info_record_t *p_iir = &p_infr->inform_record; + + fprintf(file, "InformInfo Record:" + " subscriber_gid=0x%016" PRIx64 ":0x%016" PRIx64 + " subscriber_enum=0x%x" + " InformInfo:" + " gid=0x%016" PRIx64 ":0x%016" PRIx64 + " lid_range_begin=0x%x" + " lid_range_end=0x%x" + " is_generic=0x%x" + " subscribe=0x%x" + " trap_type=0x%x" + " trap_num=0x%x" + " qpn_resp_time_val=0x%x" + " node_type=0x%06x" + " rep_addr: lid=0x%04x path_bits=0x%02x static_rate=0x%02x" + " remote_qp=0x%08x remote_qkey=0x%08x pkey=0x%04x sl=0x%02x" + "\n\n", + cl_ntoh64(p_iir->subscriber_gid.unicast.prefix), + cl_ntoh64(p_iir->subscriber_gid.unicast.interface_id), + cl_ntoh16(p_iir->subscriber_enum), + cl_ntoh64(p_iir->inform_info.gid.unicast.prefix), + cl_ntoh64(p_iir->inform_info.gid.unicast.interface_id), + cl_ntoh16(p_iir->inform_info.lid_range_begin), + cl_ntoh16(p_iir->inform_info.lid_range_end), + p_iir->inform_info.is_generic, + p_iir->inform_info.subscribe, + cl_ntoh16(p_iir->inform_info.trap_type), + cl_ntoh16(p_iir->inform_info.g_or_v.generic.trap_num), + cl_ntoh32(p_iir->inform_info.g_or_v.generic.qpn_resp_time_val), + cl_ntoh32(ib_inform_info_get_node_type(&p_iir->inform_info)), + cl_ntoh16(p_infr->report_addr.dest_lid), + p_infr->report_addr.path_bits, + p_infr->report_addr.static_rate, + cl_ntoh32(p_infr->report_addr.addr_type.gsi.remote_qp), + cl_ntoh32(p_infr->report_addr.addr_type.gsi.remote_qkey), + cl_ntoh16(p_infr->report_addr.addr_type.gsi.pkey), + p_infr->report_addr.addr_type.gsi.service_level); +} + +static void +sa_dump_one_service(cl_list_item_t *p_list_item, void *cxt) +{ + FILE *file = ((struct opensm_dump_context *)cxt)->file; + osm_svcr_t *p_svcr = (osm_svcr_t *)p_list_item; + ib_service_record_t *p_sr = &p_svcr->service_record; + + fprintf(file, "Service Record: id=0x%016" PRIx64 + " gid=0x%016" PRIx64 ":0x%016" PRIx64 + " pkey=0x%x" + " lease=0x%x" + " key=0x%02x%02x%02x%02x%02x%02x%02x%02x" + ":0x%02x%02x%02x%02x%02x%02x%02x%02x" + " name=\'%s\'" + " data8=0x%02x%02x%02x%02x%02x%02x%02x%02x" + ":0x%02x%02x%02x%02x%02x%02x%02x%02x" + " data16=0x%04x%04x%04x%04x:0x%04x%04x%04x%04x" + " data32=0x%08x%08x:0x%08x%08x" + " data64=0x%016" PRIx64 ":0x%016" PRIx64 + " modified_time=0x%x lease_period=0x%x\n\n", + cl_ntoh64( p_sr->service_id ), + cl_ntoh64( p_sr->service_gid.unicast.prefix ), + cl_ntoh64( p_sr->service_gid.unicast.interface_id ), + cl_ntoh16( p_sr->service_pkey ), + cl_ntoh32( p_sr->service_lease ), + p_sr->service_key[0], p_sr->service_key[1], + p_sr->service_key[2], p_sr->service_key[3], + p_sr->service_key[4], p_sr->service_key[5], + p_sr->service_key[6], p_sr->service_key[7], + p_sr->service_key[8], p_sr->service_key[9], + p_sr->service_key[10], p_sr->service_key[11], + p_sr->service_key[12], p_sr->service_key[13], + p_sr->service_key[14], p_sr->service_key[15], + p_sr->service_name, + p_sr->service_data8[0], p_sr->service_data8[1], + p_sr->service_data8[2], p_sr->service_data8[3], + p_sr->service_data8[4], p_sr->service_data8[5], + p_sr->service_data8[6], p_sr->service_data8[7], + p_sr->service_data8[8], p_sr->service_data8[9], + p_sr->service_data8[10], p_sr->service_data8[11], + p_sr->service_data8[12], p_sr->service_data8[13], + p_sr->service_data8[14], p_sr->service_data8[15], + cl_ntoh16(p_sr->service_data16[0]), + cl_ntoh16(p_sr->service_data16[1]), + cl_ntoh16(p_sr->service_data16[2]), + cl_ntoh16(p_sr->service_data16[3]), + cl_ntoh16(p_sr->service_data16[4]), + cl_ntoh16(p_sr->service_data16[5]), + cl_ntoh16(p_sr->service_data16[6]), + cl_ntoh16(p_sr->service_data16[7]), + cl_ntoh32(p_sr->service_data32[0]), + cl_ntoh32(p_sr->service_data32[1]), + cl_ntoh32(p_sr->service_data32[2]), + cl_ntoh32(p_sr->service_data32[3]), + cl_ntoh64(p_sr->service_data64[0]), + cl_ntoh64(p_sr->service_data64[1]), + p_svcr->modified_time, p_svcr->lease_period); +} + +static void +sa_dump_all_sa(osm_opensm_t *p_osm, FILE *file) +{ + struct opensm_dump_context dump_context; + + dump_context.p_osm = p_osm; + dump_context.file = file; + osm_log(&p_osm->log, OSM_LOG_DEBUG, "sa_dump_all_sa: Dump multicast:\n"); + cl_plock_acquire(&p_osm->lock); + cl_qmap_apply_func(&p_osm->subn.mgrp_mlid_tbl, + sa_dump_one_mgrp, &dump_context); + osm_log(&p_osm->log, OSM_LOG_DEBUG, "sa_dump_all_sa: Dump inform:\n"); + cl_qlist_apply_func(&p_osm->subn.sa_infr_list, + sa_dump_one_inform, &dump_context); + osm_log(&p_osm->log, OSM_LOG_DEBUG, "sa_dump_all_sa: Dump services:\n"); + cl_qlist_apply_func(&p_osm->subn.sa_sr_list, + sa_dump_one_service, &dump_context); + cl_plock_release(&p_osm->lock); +} + +int osm_sa_db_file_dump(osm_opensm_t *p_osm) +{ + return opensm_dump_to_file(p_osm, "opensm-sa.dump", sa_dump_all_sa); +} + +/* + * SA DB Loader + * + */ + +osm_mgrp_t *load_mcgroup(osm_opensm_t *p_osm, ib_net16_t mlid, + ib_member_rec_t *p_mcm_rec, unsigned well_known) +{ + ib_net64_t comp_mask; + cl_map_item_t *p_next; + osm_mgrp_t *p_mgrp; + + cl_plock_excl_acquire(&p_osm->lock); + + if ((p_next = cl_qmap_get(&p_osm->subn.mgrp_mlid_tbl, mlid)) != + cl_qmap_end(&p_osm->subn.mgrp_mlid_tbl)) { + p_mgrp = (osm_mgrp_t *)p_next; + if (!memcmp(&p_mgrp->mcmember_rec.mgid, &p_mcm_rec->mgid, + sizeof(ib_gid_t))) { + osm_log(&p_osm->log, OSM_LOG_DEBUG, + "load_mcgroup: mgrp %04x is already here.", + cl_ntoh16(mlid)); + goto _out; + } + osm_log(&p_osm->log, OSM_LOG_VERBOSE, + "load_mcgroup: mlid %04x is already used by another " + "MC group. Will request clients reregistration.\n", + cl_ntoh16(mlid)); + p_mgrp = NULL; + goto _out; + } + + comp_mask = IB_MCR_COMPMASK_MTU | IB_MCR_COMPMASK_MTU_SEL + | IB_MCR_COMPMASK_RATE | IB_MCR_COMPMASK_RATE_SEL; + if (osm_mcmr_rcv_find_or_create_new_mgrp(&p_osm->sa.mcmr_rcv, + comp_mask, p_mcm_rec, + &p_mgrp) != IB_SUCCESS || + !p_mgrp || p_mgrp->mlid != mlid) { + osm_log(&p_osm->log, OSM_LOG_ERROR, + "load_mcgroup: cannot create MC group with mlid " + "0x%04x and mgid 0x%016" PRIx64 ":0x%016" PRIx64 "\n", + cl_ntoh16(mlid), + cl_ntoh64(p_mcm_rec->mgid.unicast.prefix), + cl_ntoh64(p_mcm_rec->mgid.unicast.interface_id)); + p_mgrp=NULL; + } + else if (well_known) + p_mgrp->well_known = TRUE; + + _out: + cl_plock_release(&p_osm->lock); + + return p_mgrp; +} + +static int load_svcr(osm_opensm_t *p_osm, ib_service_record_t *sr, + uint32_t modified_time, uint32_t lease_period) +{ + osm_svcr_t *p_svcr; + int ret = 0; + + cl_plock_excl_acquire(&p_osm->lock); + + if(osm_svcr_get_by_rid(&p_osm->subn, &p_osm->log, sr)) { + osm_log(&p_osm->log, OSM_LOG_VERBOSE, + "load_svcr ServiceRecord already exists.\n"); + goto _out; + } + + if (!(p_svcr = osm_svcr_new(sr))) { + osm_log(&p_osm->log, OSM_LOG_ERROR, + "load_svcr: cannot allocate new service struct\n"); + ret = -1; + goto _out; + } + + p_svcr->modified_time = modified_time; + p_svcr->lease_period = lease_period; + + osm_log(&p_osm->log, OSM_LOG_DEBUG, + "load_svcr: adding ServiceRecord...\n"); + + osm_svcr_insert_to_db(&p_osm->subn, &p_osm->log, p_svcr); + + if (lease_period != 0xffffffff) + cl_timer_trim(&p_osm->sa.sr_rcv.sr_timer, 1000); + + _out: + cl_plock_release(&p_osm->lock); + + return ret; +} + +static int load_infr(osm_opensm_t *p_osm, ib_inform_info_record_t *iir, + osm_mad_addr_t *addr) +{ + osm_infr_t infr, *p_infr; + int ret = 0; + + infr.h_bind = p_osm->sa.mad_ctrl.h_bind; + infr.p_infr_rcv = &p_osm->sa.infr_rcv; + /* other possible way to restore mad_addr partially is + to extract qpn from InformInfo and to find lid by gid */ + infr.report_addr = *addr; + infr.inform_record = *iir; + + cl_plock_excl_acquire(&p_osm->lock); + if (osm_infr_get_by_rec(&p_osm->subn, &p_osm->log, &infr)) { + osm_log(&p_osm->log, OSM_LOG_VERBOSE, + "load_infr: InformInfo Record already exists\n"); + goto _out; + } + + if (!(p_infr = osm_infr_new(&infr))) { + osm_log(&p_osm->log, OSM_LOG_ERROR, + "load_infr: cannot allocate new infr struct\n"); + ret = -1; + goto _out; + } + + osm_log(&p_osm->log, OSM_LOG_DEBUG, + "load_infr: adding InformInfo Record...\n"); + + osm_infr_insert_to_db(&p_osm->subn, &p_osm->log, p_infr); + + _out: + cl_plock_release(&p_osm->lock); + + return ret; +} + + +#define UNPACK_FUNC(name,x) \ +int unpack_##name##x(char *p, uint##x##_t *val_ptr) \ +{ \ + char *q; \ + unsigned long long num; \ + num = strtoull(p, &q, 16); \ + if (num > ~((uint##x##_t)0x0) \ + || q == p || (!isspace(*q) && *q != ':')) { \ + *val_ptr = 0; \ + return -1; \ + } \ + *val_ptr = cl_hton##x((uint##x##_t)num); \ + return (int)(q - p); \ +} + +#define cl_hton8(x) (x) + +UNPACK_FUNC(net,8); +UNPACK_FUNC(net,16); +UNPACK_FUNC(net,32); +UNPACK_FUNC(net,64); + +static int unpack_string(char *p, uint8_t *buf, unsigned len) +{ + char *q = p; + char delim = ' '; + + if (*q == '\'' || *q == '\"') + delim = *q++; + while (--len && *q && *q != delim) + *buf++ = *q++; + *buf = '\0'; + if (*q == delim && delim != ' ') + q++; + return (int)(q - p); +} + +static int unpack_string64(char *p, uint8_t *buf) +{ + return unpack_string(p, buf, 64); +} + +#define PARSE_AHEAD(p, x, name, val_ptr) { int _ret; \ + p = strstr(p, name); \ + if (!p) { \ + osm_log(&p_osm->log, OSM_LOG_ERROR, \ + "PARSE ERROR: %s:%u: cannot find \"%s\" string\n", \ + file_name, lineno, (name)); \ + ret = -2; \ + goto _error; \ + } \ + p += strlen(name); \ + _ret = unpack_##x(p, (val_ptr)); \ + if (_ret < 0) { \ + osm_log(&p_osm->log, OSM_LOG_ERROR, \ + "PARSE ERROR: %s:%u: cannot parse "#x" value " \ + "after \"%s\"\n", file_name, lineno, (name)); \ + ret = _ret; \ + goto _error; \ + } \ + p += _ret; \ +} + +int osm_sa_db_file_load(osm_opensm_t *p_osm) +{ + char line[1024]; + char *file_name; + FILE *file; + int ret = 0; + osm_mgrp_t *p_mgrp = NULL; + unsigned rereg_clients = 0; + unsigned lineno; + + file_name = p_osm->subn.opt.sa_db_file; + if (!file_name) { + osm_log(&p_osm->log, OSM_LOG_VERBOSE, + "osm_sa_db_file_load: sa db file name is not " + "specifed. Skip restore\n"); + return 0; + } + + file = fopen(file_name, "r"); + if (!file) { + osm_log(&p_osm->log, OSM_LOG_ERROR|OSM_LOG_SYS, + "osm_sa_db_file_load: ERR 0000: " + "cannot open sa db file \'%s\'. " + "Skip restoring\n", file_name); + return -1; + } + + lineno = 0; + + while (fgets(line, sizeof(line) - 1, file) != NULL) { + char *p; + uint8_t val; + + lineno++; + + p = line; + while (isspace(*p)) + p++; + + if (*p == '#') + continue; + + if (!strncmp(p, "MC Group", 8)) { + ib_member_rec_t mcm_rec; + ib_net16_t mlid; + unsigned well_known = 0; + + p_mgrp = NULL; + memset(&mcm_rec, 0, sizeof(mcm_rec)); + + PARSE_AHEAD(p, net16, " 0x", &mlid); + if(strstr(p, "well known")) + well_known = 1; + PARSE_AHEAD(p, net64, " mgid=0x", + &mcm_rec.mgid.unicast.prefix); + PARSE_AHEAD(p, net64, ":0x", + &mcm_rec.mgid.unicast.interface_id); + PARSE_AHEAD(p, net64, " port_gid=0x", + &mcm_rec.port_gid.unicast.prefix); + PARSE_AHEAD(p, net64, ":0x", + &mcm_rec.port_gid.unicast.interface_id); + PARSE_AHEAD(p, net32, " qkey=0x", &mcm_rec.qkey); + PARSE_AHEAD(p, net16, " mlid=0x", &mcm_rec.mlid); + PARSE_AHEAD(p, net8, " mtu=0x", &mcm_rec.mtu); + PARSE_AHEAD(p, net8, " tclass=0x", &mcm_rec.tclass); + PARSE_AHEAD(p, net16, " pkey=0x", &mcm_rec.pkey); + PARSE_AHEAD(p, net8, " rate=0x", &mcm_rec.rate); + PARSE_AHEAD(p, net8, " pkt_life=0x", &mcm_rec.pkt_life); + PARSE_AHEAD(p, net32, " sl_flow_hop=0x", + &mcm_rec.sl_flow_hop); + PARSE_AHEAD(p, net8, " scope_state=0x", + &mcm_rec.scope_state); + PARSE_AHEAD(p, net8, " proxy_join=0x", &val); + mcm_rec.proxy_join = val; + + p_mgrp = load_mcgroup(p_osm, mlid, &mcm_rec, + well_known); + if (!p_mgrp) + rereg_clients = 1; + } + else if (p_mgrp && !strncmp(p, "mcm_port", 8)) { + ib_gid_t port_gid; + ib_net64_t guid; + uint8_t scope_state; + boolean_t proxy_join; + + PARSE_AHEAD(p, net64, " port_gid=0x", + &port_gid.unicast.prefix); + PARSE_AHEAD(p, net64, ":0x", + &port_gid.unicast.interface_id); + PARSE_AHEAD(p, net8, " scope_state=0x", &scope_state); + PARSE_AHEAD(p, net8, " proxy_join=0x", &val); + proxy_join = val; + + guid = port_gid.unicast.interface_id; + if (cl_qmap_get(&p_mgrp->mcm_port_tbl, + port_gid.unicast.interface_id) == + cl_qmap_end(&p_mgrp->mcm_port_tbl)) + osm_mgrp_add_port(p_mgrp, &port_gid, + scope_state, proxy_join); + } + else if (!strncmp(p, "Service Record:", 15)) { + ib_service_record_t s_rec; + uint32_t modified_time, lease_period; + + p_mgrp = NULL; + memset(&s_rec, 0, sizeof(s_rec)); + + PARSE_AHEAD(p, net64, " id=0x", &s_rec.service_id); + PARSE_AHEAD(p, net64, " gid=0x", + &s_rec.service_gid.unicast.prefix); + PARSE_AHEAD(p, net64, ":0x", + &s_rec.service_gid.unicast.interface_id); + PARSE_AHEAD(p, net16, " pkey=0x", &s_rec.service_pkey); + PARSE_AHEAD(p, net32, " lease=0x", &s_rec.service_lease); + PARSE_AHEAD(p, net64, " key=0x", + (ib_net64_t *)(&s_rec.service_key[0])); + PARSE_AHEAD(p, net64, ":0x", + (ib_net64_t *)(&s_rec.service_key[8])); + PARSE_AHEAD(p, string64, " name=", s_rec.service_name); + PARSE_AHEAD(p, net64, " data8=0x", + (ib_net64_t *)(&s_rec.service_data8[0])); + PARSE_AHEAD(p, net64, ":0x", + (ib_net64_t *)(&s_rec.service_data8[8])); + PARSE_AHEAD(p, net64, " data16=0x", + (ib_net64_t *)(&s_rec.service_data16[0])); + PARSE_AHEAD(p, net64, ":0x", + (ib_net64_t *)(&s_rec.service_data16[4])); + PARSE_AHEAD(p, net64, " data32=0x", + (ib_net64_t *)(&s_rec.service_data32[0])); + PARSE_AHEAD(p, net64, ":0x", + (ib_net64_t *)(&s_rec.service_data32[2])); + PARSE_AHEAD(p, net64, " data64=0x", &s_rec.service_data64[0]); + PARSE_AHEAD(p, net64, ":0x", &s_rec.service_data64[1]); + PARSE_AHEAD(p, net32, " modified_time=0x", + &modified_time); + PARSE_AHEAD(p, net32, " lease_period=0x", + &lease_period); + + if (load_svcr(p_osm, &s_rec, cl_ntoh32(modified_time), + cl_ntoh32(lease_period))) + rereg_clients = 1; + } + else if (!strncmp(p, "InformInfo Record:", 18)) { + ib_inform_info_record_t i_rec; + osm_mad_addr_t rep_addr; + + p_mgrp = NULL; + memset(&i_rec, 0, sizeof(i_rec)); + memset(&rep_addr, 0, sizeof(rep_addr)); + + PARSE_AHEAD(p, net64, " subscriber_gid=0x", + &i_rec.subscriber_gid.unicast.prefix); + PARSE_AHEAD(p, net64, ":0x", + &i_rec.subscriber_gid.unicast.interface_id); + PARSE_AHEAD(p, net16, " subscriber_enum=0x", + &i_rec.subscriber_enum); + PARSE_AHEAD(p, net64, " gid=0x", + &i_rec.inform_info.gid.unicast.prefix); + PARSE_AHEAD(p, net64, ":0x", + &i_rec.inform_info.gid.unicast.interface_id); + PARSE_AHEAD(p, net16, " lid_range_begin=0x", + &i_rec.inform_info.lid_range_begin); + PARSE_AHEAD(p, net16, " lid_range_end=0x", + &i_rec.inform_info.lid_range_end); + PARSE_AHEAD(p, net8, " is_generic=0x", + &i_rec.inform_info.is_generic); + PARSE_AHEAD(p, net8, " subscribe=0x", + &i_rec.inform_info.subscribe); + PARSE_AHEAD(p, net16, " trap_type=0x", + &i_rec.inform_info.trap_type); + PARSE_AHEAD(p, net16, " trap_num=0x", + &i_rec.inform_info.g_or_v.generic.trap_num); + PARSE_AHEAD(p, net32, " qpn_resp_time_val=0x", + &i_rec.inform_info.g_or_v.generic.qpn_resp_time_val); + PARSE_AHEAD(p, net32, " node_type=0x", + (uint32_t *)&i_rec.inform_info.g_or_v.generic.reserved2); + + PARSE_AHEAD(p, net16, " rep_addr: lid=0x", + &rep_addr.dest_lid); + PARSE_AHEAD(p, net8, " path_bits=0x", + &rep_addr.path_bits); + PARSE_AHEAD(p, net8, " static_rate=0x", + &rep_addr.static_rate); + PARSE_AHEAD(p, net32, " remote_qp=0x", + &rep_addr.addr_type.gsi.remote_qp); + PARSE_AHEAD(p, net32, " remote_qkey=0x", + &rep_addr.addr_type.gsi.remote_qkey); + PARSE_AHEAD(p, net16, " pkey=0x", + &rep_addr.addr_type.gsi.pkey); + PARSE_AHEAD(p, net8, " sl=0x", + &rep_addr.addr_type.gsi.service_level); + + if (load_infr(p_osm, &i_rec, &rep_addr)) + rereg_clients = 1; + } + } + + if (!rereg_clients) + p_osm->subn.opt.no_clients_rereg = TRUE; + + _error: + fclose(file); + return ret; +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_class_port_info.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_class_port_info.c new file mode 100644 index 00000000..bae104d9 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_class_port_info.c @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_class_port_info.c 1931 2009-02-04 17:56:23Z stansmith $ + */ + + + +/* + * Abstract: + * Implementation of osm_cpi_rcv_t. + * This object represents the ClassPortInfo Receiver object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.8 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_MSECS_TO_RTV 24 +/* Precalculated table in msec (index is related to encoded value) */ +/* 4.096 usec * 2 ** n (where n = 8 - 31) */ +static uint32_t __msecs_to_rtv_table[MAX_MSECS_TO_RTV] = + { 1, 2, 4, 8, + 16, 33, 67, 134, + 268, 536, 1073, 2147, + 4294, 8589, 17179, 34359, + 68719, 137438, 274877, 549755, + 1099511, 2199023, 4398046, 8796093 }; + +/********************************************************************** + **********************************************************************/ +void +osm_cpi_rcv_construct( + IN osm_cpi_rcv_t* const p_rcv ) +{ + memset( p_rcv, 0, sizeof(*p_rcv) ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_cpi_rcv_destroy( + IN osm_cpi_rcv_t* const p_rcv ) +{ + OSM_LOG_ENTER( p_rcv->p_log, osm_cpi_rcv_destroy ); + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_cpi_rcv_init( + IN osm_cpi_rcv_t* const p_rcv, + IN osm_sa_resp_t* const p_resp, + IN osm_mad_pool_t* const p_mad_pool, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_cpi_rcv_init ); + + osm_cpi_rcv_construct( p_rcv ); + + p_rcv->p_log = p_log; + p_rcv->p_subn = p_subn; + p_rcv->p_lock = p_lock; + p_rcv->p_resp = p_resp; + p_rcv->p_mad_pool = p_mad_pool; + + OSM_LOG_EXIT( p_rcv->p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_cpi_rcv_respond( + IN osm_cpi_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ) +{ + osm_madw_t* p_resp_madw; + const ib_sa_mad_t* p_sa_mad; + ib_sa_mad_t* p_resp_sa_mad; + ib_class_port_info_t *p_resp_cpi; + ib_api_status_t status; + ib_gid_t zero_gid; + uint8_t rtv; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_cpi_rcv_respond ); + + memset(&zero_gid, 0, sizeof(ib_gid_t)); + + /* + Get a MAD to reply. Address of Mad is in the received mad_wrapper + */ + p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool, + p_madw->h_bind, + MAD_BLOCK_SIZE, + &p_madw->mad_addr ); + if( !p_resp_madw ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_cpi_rcv_respond: ERR 1408: " + "Unable to allocate MAD\n" ); + goto Exit; + } + + p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw ); + p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw ); + + memcpy( p_resp_sa_mad, p_sa_mad, IB_SA_MAD_HDR_SIZE ); + p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK; + /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */ + p_resp_sa_mad->sm_key = 0; + + p_resp_cpi = (ib_class_port_info_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad ); + + /* finally do it (the job) man ! */ + p_resp_cpi->base_ver = 1; + p_resp_cpi->class_ver = 2; + /* Calculate encoded response time value */ + /* transaction timeout is in msec */ + if (p_rcv->p_subn->opt.transaction_timeout > __msecs_to_rtv_table[MAX_MSECS_TO_RTV]) + rtv = MAX_MSECS_TO_RTV - 1; + else + { + for (rtv = 0; rtv < MAX_MSECS_TO_RTV; rtv++) { + if (p_rcv->p_subn->opt.transaction_timeout <= __msecs_to_rtv_table[rtv]) + break; + } + } + rtv += 8; + p_resp_cpi->cap_mask2_resp_time = rtv; + p_resp_cpi->redir_gid = zero_gid; + p_resp_cpi->redir_tc_sl_fl = 0; + p_resp_cpi->redir_lid = 0; + p_resp_cpi->redir_pkey = 0; + p_resp_cpi->redir_qp = CL_NTOH32(1); + p_resp_cpi->redir_qkey = IB_QP1_WELL_KNOWN_Q_KEY; + p_resp_cpi->trap_gid = zero_gid; + p_resp_cpi->trap_tc_sl_fl = 0; + p_resp_cpi->trap_lid = 0; + p_resp_cpi->trap_pkey = 0; + p_resp_cpi->trap_hop_qp = 0; + p_resp_cpi->trap_qkey = IB_QP1_WELL_KNOWN_Q_KEY; + + /* set specific capability mask bits */ + /* we do not support the following optional records: + OSM_CAP_IS_SUBN_OPT_RECS_SUP : + RandomForwardingTableRecord, + ServiceAssociationRecord + other optional records supported "under the table" + + OSM_CAP_IS_MULTIPATH_SUP: + TraceRecord + + OSM_CAP_IS_REINIT_SUP: + For reinitialization functionality. + + So not sending traps, but supporting Get(Notice) and Set(Notice). + */ + + /* Note host notation replaced later */ +#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP) + p_resp_cpi->cap_mask = OSM_CAP_IS_SUBN_GET_SET_NOTICE_SUP | + OSM_CAP_IS_PORT_INFO_CAPMASK_MATCH_SUPPORTED | + OSM_CAP_IS_MULTIPATH_SUP; +#else + p_resp_cpi->cap_mask = OSM_CAP_IS_SUBN_GET_SET_NOTICE_SUP | + OSM_CAP_IS_PORT_INFO_CAPMASK_MATCH_SUPPORTED; +#endif + if (p_rcv->p_subn->opt.no_multicast_option != TRUE) + p_resp_cpi->cap_mask |= OSM_CAP_IS_UD_MCAST_SUP; + p_resp_cpi->cap_mask = cl_hton16(p_resp_cpi->cap_mask); + + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_FRAMES ) ) + osm_dump_sa_mad( p_rcv->p_log, p_resp_sa_mad, OSM_LOG_FRAMES ); + + status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE ); + if( status != IB_SUCCESS ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_cpi_rcv_respond: ERR 1409: " + "Unable to send MAD (%s)\n", ib_get_err_str( status ) ); + /* osm_mad_pool_put( p_rcv->p_mad_pool, p_resp_madw ); */ + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + * This code actually handles the call + **********************************************************************/ +void +osm_cpi_rcv_process( + IN osm_cpi_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ) +{ + const ib_path_rec_t* p_pr; + const ib_sa_mad_t* p_sa_mad; + + OSM_LOG_ENTER( p_rcv->p_log, osm_cpi_rcv_process ); + + CL_ASSERT( p_madw ); + + p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw ); + + /* we only support GET */ + if (p_sa_mad->method != IB_MAD_METHOD_GET) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_cpi_rcv_process: ERR 1403: " + "Unsupported Method (%s)\n", + ib_get_sa_method_str( p_sa_mad->method ) ); + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); + goto Exit; + } + + p_pr = (ib_path_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad ); + + CL_ASSERT( p_sa_mad->attr_id == IB_MAD_ATTR_CLASS_PORT_INFO ); + + /* + CLASS PORT INFO does not really look on the SMDB - no lock required. + */ + + __osm_cpi_rcv_respond( p_rcv, p_madw); + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_class_port_info_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_class_port_info_ctrl.c new file mode 100644 index 00000000..22ad8f3f --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_class_port_info_ctrl.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_class_port_info_ctrl.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_pr_rcv_ctrl_t. + * This object represents the ClassPortInfo request controller object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.3 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +__osm_cpi_rcv_ctrl_disp_callback( + IN void *context, + IN void *p_data ) +{ + /* ignore return status when invoked via the dispatcher */ + osm_cpi_rcv_process( ((osm_cpi_rcv_ctrl_t*)context)->p_rcv, + (osm_madw_t*)p_data ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_cpi_rcv_ctrl_construct( + IN osm_cpi_rcv_ctrl_t* const p_ctrl ) +{ + memset( p_ctrl, 0, sizeof(*p_ctrl) ); + p_ctrl->h_disp = CL_DISP_INVALID_HANDLE; +} + +/********************************************************************** + **********************************************************************/ +void +osm_cpi_rcv_ctrl_destroy( + IN osm_cpi_rcv_ctrl_t* const p_ctrl ) +{ + CL_ASSERT( p_ctrl ); + cl_disp_unregister( p_ctrl->h_disp ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_cpi_rcv_ctrl_init( + IN osm_cpi_rcv_ctrl_t* const p_ctrl, + IN osm_cpi_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_cpi_rcv_ctrl_init ); + + osm_cpi_rcv_ctrl_construct( p_ctrl ); + p_ctrl->p_log = p_log; + p_ctrl->p_rcv = p_rcv; + p_ctrl->p_disp = p_disp; + + p_ctrl->h_disp = cl_disp_register( + p_disp, + OSM_MSG_MAD_CLASS_PORT_INFO, + __osm_cpi_rcv_ctrl_disp_callback, + p_ctrl ); + + if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_cpi_rcv_ctrl_init: ERR 1501: " + "Dispatcher registration failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return( status ); +} + + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_guidinfo_record.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_guidinfo_record.c new file mode 100644 index 00000000..90618b93 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_guidinfo_record.c @@ -0,0 +1,611 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_guidinfo_record.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_gir_rcv_t. + * This object represents the GUIDInfoRecord Receiver object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define OSM_GIR_RCV_POOL_MIN_SIZE 32 +#define OSM_GIR_RCV_POOL_GROW_SIZE 32 + +typedef struct _osm_gir_item +{ + cl_pool_item_t pool_item; + ib_guidinfo_record_t rec; +} osm_gir_item_t; + +typedef struct _osm_gir_search_ctxt +{ + const ib_guidinfo_record_t* p_rcvd_rec; + ib_net64_t comp_mask; + cl_qlist_t* p_list; + osm_gir_rcv_t* p_rcv; + const osm_physp_t* p_req_physp; +} osm_gir_search_ctxt_t; + +/********************************************************************** + **********************************************************************/ +void +osm_gir_rcv_construct( + IN osm_gir_rcv_t* const p_rcv ) +{ + memset( p_rcv, 0, sizeof(*p_rcv) ); + cl_qlock_pool_construct( &p_rcv->pool ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_gir_rcv_destroy( + IN osm_gir_rcv_t* const p_rcv ) +{ + OSM_LOG_ENTER( p_rcv->p_log, osm_gir_rcv_destroy ); + cl_qlock_pool_destroy( &p_rcv->pool ); + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_gir_rcv_init( + IN osm_gir_rcv_t* const p_rcv, + IN osm_sa_resp_t* const p_resp, + IN osm_mad_pool_t* const p_mad_pool, + IN const osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ) +{ + ib_api_status_t status; + + OSM_LOG_ENTER( p_log, osm_gir_rcv_init ); + + osm_gir_rcv_construct( p_rcv ); + + p_rcv->p_log = p_log; + p_rcv->p_subn = p_subn; + p_rcv->p_lock = p_lock; + p_rcv->p_resp = p_resp; + p_rcv->p_mad_pool = p_mad_pool; + + status = cl_qlock_pool_init( &p_rcv->pool, + OSM_GIR_RCV_POOL_MIN_SIZE, + 0, + OSM_GIR_RCV_POOL_GROW_SIZE, + sizeof(osm_gir_item_t), + NULL, NULL, NULL ); + + OSM_LOG_EXIT( p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +static ib_api_status_t +__osm_gir_rcv_new_gir( + IN osm_gir_rcv_t* const p_rcv, + IN const osm_node_t* const p_node, + IN cl_qlist_t* const p_list, + IN ib_net64_t const match_port_guid, + IN ib_net16_t const match_lid, + IN const osm_physp_t* const p_req_physp, + IN uint8_t const block_num ) +{ + osm_gir_item_t* p_rec_item; + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_gir_rcv_new_gir ); + + p_rec_item = (osm_gir_item_t*)cl_qlock_pool_get( &p_rcv->pool ); + if( p_rec_item == NULL ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_gir_rcv_new_gir: ERR 5102: " + "cl_qlock_pool_get failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_gir_rcv_new_gir: " + "New GUIDInfoRecord: lid 0x%X, block num %d\n", + cl_ntoh16( match_lid ), block_num ); + } + + memset( &p_rec_item->rec, 0, sizeof( p_rec_item->rec ) ); + + p_rec_item->rec.lid = match_lid; + p_rec_item->rec.block_num = block_num; + if (!block_num) + p_rec_item->rec.guid_info.guid[0] = osm_physp_get_port_guid( p_req_physp ); + + cl_qlist_insert_tail( p_list, (cl_list_item_t*)&p_rec_item->pool_item ); + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +void +__osm_sa_gir_create_gir( + IN osm_gir_rcv_t* const p_rcv, + IN const osm_node_t* const p_node, + IN cl_qlist_t* const p_list, + IN ib_net64_t const match_port_guid, + IN ib_net16_t const match_lid, + IN const osm_physp_t* const p_req_physp, + IN uint8_t const match_block_num ) +{ + const osm_physp_t* p_physp; + uint8_t port_num; + uint8_t num_ports; + uint16_t match_lid_ho; + ib_net16_t base_lid_ho; + ib_net16_t max_lid_ho; + uint8_t lmc; + ib_net64_t port_guid; + const ib_port_info_t* p_pi; + uint8_t block_num, start_block_num, end_block_num, num_blocks; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_gir_create_gir ); + + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_sa_gir_create_gir: " + "Looking for GUIDRecord with LID: 0x%X GUID:0x%016" PRIx64 "\n", + cl_ntoh16( match_lid ), + cl_ntoh64( match_port_guid ) + ); + } + + /* + For switches, do not return the GUIDInfo record(s) + for each port on the switch, just for port 0. + */ + if( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH ) + num_ports = 1; + else + num_ports = osm_node_get_num_physp( p_node ); + + for( port_num = 0; port_num < num_ports; port_num++ ) + { + p_physp = osm_node_get_physp_ptr( p_node, port_num ); + + if( !osm_physp_is_valid( p_physp ) ) + continue; + + /* Check to see if the found p_physp and the requester physp + share a pkey. If not, continue */ + if (!osm_physp_share_pkey( p_rcv->p_log, p_physp, p_req_physp ) ) + continue; + + port_guid = osm_physp_get_port_guid( p_physp ); + + if( match_port_guid && ( port_guid != match_port_guid ) ) + continue; + + p_pi = osm_physp_get_port_info_ptr( p_physp ); + + /* + Note: the following check is a temporary workaround + Since 1. GUIDCap should never be 0 on ports where this applies + and 2. GUIDCap should not be used on ports where it doesn't apply + So this should really be a check for whether the port is a + switch external port or not! + */ + if ( p_pi->guid_cap == 0 ) + continue; + + num_blocks = p_pi->guid_cap / 8; + if ( p_pi->guid_cap % 8 ) + num_blocks++; + if ( match_block_num == 255 ) + { + start_block_num = 0; + end_block_num = num_blocks - 1; + } + else + { + if ( match_block_num >= num_blocks ) + continue; + end_block_num = start_block_num = match_block_num; + } + + base_lid_ho = cl_ntoh16( osm_physp_get_base_lid( p_physp ) ); + match_lid_ho = cl_ntoh16( match_lid ); + if( match_lid_ho ) + { + lmc = osm_physp_get_lmc( p_physp ); + max_lid_ho = (uint16_t)( base_lid_ho + (1 << lmc) - 1 ); + + /* + We validate that the lid belongs to this node. + */ + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_sa_gir_create_gir: " + "Comparing LID: 0x%X <= 0x%X <= 0x%X\n", + base_lid_ho, match_lid_ho, max_lid_ho + ); + } + + if ( match_lid_ho < base_lid_ho || match_lid_ho > max_lid_ho ) + continue; + } + + for (block_num = start_block_num; block_num <= end_block_num; block_num++) + __osm_gir_rcv_new_gir( p_rcv, p_node, p_list, + port_guid, cl_ntoh16(base_lid_ho), + p_physp, block_num ); + + } + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +void +__osm_sa_gir_by_comp_mask_cb( + IN cl_map_item_t* const p_map_item, + IN void* context ) +{ + const osm_gir_search_ctxt_t* const p_ctxt = (osm_gir_search_ctxt_t *)context; + const osm_node_t* const p_node = (osm_node_t*)p_map_item; + const ib_guidinfo_record_t* const p_rcvd_rec = p_ctxt->p_rcvd_rec; + const osm_physp_t* const p_req_physp = p_ctxt->p_req_physp; + osm_gir_rcv_t* const p_rcv = p_ctxt->p_rcv; + const ib_guid_info_t* p_comp_gi; + ib_net64_t const comp_mask = p_ctxt->comp_mask; + ib_net64_t match_port_guid = 0; + ib_net16_t match_lid = 0; + uint8_t match_block_num = 255; + + OSM_LOG_ENTER( p_ctxt->p_rcv->p_log, __osm_sa_gir_by_comp_mask_cb); + + if( comp_mask & IB_GIR_COMPMASK_LID ) + match_lid = p_rcvd_rec->lid; + + if( comp_mask & IB_GIR_COMPMASK_BLOCKNUM ) + match_block_num = p_rcvd_rec->block_num; + + p_comp_gi = &p_rcvd_rec->guid_info; + /* Different rule for block 0 v. other blocks */ + if( comp_mask & IB_GIR_COMPMASK_GID0 ) + { + if ( !p_rcvd_rec->block_num ) + match_port_guid = osm_physp_get_port_guid( p_req_physp ); + if ( p_comp_gi->guid[0] != match_port_guid ) + goto Exit; + } + + if( comp_mask & IB_GIR_COMPMASK_GID1 ) + { + if ( p_comp_gi->guid[1] != 0) + goto Exit; + } + + if( comp_mask & IB_GIR_COMPMASK_GID2 ) + { + if ( p_comp_gi->guid[2] != 0) + goto Exit; + } + + if( comp_mask & IB_GIR_COMPMASK_GID3 ) + { + if ( p_comp_gi->guid[3] != 0) + goto Exit; + } + + if( comp_mask & IB_GIR_COMPMASK_GID4 ) + { + if ( p_comp_gi->guid[4] != 0) + goto Exit; + } + + if( comp_mask & IB_GIR_COMPMASK_GID5 ) + { + if ( p_comp_gi->guid[5] != 0) + goto Exit; + } + + if( comp_mask & IB_GIR_COMPMASK_GID6 ) + { + if ( p_comp_gi->guid[6] != 0) + goto Exit; + } + + if( comp_mask & IB_GIR_COMPMASK_GID7 ) + { + if ( p_comp_gi->guid[7] != 0) + goto Exit; + } + + __osm_sa_gir_create_gir( p_rcv, p_node, p_ctxt->p_list, + match_port_guid, match_lid, p_req_physp, + match_block_num ); + + Exit: + OSM_LOG_EXIT( p_ctxt->p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_gir_rcv_process( + IN osm_gir_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ) +{ + const ib_sa_mad_t* p_rcvd_mad; + const ib_guidinfo_record_t* p_rcvd_rec; + cl_qlist_t rec_list; + osm_madw_t* p_resp_madw; + ib_sa_mad_t* p_resp_sa_mad; + ib_guidinfo_record_t* p_resp_rec; + uint32_t num_rec, pre_trim_num_rec; +#ifndef VENDOR_RMPP_SUPPORT + uint32_t trim_num_rec; +#endif + uint32_t i; + osm_gir_search_ctxt_t context; + osm_gir_item_t* p_rec_item; + ib_api_status_t status; + osm_physp_t* p_req_physp; + + CL_ASSERT( p_rcv ); + + OSM_LOG_ENTER( p_rcv->p_log, osm_gir_rcv_process ); + + CL_ASSERT( p_madw ); + + p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw ); + p_rcvd_rec = (ib_guidinfo_record_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad ); + + CL_ASSERT( p_rcvd_mad->attr_id == IB_MAD_ATTR_GUIDINFO_RECORD ); + + /* we only support SubnAdmGet and SubnAdmGetTable methods */ + if ( (p_rcvd_mad->method != IB_MAD_METHOD_GET) && + (p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_gir_rcv_process: ERR 5105: " + "Unsupported Method (%s)\n", + ib_get_sa_method_str( p_rcvd_mad->method ) ); + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR ); + goto Exit; + } + + /* update the requester physical port. */ + p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log, + p_rcv->p_subn, + osm_madw_get_mad_addr_ptr(p_madw) ); + if (p_req_physp == NULL) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_gir_rcv_process: ERR 5104: " + "Cannot find requester physical port\n" ); + goto Exit; + } + + if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + osm_dump_guidinfo_record( p_rcv->p_log, p_rcvd_rec, OSM_LOG_DEBUG ); + + cl_qlist_init( &rec_list ); + + context.p_rcvd_rec = p_rcvd_rec; + context.p_list = &rec_list; + context.comp_mask = p_rcvd_mad->comp_mask; + context.p_rcv = p_rcv; + context.p_req_physp = p_req_physp; + + cl_plock_acquire( p_rcv->p_lock ); + + cl_qmap_apply_func( &p_rcv->p_subn->node_guid_tbl, + __osm_sa_gir_by_comp_mask_cb, + &context ); + + cl_plock_release( p_rcv->p_lock ); + + num_rec = cl_qlist_count( &rec_list ); + + /* + * C15-0.1.30: + * If we do a SubnAdmGet and got more than one record it is an error ! + */ + if (p_rcvd_mad->method == IB_MAD_METHOD_GET) + { + if (num_rec == 0) + { + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS ); + goto Exit; + } + if (num_rec > 1) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_gir_rcv_process: ERR 5103: " + "Got more than one record for SubnAdmGet (%u)\n", + num_rec ); + osm_sa_send_error( p_rcv->p_resp, p_madw, + IB_SA_MAD_STATUS_TOO_MANY_RECORDS ); + + /* need to set the mem free ... */ + p_rec_item = (osm_gir_item_t*)cl_qlist_remove_head( &rec_list ); + while( p_rec_item != (osm_gir_item_t*)cl_qlist_end( &rec_list ) ) + { + cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item ); + p_rec_item = (osm_gir_item_t*)cl_qlist_remove_head( &rec_list ); + } + + goto Exit; + } + } + + pre_trim_num_rec = num_rec; +#ifndef VENDOR_RMPP_SUPPORT + trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_guidinfo_record_t); + if (trim_num_rec < num_rec) + { + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "osm_gir_rcv_process: " + "Number of records:%u trimmed to:%u to fit in one MAD\n", + num_rec, trim_num_rec ); + num_rec = trim_num_rec; + } +#endif + + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "osm_gir_rcv_process: " + "Returning %u records\n", num_rec ); + + if ((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0)) + { + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS ); + goto Exit; + } + + /* + * Get a MAD to reply. Address of Mad is in the received mad_wrapper + */ + p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool, + p_madw->h_bind, + num_rec * sizeof(ib_guidinfo_record_t) + IB_SA_MAD_HDR_SIZE, + &p_madw->mad_addr ); + + if( !p_resp_madw ) + { + osm_log(p_rcv->p_log, OSM_LOG_ERROR, + "osm_gir_rcv_process: ERR 5106: " + "osm_mad_pool_get failed\n" ); + + for( i = 0; i < num_rec; i++ ) + { + p_rec_item = (osm_gir_item_t*)cl_qlist_remove_head( &rec_list ); + cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item ); + } + + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES ); + goto Exit; + } + + p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw ); + + /* + Copy the MAD header back into the response mad. + Set the 'R' bit and the payload length, + Then copy all records from the list into the response payload. + */ + + memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE ); + p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK; + /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */ + p_resp_sa_mad->sm_key = 0; + /* Fill in the offset (paylen will be done by the rmpp SAR) */ + p_resp_sa_mad->attr_offset = + ib_get_attr_offset( sizeof(ib_guidinfo_record_t) ); + + p_resp_rec = (ib_guidinfo_record_t*) + ib_sa_mad_get_payload_ptr( p_resp_sa_mad ); + +#ifndef VENDOR_RMPP_SUPPORT + /* we support only one packet RMPP - so we will set the first and + last flags for gettable */ + if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP) + { + p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA; + p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE; + } +#else + /* forcefully define the packet as RMPP one */ + if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP) + p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE; +#endif + + for( i = 0; i < pre_trim_num_rec; i++ ) + { + p_rec_item = (osm_gir_item_t*)cl_qlist_remove_head( &rec_list ); + /* copy only if not trimmed */ + if (i < num_rec) + { + *p_resp_rec = p_rec_item->rec; + } + cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item ); + p_resp_rec++; + } + + CL_ASSERT( cl_is_qlist_empty( &rec_list ) ); + + status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE); + if (status != IB_SUCCESS) + { + osm_log(p_rcv->p_log, OSM_LOG_ERROR, + "osm_gir_rcv_process: ERR 5107: " + "osm_vendor_send status = %s\n", + ib_get_err_str(status)); + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_guidinfo_record_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_guidinfo_record_ctrl.c new file mode 100644 index 00000000..4431a111 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_guidinfo_record_ctrl.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_guidinfo_record_ctrl.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_gir_rcv_ctrl_t. + * This object represents the GUIDInfoRecord request controller object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +__osm_gir_rcv_ctrl_disp_callback( + IN void *context, + IN void *p_data ) +{ + /* ignore return status when invoked via the dispatcher */ + osm_gir_rcv_process( ((osm_gir_rcv_ctrl_t*)context)->p_rcv, + (osm_madw_t*)p_data ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_gir_rcv_ctrl_construct( + IN osm_gir_rcv_ctrl_t* const p_ctrl ) +{ + memset( p_ctrl, 0, sizeof(*p_ctrl) ); + p_ctrl->h_disp = CL_DISP_INVALID_HANDLE; +} + +/********************************************************************** + **********************************************************************/ +void +osm_gir_rcv_ctrl_destroy( + IN osm_gir_rcv_ctrl_t* const p_ctrl ) +{ + CL_ASSERT( p_ctrl ); + cl_disp_unregister( p_ctrl->h_disp ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_gir_rcv_ctrl_init( + IN osm_gir_rcv_ctrl_t* const p_ctrl, + IN osm_gir_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_gir_rcv_ctrl_init ); + + osm_gir_rcv_ctrl_construct( p_ctrl ); + p_ctrl->p_log = p_log; + p_ctrl->p_rcv = p_rcv; + p_ctrl->p_disp = p_disp; + + p_ctrl->h_disp = cl_disp_register( + p_disp, + OSM_MSG_MAD_GUIDINFO_RECORD, + __osm_gir_rcv_ctrl_disp_callback, + p_ctrl ); + + if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_gir_rcv_ctrl_init: ERR 5201: " + "Dispatcher registration failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return( status ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_informinfo.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_informinfo.c new file mode 100644 index 00000000..21646daf --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_informinfo.c @@ -0,0 +1,922 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_informinfo.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Implementation of osm_infr_rcv_t. + * This object represents the InformInfo Receiver object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.8 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define OSM_IIR_RCV_POOL_MIN_SIZE 32 +#define OSM_IIR_RCV_POOL_GROW_SIZE 32 + +typedef struct _osm_iir_item +{ + cl_pool_item_t pool_item; + ib_inform_info_record_t rec; +} osm_iir_item_t; + +typedef struct _osm_iir_search_ctxt +{ + const ib_inform_info_record_t* p_rcvd_rec; + ib_net64_t comp_mask; + cl_qlist_t* p_list; + ib_gid_t subscriber_gid; + ib_net16_t subscriber_enum; + osm_infr_rcv_t* p_rcv; + osm_physp_t* p_req_physp; +} osm_iir_search_ctxt_t; + +/********************************************************************** + **********************************************************************/ +void +osm_infr_rcv_construct( + IN osm_infr_rcv_t* const p_rcv ) +{ + memset( p_rcv, 0, sizeof(*p_rcv) ); + cl_qlock_pool_construct( &p_rcv->pool ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_infr_rcv_destroy( + IN osm_infr_rcv_t* const p_rcv ) +{ + CL_ASSERT( p_rcv ); + + OSM_LOG_ENTER( p_rcv->p_log, osm_infr_rcv_destroy ); + cl_qlock_pool_destroy( &p_rcv->pool ); + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_infr_rcv_init( + IN osm_infr_rcv_t* const p_rcv, + IN osm_sa_resp_t* const p_resp, + IN osm_mad_pool_t* const p_mad_pool, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ) +{ + ib_api_status_t status = IB_ERROR; + + OSM_LOG_ENTER( p_log, osm_infr_rcv_init ); + + osm_infr_rcv_construct( p_rcv ); + + p_rcv->p_log = p_log; + p_rcv->p_subn = p_subn; + p_rcv->p_lock = p_lock; + p_rcv->p_resp = p_resp; + p_rcv->p_mad_pool = p_mad_pool; + + status = cl_qlock_pool_init( &p_rcv->pool, + OSM_IIR_RCV_POOL_MIN_SIZE, + 0, + OSM_IIR_RCV_POOL_GROW_SIZE, + sizeof(osm_iir_item_t), + NULL, NULL, NULL ); + + OSM_LOG_EXIT( p_rcv->p_log ); + return( status ); +} + +/********************************************************************** +o13-14.1.1: Except for Set(InformInfo) requests with Inform- +Info:LIDRangeBegin=0xFFFF, managers that support event forwarding +shall, upon receiving a Set(InformInfo), verify that the requester +originating the Set(InformInfo) and a Trap() source identified by Inform- +can access each other - can use path record to verify that. +**********************************************************************/ +static +boolean_t +__validate_ports_access_rights( + IN osm_infr_rcv_t* const p_rcv, + IN osm_infr_t* p_infr_rec ) +{ + boolean_t valid = TRUE; + osm_physp_t* p_requester_physp; + osm_port_t* p_port; + osm_physp_t* p_physp; + ib_net64_t portguid; + ib_net16_t lid_range_begin; + ib_net16_t lid_range_end; + ib_net16_t lid; + const cl_ptr_vector_t* p_tbl; + ib_gid_t zero_gid; + + OSM_LOG_ENTER( p_rcv->p_log, __validate_ports_access_rights ); + + /* get the requester physp from the request address */ + p_requester_physp = osm_get_physp_by_mad_addr( p_rcv->p_log, + p_rcv->p_subn, + &p_infr_rec->report_addr ); + + memset( &zero_gid, 0, sizeof(zero_gid) ); + if ( memcmp (&(p_infr_rec->inform_record.inform_info.gid), + &zero_gid, sizeof(ib_gid_t) ) ) + { + /* a gid is defined */ + portguid = p_infr_rec->inform_record.inform_info.gid.unicast.interface_id; + + p_port = osm_get_port_by_guid( p_rcv->p_subn, portguid ); + + if ( p_port == NULL ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__validate_ports_access_rights: ERR 4301: " + "Invalid port guid: 0x%016" PRIx64 "\n", + cl_ntoh64(portguid) ); + valid = FALSE; + goto Exit; + } + + /* get the destination InformInfo physical port */ + p_physp = osm_port_get_default_phys_ptr(p_port); + + /* make sure that the requester and destination port can access each other + according to the current partitioning. */ + if (! osm_physp_share_pkey( p_rcv->p_log, p_physp, p_requester_physp)) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__validate_ports_access_rights: " + "port and requester don't share pkey\n" ); + valid = FALSE; + goto Exit; + } + } + else + { + /* gid is zero - check if LID range is defined */ + lid_range_begin = cl_ntoh16(p_infr_rec->inform_record.inform_info.lid_range_begin); + /* if lid is 0xFFFF - meaning all endports managed by the manager */ + if ( lid_range_begin == 0xFFFF ) + goto Exit; + + lid_range_end = cl_ntoh16(p_infr_rec->inform_record.inform_info.lid_range_end); + + /* lid_range_end is set to zero if no range desired. In this case - + just make it equal to the lid_range_begin. */ + if (lid_range_end == 0) + lid_range_end = lid_range_begin; + + /* go over all defined lids within the range and make sure that the + requester port can access them according to current partitioning. */ + for ( lid = lid_range_begin; lid <= lid_range_end; lid++ ) + { + p_tbl = &p_rcv->p_subn->port_lid_tbl; + if ( cl_ptr_vector_get_size( p_tbl ) > lid ) + { + p_port = cl_ptr_vector_get( p_tbl, lid ); + } + else + { + /* lid requested is out of range */ + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__validate_ports_access_rights: ERR 4302: " + "Given LID (0x%X) is out of range:0x%X\n", + lid, cl_ptr_vector_get_size(p_tbl) ); + valid = FALSE; + goto Exit; + } + if ( p_port == NULL ) + continue; + + p_physp = osm_port_get_default_phys_ptr(p_port); + /* make sure that the requester and destination port can access + each other according to the current partitioning. */ + if (! osm_physp_share_pkey( p_rcv->p_log, p_physp, p_requester_physp)) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__validate_ports_access_rights: " + "port and requester don't share pkey\n" ); + valid = FALSE; + goto Exit; + } + } + } + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); + return valid; +} + +/********************************************************************** + **********************************************************************/ +static +boolean_t +__validate_infr( + IN osm_infr_rcv_t* const p_rcv, + IN osm_infr_t* p_infr_rec ) +{ + boolean_t valid = TRUE; + + OSM_LOG_ENTER( p_rcv->p_log, __validate_infr ); + + valid = __validate_ports_access_rights( p_rcv, p_infr_rec ); + if (!valid) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__validate_infr: " + "Invalid Access for InformInfo\n" ); + valid = FALSE; + } + + OSM_LOG_EXIT( p_rcv->p_log ); + return valid; +} + +/********************************************************************** +o13-12.1.1: Confirm a valid request for event subscription by responding +with an InformInfo attribute that is a copy of the data in the +Set(InformInfo) request. +**********************************************************************/ +static void +__osm_infr_rcv_respond( + IN osm_infr_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ) +{ + osm_madw_t* p_resp_madw; + const ib_sa_mad_t* p_sa_mad; + ib_sa_mad_t* p_resp_sa_mad; + ib_inform_info_t* p_resp_infr; + ib_api_status_t status; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_infr_rcv_respond ); + + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_infr_rcv_respond: " + "Generating successful InformInfo response\n"); + } + + /* + Get a MAD to reply. Address of Mad is in the received mad_wrapper + */ + p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool, + p_madw->h_bind, + MAD_BLOCK_SIZE, + &p_madw->mad_addr ); + if ( !p_resp_madw ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_infr_rcv_respond: ERR 4303: " + "Unable to allocate MAD\n" ); + goto Exit; + } + + p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw ); + p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw ); + + /* copy the request InformInfo */ + memcpy( p_resp_sa_mad, p_sa_mad, MAD_BLOCK_SIZE ); + p_resp_sa_mad->method = IB_MAD_METHOD_GET_RESP; + /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */ + p_resp_sa_mad->sm_key = 0; + + p_resp_infr = (ib_inform_info_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad ); + + status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE ); + + if ( status != IB_SUCCESS ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_infr_rcv_respond: ERR 4304: " + "Unable to send MAD (%s)\n", ib_get_err_str( status ) ); + /* osm_mad_pool_put( p_rcv->p_mad_pool, p_resp_madw ); */ + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_sa_inform_info_rec_by_comp_mask( + IN osm_infr_rcv_t* const p_rcv, + IN const osm_infr_t* const p_infr, + osm_iir_search_ctxt_t* const p_ctxt ) +{ + const ib_inform_info_record_t* p_rcvd_rec = NULL; + ib_net64_t comp_mask; + ib_net64_t portguid; + osm_port_t * p_subscriber_port; + osm_physp_t * p_subscriber_physp; + const osm_physp_t* p_req_physp; + osm_iir_item_t* p_rec_item; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_inform_info_rec_by_comp_mask ); + + p_rcvd_rec = p_ctxt->p_rcvd_rec; + comp_mask = p_ctxt->comp_mask; + p_req_physp = p_ctxt->p_req_physp; + + if (comp_mask & IB_IIR_COMPMASK_SUBSCRIBERGID) + { + if (memcmp(&p_infr->inform_record.subscriber_gid, + &p_ctxt->subscriber_gid, + sizeof(p_infr->inform_record.subscriber_gid))) + goto Exit; + } + + if (comp_mask & IB_IIR_COMPMASK_ENUM) + { + if (p_infr->inform_record.subscriber_enum != p_ctxt->subscriber_enum) + goto Exit; + } + + /* Implement any other needed search cases */ + + /* Ensure pkey is shared before returning any records */ + portguid = p_infr->inform_record.subscriber_gid.unicast.interface_id; + p_subscriber_port = osm_get_port_by_guid( p_rcv->p_subn, portguid ); + if ( p_subscriber_port == NULL ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_sa_inform_info_rec_by_comp_mask: ERR 430D: " + "Invalid subscriber port guid: 0x%016" PRIx64 "\n", + cl_ntoh64(portguid) ); + goto Exit; + } + + /* get the subscriber InformInfo physical port */ + p_subscriber_physp = osm_port_get_default_phys_ptr(p_subscriber_port); + /* make sure that the requester and subscriber port can access each other + according to the current partitioning. */ + if (! osm_physp_share_pkey( p_rcv->p_log, p_req_physp, p_subscriber_physp )) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_sa_inform_info_rec_by_comp_mask: " + "requester and subscriber ports don't share pkey\n" ); + goto Exit; + } + + p_rec_item = (osm_iir_item_t*)cl_qlock_pool_get( &p_rcv->pool ); + if( p_rec_item == NULL ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_sa_inform_info_rec_by_comp_mask: ERR 430E: " + "cl_qlock_pool_get failed\n" ); + goto Exit; + } + + memcpy((void *)&p_rec_item->rec, (void *)&p_infr->inform_record, sizeof(ib_inform_info_record_t)); + cl_qlist_insert_tail( p_ctxt->p_list, (cl_list_item_t*)&p_rec_item->pool_item ); + +Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_sa_inform_info_rec_by_comp_mask_cb( + IN cl_list_item_t* const p_list_item, + IN void* context ) +{ + const osm_infr_t* const p_infr = (osm_infr_t *)p_list_item; + osm_iir_search_ctxt_t* const p_ctxt = (osm_iir_search_ctxt_t *)context; + + __osm_sa_inform_info_rec_by_comp_mask( p_ctxt->p_rcv, p_infr, p_ctxt ); +} + +/********************************************************************** +Received a Get(InformInfoRecord) or GetTable(InformInfoRecord) MAD +**********************************************************************/ +static void +osm_infr_rcv_process_get_method( + IN osm_infr_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ) +{ + ib_sa_mad_t* p_rcvd_mad; + const ib_inform_info_record_t* p_rcvd_rec; + ib_inform_info_record_t* p_resp_rec; + cl_qlist_t rec_list; + osm_madw_t* p_resp_madw; + ib_sa_mad_t* p_resp_sa_mad; + uint32_t num_rec, pre_trim_num_rec; +#ifndef VENDOR_RMPP_SUPPORT + uint32_t trim_num_rec; +#endif + uint32_t i, j; + osm_iir_search_ctxt_t context; + osm_iir_item_t* p_rec_item; + ib_api_status_t status = IB_SUCCESS; + osm_physp_t* p_req_physp; + + OSM_LOG_ENTER( p_rcv->p_log, osm_infr_rcv_process_get_method ); + + CL_ASSERT( p_madw ); + p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw ); + p_rcvd_rec = + (ib_inform_info_record_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad ); + + /* update the requester physical port. */ + p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log, + p_rcv->p_subn, + osm_madw_get_mad_addr_ptr(p_madw) ); + if (p_req_physp == NULL) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_infr_rcv_process_get_method: ERR 4309: " + "Cannot find requester physical port\n" ); + goto Exit; + } + + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + osm_dump_inform_info_record( p_rcv->p_log, p_rcvd_rec, OSM_LOG_DEBUG ); + + cl_qlist_init( &rec_list ); + + context.p_rcvd_rec = p_rcvd_rec; + context.p_list = &rec_list; + context.comp_mask = p_rcvd_mad->comp_mask; + context.subscriber_gid = p_rcvd_rec->subscriber_gid; + context.subscriber_enum = p_rcvd_rec->subscriber_enum; + context.p_rcv = p_rcv; + context.p_req_physp = p_req_physp; + + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "osm_infr_rcv_process_get_method: " + "Query Subscriber GID:0x%016" PRIx64 " : 0x%016" PRIx64 "(%02X) Enum:0x%X(%02X)\n", + cl_ntoh64(p_rcvd_rec->subscriber_gid.unicast.prefix), + cl_ntoh64(p_rcvd_rec->subscriber_gid.unicast.interface_id), + (p_rcvd_mad->comp_mask & IB_IIR_COMPMASK_SUBSCRIBERGID) != 0, + cl_ntoh16(p_rcvd_rec->subscriber_enum), + (p_rcvd_mad->comp_mask & IB_IIR_COMPMASK_ENUM) != 0 ); + + cl_plock_acquire( p_rcv->p_lock ); + + cl_qlist_apply_func( &p_rcv->p_subn->sa_infr_list, + __osm_sa_inform_info_rec_by_comp_mask_cb, + &context ); + + cl_plock_release( p_rcv->p_lock ); + + num_rec = cl_qlist_count( &rec_list ); + + /* + * C15-0.1.30: + * If we do a SubnAdmGet and got more than one record it is an error ! + */ + if (p_rcvd_mad->method == IB_MAD_METHOD_GET) + { + if (num_rec == 0) + { + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS ); + goto Exit; + } + if (num_rec > 1) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_infr_rcv_process_get_method: ERR 430A: " + "More than one record for SubnAdmGet (%u)\n", + num_rec ); + osm_sa_send_error( p_rcv->p_resp, p_madw, + IB_SA_MAD_STATUS_TOO_MANY_RECORDS); + + /* need to set the mem free ... */ + p_rec_item = (osm_iir_item_t*)cl_qlist_remove_head( &rec_list ); + while( p_rec_item != (osm_iir_item_t*)cl_qlist_end( &rec_list ) ) + { + cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item ); + p_rec_item = (osm_iir_item_t*)cl_qlist_remove_head( &rec_list ); + } + + goto Exit; + } + } + + pre_trim_num_rec = num_rec; +#ifndef VENDOR_RMPP_SUPPORT + /* we limit the number of records to a single packet */ + trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_inform_info_record_t); + if (trim_num_rec < num_rec) + { + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "osm_infr_rcv_process_get_method: " + "Number of records:%u trimmed to:%u to fit in one MAD\n", + num_rec, trim_num_rec ); + num_rec = trim_num_rec; + } +#endif + + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "osm_infr_rcv_process_get_method: " + "Returning %u records\n", num_rec ); + + /* + * Get a MAD to reply. Address of Mad is in the received mad_wrapper + */ + p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool, + p_madw->h_bind, + num_rec * sizeof(ib_inform_info_record_t) + IB_SA_MAD_HDR_SIZE, + &p_madw->mad_addr ); + + if( !p_resp_madw ) + { + osm_log(p_rcv->p_log, OSM_LOG_ERROR, + "osm_infr_rcv_process_get_method: ERR 430B: " + "osm_mad_pool_get failed\n" ); + + for( i = 0; i < num_rec; i++ ) + { + p_rec_item = (osm_iir_item_t*)cl_qlist_remove_head( &rec_list ); + cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item ); + } + + osm_sa_send_error( p_rcv->p_resp, p_madw, + IB_SA_MAD_STATUS_NO_RESOURCES ); + + goto Exit; + } + + p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw ); + + /* + Copy the MAD header back into the response mad. + Set the 'R' bit and the payload length, + Then copy all records from the list into the response payload. + */ + + memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE ); + p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK; + /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */ + p_resp_sa_mad->sm_key = 0; + /* Fill in the offset (paylen will be done by the rmpp SAR) */ + p_resp_sa_mad->attr_offset = + ib_get_attr_offset( sizeof(ib_inform_info_record_t) ); + + p_resp_rec = (ib_inform_info_record_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad ); + +#ifndef VENDOR_RMPP_SUPPORT + /* we support only one packet RMPP - so we will set the first and + last flags for gettable */ + if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP) + { + p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA; + p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE; + } +#else + /* forcefully define the packet as RMPP one */ + if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP) + p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE; +#endif + + for( i = 0; i < pre_trim_num_rec; i++ ) + { + p_rec_item = (osm_iir_item_t*)cl_qlist_remove_head( &rec_list ); + /* copy only if not trimmed */ + if (i < num_rec) + { + *p_resp_rec = p_rec_item->rec; + /* clear reserved and pad fields in InformInfoRecord */ + for (j = 0; j < 6; j++) + p_resp_rec->reserved[j] = 0; + for (j = 0; j < 4; j++) + p_resp_rec->pad[j] = 0; + } + cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item ); + p_resp_rec++; + } + + CL_ASSERT( cl_is_qlist_empty( &rec_list ) ); + + status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE ); + if (status != IB_SUCCESS) + { + osm_log(p_rcv->p_log, OSM_LOG_ERROR, + "osm_infr_rcv_process_get_method: ERR 430C: " + "osm_vendor_send status = %s\n", + ib_get_err_str(status)); + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************* +Received a Set(InformInfo) MAD +**********************************************************************/ +static void +osm_infr_rcv_process_set_method( + IN osm_infr_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ) +{ + ib_sa_mad_t *p_sa_mad; + ib_inform_info_t *p_recvd_inform_info; + osm_infr_t inform_info_rec; /* actual inform record to be stored for reports */ + osm_infr_t *p_infr; + ib_net32_t qpn; + uint8_t resp_time_val; + ib_api_status_t res; + + OSM_LOG_ENTER( p_rcv->p_log, osm_infr_rcv_process_set_method ); + + CL_ASSERT( p_madw ); + + p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw ); + p_recvd_inform_info = + (ib_inform_info_t*)ib_sa_mad_get_payload_ptr( p_sa_mad ); + +#if 0 + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + osm_dump_inform_info( p_rcv->p_log, p_recvd_inform_info, OSM_LOG_DEBUG ); +#endif + + /* Grab the lock */ + cl_plock_excl_acquire( p_rcv->p_lock ); + + /* define the inform record */ + inform_info_rec.inform_record.inform_info = *p_recvd_inform_info; + + /* following C13-32.1.2 Tbl 120: we only copy the source address vector */ + inform_info_rec.report_addr = p_madw->mad_addr; + + /* we will need to know the mad srvc to send back through */ + inform_info_rec.h_bind = p_madw->h_bind; + inform_info_rec.p_infr_rcv = p_rcv; + + /* update the subscriber GID according to mad address */ + res = osm_get_gid_by_mad_addr( + p_rcv->p_log, + p_rcv->p_subn, + &p_madw->mad_addr, + &inform_info_rec.inform_record.subscriber_gid ); + if ( res != IB_SUCCESS ) + { + cl_plock_release( p_rcv->p_lock ); + + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_infr_rcv_process_set_method: ERR 4308 " + "Subscribe Request from unknown LID: 0x%04X\n", + cl_ntoh16(p_madw->mad_addr.dest_lid) + ); + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_REQ_INVALID ); + goto Exit; + } + + /* HACK: enum is always 0 (currently) */ + inform_info_rec.inform_record.subscriber_enum = 0; + + /* Subscribe values above 1 are undefined */ + if ( p_recvd_inform_info->subscribe > 1 ) + { + cl_plock_release( p_rcv->p_lock ); + + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_infr_rcv_process_set_method: ERR 4308 " + "Invalid subscribe: %d\n", + p_recvd_inform_info->subscribe + ); + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_REQ_INVALID ); + goto Exit; + } + + /* + * MODIFICATIONS DONE ON INCOMING REQUEST: + * + * QPN: + * Internally we keep the QPN field of the InformInfo updated + * so we can simply compare it in the record - when finding such. + */ + if ( p_recvd_inform_info->subscribe ) + { + ib_inform_info_set_qpn( + &inform_info_rec.inform_record.inform_info, + inform_info_rec.report_addr.addr_type.gsi.remote_qp ); + + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "osm_infr_rcv_process_set_method: " + "Subscribe Request with QPN: 0x%06X\n", + cl_ntoh32(inform_info_rec.report_addr.addr_type.gsi.remote_qp) + ); + } + else + { + ib_inform_info_get_qpn_resp_time( + p_recvd_inform_info->g_or_v.generic.qpn_resp_time_val, + &qpn, &resp_time_val ); + + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "osm_infr_rcv_process_set_method: " + "UnSubscribe Request with QPN: 0x%06X\n", + cl_ntoh32(qpn) + ); + } + + /* If record exists with matching InformInfo */ + p_infr = osm_infr_get_by_rec( p_rcv->p_subn, p_rcv->p_log, &inform_info_rec ); + + /* check to see if the request was for subscribe */ + if ( p_recvd_inform_info->subscribe ) + { + /* validate the request for a new or update InformInfo */ + if ( __validate_infr( p_rcv, &inform_info_rec ) != TRUE ) + { + cl_plock_release( p_rcv->p_lock ); + + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_infr_rcv_process_set_method: ERR 4305: " + "Failed to validate a new inform object\n"); + + /* o13-13.1.1: we need to set the subscribe bit to 0 */ + p_recvd_inform_info->subscribe = 0; + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_REQ_INVALID ); + goto Exit; + } + + /* ok - we can try and create a new entry */ + if (p_infr == NULL) + { + /* Create the instance of the osm_infr_t object */ + p_infr = osm_infr_new( &inform_info_rec ); + if (p_infr == NULL) + { + cl_plock_release( p_rcv->p_lock ); + + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_infr_rcv_process_set_method: ERR 4306: " + "Failed to create a new inform object\n"); + + /* o13-13.1.1: we need to set the subscribe bit to 0 */ + p_recvd_inform_info->subscribe = 0; + osm_sa_send_error( p_rcv->p_resp, p_madw, + IB_SA_MAD_STATUS_NO_RESOURCES ); + goto Exit; + } + + /* Add this new osm_infr_t object to subnet object */ + osm_infr_insert_to_db( p_rcv->p_subn, p_rcv->p_log, p_infr ); + } + else + { + /* Update the old instance of the osm_infr_t object */ + p_infr->inform_record = inform_info_rec.inform_record; + } + } + else + { + /* We got an UnSubscribe request */ + if (p_infr == NULL) + { + cl_plock_release( p_rcv->p_lock ); + + /* No Such Item - So Error */ + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_infr_rcv_process_set_method: ERR 4307: " + "Failed to UnSubscribe to non existing inform object\n"); + + /* o13-13.1.1: we need to set the subscribe bit to 0 */ + p_recvd_inform_info->subscribe = 0; + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_REQ_INVALID ); + goto Exit; + } + else + { + /* Delete this object from the subnet list of informs */ + osm_infr_remove_from_db( p_rcv->p_subn, p_rcv->p_log, p_infr ); + } + } + + cl_plock_release( p_rcv->p_lock ); + + /* send the success response */ + __osm_infr_rcv_respond( p_rcv, p_madw ); + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************* +**********************************************************************/ +void +osm_infr_rcv_process( + IN osm_infr_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ) +{ + ib_sa_mad_t *p_sa_mad; + + OSM_LOG_ENTER( p_rcv->p_log, osm_infr_rcv_process ); + + CL_ASSERT( p_madw ); + + p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw ); + + CL_ASSERT( p_sa_mad->attr_id == IB_MAD_ATTR_INFORM_INFO ); + + if (p_sa_mad->method != IB_MAD_METHOD_SET) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "osm_infr_rcv_process: " + "Unsupported Method (%s)\n", + ib_get_sa_method_str( p_sa_mad->method ) ); + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR ); + goto Exit; + } + + osm_infr_rcv_process_set_method( p_rcv, p_madw ); + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************* +**********************************************************************/ +void +osm_infir_rcv_process( + IN osm_infr_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ) +{ + ib_sa_mad_t *p_sa_mad; + + OSM_LOG_ENTER( p_rcv->p_log, osm_infr_rcv_process ); + + CL_ASSERT( p_madw ); + + p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw ); + + CL_ASSERT( p_sa_mad->attr_id == IB_MAD_ATTR_INFORM_INFO_RECORD ); + + if ( (p_sa_mad->method != IB_MAD_METHOD_GET) && + (p_sa_mad->method != IB_MAD_METHOD_GETTABLE) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "osm_infir_rcv_process: " + "Unsupported Method (%s)\n", + ib_get_sa_method_str( p_sa_mad->method ) ); + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR ); + goto Exit; + } + + osm_infr_rcv_process_get_method( p_rcv, p_madw ); + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_informinfo_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_informinfo_ctrl.c new file mode 100644 index 00000000..33a767cd --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_informinfo_ctrl.c @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_informinfo_ctrl.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Implementation of osm_infr_rcv_ctrl_t. + * This object represents the InformInfo set request controller object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +static void +__osm_infr_rcv_ctrl_disp_callback( + IN void *context, + IN void *p_data ) +{ + /* ignore return status when invoked via the dispatcher */ + osm_infr_rcv_process( ((osm_infr_rcv_ctrl_t*)context)->p_rcv, + (osm_madw_t*)p_data ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_infir_rcv_ctrl_disp_callback( + IN void *context, + IN void *p_data ) +{ + /* ignore return status when invoked via the dispatcher */ + osm_infir_rcv_process( ((osm_infr_rcv_ctrl_t*)context)->p_rcv, + (osm_madw_t*)p_data ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_infr_rcv_ctrl_construct( + IN osm_infr_rcv_ctrl_t* const p_ctrl ) +{ + memset( p_ctrl, 0, sizeof(*p_ctrl) ); + p_ctrl->h_disp = CL_DISP_INVALID_HANDLE; + p_ctrl->h_disp2 = CL_DISP_INVALID_HANDLE; +} + +/********************************************************************** + **********************************************************************/ +void +osm_infr_rcv_ctrl_destroy( + IN osm_infr_rcv_ctrl_t* const p_ctrl ) +{ + CL_ASSERT( p_ctrl ); + cl_disp_unregister( p_ctrl->h_disp2 ); + cl_disp_unregister( p_ctrl->h_disp ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_infr_rcv_ctrl_init( + IN osm_infr_rcv_ctrl_t* const p_ctrl, + IN osm_infr_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_infr_rcv_ctrl_init ); + + osm_infr_rcv_ctrl_construct( p_ctrl ); + p_ctrl->p_log = p_log; + p_ctrl->p_rcv = p_rcv; + p_ctrl->p_disp = p_disp; + + p_ctrl->h_disp = cl_disp_register( + p_disp, + OSM_MSG_MAD_INFORM_INFO, + __osm_infr_rcv_ctrl_disp_callback, + p_ctrl ); + + if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_infr_rcv_ctrl_init: ERR 1701: " + "Dispatcher registration failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + p_ctrl->h_disp2 = cl_disp_register( + p_disp, + OSM_MSG_MAD_INFORM_INFO_RECORD, + __osm_infir_rcv_ctrl_disp_callback, + p_ctrl ); + + if( p_ctrl->h_disp2 == CL_DISP_INVALID_HANDLE ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_infr_rcv_ctrl_init: ERR 1702: " + "Dispatcher registration failed\n" ); + cl_disp_unregister( p_ctrl->h_disp ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return( status ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_lft_record.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_lft_record.c new file mode 100644 index 00000000..f116ed30 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_lft_record.c @@ -0,0 +1,515 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_lft_record.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Implementation of osm_lftr_rcv_t. + * This object represents the LinearForwardingTable Receiver object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define OSM_LFTR_RCV_POOL_MIN_SIZE 32 +#define OSM_LFTR_RCV_POOL_GROW_SIZE 32 + +typedef struct _osm_lftr_item +{ + cl_pool_item_t pool_item; + ib_lft_record_t rec; +} osm_lftr_item_t; + +typedef struct _osm_lftr_search_ctxt +{ + const ib_lft_record_t* p_rcvd_rec; + ib_net64_t comp_mask; + cl_qlist_t* p_list; + osm_lftr_rcv_t* p_rcv; + const osm_physp_t* p_req_physp; +} osm_lftr_search_ctxt_t; + +/********************************************************************** + **********************************************************************/ +void +osm_lftr_rcv_construct( + IN osm_lftr_rcv_t* const p_rcv ) +{ + memset( p_rcv, 0, sizeof(*p_rcv) ); + cl_qlock_pool_construct( &p_rcv->pool ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_lftr_rcv_destroy( + IN osm_lftr_rcv_t* const p_rcv ) +{ + OSM_LOG_ENTER( p_rcv->p_log, osm_lftr_rcv_destroy ); + cl_qlock_pool_destroy( &p_rcv->pool ); + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_lftr_rcv_init( + IN osm_lftr_rcv_t* const p_rcv, + IN osm_sa_resp_t* const p_resp, + IN osm_mad_pool_t* const p_mad_pool, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ) +{ + ib_api_status_t status; + + OSM_LOG_ENTER( p_log, osm_lftr_rcv_init ); + + osm_lftr_rcv_construct( p_rcv ); + + p_rcv->p_log = p_log; + p_rcv->p_subn = p_subn; + p_rcv->p_lock = p_lock; + p_rcv->p_resp = p_resp; + p_rcv->p_mad_pool = p_mad_pool; + + status = cl_qlock_pool_init( &p_rcv->pool, + OSM_LFTR_RCV_POOL_MIN_SIZE, + 0, + OSM_LFTR_RCV_POOL_GROW_SIZE, + sizeof(osm_lftr_item_t), + NULL, NULL, NULL ); + + OSM_LOG_EXIT( p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +static ib_api_status_t +__osm_lftr_rcv_new_lftr( + IN osm_lftr_rcv_t* const p_rcv, + IN const osm_switch_t* const p_sw, + IN cl_qlist_t* const p_list, + IN ib_net16_t const lid, + IN ib_net16_t const block ) +{ + osm_lftr_item_t* p_rec_item; + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_lftr_rcv_new_lftr ); + + p_rec_item = (osm_lftr_item_t*)cl_qlock_pool_get( &p_rcv->pool ); + if( p_rec_item == NULL ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_lftr_rcv_new_lftr: ERR 4402: " + "cl_qlock_pool_get failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_lftr_rcv_new_lftr: " + "New LinearForwardingTable: sw 0x%016" PRIx64 + "\n\t\t\t\tblock 0x%02X lid 0x%02X\n", + cl_ntoh64( osm_node_get_node_guid( p_sw->p_node ) ), + cl_ntoh16( block ), cl_ntoh16( lid ) + ); + } + + memset( &p_rec_item->rec, 0, sizeof(ib_lft_record_t) ); + + p_rec_item->rec.lid = lid; + p_rec_item->rec.block_num = block; + + /* copy the lft block */ + osm_switch_get_fwd_tbl_block( p_sw, cl_ntoh16(block), p_rec_item->rec.lft ); + + cl_qlist_insert_tail( p_list, (cl_list_item_t*)&p_rec_item->pool_item ); + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +static osm_port_t* +__osm_lftr_get_port_by_guid( + IN osm_lftr_rcv_t* const p_rcv, + IN uint64_t port_guid ) +{ + osm_port_t* p_port; + + CL_PLOCK_ACQUIRE(p_rcv->p_lock); + + p_port = (osm_port_t *)cl_qmap_get(&p_rcv->p_subn->port_guid_tbl, + port_guid); + if (p_port == (osm_port_t *)cl_qmap_end(&p_rcv->p_subn->port_guid_tbl)) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_lftr_get_port_by_guid ERR 4404: " + "Invalid port GUID 0x%016" PRIx64 "\n", + port_guid ); + p_port = NULL; + } + + CL_PLOCK_RELEASE(p_rcv->p_lock); + return p_port; +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_lftr_rcv_by_comp_mask( + IN cl_map_item_t* const p_map_item, + IN void* context ) +{ + const osm_lftr_search_ctxt_t* const p_ctxt = + (osm_lftr_search_ctxt_t *)context; + const osm_switch_t* const p_sw = (osm_switch_t*)p_map_item; + const ib_lft_record_t* const p_rcvd_rec = p_ctxt->p_rcvd_rec; + osm_lftr_rcv_t* const p_rcv = p_ctxt->p_rcv; + ib_net64_t const comp_mask = p_ctxt->comp_mask; + const osm_physp_t* const p_req_physp = p_ctxt->p_req_physp; + osm_port_t* p_port; + uint16_t min_lid_ho, max_lid_ho; + uint16_t min_block, max_block, block; + const osm_physp_t* p_physp; + + /* In switches, the port guid is the node guid. */ + p_port = + __osm_lftr_get_port_by_guid( p_rcv, p_sw->p_node->node_info.port_guid ); + if (! p_port) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_lftr_rcv_by_comp_mask: ERR 4405: " + "Failed to find Port by Node Guid:0x%016" PRIx64 + "\n", + cl_ntoh64( p_sw->p_node->node_info.node_guid ) + ); + return; + } + + /* check that the requester physp and the current physp are under + the same partition. */ + p_physp = osm_port_get_default_phys_ptr( p_port ); + if (! p_physp) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_lftr_rcv_by_comp_mask: ERR 4406: " + "Failed to find default physical Port by Node Guid:0x%016" PRIx64 + "\n", + cl_ntoh64( p_sw->p_node->node_info.node_guid ) + ); + return; + } + if (! osm_physp_share_pkey( p_rcv->p_log, p_req_physp, p_physp )) + return; + + /* get the port 0 of the switch */ + osm_port_get_lid_range_ho( p_port, &min_lid_ho, &max_lid_ho ); + + /* compare the lids - if required */ + if( comp_mask & IB_LFTR_COMPMASK_LID ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_lftr_rcv_by_comp_mask: " + "Comparing lid:0x%02X to port lid range: 0x%02X .. 0x%02X\n", + cl_ntoh16( p_rcvd_rec->lid ), min_lid_ho, max_lid_ho + ); + /* ok we are ready for range check */ + if (min_lid_ho > cl_ntoh16(p_rcvd_rec->lid) || + max_lid_ho < cl_ntoh16(p_rcvd_rec->lid)) + return; + } + + /* now we need to decide which blocks to output */ + if( comp_mask & IB_LFTR_COMPMASK_BLOCK ) + { + max_block = min_block = cl_ntoh16(p_rcvd_rec->block_num); + } + else + { + /* use as many blocks as "in use" */ + min_block = 0; + max_block = osm_switch_get_max_block_id_in_use(p_sw); + } + + /* so we can add these blocks one by one ... */ + for (block = min_block; block <= max_block; block++) + __osm_lftr_rcv_new_lftr( p_rcv, p_sw, p_ctxt->p_list, + osm_port_get_base_lid(p_port), + cl_hton16(block) ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_lftr_rcv_process( + IN osm_lftr_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ) +{ + const ib_sa_mad_t* p_rcvd_mad; + const ib_lft_record_t* p_rcvd_rec; + ib_lft_record_t* p_resp_rec; + cl_qlist_t rec_list; + osm_madw_t* p_resp_madw; + ib_sa_mad_t* p_resp_sa_mad; + uint32_t num_rec, pre_trim_num_rec; +#ifndef VENDOR_RMPP_SUPPORT + uint32_t trim_num_rec; +#endif + uint32_t i; + osm_lftr_search_ctxt_t context; + osm_lftr_item_t* p_rec_item; + ib_api_status_t status = IB_SUCCESS; + osm_physp_t* p_req_physp; + + CL_ASSERT( p_rcv ); + + OSM_LOG_ENTER( p_rcv->p_log, osm_lftr_rcv_process ); + + CL_ASSERT( p_madw ); + + p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw ); + p_rcvd_rec = (ib_lft_record_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad ); + + CL_ASSERT( p_rcvd_mad->attr_id == IB_MAD_ATTR_LFT_RECORD ); + + /* we only support SubnAdmGet and SubnAdmGetTable methods */ + if ( (p_rcvd_mad->method != IB_MAD_METHOD_GET) && + (p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) ) { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_lftr_rcv_process: ERR 4408: " + "Unsupported Method (%s)\n", + ib_get_sa_method_str( p_rcvd_mad->method ) ); + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR ); + goto Exit; + } + + /* update the requester physical port. */ + p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log, + p_rcv->p_subn, + osm_madw_get_mad_addr_ptr(p_madw) ); + if (p_req_physp == NULL) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_lftr_rcv_process: ERR 4407: " + "Cannot find requester physical port\n" ); + goto Exit; + } + + cl_qlist_init( &rec_list ); + + context.p_rcvd_rec = p_rcvd_rec; + context.p_list = &rec_list; + context.comp_mask = p_rcvd_mad->comp_mask; + context.p_rcv = p_rcv; + context.p_req_physp = p_req_physp; + + cl_plock_acquire( p_rcv->p_lock ); + + /* Go over all switches */ + cl_qmap_apply_func( &p_rcv->p_subn->sw_guid_tbl, + __osm_lftr_rcv_by_comp_mask, + &context ); + + cl_plock_release( p_rcv->p_lock ); + + num_rec = cl_qlist_count( &rec_list ); + + /* + * C15-0.1.30: + * If we do a SubnAdmGet and got more than one record it is an error ! + */ + if (p_rcvd_mad->method == IB_MAD_METHOD_GET) + { + if (num_rec == 0) + { + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS ); + goto Exit; + } + if (num_rec > 1) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_lftr_rcv_process: ERR 4409: " + "Got more than one record for SubnAdmGet (%u)\n", + num_rec ); + osm_sa_send_error( p_rcv->p_resp, p_madw, + IB_SA_MAD_STATUS_TOO_MANY_RECORDS); + + /* need to set the mem free ... */ + p_rec_item = (osm_lftr_item_t*)cl_qlist_remove_head( &rec_list ); + while( p_rec_item != (osm_lftr_item_t*)cl_qlist_end( &rec_list ) ) + { + cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item ); + p_rec_item = (osm_lftr_item_t*)cl_qlist_remove_head( &rec_list ); + } + + goto Exit; + } + } + + pre_trim_num_rec = num_rec; +#ifndef VENDOR_RMPP_SUPPORT + /* we limit the number of records to a single packet */ + trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_lft_record_t); + if (trim_num_rec < num_rec) + { + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "osm_lftr_rcv_process: " + "Number of records:%u trimmed to:%u to fit in one MAD\n", + num_rec, trim_num_rec ); + num_rec = trim_num_rec; + } +#endif + + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "osm_lftr_rcv_process: " + "Returning %u records\n", num_rec ); + + if ((p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) && + (num_rec == 0)) + { + osm_sa_send_error( p_rcv->p_resp, p_madw, + IB_SA_MAD_STATUS_NO_RECORDS ); + goto Exit; + } + + /* + * Get a MAD to reply. Address of Mad is in the received mad_wrapper + */ + p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool, + p_madw->h_bind, + num_rec * sizeof(ib_lft_record_t) + IB_SA_MAD_HDR_SIZE, + &p_madw->mad_addr ); + + if( !p_resp_madw ) + { + osm_log(p_rcv->p_log, OSM_LOG_ERROR, + "osm_lftr_rcv_process: ERR 4410: " + "osm_mad_pool_get failed\n" ); + + for( i = 0; i < num_rec; i++ ) + { + p_rec_item = (osm_lftr_item_t*)cl_qlist_remove_head( &rec_list ); + cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item ); + } + + osm_sa_send_error( p_rcv->p_resp, p_madw, + IB_SA_MAD_STATUS_NO_RESOURCES ); + + goto Exit; + } + + p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw ); + + /* + Copy the MAD header back into the response mad. + Set the 'R' bit and the payload length, + Then copy all records from the list into the response payload. + */ + + memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE ); + p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK; + /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */ + p_resp_sa_mad->sm_key = 0; + /* Fill in the offset (paylen will be done by the rmpp SAR) */ + p_resp_sa_mad->attr_offset = + ib_get_attr_offset( sizeof(ib_lft_record_t) ); + + p_resp_rec = (ib_lft_record_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad ); + +#ifndef VENDOR_RMPP_SUPPORT + /* we support only one packet RMPP - so we will set the first and + last flags for gettable */ + if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP) + { + p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA; + p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE; + } +#else + /* forcefully define the packet as RMPP one */ + if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP) + p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE; +#endif + + for( i = 0; i < pre_trim_num_rec; i++ ) + { + p_rec_item = (osm_lftr_item_t*)cl_qlist_remove_head( &rec_list ); + /* copy only if not trimmed */ + if (i < num_rec) + { + *p_resp_rec = p_rec_item->rec; + } + cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item ); + p_resp_rec++; + } + + CL_ASSERT( cl_is_qlist_empty( &rec_list ) ); + + status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE ); + if (status != IB_SUCCESS) + { + osm_log(p_rcv->p_log, OSM_LOG_ERROR, + "osm_lftr_rcv_process: ERR 4411: " + "osm_vendor_send status = %s\n", + ib_get_err_str(status)); + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_lft_record_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_lft_record_ctrl.c new file mode 100644 index 00000000..b11ebaff --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_lft_record_ctrl.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_lft_record_ctrl.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Implementation of osm_lftr_rcv_ctrl_t. + * This object represents the LinearForwardingTable request controller object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +__osm_lftr_rcv_ctrl_disp_callback( + IN void *context, + IN void *p_data ) +{ + /* ignore return status when invoked via the dispatcher */ + osm_lftr_rcv_process( ((osm_lftr_rcv_ctrl_t*)context)->p_rcv, + (osm_madw_t*)p_data ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_lftr_rcv_ctrl_construct( + IN osm_lftr_rcv_ctrl_t* const p_ctrl ) +{ + memset( p_ctrl, 0, sizeof(*p_ctrl) ); + p_ctrl->h_disp = CL_DISP_INVALID_HANDLE; +} + +/********************************************************************** + **********************************************************************/ +void +osm_lftr_rcv_ctrl_destroy( + IN osm_lftr_rcv_ctrl_t* const p_ctrl ) +{ + CL_ASSERT( p_ctrl ); + cl_disp_unregister( p_ctrl->h_disp ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_lftr_rcv_ctrl_init( + IN osm_lftr_rcv_ctrl_t* const p_ctrl, + IN osm_lftr_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_lftr_rcv_ctrl_init ); + + osm_lftr_rcv_ctrl_construct( p_ctrl ); + p_ctrl->p_log = p_log; + p_ctrl->p_rcv = p_rcv; + p_ctrl->p_disp = p_disp; + + p_ctrl->h_disp = cl_disp_register( + p_disp, + OSM_MSG_MAD_LFT_RECORD, + __osm_lftr_rcv_ctrl_disp_callback, + p_ctrl ); + + if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_lftr_rcv_ctrl_init: ERR 4501: " + "Dispatcher registration failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return( status ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_link_record.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_link_record.c new file mode 100644 index 00000000..b87bd408 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_link_record.c @@ -0,0 +1,777 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_link_record.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_lr_rcv_t. + * This object represents the LinkRecord Receiver object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.8 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define OSM_LR_RCV_POOL_MIN_SIZE 64 +#define OSM_LR_RCV_POOL_GROW_SIZE 64 + +typedef struct _osm_lr_item +{ + cl_pool_item_t pool_item; + ib_link_record_t link_rec; +} osm_lr_item_t; + +/********************************************************************** + **********************************************************************/ +void +osm_lr_rcv_construct( + IN osm_lr_rcv_t* const p_rcv ) +{ + memset( p_rcv, 0, sizeof(*p_rcv) ); + cl_qlock_pool_construct( &p_rcv->lr_pool ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_lr_rcv_destroy( + IN osm_lr_rcv_t* const p_rcv ) +{ + OSM_LOG_ENTER( p_rcv->p_log, osm_lr_rcv_destroy ); + cl_qlock_pool_destroy( &p_rcv->lr_pool ); + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_lr_rcv_init( + IN osm_lr_rcv_t* const p_rcv, + IN osm_sa_resp_t* const p_resp, + IN osm_mad_pool_t* const p_mad_pool, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_lr_rcv_init ); + + osm_lr_rcv_construct( p_rcv ); + + p_rcv->p_log = p_log; + p_rcv->p_subn = p_subn; + p_rcv->p_lock = p_lock; + p_rcv->p_resp = p_resp; + p_rcv->p_mad_pool = p_mad_pool; + + status = cl_qlock_pool_init( &p_rcv->lr_pool, + OSM_LR_RCV_POOL_MIN_SIZE, + 0, + OSM_LR_RCV_POOL_GROW_SIZE, + sizeof(osm_lr_item_t), + NULL, NULL, NULL ); + + OSM_LOG_EXIT( p_rcv->p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_lr_rcv_build_physp_link( + IN osm_lr_rcv_t* const p_rcv, + IN const ib_net16_t from_lid, + IN const ib_net16_t to_lid, + IN const uint8_t from_port, + IN const uint8_t to_port, + IN cl_qlist_t* p_list ) +{ + osm_lr_item_t* p_lr_item; + + p_lr_item = (osm_lr_item_t*)cl_qlock_pool_get( &p_rcv->lr_pool ); + if( p_lr_item == NULL ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_lr_rcv_build_physp_link: ERR 1801: " + "Unable to acquire link record\n" + "\t\t\t\tFrom port 0x%u\n" + "\t\t\t\tTo port 0x%u\n" + "\t\t\t\tFrom lid 0x%X\n" + "\t\t\t\tTo lid 0x%X\n", + from_port, to_port, + cl_ntoh16(from_lid), + cl_ntoh16(to_lid) ); + return; + } + + p_lr_item->link_rec.from_port_num = from_port; + p_lr_item->link_rec.to_port_num = to_port; + p_lr_item->link_rec.to_lid = to_lid; + p_lr_item->link_rec.from_lid = from_lid; + + cl_qlist_insert_tail( p_list, (cl_list_item_t*)&p_lr_item->pool_item ); +} + +/********************************************************************** + **********************************************************************/ +static void +__get_base_lid( + IN const osm_physp_t* p_physp, + OUT uint16_t * p_base_lid ) +{ + if(p_physp->p_node->node_info.node_type == IB_NODE_TYPE_SWITCH) + { + *p_base_lid = + cl_ntoh16( + osm_physp_get_base_lid( + osm_node_get_physp_ptr(p_physp->p_node, 0)) + ); + } + else + { + *p_base_lid = + cl_ntoh16(osm_physp_get_base_lid(p_physp)); + } +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_lr_rcv_get_physp_link( + IN osm_lr_rcv_t* const p_rcv, + IN const ib_link_record_t* const p_lr, + IN const osm_physp_t* p_src_physp, + IN const osm_physp_t* p_dest_physp, + IN const ib_net64_t comp_mask, + IN cl_qlist_t* const p_list, + IN const osm_physp_t* p_req_physp ) +{ + uint8_t src_port_num; + uint8_t dest_port_num; + ib_net16_t from_base_lid_ho; + ib_net16_t to_base_lid_ho; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_lr_rcv_get_physp_link ); + + /* + If only one end of the link is specified, determine + the other side. + */ + if( p_src_physp ) + { + if( !osm_physp_is_valid( p_src_physp ) ) + goto Exit; + + if( p_dest_physp ) + { + if( !osm_physp_is_valid( p_dest_physp ) ) + goto Exit; + /* + Ensure the two physp's are actually connected. + If not, bail out. + */ + if( osm_physp_get_remote( p_src_physp ) != p_dest_physp ) + goto Exit; + } + else + { + p_dest_physp = osm_physp_get_remote( p_src_physp ); + + if(p_dest_physp == NULL) + goto Exit; + + if( !osm_physp_is_valid( p_dest_physp ) ) + goto Exit; + } + } + else + { + if( p_dest_physp ) + { + if( !osm_physp_is_valid( p_dest_physp ) ) + goto Exit; + + p_src_physp = osm_physp_get_remote( p_dest_physp ); + + if(p_src_physp == NULL) + goto Exit; + } + else + goto Exit; /* no physp's, so nothing to do */ + } + + CL_ASSERT( p_src_physp ); + CL_ASSERT( p_dest_physp ); + CL_ASSERT( osm_physp_is_valid( p_src_physp ) ); + CL_ASSERT( osm_physp_is_valid( p_dest_physp ) ); + + /* Check that the p_src_physp, p_dest_physp and p_req_physp + all share a pkey (doesn't have to be the same p_key). */ + if (! osm_physp_share_pkey(p_rcv->p_log, p_src_physp, p_dest_physp)) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_lr_rcv_get_physp_link: " + "Source and Dest PhysPorts do not share PKey\n"); + goto Exit; + } + if (! osm_physp_share_pkey(p_rcv->p_log, p_src_physp, p_req_physp)) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_lr_rcv_get_physp_link: " + "Source and Requester PhysPorts do not share PKey\n"); + goto Exit; + } + if (! osm_physp_share_pkey(p_rcv->p_log, p_req_physp, p_dest_physp) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_lr_rcv_get_physp_link: " + "Requester and Dest PhysPorts do not share PKey\n"); + goto Exit; + } + + src_port_num = osm_physp_get_port_num( p_src_physp ); + dest_port_num = osm_physp_get_port_num( p_dest_physp ); + + if( comp_mask & IB_LR_COMPMASK_FROM_PORT ) + if( src_port_num != p_lr->from_port_num ) + goto Exit; + + if( comp_mask & IB_LR_COMPMASK_TO_PORT ) + if( dest_port_num != p_lr->to_port_num ) + goto Exit; + + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_lr_rcv_get_physp_link: " + "Acquiring link record\n" + "\t\t\t\tsrc port 0x%" PRIx64 " (port 0x%X)" + ", dest port 0x%" PRIx64 " (port 0x%X)\n", + cl_ntoh64( osm_physp_get_port_guid( p_src_physp ) ), + src_port_num, + cl_ntoh64( osm_physp_get_port_guid( p_dest_physp ) ), + dest_port_num ); + } + + __get_base_lid(p_src_physp, &from_base_lid_ho); + __get_base_lid(p_dest_physp, &to_base_lid_ho); + + __osm_lr_rcv_build_physp_link(p_rcv, cl_ntoh16(from_base_lid_ho), + cl_ntoh16(to_base_lid_ho), + src_port_num, dest_port_num, p_list); + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_lr_rcv_get_port_links( + IN osm_lr_rcv_t* const p_rcv, + IN const ib_link_record_t* const p_lr, + IN const osm_port_t* p_src_port, + IN const osm_port_t* p_dest_port, + IN const ib_net64_t comp_mask, + IN cl_qlist_t* const p_list, + IN const osm_physp_t* p_req_physp ) +{ + const osm_physp_t* p_src_physp; + const osm_physp_t* p_dest_physp; + const cl_qmap_t* p_port_tbl; + uint8_t port_num; + uint8_t num_ports; + uint8_t dest_num_ports; + uint8_t dest_port_num; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_lr_rcv_get_port_links ); + + if( p_src_port ) + { + if( p_dest_port ) + { + /* + Build an LR for every link connected between both ports. + The inner function will discard physp combinations + that do not actually connect. Don't bother screening + for that here. + */ + num_ports = osm_port_get_num_physp( p_src_port ); + dest_num_ports = osm_port_get_num_physp( p_dest_port ); + for( port_num = 1; port_num < num_ports; port_num++ ) + { + p_src_physp = osm_port_get_phys_ptr( p_src_port, port_num ); + for( dest_port_num = 1; dest_port_num < dest_num_ports; + dest_port_num++ ) + { + p_dest_physp = osm_port_get_phys_ptr( p_dest_port, + dest_port_num ); + /* both physical ports should be with data */ + if (p_src_physp && p_dest_physp) + __osm_lr_rcv_get_physp_link( p_rcv, p_lr, p_src_physp, + p_dest_physp, comp_mask, + p_list, p_req_physp ); + } + } + } + else + { + /* + Build an LR for every link connected from the source port. + */ + if( comp_mask & IB_LR_COMPMASK_FROM_PORT ) + { + port_num = p_lr->from_port_num; + /* If the port number is out of the range of the p_src_port, then + this couldn't be a relevant record. */ + if (port_num < p_src_port->physp_tbl_size) + { + p_src_physp = osm_port_get_phys_ptr( p_src_port, port_num ); + if (p_src_physp) + __osm_lr_rcv_get_physp_link( p_rcv, p_lr, p_src_physp, + NULL, comp_mask, p_list, + p_req_physp ); + } + } + else + { + num_ports = osm_port_get_num_physp( p_src_port ); + for( port_num = 1; port_num < num_ports; port_num++ ) + { + p_src_physp = osm_port_get_phys_ptr( p_src_port, port_num ); + if (p_src_physp) + __osm_lr_rcv_get_physp_link( p_rcv, p_lr, p_src_physp, + NULL, comp_mask, p_list, + p_req_physp ); + } + } + } + } + else + { + if( p_dest_port ) + { + /* + Build an LR for every link connected to the dest port. + */ + if( comp_mask & IB_LR_COMPMASK_TO_PORT ) + { + port_num = p_lr->to_port_num; + /* If the port number is out of the range of the p_dest_port, then + this couldn't be a relevant record. */ + if (port_num < p_dest_port->physp_tbl_size ) + { + p_dest_physp = osm_port_get_phys_ptr( + p_dest_port, port_num ); + if (p_dest_physp) + __osm_lr_rcv_get_physp_link( p_rcv, p_lr, NULL, + p_dest_physp, comp_mask, + p_list, p_req_physp ); + } + } + else + { + num_ports = osm_port_get_num_physp( p_dest_port ); + for( port_num = 1; port_num < num_ports; port_num++ ) + { + p_dest_physp = osm_port_get_phys_ptr( + p_dest_port, port_num ); + if (p_dest_physp) + __osm_lr_rcv_get_physp_link( p_rcv, p_lr, NULL, + p_dest_physp, comp_mask, + p_list, p_req_physp ); + } + } + } + else + { + /* + Process the world (recurse once back into this function). + */ + p_port_tbl = &p_rcv->p_subn->port_guid_tbl; + p_src_port = (osm_port_t*)cl_qmap_head( p_port_tbl ); + + while( p_src_port != (osm_port_t*)cl_qmap_end( p_port_tbl ) ) + { + __osm_lr_rcv_get_port_links( p_rcv, p_lr, p_src_port, + NULL, comp_mask, p_list, + p_req_physp ); + + p_src_port = (osm_port_t*)cl_qmap_next( + &p_src_port->map_item ); + } + } + } + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + Returns the SA status to return to the client. + **********************************************************************/ +static ib_net16_t +__osm_lr_rcv_get_end_points( + IN osm_lr_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw, + OUT const osm_port_t** const pp_src_port, + OUT const osm_port_t** const pp_dest_port ) +{ + const ib_link_record_t* p_lr; + const ib_sa_mad_t* p_sa_mad; + ib_net64_t comp_mask; + ib_api_status_t status; + ib_net16_t sa_status = IB_SA_MAD_STATUS_SUCCESS; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_lr_rcv_get_end_points ); + + /* + Determine what fields are valid and then get a pointer + to the source and destination port objects, if possible. + */ + p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw ); + p_lr = (ib_link_record_t*)ib_sa_mad_get_payload_ptr( p_sa_mad ); + + comp_mask = p_sa_mad->comp_mask; + *pp_src_port = NULL; + *pp_dest_port = NULL; + + if( p_sa_mad->comp_mask & IB_LR_COMPMASK_FROM_LID ) + { + status = osm_get_port_by_base_lid( p_rcv->p_subn, + p_lr->from_lid, + pp_src_port ); + + if( (status != IB_SUCCESS) || (*pp_src_port == NULL) ) + { + /* + This 'error' is the client's fault (bad lid) so + don't enter it as an error in our own log. + Return an error response to the client. + */ + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "__osm_lr_rcv_get_end_points: " + "No source port with LID = 0x%X\n", + cl_ntoh16( p_lr->from_lid ) ); + + sa_status = IB_SA_MAD_STATUS_NO_RECORDS; + goto Exit; + } + } + + if( p_sa_mad->comp_mask & IB_LR_COMPMASK_TO_LID ) + { + status = osm_get_port_by_base_lid( p_rcv->p_subn, + p_lr->to_lid, + pp_dest_port ); + + if( (status != IB_SUCCESS) || (*pp_dest_port == NULL) ) + { + /* + This 'error' is the client's fault (bad lid) so + don't enter it as an error in our own log. + Return an error response to the client. + */ + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "__osm_lr_rcv_get_end_points: " + "No dest port with LID = 0x%X\n", + cl_ntoh16( p_lr->to_lid ) ); + + sa_status = IB_SA_MAD_STATUS_NO_RECORDS; + goto Exit; + } + } + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); + return( sa_status ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_lr_rcv_respond( + IN osm_lr_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw, + IN cl_qlist_t* const p_list ) +{ + osm_madw_t* p_resp_madw; + const ib_sa_mad_t* p_sa_mad; + ib_sa_mad_t* p_resp_sa_mad; + size_t num_rec, num_copied; +#ifndef VENDOR_RMPP_SUPPORT + size_t trim_num_rec; +#endif + ib_link_record_t* p_resp_lr; + ib_api_status_t status; + osm_lr_item_t* p_lr_item; + const ib_sa_mad_t* p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw ); + + OSM_LOG_ENTER( p_rcv->p_log, __osm_lr_rcv_respond ); + + num_rec = cl_qlist_count( p_list ); + /* + * C15-0.1.30: + * If we do a SubnAdmGet and got more than one record it is an error ! + */ + if ( (p_rcvd_mad->method == IB_MAD_METHOD_GET) && + (num_rec > 1)) { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_lr_rcv_respond: ERR 1806: " + "Got more than one record for SubnAdmGet (%zu)\n", + num_rec ); + osm_sa_send_error( p_rcv->p_resp, p_madw, + IB_SA_MAD_STATUS_TOO_MANY_RECORDS ); + + /* need to set the mem free ... */ + p_lr_item = (osm_lr_item_t*)cl_qlist_remove_head( p_list ); + while( p_lr_item != (osm_lr_item_t*)cl_qlist_end( p_list ) ) + { + cl_qlock_pool_put( &p_rcv->lr_pool, &p_lr_item->pool_item ); + p_lr_item = (osm_lr_item_t*)cl_qlist_remove_head( p_list ); + } + + goto Exit; + } + +#ifndef VENDOR_RMPP_SUPPORT + trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_link_record_t); + if (trim_num_rec < num_rec) + { + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "__osm_lr_rcv_respond: " + "Number of records:%u trimmed to:%u to fit in one MAD\n", + num_rec, trim_num_rec ); + num_rec = trim_num_rec; + } +#endif + + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_lr_rcv_respond: " + "Generating response with %zu records", num_rec ); + } + + /* + Get a MAD to reply. Address of Mad is in the received mad_wrapper + */ + p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool, + p_madw->h_bind, + num_rec * sizeof(ib_link_record_t) + IB_SA_MAD_HDR_SIZE, + &p_madw->mad_addr ); + if( !p_resp_madw ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_lr_rcv_respond: ERR 1802: " + "Unable to allocate MAD\n" ); + /* Release the quick pool items */ + p_lr_item = (osm_lr_item_t*)cl_qlist_remove_head( p_list ); + while( p_lr_item != (osm_lr_item_t*)cl_qlist_end( p_list ) ) + { + cl_qlock_pool_put( &p_rcv->lr_pool, &p_lr_item->pool_item ); + p_lr_item = (osm_lr_item_t*)cl_qlist_remove_head( p_list ); + } + + goto Exit; + } + + p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw ); + p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw ); + + /* Copy the header from the request to response */ + memcpy( p_resp_sa_mad, p_sa_mad, IB_SA_MAD_HDR_SIZE ); + p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK; + p_resp_sa_mad->attr_offset = + ib_get_attr_offset( sizeof(ib_link_record_t) ); + /* C15-0.1.5 - always return SM_Key = 0 (table table 185 p 884) */ + p_resp_sa_mad->sm_key = 0; + +#ifndef VENDOR_RMPP_SUPPORT + /* we support only one packet RMPP - so we will set the first and + last flags for gettable */ + if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP) + { + p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA; + p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE; + } +#else + /* forcefully define the packet as RMPP one */ + if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP) + p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE; +#endif + + p_resp_lr = (ib_link_record_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad ); + + if ((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0)) + { + p_resp_sa_mad->status = IB_SA_MAD_STATUS_NO_RECORDS; + memset( p_resp_lr, 0, sizeof(*p_resp_lr) ); + } + else + { + p_lr_item = (osm_lr_item_t*)cl_qlist_remove_head( p_list ); + /* we need to track the number of copied items so we can + * stop the copy - but clear them all + */ + num_copied = 0; + while( p_lr_item != (osm_lr_item_t*)cl_qlist_end( p_list ) ) + { + /* Copy the Link Records from the list into the MAD */ + /* only if we did not go over the mad size (since we might trimmed it) */ + if (num_copied < num_rec) + { + *p_resp_lr = p_lr_item->link_rec; + num_copied++; + } + cl_qlock_pool_put( &p_rcv->lr_pool, &p_lr_item->pool_item ); + p_resp_lr++; + p_lr_item = (osm_lr_item_t*)cl_qlist_remove_head( p_list ); + } + } + + status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE ); + if (status != IB_SUCCESS) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_lr_rcv_respond: ERR 1803: " + "Unable to send MAD (%s)\n", ib_get_err_str( status ) ); + /* osm_mad_pool_put( p_rcv->p_mad_pool, p_resp_madw ); */ + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_lr_rcv_process( + IN osm_lr_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ) +{ + const ib_link_record_t* p_lr; + const ib_sa_mad_t* p_sa_mad; + const osm_port_t* p_src_port; + const osm_port_t* p_dest_port; + cl_qlist_t lr_list; + ib_net16_t sa_status; + osm_physp_t* p_req_physp; + + OSM_LOG_ENTER( p_rcv->p_log, osm_lr_rcv_process ); + + CL_ASSERT( p_madw ); + + p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw ); + p_lr = (ib_link_record_t*)ib_sa_mad_get_payload_ptr( p_sa_mad ); + + CL_ASSERT( p_sa_mad->attr_id == IB_MAD_ATTR_LINK_RECORD ); + + /* we only support SubnAdmGet and SubnAdmGetTable methods */ + if ( (p_sa_mad->method != IB_MAD_METHOD_GET) && + (p_sa_mad->method != IB_MAD_METHOD_GETTABLE)) { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_lr_rcv_process: ERR 1804: " + "Unsupported Method (%s)\n", + ib_get_sa_method_str( p_sa_mad->method ) ); + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR ); + goto Exit; + } + + /* update the requester physical port. */ + p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log, + p_rcv->p_subn, + osm_madw_get_mad_addr_ptr(p_madw) ); + if (p_req_physp == NULL) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_lr_rcv_process: ERR 1805: " + "Cannot find requester physical port\n" ); + goto Exit; + } + + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + osm_dump_link_record( p_rcv->p_log, p_lr, OSM_LOG_DEBUG ); + + cl_qlist_init( &lr_list ); + + /* + Most SA functions (including this one) are read-only on the + subnet object, so we grab the lock non-exclusively. + */ + cl_plock_acquire( p_rcv->p_lock ); + + sa_status = __osm_lr_rcv_get_end_points( p_rcv, p_madw, + &p_src_port, &p_dest_port ); + + if( sa_status == IB_SA_MAD_STATUS_SUCCESS ) + { + __osm_lr_rcv_get_port_links( p_rcv, p_lr, p_src_port, p_dest_port, + p_sa_mad->comp_mask, &lr_list, p_req_physp ); + } + + cl_plock_release( p_rcv->p_lock ); + + if( (cl_qlist_count( &lr_list ) == 0) && + (p_sa_mad->method == IB_MAD_METHOD_GET) ) + { + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS ); + goto Exit; + } + + __osm_lr_rcv_respond( p_rcv, p_madw, &lr_list ); + + Exit: + + OSM_LOG_EXIT( p_rcv->p_log ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_link_record_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_link_record_ctrl.c new file mode 100644 index 00000000..56b3c7ec --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_link_record_ctrl.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_link_record_ctrl.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_lr_rcv_ctrl_t. + * This object represents the link record controller object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +__osm_lr_rcv_ctrl_disp_callback( + IN void *context, + IN void *p_data ) +{ + /* ignore return status when invoked via the dispatcher */ + osm_lr_rcv_process( ((osm_lr_rcv_ctrl_t*)context)->p_rcv, + (osm_madw_t*)p_data ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_lr_rcv_ctrl_construct( + IN osm_lr_rcv_ctrl_t* const p_ctrl ) +{ + memset( p_ctrl, 0, sizeof(*p_ctrl) ); + p_ctrl->h_disp = CL_DISP_INVALID_HANDLE; +} + +/********************************************************************** + **********************************************************************/ +void +osm_lr_rcv_ctrl_destroy( + IN osm_lr_rcv_ctrl_t* const p_ctrl ) +{ + CL_ASSERT( p_ctrl ); + cl_disp_unregister( p_ctrl->h_disp ); +} + + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_lr_rcv_ctrl_init( + IN osm_lr_rcv_ctrl_t* const p_ctrl, + IN osm_lr_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_lr_rcv_ctrl_init ); + + osm_lr_rcv_ctrl_construct( p_ctrl ); + p_ctrl->p_log = p_log; + p_ctrl->p_rcv = p_rcv; + p_ctrl->p_disp = p_disp; + + p_ctrl->h_disp = cl_disp_register( + p_disp, + OSM_MSG_MAD_LINK_RECORD, + __osm_lr_rcv_ctrl_disp_callback, + p_ctrl ); + + if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_lr_rcv_ctrl_init: ERR 1901: " + "Dispatcher registration failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return( status ); +} + + + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_mad_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_mad_ctrl.c new file mode 100644 index 00000000..07a389fe --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_mad_ctrl.c @@ -0,0 +1,651 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_mad_ctrl.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_sa_mad_ctrl_t. + * This object is part of the SA object. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.7 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/****f* opensm: SA/__osm_sa_mad_ctrl_disp_done_callback + * NAME + * __osm_sa_mad_ctrl_disp_done_callback + * + * DESCRIPTION + * This function is the Dispatcher callback that indicates + * a received MAD has been processed by the recipient. + * + * SYNOPSIS + */ +static void +__osm_sa_mad_ctrl_disp_done_callback( + IN void* context, + IN void* p_data ) +{ + osm_sa_mad_ctrl_t* const p_ctrl = (osm_sa_mad_ctrl_t*)context; + osm_madw_t* const p_madw = (osm_madw_t*)p_data; + + OSM_LOG_ENTER( p_ctrl->p_log, __osm_sa_mad_ctrl_disp_done_callback ); + + CL_ASSERT( p_madw ); + /* + Return the MAD & wrapper to the pool. + */ + osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw ); + OSM_LOG_EXIT( p_ctrl->p_log ); +} +/************/ + +/****f* opensm: SA/__osm_sa_mad_ctrl_process + * NAME + * __osm_sa_mad_ctrl_process + * + * DESCRIPTION + * This function handles known methods for received MADs. + * + * SYNOPSIS + */ +static void +__osm_sa_mad_ctrl_process( + IN osm_sa_mad_ctrl_t* const p_ctrl, + IN osm_madw_t *p_madw ) +{ + ib_sa_mad_t* p_sa_mad; + cl_status_t status; + cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE; + uint64_t last_dispatched_msg_queue_time_msec; + uint32_t num_messages; + + OSM_LOG_ENTER( p_ctrl->p_log, __osm_sa_mad_ctrl_process ); + + /* + If the dispatcher is showing us that it is overloaded + there is no point in placing the request in. We should instead provide + immediate response - IB_RESOURCE_BUSY + But how do we know? + The dispatcher reports back the number of outstanding messages and the + time the last message stayed in the queue. + HACK: Actually, we cannot send a mad from within the receive callback; + thus - we will just drop it. + */ + cl_disp_get_queue_status(p_ctrl->h_disp, + &num_messages, + &last_dispatched_msg_queue_time_msec); + if ((num_messages > 1) && + (p_ctrl->p_subn->opt.max_msg_fifo_timeout) && + (last_dispatched_msg_queue_time_msec > + p_ctrl->p_subn->opt.max_msg_fifo_timeout)) + { + osm_log( p_ctrl->p_log, OSM_LOG_INFO, + "__osm_sa_mad_ctrl_process: " + /* "Responding BUSY status since the dispatcher is already"*/ + "Dropping MAD since the dispatcher is already" + " overloaded with %u messages and queue time of:" + "%" PRIu64 "[msec]\n", + num_messages, last_dispatched_msg_queue_time_msec ); + + /* send a busy response */ + /* osm_sa_send_error( p_ctrl->p_resp, p_madw, IB_RESOURCE_BUSY ); */ + + /* return the request to the pool */ + osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw ); + + goto Exit; + } + + p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw ); + + /* + Note that attr_id (like the rest of the MAD) is in + network byte order. + */ + switch( p_sa_mad->attr_id ) + { + case IB_MAD_ATTR_CLASS_PORT_INFO: + msg_id = OSM_MSG_MAD_CLASS_PORT_INFO; + break; + + case IB_MAD_ATTR_NODE_RECORD: + msg_id = OSM_MSG_MAD_NODE_RECORD; + break; + + case IB_MAD_ATTR_PORTINFO_RECORD: + msg_id = OSM_MSG_MAD_PORTINFO_RECORD; + break; + + case IB_MAD_ATTR_LINK_RECORD: + msg_id = OSM_MSG_MAD_LINK_RECORD; + break; + + case IB_MAD_ATTR_SMINFO_RECORD: + msg_id = OSM_MSG_MAD_SMINFO_RECORD; + break; + + case IB_MAD_ATTR_SERVICE_RECORD: + msg_id = OSM_MSG_MAD_SERVICE_RECORD; + break; + + case IB_MAD_ATTR_PATH_RECORD: + msg_id = OSM_MSG_MAD_PATH_RECORD; + break; + + case IB_MAD_ATTR_MCMEMBER_RECORD: + msg_id = OSM_MSG_MAD_MCMEMBER_RECORD; + break; + + case IB_MAD_ATTR_INFORM_INFO: + msg_id = OSM_MSG_MAD_INFORM_INFO; + break; + + case IB_MAD_ATTR_VLARB_RECORD: + msg_id = OSM_MSG_MAD_VL_ARB_RECORD; + break; + + case IB_MAD_ATTR_SLVL_RECORD: + msg_id = OSM_MSG_MAD_SLVL_TBL_RECORD; + break; + + case IB_MAD_ATTR_PKEY_TBL_RECORD: + msg_id = OSM_MSG_MAD_PKEY_TBL_RECORD; + break; + + case IB_MAD_ATTR_LFT_RECORD: + msg_id = OSM_MSG_MAD_LFT_RECORD; + break; + + case IB_MAD_ATTR_GUIDINFO_RECORD: + msg_id = OSM_MSG_MAD_GUIDINFO_RECORD; + break; + + case IB_MAD_ATTR_INFORM_INFO_RECORD: + msg_id = OSM_MSG_MAD_INFORM_INFO_RECORD; + break; + + case IB_MAD_ATTR_SWITCH_INFO_RECORD: + msg_id = OSM_MSG_MAD_SWITCH_INFO_RECORD; + break; + + case IB_MAD_ATTR_MFT_RECORD: + msg_id = OSM_MSG_MAD_MFT_RECORD; + break; + +#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP) + case IB_MAD_ATTR_MULTIPATH_RECORD: + msg_id = OSM_MSG_MAD_MULTIPATH_RECORD; + break; +#endif + + default: + osm_log( p_ctrl->p_log, OSM_LOG_ERROR, + "__osm_sa_mad_ctrl_process: ERR 1A01: " + "Unsupported attribute = 0x%X\n", + cl_ntoh16( p_sa_mad->attr_id ) ); + osm_dump_sa_mad( p_ctrl->p_log, p_sa_mad, OSM_LOG_ERROR ); + } + + if( msg_id != CL_DISP_MSGID_NONE ) + { + /* + Post this MAD to the dispatcher for asynchronous + processing by the appropriate controller. + */ + + osm_log( p_ctrl->p_log, OSM_LOG_DEBUG, + "__osm_sa_mad_ctrl_process: " + "Posting Dispatcher message %s\n", + osm_get_disp_msg_str( msg_id ) ); + + status = cl_disp_post( p_ctrl->h_disp, + msg_id, + p_madw, + __osm_sa_mad_ctrl_disp_done_callback, + p_ctrl ); + + if( status != CL_SUCCESS ) + { + osm_log( p_ctrl->p_log, OSM_LOG_ERROR, + "__osm_sa_mad_ctrl_process: ERR 1A02: " + "Dispatcher post message failed (%s) for attribute = 0x%X\n", + CL_STATUS_MSG( status ), + cl_ntoh16( p_sa_mad->attr_id ) ); + + osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw ); + goto Exit; + } + } + else + { + /* + There is an unknown MAD attribute type for which there is + no recipient. Simply retire the MAD here. + */ + osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw ); + } + + Exit: + OSM_LOG_EXIT( p_ctrl->p_log ); +} +/* + * PARAMETERS + * + * RETURN VALUES + * + * NOTES + * + * SEE ALSO + *********/ + +/****f* opensm: SA/__osm_sa_mad_ctrl_rcv_callback + * NAME + * __osm_sa_mad_ctrl_rcv_callback + * + * DESCRIPTION + * This is the callback from the transport layer for received MADs. + * + * SYNOPSIS + */ +static void +__osm_sa_mad_ctrl_rcv_callback( + IN osm_madw_t *p_madw, + IN void *bind_context, + IN osm_madw_t *p_req_madw ) +{ + osm_sa_mad_ctrl_t* p_ctrl = (osm_sa_mad_ctrl_t*)bind_context; + ib_sa_mad_t* p_sa_mad; + + OSM_LOG_ENTER( p_ctrl->p_log, __osm_sa_mad_ctrl_rcv_callback ); + + CL_ASSERT( p_madw ); + + /* + A MAD was received from the wire, possibly in response to a request. + */ + cl_atomic_inc( &p_ctrl->p_stats->qp1_mads_rcvd ); + + if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_ctrl->p_log, OSM_LOG_DEBUG, + "__osm_sa_mad_ctrl_rcv_callback: " + "%u QP1 MADs received\n", + p_ctrl->p_stats->qp1_mads_rcvd ); + } + + /* + * C15-0.1.3 requires not responding to any MAD if the SM is + * not in active state! + * We will not respond if the sm_state is not MASTER, or if the + * first_time_master_sweep flag (of the subnet) is TRUE - this + * flag indicates that the master still didn't finish its first + * sweep, so the subnet is not up and stable yet. + */ + if ( p_ctrl->p_subn->sm_state != IB_SMINFO_STATE_MASTER ) + { + osm_log( p_ctrl->p_log, OSM_LOG_VERBOSE, + "__osm_sa_mad_ctrl_rcv_callback: " + "Received SA MAD while SM not MASTER. MAD ignored\n"); + osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw ); + goto Exit; + } + if ( p_ctrl->p_subn->first_time_master_sweep == TRUE ) + { + osm_log( p_ctrl->p_log, OSM_LOG_VERBOSE, + "__osm_sa_mad_ctrl_rcv_callback: " + "Received SA MAD while SM in first sweep. MAD ignored\n"); + osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw ); + goto Exit; + } + + p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw ); + + if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_FRAMES ) ) + osm_dump_sa_mad( p_ctrl->p_log, p_sa_mad, OSM_LOG_FRAMES ); + + /* + * C15-0.1.5 - Table 185: SA Header - p884 + * SM_key should be either 0 or match the current SM_Key + * otherwise discard the MAD. + */ + if ((p_sa_mad->sm_key != 0) && + (p_sa_mad->sm_key != p_ctrl->p_subn->opt.sm_key)) { + osm_log( p_ctrl->p_log, OSM_LOG_ERROR, + "__osm_sa_mad_ctrl_rcv_callback: ERR 1A04: " + "Non-Zero SA MAD SM_Key: 0x%" PRIx64 " != SM_Key: 0x%" PRIx64 + "; MAD ignored\n", + cl_ntoh64(p_sa_mad->sm_key), + cl_ntoh64(p_ctrl->p_subn->opt.sm_key) + ); + osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw ); + goto Exit; + } + + switch( p_sa_mad->method ) + { + case IB_MAD_METHOD_REPORT_RESP: + /* we do not really do anything with report represses - + just retire the transaction */ + osm_log( p_ctrl->p_log, OSM_LOG_DEBUG, + "__osm_sa_mad_ctrl_rcv_callback: " + "Received Report Repress. Retiring the transaction\n"); + + if (p_req_madw) + osm_mad_pool_put( p_ctrl->p_mad_pool, p_req_madw ); + osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw ); + + break; + + case IB_MAD_METHOD_GET: + case IB_MAD_METHOD_GETTABLE: +#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP) + case IB_MAD_METHOD_GETMULTI: +#endif + case IB_MAD_METHOD_SET: + case IB_MAD_METHOD_DELETE: + __osm_sa_mad_ctrl_process( p_ctrl, p_madw ); + break; + + default: + osm_log( p_ctrl->p_log, OSM_LOG_ERROR, + "__osm_sa_mad_ctrl_rcv_callback: ERR 1A05: " + "Unsupported method = 0x%X\n", + p_sa_mad->method ); + osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw ); + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_ctrl->p_log ); +} +/* + * PARAMETERS + * + * RETURN VALUES + * + * NOTES + * + * SEE ALSO + *********/ + +/****f* opensm: SA/__osm_sa_mad_ctrl_send_err_callback + * NAME + * __osm_sa_mad_ctrl_send_err_callback + * + * DESCRIPTION + * This is the callback from the transport layer for send errors + * on MADs that were expecting a response. + * + * SYNOPSIS + */ +void +__osm_sa_mad_ctrl_send_err_callback( + IN void *bind_context, + IN osm_madw_t *p_madw ) +{ + osm_sa_mad_ctrl_t* p_ctrl = (osm_sa_mad_ctrl_t*)bind_context; + cl_status_t status; + + OSM_LOG_ENTER( p_ctrl->p_log, __osm_sa_mad_ctrl_send_err_callback ); + + osm_log( p_ctrl->p_log, OSM_LOG_ERROR, + "__osm_sa_mad_ctrl_send_err_callback: ERR 1A06: " + "MAD transaction completed in error\n" ); + + /* + We should never be here since the SA never originates a request. + Unless we generated a Report(Notice) + */ + + CL_ASSERT( p_madw ); + + /* + An error occurred. No response was received to a request MAD. + Retire the original request MAD. + */ + + osm_dump_sa_mad(p_ctrl->p_log, osm_madw_get_sa_mad_ptr( p_madw ), + OSM_LOG_ERROR ); + + /* __osm_sm_mad_ctrl_update_wire_stats( p_ctrl ); */ + + if( osm_madw_get_err_msg( p_madw ) != CL_DISP_MSGID_NONE ) + { + if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_ctrl->p_log, OSM_LOG_DEBUG, + "__osm_sa_mad_ctrl_send_err_callback: " + "Posting Dispatcher message %s\n", + osm_get_disp_msg_str( osm_madw_get_err_msg( p_madw ) ) ); + } + + status = cl_disp_post( p_ctrl->h_disp, + osm_madw_get_err_msg( p_madw ), + p_madw, + __osm_sa_mad_ctrl_disp_done_callback, + p_ctrl ); + if( status != CL_SUCCESS ) + { + osm_log( p_ctrl->p_log, OSM_LOG_ERROR, + "__osm_sa_mad_ctrl_send_err_callback: ERR 1A07: " + "Dispatcher post message failed (%s)\n", + CL_STATUS_MSG( status ) ); + } + } + else + { + /* + No error message was provided, just retire the MAD. + */ + osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw ); + } + + OSM_LOG_EXIT( p_ctrl->p_log ); +} +/* + * PARAMETERS + * + * RETURN VALUES + * + * NOTES + * + * SEE ALSO + *********/ + +/********************************************************************** + **********************************************************************/ +void +osm_sa_mad_ctrl_construct( + IN osm_sa_mad_ctrl_t* const p_ctrl ) +{ + CL_ASSERT( p_ctrl ); + memset( p_ctrl, 0, sizeof(*p_ctrl) ); + p_ctrl->h_disp = CL_DISP_INVALID_HANDLE; +} + +/********************************************************************** + **********************************************************************/ +void +osm_sa_mad_ctrl_destroy( + IN osm_sa_mad_ctrl_t* const p_ctrl ) +{ + CL_ASSERT( p_ctrl ); + cl_disp_unregister( p_ctrl->h_disp ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_sa_mad_ctrl_init( + IN osm_sa_mad_ctrl_t* const p_ctrl, + IN osm_sa_resp_t* const p_resp, + IN osm_mad_pool_t* const p_mad_pool, + IN osm_vendor_t* const p_vendor, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN osm_stats_t* const p_stats, + IN cl_dispatcher_t* const p_disp ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_sa_mad_ctrl_init ); + + osm_sa_mad_ctrl_construct( p_ctrl ); + + p_ctrl->p_log = p_log; + p_ctrl->p_disp = p_disp; + p_ctrl->p_mad_pool = p_mad_pool; + p_ctrl->p_vendor = p_vendor; + p_ctrl->p_stats = p_stats; + p_ctrl->p_subn = p_subn; + p_ctrl->p_resp = p_resp; + + p_ctrl->h_disp = cl_disp_register( + p_disp, + CL_DISP_MSGID_NONE, + NULL, + p_ctrl ); + + if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_sa_mad_ctrl_init: ERR 1A08: " + "Dispatcher registration failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_sa_mad_ctrl_bind( + IN osm_sa_mad_ctrl_t* const p_ctrl, + IN const ib_net64_t port_guid ) +{ + osm_bind_info_t bind_info; + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_ctrl->p_log, osm_sa_mad_ctrl_bind ); + + if( p_ctrl->h_bind != OSM_BIND_INVALID_HANDLE ) + { + osm_log( p_ctrl->p_log, OSM_LOG_ERROR, + "osm_sa_mad_ctrl_bind: ERR 1A09: " + "Multiple binds not allowed\n" ); + status = IB_ERROR; + goto Exit; + } + + bind_info.class_version = 2; + bind_info.is_responder = TRUE; + bind_info.is_report_processor = FALSE; + bind_info.is_trap_processor = FALSE; + bind_info.mad_class = IB_MCLASS_SUBN_ADM; + bind_info.port_guid = port_guid; + bind_info.recv_q_size = OSM_SM_DEFAULT_QP1_RCV_SIZE; + bind_info.send_q_size = OSM_SM_DEFAULT_QP1_SEND_SIZE; + + osm_log( p_ctrl->p_log, OSM_LOG_VERBOSE, + "osm_sa_mad_ctrl_bind: " + "Binding to port GUID 0x%" PRIx64 "\n", + cl_ntoh64( port_guid ) ); + + p_ctrl->h_bind = osm_vendor_bind( p_ctrl->p_vendor, + &bind_info, + p_ctrl->p_mad_pool, + __osm_sa_mad_ctrl_rcv_callback, + __osm_sa_mad_ctrl_send_err_callback, + p_ctrl ); + + if( p_ctrl->h_bind == OSM_BIND_INVALID_HANDLE ) + { + status = IB_ERROR; + osm_log( p_ctrl->p_log, OSM_LOG_ERROR, + "osm_sa_mad_ctrl_bind: ERR 1A10: " + "Vendor specific bind failed (%s)\n", + ib_get_err_str(status) ); + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_ctrl->p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_sa_mad_ctrl_unbind( + IN osm_sa_mad_ctrl_t* const p_ctrl) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_ctrl->p_log, osm_sa_mad_ctrl_unbind ); + + if( p_ctrl->h_bind == OSM_BIND_INVALID_HANDLE ) + { + osm_log( p_ctrl->p_log, OSM_LOG_ERROR, + "osm_sa_mad_ctrl_unbind: ERR 1A11: " + "No previous bind\n" ); + status = IB_ERROR; + goto Exit; + } + + osm_vendor_unbind( p_ctrl->h_bind ); + Exit: + OSM_LOG_EXIT( p_ctrl->p_log ); + return( status ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_mcmember_record.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_mcmember_record.c new file mode 100644 index 00000000..771bed0d --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_mcmember_record.c @@ -0,0 +1,2383 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_mcmember_record.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Implementation of osm_mcmr_recv_t. + * This object represents the MCMemberRecord Receiver object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.15 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define OSM_MCMR_RCV_POOL_MIN_SIZE 32 +#define OSM_MCMR_RCV_POOL_GROW_SIZE 32 + +typedef struct _osm_mcmr_item +{ + cl_pool_item_t pool_item; + ib_member_rec_t rec; +} osm_mcmr_item_t; + +typedef struct osm_sa_mcmr_search_ctxt { + const ib_member_rec_t *p_mcmember_rec; + osm_mgrp_t *p_mgrp; + osm_mcmr_recv_t *p_rcv; + cl_qlist_t *p_list; /* hold results */ + ib_net64_t comp_mask; + const osm_physp_t* p_req_physp; + boolean_t trusted_req; +} osm_sa_mcmr_search_ctxt_t; + +/********************************************************************** + **********************************************************************/ +void +osm_mcmr_rcv_construct( + IN osm_mcmr_recv_t* const p_rcv ) +{ + memset( p_rcv, 0, sizeof(*p_rcv) ); + cl_qlock_pool_construct( &p_rcv->pool ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_mcmr_rcv_destroy( + IN osm_mcmr_recv_t* const p_rcv ) +{ + CL_ASSERT( p_rcv ); + + OSM_LOG_ENTER( p_rcv->p_log, osm_mcmr_rcv_destroy ); + + cl_qlock_pool_destroy( &p_rcv->pool ); + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_mcmr_rcv_init( + IN osm_sm_t * const p_sm, + IN osm_mcmr_recv_t* const p_rcv, + IN osm_sa_resp_t* const p_resp, + IN osm_mad_pool_t* const p_mad_pool, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_mcmr_rcv_init ); + + osm_mcmr_rcv_construct( p_rcv ); + + p_rcv->p_log = p_log; + p_rcv->p_subn = p_subn; + p_rcv->p_sm = p_sm; + p_rcv->p_lock = p_lock; + p_rcv->p_resp = p_resp; + p_rcv->p_mad_pool = p_mad_pool; + p_rcv->mlid_ho = 0xC000; + + status = cl_qlock_pool_init( &p_rcv->pool, + OSM_MCMR_RCV_POOL_MIN_SIZE, + 0, + OSM_MCMR_RCV_POOL_GROW_SIZE, + sizeof(osm_mcmr_item_t), + NULL, NULL, NULL ); + if (status != CL_SUCCESS) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_mcmr_rcv_init: ERR 1B02: " + "qlock pool init failed (%d)\n", + status ); + } + OSM_LOG_EXIT( p_rcv->p_log ); + return( status ); +} + +/********************************************************************** + A search function that compares the given mgrp with the search context + if there is a match by mgid the p_mgrp is copied to the search context + p_mgrp component + + Inputs: + p_map_item - which is part of a mgrp object + context - points to the osm_sa_mcmr_search_ctxt_t including the mgid + looked for and the result p_mgrp +**********************************************************************/ +static void +__search_mgrp_by_mgid( + IN cl_map_item_t* const p_map_item, + IN void* context ) +{ + osm_mgrp_t* p_mgrp = (osm_mgrp_t*)p_map_item; + osm_sa_mcmr_search_ctxt_t *p_ctxt = (osm_sa_mcmr_search_ctxt_t *) context; + const ib_member_rec_t *p_recvd_mcmember_rec; + osm_mcmr_recv_t *p_rcv; + + p_recvd_mcmember_rec = p_ctxt->p_mcmember_rec; + p_rcv = p_ctxt->p_rcv; + + /* ignore groups marked for deletion */ + if (p_mgrp->to_be_deleted) + return; + + /* compare entire MGID so different scope will not sneak in for + the same MGID */ + if (memcmp(&p_mgrp->mcmember_rec.mgid, + &p_recvd_mcmember_rec->mgid, + sizeof(ib_gid_t))) + return; + + if (p_ctxt->p_mgrp) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__search_mgrp_by_mgid: ERR 1B03: " + "Multiple MC groups for same MGID\n" ); + return; + } + + p_ctxt->p_mgrp = p_mgrp; + +} + +/********************************************************************** + Look for a MGRP in the mgrp_mlid_tbl by mlid +**********************************************************************/ +static osm_mgrp_t * +__get_mgrp_by_mlid( + IN osm_mcmr_recv_t* const p_rcv, + IN ib_net16_t const mlid) +{ + cl_map_item_t *map_item; + + map_item = cl_qmap_get(&p_rcv->p_subn->mgrp_mlid_tbl, mlid); + if (map_item == cl_qmap_end(&p_rcv->p_subn->mgrp_mlid_tbl)) + { + return NULL; + } + return (osm_mgrp_t *)map_item; + +} + +/********************************************************************** +Look for a MGRP in the mgrp_mlid_tbl by mgid +***********************************************************************/ +static ib_api_status_t +__get_mgrp_by_mgid( + IN osm_mcmr_recv_t* const p_rcv, + IN ib_member_rec_t* p_recvd_mcmember_rec, + OUT osm_mgrp_t **pp_mgrp) +{ + osm_sa_mcmr_search_ctxt_t mcmr_search_context; + + mcmr_search_context.p_mcmember_rec = p_recvd_mcmember_rec; + mcmr_search_context.p_rcv = p_rcv; + mcmr_search_context.p_mgrp = NULL; + + cl_qmap_apply_func( &p_rcv->p_subn->mgrp_mlid_tbl, + __search_mgrp_by_mgid, + &mcmr_search_context); + + if (mcmr_search_context.p_mgrp == NULL) + { + return IB_NOT_FOUND; + } + + *pp_mgrp = mcmr_search_context.p_mgrp; + return IB_SUCCESS; +} + +/********************************************************************* +Copy certain fields between two mcmember records +used during the process of join request to copy data from the mgrp to the +port record. +**********************************************************************/ +static inline void +__copy_from_create_mc_rec( + IN ib_member_rec_t * const dest, + IN const ib_member_rec_t *const src) +{ + dest->qkey = src->qkey; + dest->mlid = src->mlid; + dest->tclass = src->tclass; + dest->pkey = src->pkey; + dest->sl_flow_hop = src->sl_flow_hop; + dest->mtu = src->mtu; + dest->rate = src->rate; + dest->pkt_life = src->pkt_life; +} + +/********************************************************************* +Return an mlid to the pool of free mlids. +But this implementation is not a pool - it is simply scanning through +the MGRP database for unused mlids... +*********************************************************************/ +static void +__free_mlid( + IN osm_mcmr_recv_t* const p_rcv, + IN uint16_t mlid) +{ + UNUSED_PARAM(p_rcv); + UNUSED_PARAM(mlid); +} + +/********************************************************************* +Get a new unused mlid by scanning all the used ones in the subnet. +TODO: Implement a more scalable - O(1) solution based on pool of +available mlids. +**********************************************************************/ +static ib_net16_t +__get_new_mlid( + IN osm_mcmr_recv_t* const p_rcv, + IN ib_net16_t requested_mlid) +{ + osm_subn_t *p_subn = p_rcv->p_subn; + osm_mgrp_t *p_mgrp; + uint8_t *used_mlids_array; + uint16_t idx; + uint16_t mlid; /* the result */ + uint16_t max_num_mlids; + + OSM_LOG_ENTER(p_rcv->p_log, __get_new_mlid); + + if (requested_mlid && cl_ntoh16(requested_mlid) >= IB_LID_MCAST_START_HO && + cl_ntoh16(requested_mlid) < p_subn->max_multicast_lid_ho && + cl_qmap_get(&p_subn->mgrp_mlid_tbl, requested_mlid) == + cl_qmap_end(&p_subn->mgrp_mlid_tbl) ) { + mlid = cl_ntoh16(requested_mlid); + goto Exit; + } + + /* If MCGroups table empty, first return the min mlid */ + p_mgrp = (osm_mgrp_t*)cl_qmap_head( &p_subn->mgrp_mlid_tbl ); + if (p_mgrp == (osm_mgrp_t*)cl_qmap_end( &p_subn->mgrp_mlid_tbl )) + { + mlid = IB_LID_MCAST_START_HO; + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "__get_new_mlid: " + "No multicast groups found using minimal mlid:0x%04X\n", + mlid ); + goto Exit; + } + + max_num_mlids = + p_rcv->p_subn->max_multicast_lid_ho - IB_LID_MCAST_START_HO; + + /* track all used mlids in the array (by mlid index) */ + used_mlids_array = + (uint8_t *)malloc(sizeof(uint8_t)*max_num_mlids); + if (used_mlids_array) + memset(used_mlids_array, 0, sizeof(uint8_t)*max_num_mlids); + if (!used_mlids_array) + return 0; + + /* scan all available multicast groups in the DB and fill in the table */ + while( p_mgrp != (osm_mgrp_t*)cl_qmap_end( &p_subn->mgrp_mlid_tbl ) ) + { + /* ignore mgrps marked for deletion */ + if (p_mgrp->to_be_deleted == FALSE) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__get_new_mlid: " + "Found mgrp with lid:0x%X MGID: 0x%016" PRIx64 " : " + "0x%016" PRIx64 "\n", + cl_ntoh16( p_mgrp->mlid), + cl_ntoh64( p_mgrp->mcmember_rec.mgid.unicast.prefix ), + cl_ntoh64( p_mgrp->mcmember_rec.mgid.unicast.interface_id ) ); + + /* Map in table */ + if (cl_ntoh16(p_mgrp->mlid) > p_rcv->p_subn->max_multicast_lid_ho) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__get_new_mlid: ERR 1B27: " + "Found mgrp with mlid:0x%04X > max allowed mlid:0x%04X\n", + cl_ntoh16(p_mgrp->mlid), + max_num_mlids + IB_LID_MCAST_START_HO ); + } + else + { + used_mlids_array[cl_ntoh16(p_mgrp->mlid) - IB_LID_MCAST_START_HO] = 1; + } + } + p_mgrp = (osm_mgrp_t*)cl_qmap_next( &p_mgrp->map_item ); + } + + /* Find "mlid holes" in the mgrp table */ + for (idx = 0; + (idx < max_num_mlids) && (used_mlids_array[idx] == 1); + idx++); + + /* did it go above the maximal mlid allowed */ + if ( idx < max_num_mlids ) + { + mlid = idx + IB_LID_MCAST_START_HO; + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "__get_new_mlid: " + "Found available mlid:0x%04X at idx:%u\n", + mlid, idx ); + } + else + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__get_new_mlid: ERR 1B23: " + "All available:%u mlids are taken\n", + max_num_mlids ); + mlid = 0; + } + + free(used_mlids_array); + + Exit: + OSM_LOG_EXIT(p_rcv->p_log); + return cl_hton16(mlid); +} + +/********************************************************************* +This procedure is only invoked to cleanup an INTERMEDIATE mgrp. +If there is only one port on the mgrp it means that the current +request was the only member and the group is not really needed. So we +silently drop it. Since it was an intermediate group no need to +re-route it. +**********************************************************************/ +static void +__cleanup_mgrp( + IN osm_mcmr_recv_t* const p_rcv, + IN ib_net16_t const mlid) +{ + osm_mgrp_t *p_mgrp; + + p_mgrp = __get_mgrp_by_mlid(p_rcv, mlid); + if(p_mgrp) + { + /* Remove MGRP only if osm_mcm_port_t count is 0 and + * Not a well known group + */ + if(cl_is_qmap_empty(&p_mgrp->mcm_port_tbl) && + (p_mgrp->well_known == FALSE)) + { + cl_qmap_remove_item(&p_rcv->p_subn->mgrp_mlid_tbl, + (cl_map_item_t *)p_mgrp ); + osm_mgrp_destroy(p_mgrp); + } + } +} + +/********************************************************************* +Add a port to the group. Calculating its PROXY_JOIN by the Port and +requester gids. +**********************************************************************/ +static ib_api_status_t +__add_new_mgrp_port( + IN osm_mcmr_recv_t *p_rcv, + IN osm_mgrp_t *p_mgrp, + IN ib_member_rec_t *p_recvd_mcmember_rec, + IN osm_mad_addr_t *p_mad_addr, + OUT osm_mcm_port_t **pp_mcmr_port) +{ + boolean_t proxy_join; + ib_gid_t requester_gid; + ib_api_status_t res; + + /* set the proxy_join if the requester gid is not identical to the + joined gid */ + res = osm_get_gid_by_mad_addr( p_rcv->p_log, + p_rcv->p_subn, + p_mad_addr, &requester_gid ); + if ( res != IB_SUCCESS ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__add_new_mgrp_port: ERR 1B29: " + "Could not find GID for requester\n" ); + + return IB_INVALID_PARAMETER; + } + + if (!memcmp(&p_recvd_mcmember_rec->port_gid, &requester_gid, + sizeof(ib_gid_t))) + { + proxy_join = FALSE; + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__add_new_mgrp_port: " + "Create new port with proxy_join FALSE\n" ); + } + else + { + /* The port is not the one specified in PortGID. + The check that the requester is in the same partition as + the PortGID is done before - just need to update the proxy_join. */ + proxy_join = TRUE; + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__add_new_mgrp_port: " + "Create new port with proxy_join TRUE\n" ); + } + + *pp_mcmr_port = osm_mgrp_add_port( p_mgrp, + &p_recvd_mcmember_rec->port_gid, + p_recvd_mcmember_rec->scope_state, + proxy_join ); + if(*pp_mcmr_port == NULL) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__add_new_mgrp_port: ERR 1B06: " + "osm_mgrp_add_port failed\n" ); + + return IB_INSUFFICIENT_MEMORY; + } + + return IB_SUCCESS; +} + +/********************************************************************** + **********************************************************************/ +static inline boolean_t +__check_join_comp_mask(ib_net64_t comp_mask) +{ + return( (comp_mask & JOIN_MC_COMP_MASK) == JOIN_MC_COMP_MASK ); +} + +/********************************************************************** + **********************************************************************/ +static inline boolean_t +__check_create_comp_mask(ib_net64_t comp_mask, + ib_member_rec_t *p_recvd_mcmember_rec) +{ + return( + ((comp_mask & REQUIRED_MC_CREATE_COMP_MASK) == REQUIRED_MC_CREATE_COMP_MASK) + ); +} + +/********************************************************************** +Generate the response MAD +**********************************************************************/ +static void +__osm_mcmr_rcv_respond( + IN const osm_mcmr_recv_t* const p_rcv, + IN const osm_madw_t* const p_madw, + IN ib_member_rec_t *p_mcmember_rec ) +{ + osm_madw_t *p_resp_madw; + ib_sa_mad_t *p_sa_mad, *p_resp_sa_mad; + ib_member_rec_t *p_resp_mcmember_rec; + ib_api_status_t status; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_mcmr_rcv_respond ); + + /* + * Get a MAD to reply. Address of Mad is in the received mad_wrapper + */ + p_resp_madw = osm_mad_pool_get(p_rcv->p_mad_pool, + p_madw->h_bind, + sizeof(ib_member_rec_t)+IB_SA_MAD_HDR_SIZE, + osm_madw_get_mad_addr_ptr(p_madw) ); + if ( !p_resp_madw ) + { + goto Exit; + } + + p_resp_sa_mad = (ib_sa_mad_t*)p_resp_madw->p_mad; + p_sa_mad = (ib_sa_mad_t*)p_madw->p_mad; + /* Copy the MAD header back into the response mad */ + memcpy(p_resp_sa_mad, p_sa_mad, IB_SA_MAD_HDR_SIZE); + /* based on the current method decide about the response: */ + if ((p_resp_sa_mad->method == IB_MAD_METHOD_GET) || + (p_resp_sa_mad->method == IB_MAD_METHOD_SET)) { + p_resp_sa_mad->method = IB_MAD_METHOD_GET_RESP; + } + else if (p_resp_sa_mad->method == IB_MAD_METHOD_DELETE) { + p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK; + } + else + { + CL_ASSERT( p_resp_sa_mad->method == 0); + } + + /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */ + p_resp_sa_mad->sm_key = 0; + + /* Fill in the offset (paylen will be done by the rmpp SAR) */ + p_resp_sa_mad->attr_offset = + ib_get_attr_offset( sizeof(ib_member_rec_t) ); + p_resp_mcmember_rec = (ib_member_rec_t*)&p_resp_sa_mad->data; + + *p_resp_mcmember_rec = *p_mcmember_rec; + + /* Fill in the mtu, rate, and packet lifetime selectors */ + p_resp_mcmember_rec->mtu &= 0x3f; + p_resp_mcmember_rec->mtu |= 2<<6; /* exactly */ + p_resp_mcmember_rec->rate &= 0x3f; + p_resp_mcmember_rec->rate |= 2<<6; /* exactly */ + p_resp_mcmember_rec->pkt_life &= 0x3f; + p_resp_mcmember_rec->pkt_life |= 2<<6; /* exactly */ + + status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE ); + + if(status != IB_SUCCESS) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_mcmr_rcv_respond: ERR 1B07: " + "Unable to send MAD (%s) for TID <0x%"PRIx64">\n", + ib_get_err_str( status ), + p_resp_sa_mad->trans_id ); + } + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); + return; +} + +/********************************************************************* +In joining an existing group, or when querying the mc groups, +we make sure the following components provided match: MTU and RATE +HACK: Currently we ignore the PKT_LIFETIME field. +**********************************************************************/ +static boolean_t +__validate_more_comp_fields( + osm_log_t *p_log, + const osm_mgrp_t *p_mgrp, + const ib_member_rec_t *p_recvd_mcmember_rec, + ib_net64_t comp_mask) +{ + uint8_t mtu_sel; + uint8_t mtu_required; + uint8_t mtu_mgrp; + uint8_t rate_sel; + uint8_t rate_required; + uint8_t rate_mgrp; + + if ( comp_mask & IB_MCR_COMPMASK_MTU_SEL) + { + mtu_sel = (uint8_t)(p_recvd_mcmember_rec->mtu >> 6); + /* Clearing last 2 bits */ + mtu_required = (uint8_t)(p_recvd_mcmember_rec->mtu & 0x3F); + mtu_mgrp = (uint8_t)(p_mgrp->mcmember_rec.mtu & 0x3F); + switch (mtu_sel) + { + case 0: /* Greater than MTU specified */ + if(mtu_mgrp <= mtu_required) + { + osm_log( p_log, OSM_LOG_DEBUG, + "__validate_more_comp_fields: " + "Requested MTU %x is not greater than %x\n", + mtu_mgrp, mtu_required ); + return FALSE; + } + break; + case 1: /* Less than MTU specified */ + if(mtu_mgrp >= mtu_required) + { + osm_log( p_log, OSM_LOG_DEBUG, + "__validate_more_comp_fields: " + "Requested MTU %x is not less than %x\n", + mtu_mgrp, mtu_required ); + return FALSE; + } + break; + case 2: /* Exactly MTU specified */ + if(mtu_mgrp != mtu_required) + { + osm_log( p_log, OSM_LOG_DEBUG, + "__validate_more_comp_fields: " + "Requested MTU %x is not equal to %x\n", + mtu_mgrp, mtu_required ); + return FALSE; + } + break; + default: + break; + } + } + + /* what about rate ? */ + if ( comp_mask & IB_MCR_COMPMASK_RATE_SEL) + { + rate_sel = (uint8_t)(p_recvd_mcmember_rec->rate >> 6); + /* Clearing last 2 bits */ + rate_required = (uint8_t)(p_recvd_mcmember_rec->rate & 0x3F); + rate_mgrp = (uint8_t)(p_mgrp->mcmember_rec.rate & 0x3F); + switch (rate_sel) + { + case 0: /* Greater than RATE specified */ + if(rate_mgrp <= rate_required) + { + osm_log( p_log, OSM_LOG_DEBUG, + "__validate_more_comp_fields: " + "Requested RATE %x is not greater than %x\n", + rate_mgrp, rate_required ); + return FALSE; + } + break; + case 1: /* Less than RATE specified */ + if(rate_mgrp >= rate_required) + { + osm_log( p_log, OSM_LOG_DEBUG, + "__validate_more_comp_fields: " + "Requested RATE %x is not less than %x\n", + rate_mgrp, rate_required ); + return FALSE; + } + break; + case 2: /* Exactly RATE specified */ + if(rate_mgrp != rate_required) + { + osm_log( p_log, OSM_LOG_DEBUG, + "__validate_more_comp_fields: " + "Requested RATE %x is not equal to %x\n", + rate_mgrp, rate_required ); + return FALSE; + } + break; + default: + break; + } + } + + return TRUE; +} + +/********************************************************************* +In joining an existing group, we make sure the following components +are physically realizable: MTU and RATE +**********************************************************************/ +static boolean_t +__validate_port_caps( + osm_log_t * const p_log, + const osm_mgrp_t *p_mgrp, + const osm_physp_t *p_physp) +{ + ib_port_info_t *p_pi; + uint8_t mtu_required; + uint8_t mtu_mgrp; + uint8_t rate_required; + uint8_t rate_mgrp; + + p_pi = osm_physp_get_port_info_ptr(p_physp); + if (!p_pi) + { + osm_log( p_log, OSM_LOG_DEBUG, + "__validate_port_caps: " + "Cannot get Port's 0x%016" PRIx64 " PortInfo\n", + cl_ntoh64( osm_physp_get_port_guid(p_physp) ) ); + return FALSE; + } + + mtu_required = ib_port_info_get_mtu_cap(p_pi); + mtu_mgrp = (uint8_t)(p_mgrp->mcmember_rec.mtu & 0x3F); + if (mtu_required < mtu_mgrp) + { + osm_log( p_log, OSM_LOG_DEBUG, + "__validate_port_caps: " + "Port's MTU %x is less than %x\n", + mtu_required, mtu_mgrp ); + return FALSE; + } + + rate_required = ib_port_info_compute_rate(p_pi); + rate_mgrp = (uint8_t)(p_mgrp->mcmember_rec.rate & 0x3F); + if (rate_required < rate_mgrp) + { + osm_log( p_log, OSM_LOG_DEBUG, + "__validate_port_caps: " + "Port's RATE %x is less than %x\n", + rate_required, rate_mgrp ); + return FALSE; + } + + return TRUE; +} + +/********************************************************************** + * o15-0.2.1: If SA supports UD multicast, then if SA receives a SubnAdmSet() + * or SubnAdmDelete() method that would modify an existing + * MCMemberRecord, SA shall not modify that MCMemberRecord and shall + * return an error status of ERR_REQ_INVALID in response in the + * following cases: + * 1. Saved MCMemberRecord.ProxyJoin is not set and the request is + * issued by a requester with a GID other than the Port-GID. + * 2. Saved MCMemberRecord.ProxyJoin is set and the requester is not + * part of the partition for that MCMemberRecord. + **********************************************************************/ +static boolean_t +__validate_modify(IN osm_mcmr_recv_t* const p_rcv, + IN osm_mgrp_t* p_mgrp, + IN osm_mad_addr_t* p_mad_addr, + IN ib_member_rec_t* p_recvd_mcmember_rec, + OUT osm_mcm_port_t **pp_mcm_port) +{ + ib_net64_t portguid; + ib_gid_t request_gid; + osm_physp_t* p_request_physp; + ib_api_status_t res; + + portguid = p_recvd_mcmember_rec->port_gid.unicast.interface_id; + + *pp_mcm_port = NULL; + + /* o15-0.2.1: If this is a new port being added - nothing to check */ + if (!osm_mgrp_is_port_present(p_mgrp, portguid, pp_mcm_port)) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__validate_modify: " + "This is a new port in the MC group\n" ); + return TRUE; + } + + /* We validate the request according the the proxy_join. + Check if the proxy_join is set or not */ + if ( (*pp_mcm_port)->proxy_join == FALSE ) + { + /* The proxy_join is not set. Modifying can by done only + if the requester GID == PortGID */ + res = osm_get_gid_by_mad_addr(p_rcv->p_log, + p_rcv->p_subn, + p_mad_addr, + &request_gid); + + if ( res != IB_SUCCESS ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__validate_modify: " + "Could not find port for requested address\n" + ); + return FALSE; + } + + if (memcmp(&((*pp_mcm_port)->port_gid), &request_gid, sizeof(ib_gid_t))) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__validate_modify: " + "No ProxyJoin but different ports: stored:0x%016"PRIx64 + " request:0x%016"PRIx64"\n", + cl_ntoh64((*pp_mcm_port)->port_gid.unicast.interface_id), + cl_ntoh64(p_mad_addr->addr_type.gsi.grh_info.src_gid.unicast.interface_id) + ); + return FALSE; + } + } + else + { + /* the proxy_join is set. Modification allowed only if the + requester is part of the partition for this MCMemberRecord */ + p_request_physp = osm_get_physp_by_mad_addr(p_rcv->p_log, + p_rcv->p_subn, + p_mad_addr); + if (p_request_physp == NULL) + return FALSE; + + if (!osm_physp_has_pkey(p_rcv->p_log, p_mgrp->mcmember_rec.pkey, + p_request_physp)) + { + /* the request port is not part of the partition for this mgrp */ + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__validate_modify: " + "ProxyJoin but port not in partition. stored:0x%016"PRIx64 + " request:0x%016"PRIx64"\n", + cl_ntoh64((*pp_mcm_port)->port_gid.unicast.interface_id), + cl_ntoh64(p_mad_addr->addr_type.gsi.grh_info.src_gid.unicast.interface_id) + ); + return FALSE; + } + } + return TRUE; +} + +/********************************************************************** + **********************************************************************/ +/* + * Check legality of the requested MGID DELETE + * o15-0.1.14 = VALID DELETE: + * To be a valid delete MAD needs to: + * 1 the MADs PortGID and MGID components match the PortGID and + * MGID of a stored MCMemberRecord; + * 2 the MADs JoinState component contains at least one bit set to 1 + * in the same position as that stored MCMemberRecords JoinState + * has a bit set to 1, + * i.e., the logical AND of the two JoinState components + * is not all zeros; + * 3 the MADs JoinState component does not have some bits set + * which are not set in the stored MCMemberRecords JoinState component; + * 4 either the stored MCMemberRecord:ProxyJoin is reset (0), and the + * MADs source is the stored PortGID; + * OR + * the stored MCMemberRecord:ProxyJoin is set (1), (see o15- + * 0.1.2:); and the MADs source is a member of the partition indicated + * by the stored MCMemberRecord:P_Key. + */ +static boolean_t +__validate_delete(IN osm_mcmr_recv_t* const p_rcv, + IN osm_mgrp_t *p_mgrp, + IN osm_mad_addr_t* p_mad_addr, + IN ib_member_rec_t* p_recvd_mcmember_rec, + OUT osm_mcm_port_t **pp_mcm_port) +{ + ib_net64_t portguid; + + portguid = p_recvd_mcmember_rec->port_gid.unicast.interface_id; + + *pp_mcm_port = NULL; + + /* 1 */ + if (!osm_mgrp_is_port_present(p_mgrp, portguid, pp_mcm_port)) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__validate_delete: " + "Failed to find the port in the MC group\n" ); + return FALSE; + } + + /* 2 */ + if (!(p_recvd_mcmember_rec->scope_state & 0x0F & + (*pp_mcm_port)->scope_state)) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__validate_delete: " + "Could not find any matching bits in the stored and requested JoinStates\n" ); + return FALSE; + } + + /* 3 */ + if ( ((p_recvd_mcmember_rec->scope_state & 0x0F) | + (0x0F & (*pp_mcm_port)->scope_state)) != + (0x0F & (*pp_mcm_port)->scope_state)) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__validate_delete: " + "Some bits in the request JoinState (0x%X) are not set in the stored port (0x%X)\n", + (p_recvd_mcmember_rec->scope_state & 0x0F), + (0x0F & (*pp_mcm_port)->scope_state) + ); + return FALSE; + } + + /* 4 */ + /* Validate according the the proxy_join (o15-0.1.2) */ + if ( __validate_modify( p_rcv, p_mgrp, p_mad_addr, p_recvd_mcmember_rec, + pp_mcm_port ) == FALSE ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__validate_delete: " + "proxy_join validation failure\n" ); + return FALSE; + } + return TRUE; +} + +/********************************************************************** + **********************************************************************/ +/* + * Check legality of the requested MGID (note this does not hold for SA + * created MGIDs) + * + * Implementing o15-0.1.5: + * A multicast GID is considered to be invalid if: + * 1. It does not comply with the rules as specified in 4.1.1 "GID Usage and + * Properties" on page 145: + * + * 14) The multicast GID format is (bytes are comma sep): + * 0xff,,,,

,

,

,

,

,

,

,

,,,, + * Fl 4bit = Flags (b) + * Sc 4bit = Scope (c) + * Si 16bit = Signature (2) + * P 64bit = GID Prefix (should be a subnet unique ID - normally Subnet Prefix) + * Id 32bit = Unique ID in the Subnet (might be MLID or Pkey ?) + * + * a) 8-bits of 11111111 at the start of the GID identifies this as being a + * multicast GID. + * b) Flags is a set of four 1-bit flags: 000T with three flags reserved + * and defined as zero (0). The T flag is defined as follows: + * i) T = 0 indicates this is a permanently assigned (i.e. wellknown) + * multicast GID. See RFC 2373 and RFC 2375 as reference + * for these permanently assigned GIDs. + * ii) T = 1 indicates this is a non-permanently assigned (i.e. transient) + * multicast GID. + * c) Scope is a 4-bit multicast scope value used to limit the scope of + * the multicast group. The following table defines scope value and + * interpretation. + * + * Multicast Address Scope Values: + * 0x2 Link-local + * 0x5 Site-local + * 0x8 Organization-local + * 0xE Global + * + * 2. It contains the SA-specific signature of 0xA01B and has the link-local + * scope bits set. (EZ: the idea here is that SA created MGIDs are the + * only source for this signature with link-local scope) + */ +ib_api_status_t +__validate_requested_mgid(IN osm_mcmr_recv_t* const p_rcv, + IN const ib_member_rec_t* p_mcm_rec) +{ + uint16_t signature; + boolean_t valid = TRUE; + + OSM_LOG_ENTER( p_rcv->p_log, __validate_requested_mgid ); + + /* 14-a: mcast GID must start with 0xFF */ + if (p_mcm_rec->mgid.multicast.header[0] != 0xFF) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__validate_requested_mgid: ERR 1B01: " + "Wrong MGID Prefix 0x%02X must be 0xFF\n", + cl_ntoh16(p_mcm_rec->mgid.multicast.header[0]) + ); + valid = FALSE; + goto Exit; + } + + /* the MGID signature can mark IPoIB or SA assigned MGIDs */ + memcpy(&signature, &(p_mcm_rec->mgid.multicast.raw_group_id), sizeof(signature)); + signature = cl_ntoh16(signature); + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__validate_requested_mgid: " + "MGID Signed as 0x%04X\n", + signature + ); + + /* + * We skip any checks for MGIDs that follow IPoIB + * GID structure as defined by the IETF ipoib-link-multicast. + * + * For IPv4 over IB, the signature will be "0x401B". + * + * | 8 | 4 | 4 | 16 bits | 16 bits | 48 bits | 32 bits | + * +--------+----+----+-----------------+---------+----------+---------+ + * |11111111|0001|scop||< P_Key >|00.......0|| + * +--------+----+----+-----------------+---------+----------+---------+ + * + * For IPv6 over IB, the signature will be "0x601B". + * + * | 8 | 4 | 4 | 16 bits | 16 bits | 80 bits | + * +--------+----+----+-----------------+---------+--------------------+ + * |11111111|0001|scop||< P_Key >|000.............0001| + * +--------+----+----+-----------------+---------+--------------------+ + * + */ + if (signature == 0x401B || signature == 0x601B) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__validate_requested_mgid: " + "Skipping MGID Validation for IPoIB Signed (0x%04X) MGIDs\n", + signature + ); + goto Exit; + } + + /* 14-b: the 3 upper bits in the "flags" should be zero: */ + if ( p_mcm_rec->mgid.multicast.header[1] & 0xE0 ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__validate_requested_mgid: ERR 1B28: " + "MGID uses Reserved Flags: flags=0x%X\n", + (p_mcm_rec->mgid.multicast.header[1] & 0xE0) >> 4 + ); + valid = FALSE; + goto Exit; + } + + /* 2 - now what if the link local format 0xA01B is used - + the scope should not be link local */ + if ( ( signature == 0xA01B ) && + ((p_mcm_rec->mgid.multicast.header[1] & 0x0F) == MC_SCOPE_LINK_LOCAL) ) { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__validate_requested_mgid: ERR 1B24: " + "MGID uses 0xA01B signature but with link-local scope\n" ); + valid = FALSE; + goto Exit; + } + + /* + * For SA assigned MGIDs (signature 0xA01B): + * There is no real way to make sure the Unique MGID Prefix is really unique. + * If we could enforce using the Subnet Prefix for that purpose it would + * have been nice. But the spec does not require it. + */ + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); + return (valid); +} + +/********************************************************************** + Check if the requested new MC group parameters are realizable. + Also set the default MTU and Rate if not provided by the user. +**********************************************************************/ +boolean_t +__mgrp_request_is_realizable( + IN osm_mcmr_recv_t* const p_rcv, + IN ib_net64_t comp_mask, + IN ib_member_rec_t * p_mcm_rec, + IN const osm_physp_t* const p_physp) +{ + uint8_t mtu_sel = 2; /* exactly */ + uint8_t mtu_required, mtu, port_mtu; + uint8_t rate_sel = 2; /* exactly */ + uint8_t rate_required, rate, port_rate; + osm_log_t *p_log = p_rcv->p_log; + ib_port_info_t *p_pi = NULL; + + OSM_LOG_ENTER( p_rcv->p_log, __mgrp_request_is_realizable ); + + if (p_physp != NULL) + p_pi = osm_physp_get_port_info_ptr(p_physp); + + /* + * End of o15-0.2.3 specifies: + * .... + * The entity may also supply the other components such as HopLimit, MTU, + * etc. during group creation time. If these components are not provided + * during group creation time, SA will provide them for the group. The values + * chosen are vendor-dependent and beyond the scope of the specification. + * + * so we might also need to assign RATE/MTU if they are not comp masked in. + */ + + port_mtu = p_pi ? ib_port_info_get_mtu_cap(p_pi) : 0; + if (!(comp_mask & IB_MCR_COMPMASK_MTU) || + !(comp_mask & IB_MCR_COMPMASK_MTU_SEL) || + (mtu_sel = (p_mcm_rec->mtu >> 6)) == 3) + mtu = port_mtu ? port_mtu : p_rcv->p_subn->min_ca_mtu; + else + { + mtu_required = (uint8_t)(p_mcm_rec->mtu & 0x3F); + mtu = mtu_required; + switch (mtu_sel) + { + case 0: /* Greater than MTU specified */ + if (port_mtu && mtu_required >= port_mtu) + { + osm_log( p_log, OSM_LOG_DEBUG, + "__mgrp_request_is_realizable: " + "Requested MTU %x >= the port\'s mtu:%x\n", + mtu_required, port_mtu ); + return FALSE; + } + /* we provide the largest MTU possible if we can */ + if (port_mtu) + mtu = port_mtu; + else if (mtu_required < p_rcv->p_subn->min_ca_mtu) + mtu = p_rcv->p_subn->min_ca_mtu; + else + mtu++; + break; + case 1: /* Less than MTU specified */ + /* use the smaller of the two: + a. one lower then the required + b. the mtu of the requesting port (if exists) */ + if (port_mtu && mtu_required > port_mtu) + mtu = port_mtu; + else + mtu--; + break; + case 2: /* Exactly MTU specified */ + default: + break; + } + /* make sure it still be in the range */ + if (mtu < IB_MIN_MTU || mtu > IB_MAX_MTU) + { + osm_log( p_log, OSM_LOG_DEBUG, + "__mgrp_request_is_realizable: " + "Calculated MTU %x is out of range\n", + mtu ); + return FALSE; + } + } + p_mcm_rec->mtu = (mtu_sel<<6) | mtu; + + port_rate = p_pi ? ib_port_info_compute_rate(p_pi) : 0; + if (!(comp_mask & IB_MCR_COMPMASK_RATE) || + !(comp_mask & IB_MCR_COMPMASK_RATE_SEL) || + (rate_sel = (p_mcm_rec->rate >> 6)) == 3) + rate = port_rate ? port_rate : p_rcv->p_subn->min_ca_rate; + else + { + rate_required = (uint8_t)(p_mcm_rec->rate & 0x3F); + rate = rate_required; + switch (rate_sel) + { + case 0: /* Greater than RATE specified */ + if (port_rate && rate_required >= port_rate) + { + osm_log( p_log, OSM_LOG_DEBUG, + "__mgrp_request_is_realizable: " + "Requested RATE %x >= the port\'s rate:%x\n", + rate_required, port_rate ); + return FALSE; + } + /* we provide the largest RATE possible if we can */ + if (port_rate) + rate = port_rate; + else if (rate_required < p_rcv->p_subn->min_ca_rate) + rate = p_rcv->p_subn->min_ca_rate; + else + rate++; + break; + case 1: /* Less than RATE specified */ + /* use the smaller of the two: + a. one lower then the required + b. the rate of the requesting port (if exists) */ + if (port_rate && rate_required > port_rate) + rate = port_rate; + else + rate--; + break; + case 2: /* Exactly RATE specified */ + default: + break; + } + /* make sure it still is in the range */ + if (rate < IB_MIN_RATE || rate > IB_MAX_RATE) + { + osm_log( p_log, OSM_LOG_DEBUG, + "__mgrp_request_is_realizable: " + "Calculated RATE %x is out of range\n", + rate ); + return FALSE; + } + } + p_mcm_rec->rate = (rate_sel<<6) | rate; + + OSM_LOG_EXIT( p_rcv->p_log ); + return TRUE; +} + +/********************************************************************** + Call this function to find or create a new mgrp. +**********************************************************************/ +ib_api_status_t +osm_mcmr_rcv_find_or_create_new_mgrp( + IN osm_mcmr_recv_t* const p_rcv, + IN ib_net64_t comp_mask, + IN ib_member_rec_t* const p_recvd_mcmember_rec, + OUT osm_mgrp_t **pp_mgrp) +{ + ib_api_status_t status; + + status = __get_mgrp_by_mgid(p_rcv, p_recvd_mcmember_rec, pp_mgrp); + if (status == IB_SUCCESS) + return status; + return osm_mcmr_rcv_create_new_mgrp(p_rcv, comp_mask, + p_recvd_mcmember_rec, NULL, pp_mgrp); +} + +/********************************************************************** + Call this function to create a new mgrp. +**********************************************************************/ +ib_api_status_t +osm_mcmr_rcv_create_new_mgrp( + IN osm_mcmr_recv_t* const p_rcv, + IN ib_net64_t comp_mask, + IN const ib_member_rec_t* const p_recvd_mcmember_rec, + IN const osm_physp_t* const p_physp, + OUT osm_mgrp_t **pp_mgrp) +{ + ib_net16_t mlid; + uint8_t zero_mgid, valid; + uint8_t scope, i; + ib_gid_t *p_mgid; + osm_mgrp_t *p_prev_mgrp; + ib_api_status_t status = IB_SUCCESS; + ib_member_rec_t mcm_rec = *p_recvd_mcmember_rec; /* copy for modifications */ + + OSM_LOG_ENTER( p_rcv->p_log, osm_mcmr_rcv_create_new_mgrp ); + + /* but what if the given MGID was not 0 ? */ + zero_mgid = 1; + for ( i = 0 ; i < sizeof(p_recvd_mcmember_rec->mgid); i++ ) + { + if (p_recvd_mcmember_rec->mgid.raw[i] != 0) + { + zero_mgid = 0; + break; + } + } + + /* + we allocate a new mlid number before we might use it + for MGID ... + */ + mlid = __get_new_mlid(p_rcv, mcm_rec.mlid); + if ( mlid == 0 ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_mcmr_rcv_create_new_mgrp: ERR 1B19: " + "__get_new_mlid failed\n" ); + status = IB_SA_MAD_STATUS_NO_RESOURCES; + goto Exit; + } + + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "osm_mcmr_rcv_create_new_mgrp: " + "Obtained new mlid 0x%X\n", cl_ntoh16(mlid) ); + + /* we need to create the new MGID if it was not defined */ + if (zero_mgid) + { + /* create a new MGID */ + + /* use the given scope state only if requested! */ + if (comp_mask & IB_MCR_COMPMASK_SCOPE) + { + ib_member_get_scope_state( + p_recvd_mcmember_rec->scope_state, &scope, NULL); + } + else + { + /* to guarantee no collision with other subnets use local scope! */ + scope = MC_SCOPE_LINK_LOCAL; + } + + p_mgid = &(mcm_rec.mgid); + p_mgid->raw[0] = 0xFF; + p_mgid->raw[1] = 0x10 | scope; + p_mgid->raw[2] = 0xA0; + p_mgid->raw[3] = 0x1B; + + /* HACK: use the SA port gid to make it globally unique */ + memcpy((&p_mgid->raw[4]), + &p_rcv->p_subn->opt.subnet_prefix, sizeof(uint64_t)); + + /* HACK: how do we get a unique number - use the mlid twice */ + memcpy(&p_mgid->raw[10], &mlid, sizeof(uint16_t)); + memcpy(&p_mgid->raw[12], &mlid, sizeof(uint16_t)); + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "osm_mcmr_rcv_create_new_mgrp: " + "Allocated new MGID:0x%016" PRIx64 " : " + "0x%016" PRIx64 "\n", + cl_ntoh64(p_mgid->unicast.prefix), + cl_ntoh64(p_mgid->unicast.interface_id) ); + } + else + { + /* a specific MGID was requested so validate the resulting MGID */ + valid = __validate_requested_mgid(p_rcv, &mcm_rec); + if (!valid) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_mcmr_rcv_create_new_mgrp: ERR 1B22: " + "Invalid requested MGID\n" ); + __free_mlid(p_rcv, mlid); + status = IB_SA_MAD_STATUS_REQ_INVALID; + goto Exit; + } + } + + /* check the requested parameters are realizable */ + if (__mgrp_request_is_realizable(p_rcv, comp_mask, &mcm_rec, p_physp) == FALSE) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_mcmr_rcv_create_new_mgrp: ERR 1B26: " + "Requested MGRP parameters are not realizable\n" ); + __free_mlid(p_rcv, mlid); + status = IB_SA_MAD_STATUS_REQ_INVALID; + goto Exit; + } + + /* create a new MC Group */ + *pp_mgrp = osm_mgrp_new(mlid); + if (*pp_mgrp == NULL) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_mcmr_rcv_create_new_mgrp: ERR 1B08: " + "osm_mgrp_new failed\n" ); + __free_mlid(p_rcv, mlid); + status = IB_SA_MAD_STATUS_NO_RESOURCES; + goto Exit; + } + + /* Initialize the mgrp */ + (*pp_mgrp)->mcmember_rec = mcm_rec; + (*pp_mgrp)->mcmember_rec.mlid = mlid; + + /* the mcmember_record should have mtu_sel, rate_sel, and pkt_lifetime_sel = 2 */ + (*pp_mgrp)->mcmember_rec.mtu &= 0x3f; + (*pp_mgrp)->mcmember_rec.mtu |= 2<<6; /* exactly */ + (*pp_mgrp)->mcmember_rec.rate &= 0x3f; + (*pp_mgrp)->mcmember_rec.rate |= 2<<6; /* exactly */ + (*pp_mgrp)->mcmember_rec.pkt_life &= 0x3f; + (*pp_mgrp)->mcmember_rec.pkt_life |= 2<<6; /* exactly */ + + /* Insert the new group in the data base */ + + /* since we might have an old group by that mlid + one whose deletion was delayed for an idle time + we need to deallocate it first */ + p_prev_mgrp = (osm_mgrp_t *)cl_qmap_get(&p_rcv->p_subn->mgrp_mlid_tbl, mlid); + if (p_prev_mgrp != (osm_mgrp_t *)cl_qmap_end(&p_rcv->p_subn->mgrp_mlid_tbl)) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "osm_mcmr_rcv_create_new_mgrp: " + "Found previous group for mlid:0x%04x - Need to destroy it\n", + cl_ntoh16(mlid) ); + cl_qmap_remove_item(&p_rcv->p_subn->mgrp_mlid_tbl, + (cl_map_item_t *)p_prev_mgrp ); + osm_mgrp_destroy( p_prev_mgrp ); + } + + cl_qmap_insert(&p_rcv->p_subn->mgrp_mlid_tbl, + mlid, + &(*pp_mgrp)->map_item); + + /* Send a Report to any InformInfo registerd for + Trap 66: MCGroup create */ + osm_mgrp_send_create_notice(p_rcv->p_subn, p_rcv->p_log, *pp_mgrp); + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); + return status; + +} + +/********************************************************************* +Process a request for leaving the group +**********************************************************************/ +static void +__osm_mcmr_rcv_leave_mgrp( + IN osm_mcmr_recv_t* const p_rcv, + IN const osm_madw_t* const p_madw ) +{ + boolean_t valid; + osm_mgrp_t *p_mgrp; + ib_api_status_t status; + ib_sa_mad_t *p_sa_mad; + ib_member_rec_t*p_recvd_mcmember_rec; + ib_member_rec_t mcmember_rec; + ib_net16_t mlid; + ib_net16_t sa_status; + ib_net64_t portguid; + osm_mcm_port_t *p_mcm_port; + uint8_t port_join_state; + uint8_t new_join_state; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_mcmr_rcv_leave_mgrp ); + + p_mgrp = NULL; + p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw ); + p_recvd_mcmember_rec = + (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad ); + + mcmember_rec = *p_recvd_mcmember_rec; + + if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_mcmr_rcv_leave_mgrp: Dump of record\n" ); + osm_dump_mc_record( p_rcv->p_log, &mcmember_rec, OSM_LOG_DEBUG ); + } + + CL_PLOCK_EXCL_ACQUIRE(p_rcv->p_lock); + status = __get_mgrp_by_mgid(p_rcv,p_recvd_mcmember_rec, &p_mgrp); + if (status == IB_SUCCESS) + { + mlid = p_mgrp->mlid; + portguid = p_recvd_mcmember_rec->port_gid.unicast.interface_id; + + /* check validity of the delete request o15-0.1.14 */ + valid = __validate_delete(p_rcv, + p_mgrp, + osm_madw_get_mad_addr_ptr(p_madw), + p_recvd_mcmember_rec, + &p_mcm_port); + + if (valid) + { + /* + * according to the same o15-0.1.14 we get the stored JoinState and the + * request JoinState and they must be opposite to leave - + * otherwise just update it + */ + port_join_state = p_mcm_port->scope_state & 0x0F; + new_join_state = + port_join_state & ~(p_recvd_mcmember_rec->scope_state & 0x0F); + if (new_join_state) + { + /* Just update the result JoinState */ + p_mcm_port->scope_state = + new_join_state | (p_mcm_port->scope_state & 0xf0); + + mcmember_rec.scope_state = p_mcm_port->scope_state; + + CL_PLOCK_RELEASE( p_rcv->p_lock ); + + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_mcmr_rcv_leave_mgrp: " + "After update JoinState != 0. Updating from 0x%X to 0x%X\n", + port_join_state, + new_join_state + ); + } + else + { + /* we need to return the stored scope state */ + mcmember_rec.scope_state = p_mcm_port->scope_state; + + /* OK we can leave */ + /* note: osm_sm_mcgrp_leave() will release p_rcv->p_lock */ + + status = osm_sm_mcgrp_leave(p_rcv->p_sm, mlid, portguid); + if(status != IB_SUCCESS) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_mcmr_rcv_leave_mgrp: ERR 1B09: " + "osm_sm_mcgrp_leave failed\n" ); + } + } + } + else + { + CL_PLOCK_RELEASE( p_rcv->p_lock ); + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_mcmr_rcv_leave_mgrp: ERR 1B25: " + "Received an invalid delete request for " + "MGID: 0x%016" PRIx64 " : " + "0x%016" PRIx64 " for " + "PortGID: 0x%016" PRIx64 " : " + "0x%016" PRIx64 "\n", + cl_ntoh64( p_recvd_mcmember_rec->mgid.unicast.prefix ), + cl_ntoh64( p_recvd_mcmember_rec->mgid.unicast.interface_id ), + cl_ntoh64( p_recvd_mcmember_rec->port_gid.unicast.prefix ), + cl_ntoh64( p_recvd_mcmember_rec->port_gid.unicast.interface_id ) ); + sa_status = IB_SA_MAD_STATUS_REQ_INVALID; + osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status ); + goto Exit; + } + } + else + { + CL_PLOCK_RELEASE( p_rcv->p_lock ); + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_mcmr_rcv_leave_mgrp: " + "Failed since multicast group not present\n" ); + sa_status = IB_SA_MAD_STATUS_REQ_INVALID; + osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status ); + goto Exit; + } + + /* Send an SA response */ + __osm_mcmr_rcv_respond( p_rcv, p_madw, &mcmember_rec ); + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); + return; +} + +/********************************************************************** + Handle a join (or create) request +**********************************************************************/ +static void +__osm_mcmr_rcv_join_mgrp( + IN osm_mcmr_recv_t* const p_rcv, + IN const osm_madw_t* const p_madw ) +{ + boolean_t valid; + osm_mgrp_t *p_mgrp = NULL; + ib_api_status_t status; + ib_sa_mad_t *p_sa_mad; + ib_member_rec_t*p_recvd_mcmember_rec; + ib_member_rec_t mcmember_rec; + ib_net16_t sa_status; + ib_net16_t mlid; + osm_mcm_port_t *p_mcmr_port; + ib_net64_t portguid; + osm_port_t * p_port; + osm_physp_t* p_physp; + osm_physp_t* p_request_physp; + uint8_t is_new_group; /* TRUE = there is a need to create a group */ + osm_mcast_req_type_t req_type; + uint8_t join_state; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_mcmr_rcv_join_mgrp ); + + p_mgrp = NULL; + p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw ); + p_recvd_mcmember_rec = + (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad ); + + portguid = p_recvd_mcmember_rec->port_gid.unicast.interface_id; + + mcmember_rec = *p_recvd_mcmember_rec; + + if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_mcmr_rcv_join_mgrp: " + "Dump of incoming record\n" ); + osm_dump_mc_record( p_rcv->p_log, &mcmember_rec, OSM_LOG_DEBUG ); + } + + CL_PLOCK_EXCL_ACQUIRE(p_rcv->p_lock); + + /* make sure the requested port guid is known to the SM */ + p_port = (osm_port_t *)cl_qmap_get(&p_rcv->p_subn->port_guid_tbl, + portguid); + + if (p_port == (osm_port_t *)cl_qmap_end(&p_rcv->p_subn->port_guid_tbl)) + { + CL_PLOCK_RELEASE( p_rcv->p_lock ); + + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_mcmr_rcv_join_mgrp: " + "Unknown port GUID 0x%016" PRIx64 "\n", + portguid ); + sa_status = IB_SA_MAD_STATUS_REQ_INVALID; + osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status ); + goto Exit; + } + + p_physp = osm_port_get_default_phys_ptr(p_port); + /* Check that the p_physp and the requester physp are in the same + partition. */ + p_request_physp = + osm_get_physp_by_mad_addr(p_rcv->p_log, + p_rcv->p_subn, + osm_madw_get_mad_addr_ptr(p_madw) ); + if (p_request_physp == NULL) + { + CL_PLOCK_RELEASE( p_rcv->p_lock ); + goto Exit; + } + + if (!osm_physp_share_pkey( p_rcv->p_log, p_physp, p_request_physp)) + { + CL_PLOCK_RELEASE( p_rcv->p_lock ); + + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_mcmr_rcv_join_mgrp: " + "Port and requester don't share pkey\n" ); + sa_status = IB_SA_MAD_STATUS_REQ_INVALID; + osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status ); + goto Exit; + } + + ib_member_get_scope_state( + p_recvd_mcmember_rec->scope_state, NULL, &join_state); + + /* do we need to create a new group? */ + status = __get_mgrp_by_mgid(p_rcv, p_recvd_mcmember_rec, &p_mgrp); + if ((status == IB_NOT_FOUND) || p_mgrp->to_be_deleted) + { + /* check for JoinState.FullMember = 1 o15.0.1.9 */ + if ((join_state & 0x01) != 0x01) + { + CL_PLOCK_RELEASE( p_rcv->p_lock ); + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_mcmr_rcv_join_mgrp: ERR 1B10: " + "Provided Join State != FullMember - required for create, " + "MGID: 0x%016" PRIx64 " : " + "0x%016" PRIx64 "\n", + cl_ntoh64( p_recvd_mcmember_rec->mgid.unicast.prefix ), + cl_ntoh64( p_recvd_mcmember_rec->mgid.unicast.interface_id ) ); + sa_status = IB_SA_MAD_STATUS_REQ_INVALID; + osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status ); + goto Exit; + } + + /* check for the comp_mask */ + valid = __check_create_comp_mask(p_sa_mad->comp_mask, + p_recvd_mcmember_rec); + if (valid) + { + status = osm_mcmr_rcv_create_new_mgrp(p_rcv, + p_sa_mad->comp_mask, + p_recvd_mcmember_rec, + p_physp, + &p_mgrp); + if (status != IB_SUCCESS) + { + CL_PLOCK_RELEASE( p_rcv->p_lock ); + sa_status = status; + osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status ); + goto Exit; + } + /* copy the MGID to the result */ + mcmember_rec.mgid = p_mgrp->mcmember_rec.mgid; + } + else + { + CL_PLOCK_RELEASE( p_rcv->p_lock ); + + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_mcmr_rcv_join_mgrp: ERR 1B11: " + "method = %s, " + "scope_state = 0x%x, " + "component mask = 0x%016" PRIx64 ", " + "expected comp mask = 0x%016" PRIx64 ", " + "MGID: 0x%016" PRIx64 " : " + "0x%016" PRIx64 " from port 0x%016" PRIx64 "\n", + ib_get_sa_method_str(p_sa_mad->method), + p_recvd_mcmember_rec->scope_state, + cl_ntoh64(p_sa_mad->comp_mask), + CL_NTOH64(REQUIRED_MC_CREATE_COMP_MASK), + cl_ntoh64( p_recvd_mcmember_rec->mgid.unicast.prefix ), + cl_ntoh64( p_recvd_mcmember_rec->mgid.unicast.interface_id ), + cl_ntoh64( portguid ) ); + + sa_status = IB_SA_MAD_STATUS_INSUF_COMPS; + osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status ); + goto Exit; + } + is_new_group = 1; + req_type = OSM_MCAST_REQ_TYPE_CREATE; + } + else + { + /* no need for a new group */ + is_new_group = 0; + req_type = OSM_MCAST_REQ_TYPE_JOIN; + } + + CL_ASSERT(p_mgrp); + mlid = p_mgrp->mlid; + + /* + * o15-0.2.4: If SA supports UD multicast, then SA shall cause an + * endport to join an existing multicast group if: + * 1. It receives a SubnAdmSet() method for a MCMemberRecord, and + * - WE KNOW THAT ALREADY + * 2. The MGID is specified and matches an existing multicast + * group, and + * - WE KNOW THAT ALREADY + * 3. The MCMemberRecord:JoinState is not all 0s, and + * 4. PortGID is specified and + * - WE KNOW THAT ALREADY (as it matched a real one) + * 5. All other components match that existing group, either by + * being wildcarded or by having values identical to those specified + * by the component mask and in use by the group with the exception + * of components such as ProxyJoin and Reserved, which are ignored + * by SA. + * + * We need to check #3 and #5 here: + */ + valid = __validate_more_comp_fields( + p_rcv->p_log, + p_mgrp, + p_recvd_mcmember_rec, + p_sa_mad->comp_mask) && __validate_port_caps( + p_rcv->p_log, + p_mgrp, + p_physp) && (join_state != 0); + + if (!valid) + { + /* since we might have created the new group we need to cleanup */ + __cleanup_mgrp(p_rcv, mlid); + + CL_PLOCK_RELEASE( p_rcv->p_lock ); + + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_mcmr_rcv_join_mgrp: ERR 1B12: " + "__validate_more_comp_fields, __validate_port_caps, " + "or JoinState = 0 failed from port 0x%016" PRIx64 ", " + "sending IB_SA_MAD_STATUS_REQ_INVALID\n", + cl_ntoh64( portguid ) ); + + sa_status = IB_SA_MAD_STATUS_REQ_INVALID; + osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status ); + goto Exit; + } + + /* + * Do some validation of the modification + */ + if (!is_new_group) + { + /* + * o15-0.2.1 requires validation of the requesting port + * in the case of modification: + */ + valid = __validate_modify(p_rcv, + p_mgrp, + osm_madw_get_mad_addr_ptr(p_madw), + p_recvd_mcmember_rec, + &p_mcmr_port); + if (!valid) + { + CL_PLOCK_RELEASE( p_rcv->p_lock ); + + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_mcmr_rcv_join_mgrp: ERR 1B13: " + "__validate_modify failed, " + "sending IB_SA_MAD_STATUS_REQ_INVALID\n" ); + + sa_status = IB_SA_MAD_STATUS_REQ_INVALID; + osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status ); + goto Exit; + } + } + + /* create or update existing port (join-state will be updated) */ + status = __add_new_mgrp_port( + p_rcv, + p_mgrp, + p_recvd_mcmember_rec, + osm_madw_get_mad_addr_ptr(p_madw), + &p_mcmr_port); + + if (status != IB_SUCCESS) + { + /* we fail to add the port so we might need to delete the group */ + __cleanup_mgrp(p_rcv, mlid); + + CL_PLOCK_RELEASE( p_rcv->p_lock ); + if (status == IB_INVALID_PARAMETER) + sa_status = IB_SA_MAD_STATUS_REQ_INVALID; + else + sa_status = IB_SA_MAD_STATUS_NO_RESOURCES; + + osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status ); + goto Exit; + } + + /* o15.0.1.11: copy the join state */ + mcmember_rec.scope_state = p_mcmr_port->scope_state; + + /* copy qkey mlid tclass pkey sl_flow_hop mtu rate pkt_life sl_flow_hop */ + __copy_from_create_mc_rec(&mcmember_rec, &p_mgrp->mcmember_rec); + + /* Release the lock as we don't need it. */ + CL_PLOCK_RELEASE( p_rcv->p_lock ); + + /* do the actual routing (actually schedule the update) */ + status = + osm_sm_mcgrp_join(p_rcv->p_sm, + mlid, + p_recvd_mcmember_rec->port_gid.unicast.interface_id, + req_type); + + if (status != IB_SUCCESS) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_mcmr_rcv_join_mgrp: ERR 1B14: " + "osm_sm_mcgrp_join failed, " + "sending IB_SA_MAD_STATUS_NO_RESOURCES\n" ); + + CL_PLOCK_EXCL_ACQUIRE(p_rcv->p_lock); + + /* the request for routing failed so we need to remove the port */ + p_mgrp = __get_mgrp_by_mlid(p_rcv, mlid); + if (p_mgrp != NULL) + { + osm_mgrp_remove_port( + p_rcv->p_subn, + p_rcv->p_log, + p_mgrp, + p_recvd_mcmember_rec->port_gid.unicast.interface_id); + __cleanup_mgrp(p_rcv, mlid); + } + CL_PLOCK_RELEASE( p_rcv->p_lock ); + sa_status = IB_SA_MAD_STATUS_NO_RESOURCES; + osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status ); + goto Exit; + + } /* failed to route */ + + if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + osm_dump_mc_record( p_rcv->p_log, &mcmember_rec, OSM_LOG_DEBUG ); + + __osm_mcmr_rcv_respond( p_rcv, p_madw, &mcmember_rec ); + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); + return; +} + +/********************************************************************** + Add a patched multicast group to the results list +**********************************************************************/ +static ib_api_status_t +__osm_mcmr_rcv_new_mcmr( + IN osm_mcmr_recv_t* const p_rcv, + IN const ib_member_rec_t* p_rcvd_rec, + IN cl_qlist_t* const p_list ) +{ + osm_mcmr_item_t* p_rec_item; + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_mcmr_rcv_new_mcmr ); + + p_rec_item = (osm_mcmr_item_t*)cl_qlock_pool_get( &p_rcv->pool ); + if( p_rec_item == NULL ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_mcmr_rcv_new_mcmr: ERR 1B15: " + "cl_qlock_pool_get failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + memset( &p_rec_item->rec, 0, sizeof( p_rec_item->rec ) ); + + /* HACK: Not trusted requesters should result with 0 Join + State, Port Guid, and Proxy */ + p_rec_item->rec = *p_rcvd_rec; + cl_qlist_insert_tail( p_list, (cl_list_item_t*)&p_rec_item->pool_item ); + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); + return( status ); +} + +/********************************************************************** + Match the given mgrp to the requested mcmr +**********************************************************************/ +void +__osm_sa_mcm_by_comp_mask_cb( + IN cl_map_item_t* const p_map_item, + IN void* context ) +{ + const osm_mgrp_t * const p_mgrp = (osm_mgrp_t *)p_map_item; + osm_sa_mcmr_search_ctxt_t* const p_ctxt = + (osm_sa_mcmr_search_ctxt_t *)context; + osm_mcmr_recv_t* const p_rcv = p_ctxt->p_rcv; + const ib_member_rec_t* p_rcvd_rec = p_ctxt->p_mcmember_rec; + const osm_physp_t* p_req_physp = p_ctxt->p_req_physp; + + /* since we might change scope_state */ + ib_member_rec_t match_rec; + ib_net64_t comp_mask = p_ctxt->comp_mask; + osm_mcm_port_t* p_mcm_port; + ib_net64_t portguid = p_rcvd_rec->port_gid.unicast.interface_id; + /* will be used for group or port info */ + uint8_t scope_state; + uint8_t scope_state_mask = 0; + cl_map_item_t *p_item; + ib_gid_t port_gid; + boolean_t proxy_join; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_mcm_by_comp_mask_cb ); + + osm_log(p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_sa_mcm_by_comp_mask_cb: " + "Checking mlid:0x%X\n", + cl_ntoh16(p_mgrp->mlid)); + + /* the group might be marked for deletion */ + if (p_mgrp->to_be_deleted) + { + osm_log(p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_sa_mcm_by_comp_mask_cb: " + "Group mlid:0x%X is marked to be deleted\n", + cl_ntoh16(p_mgrp->mlid)); + goto Exit; + } + + /* first try to eliminate the group by MGID, MLID, or P_Key */ + if ((IB_MCR_COMPMASK_MGID & comp_mask) && + memcmp(&p_rcvd_rec->mgid, &p_mgrp->mcmember_rec.mgid, sizeof(ib_gid_t))) + goto Exit; + + if ((IB_MCR_COMPMASK_MLID & comp_mask) && + memcmp(&p_rcvd_rec->mlid, &p_mgrp->mcmember_rec.mlid, sizeof(uint16_t))) + goto Exit; + + /* if the requester physical port doesn't have the pkey that is defined for + the group - exit. */ + if (!osm_physp_has_pkey( p_rcv->p_log, p_mgrp->mcmember_rec.pkey, + p_req_physp )) + goto Exit; + + /* now do the rest of the match */ + if ((IB_MCR_COMPMASK_QKEY & comp_mask) && + (p_rcvd_rec->qkey != p_mgrp->mcmember_rec.qkey)) + goto Exit; + + if ((IB_MCR_COMPMASK_PKEY & comp_mask) && + (p_rcvd_rec->pkey != p_mgrp->mcmember_rec.pkey)) + goto Exit; + + if ((IB_MCR_COMPMASK_TCLASS & comp_mask) && + (p_rcvd_rec->tclass != p_mgrp->mcmember_rec.tclass)) + goto Exit; + + /* check SL, Flow, and Hop limit */ + { + uint8_t mgrp_sl, query_sl; + uint32_t mgrp_flow, query_flow; + uint8_t mgrp_hop, query_hop; + + ib_member_get_sl_flow_hop(p_rcvd_rec->sl_flow_hop, + &query_sl, &query_flow, &query_hop); + + ib_member_get_sl_flow_hop(p_mgrp->mcmember_rec.sl_flow_hop, + &mgrp_sl, &mgrp_flow, &mgrp_hop); + + if (IB_MCR_COMPMASK_SL & comp_mask ) + if (query_sl != mgrp_sl) + goto Exit; + + if (IB_MCR_COMPMASK_FLOW & comp_mask) + if (query_flow != mgrp_flow) + goto Exit; + + if (IB_MCR_COMPMASK_HOP & comp_mask) + if (query_hop != mgrp_hop) + goto Exit; + } + + if ((IB_MCR_COMPMASK_PROXY & comp_mask) && + (p_rcvd_rec->proxy_join != p_mgrp->mcmember_rec.proxy_join)) + goto Exit; + + if (IB_MCR_COMPMASK_SCOPE & comp_mask) + scope_state_mask = 0xF0; + + if (IB_MCR_COMPMASK_JOIN_STATE & comp_mask) + scope_state_mask = scope_state_mask | 0x0F; + + /* need to validate mtu, rate, and pkt_lifetime fields. */ + if (__validate_more_comp_fields( p_rcv->p_log, + p_mgrp, + p_rcvd_rec, + comp_mask ) == FALSE) + goto Exit; + + /* Port specific fields */ + /* so did we get the PortGUID mask */ + if (IB_MCR_COMPMASK_PORT_GID & comp_mask) + { + /* try to find this port */ + if (osm_mgrp_is_port_present(p_mgrp, portguid, &p_mcm_port)) + { + scope_state = p_mcm_port->scope_state; + memcpy(&port_gid, &(p_mcm_port->port_gid), sizeof(ib_gid_t)); + proxy_join = p_mcm_port->proxy_join; + } + else + { + /* port not in group */ + goto Exit; + } + } + else + { + /* point to the group information */ + scope_state = p_mgrp->mcmember_rec.scope_state; + } + + /* Many MC records returned */ + if ( (p_ctxt->trusted_req == TRUE) && !(IB_MCR_COMPMASK_PORT_GID & comp_mask) ) + { + osm_log(p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_sa_mcm_by_comp_mask_cb: " + "Trusted req is TRUE and no specific port defined\n"); + + /* return all the ports that match in this MC group */ + p_item = cl_qmap_head(&(p_mgrp->mcm_port_tbl)); + while( p_item != cl_qmap_end(&(p_mgrp->mcm_port_tbl)) ) + { + p_mcm_port=(osm_mcm_port_t *)p_item; + + if ((scope_state_mask & p_rcvd_rec->scope_state) == + (scope_state_mask & p_mcm_port->scope_state)) + { + /* add to the list */ + match_rec = p_mgrp->mcmember_rec; + match_rec.scope_state = p_mcm_port->scope_state; + memcpy( &(match_rec.port_gid), &(p_mcm_port->port_gid), + sizeof(ib_gid_t)); + osm_log(p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_sa_mcm_by_comp_mask_cb: " + "Record of port_gid: 0x%016" PRIx64 "0x%016" PRIx64 + " in multicast_lid: 0x%X is returned\n", + cl_ntoh64(match_rec.port_gid.unicast.prefix), + cl_ntoh64(match_rec.port_gid.unicast.interface_id), + cl_ntoh16(p_mgrp->mlid) + ); + + match_rec.proxy_join = (uint8_t)(p_mcm_port->proxy_join); + + __osm_mcmr_rcv_new_mcmr(p_rcv, &match_rec, p_ctxt->p_list); + } + p_item = cl_qmap_next(p_item); + } + } + /* One MC record returned */ + else + { + if ((scope_state_mask & p_rcvd_rec->scope_state) != + (scope_state_mask & scope_state)) + goto Exit; + + /* add to the list */ + match_rec = p_mgrp->mcmember_rec; + match_rec.scope_state = scope_state; + memcpy(&(match_rec.port_gid), &port_gid, sizeof(ib_gid_t)); + match_rec.proxy_join = (uint8_t)proxy_join; + + __osm_mcmr_rcv_new_mcmr(p_rcv, &match_rec, p_ctxt->p_list); + } + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + Handle a query request +**********************************************************************/ +static void +__osm_mcmr_query_mgrp(IN osm_mcmr_recv_t* const p_rcv, + IN const osm_madw_t* const p_madw) +{ + const ib_sa_mad_t* p_rcvd_mad; + const ib_member_rec_t* p_rcvd_rec; + cl_qlist_t rec_list; + osm_madw_t* p_resp_madw; + ib_sa_mad_t* p_resp_sa_mad; + ib_member_rec_t* p_resp_rec; + uint32_t num_rec, pre_trim_num_rec; +#ifndef VENDOR_RMPP_SUPPORT + uint32_t trim_num_rec; +#endif + uint32_t i; + osm_sa_mcmr_search_ctxt_t context; + osm_mcmr_item_t* p_rec_item; + ib_api_status_t status; + ib_net64_t comp_mask; + osm_physp_t* p_req_physp; + boolean_t trusted_req; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_mcmr_query_mgrp ); + + p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw ); + p_rcvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad ); + comp_mask = p_rcvd_mad->comp_mask; + + /* + if sm_key is not zero and does not match we never get here + see main SA receiver + */ + trusted_req = (p_rcvd_mad->sm_key != 0); + + /* update the requester physical port. */ + p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log, + p_rcv->p_subn, + osm_madw_get_mad_addr_ptr(p_madw) ); + if (p_req_physp == NULL) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_mcmr_query_mgrp: ERR 1B04: " + "Cannot find requester physical port\n" ); + goto Exit; + } + + cl_qlist_init( &rec_list ); + + context.p_mcmember_rec = p_rcvd_rec; + context.p_list = &rec_list; + context.comp_mask = p_rcvd_mad->comp_mask; + context.p_rcv = p_rcv; + context.p_req_physp = p_req_physp; + context.trusted_req = trusted_req; + + CL_PLOCK_ACQUIRE( p_rcv->p_lock ); + + /* simply go over all MCGs and match */ + cl_qmap_apply_func( &p_rcv->p_subn->mgrp_mlid_tbl, + __osm_sa_mcm_by_comp_mask_cb, + &context); + + CL_PLOCK_RELEASE( p_rcv->p_lock ); + + num_rec = cl_qlist_count( &rec_list ); + + /* + * C15-0.1.30: + * If we do a SubnAdmGet and got more than one record it is an error ! + */ + if ( (p_rcvd_mad->method == IB_MAD_METHOD_GET) && + (num_rec > 1)) { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_mcmr_query_mgrp: ERR 1B05: " + "Got more than one record for SubnAdmGet (%u)\n", + num_rec ); + osm_sa_send_error( p_rcv->p_resp, p_madw, + IB_SA_MAD_STATUS_TOO_MANY_RECORDS ); + + /* need to set the mem free ... */ + p_rec_item = (osm_mcmr_item_t*)cl_qlist_remove_head( &rec_list ); + while( p_rec_item != (osm_mcmr_item_t*)cl_qlist_end( &rec_list ) ) + { + cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item ); + p_rec_item = (osm_mcmr_item_t*)cl_qlist_remove_head( &rec_list ); + } + + goto Exit; + } + + pre_trim_num_rec = num_rec; +#ifndef VENDOR_RMPP_SUPPORT + trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_member_rec_t); + if (trim_num_rec < num_rec) + { + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "__osm_mcmr_query_mgrp: " + "Number of records:%u trimmed to:%u to fit in one MAD\n", + num_rec, trim_num_rec ); + num_rec = trim_num_rec; + } +#endif + + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_mcmr_query_mgrp: " + "Returning %u records\n", num_rec ); + + if ((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0)) + { + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS ); + goto Exit; + } + + /* + * Get a MAD to reply. Address of Mad is in the received mad_wrapper + */ + p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool, + p_madw->h_bind, + num_rec * sizeof(ib_member_rec_t) + IB_SA_MAD_HDR_SIZE, + osm_madw_get_mad_addr_ptr(p_madw) ); + + if( !p_resp_madw ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_mcmr_query_mgrp: ERR 1B16: " + "osm_mad_pool_get failed\n" ); + + for( i = 0; i < num_rec; i++ ) + { + p_rec_item = (osm_mcmr_item_t*)cl_qlist_remove_head( &rec_list ); + cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item ); + } + + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES ); + goto Exit; + } + + p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw ); + + /* + Copy the MAD header back into the response mad. + Set the 'R' bit and the payload length, + Then copy all records from the list into the response payload. + */ + + memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE ); + p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK; + /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */ + p_resp_sa_mad->sm_key = 0; + + /* Fill in the offset (paylen will be done by the rmpp SAR) */ + p_resp_sa_mad->attr_offset = + ib_get_attr_offset( sizeof(ib_member_rec_t) ); + +#ifndef VENDOR_RMPP_SUPPORT + /* we support only one packet RMPP - so we will set the first and + last flags for gettable */ + if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP) + { + p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA; + p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE; + } +#else + /* forcefully define the packet as RMPP one */ + if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP) + p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE; +#endif + + p_resp_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad ); + + /* + p923 - The PortGID, JoinState and ProxyJoin shall be zero, + except in the case of a trusted request. + Note: In the mad controller we check that the SM_Key received on + the mad is valid. Meaning - is either zero or equal to the local + sm_key. + */ + + for ( i = 0; i < pre_trim_num_rec; i++ ) + { + p_rec_item = (osm_mcmr_item_t*)cl_qlist_remove_head( &rec_list ); + /* copy only if not trimmed */ + if (i < num_rec) + { + *p_resp_rec = p_rec_item->rec; + if (trusted_req == FALSE) + { + memset(&p_resp_rec->port_gid, 0, sizeof(ib_gid_t)); + ib_member_set_join_state(p_resp_rec, 0); + p_resp_rec->proxy_join = 0; + } + } + cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item ); + p_resp_rec++; + } + + CL_ASSERT( cl_is_qlist_empty( &rec_list ) ); + + status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE ); + if(status != IB_SUCCESS) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_mcmr_query_mgrp: ERR 1B17: " + "osm_vendor_send status = %s\n", + ib_get_err_str(status) ); + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_mcmr_rcv_process( + IN osm_mcmr_recv_t* const p_rcv, + const IN osm_madw_t* const p_madw ) +{ + ib_sa_mad_t *p_sa_mad; + ib_net16_t sa_status = IB_SA_MAD_STATUS_REQ_INVALID; + ib_member_rec_t *p_recvd_mcmember_rec; + boolean_t valid; + + CL_ASSERT( p_rcv ); + + OSM_LOG_ENTER( p_rcv->p_log, osm_mcmr_rcv_process ); + + CL_ASSERT( p_madw ); + + p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw ); + p_recvd_mcmember_rec = + (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad ); + + CL_ASSERT( p_sa_mad->attr_id == IB_MAD_ATTR_MCMEMBER_RECORD ); + + switch (p_sa_mad->method) + { + case IB_MAD_METHOD_SET: + valid = __check_join_comp_mask(p_sa_mad->comp_mask); + if(!valid) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_mcmr_rcv_process: ERR 1B18: " + "component mask = 0x%016" PRIx64 ", " + "expected comp mask = 0x%016" PRIx64 " ," + "MGID: 0x%016" PRIx64 " : " + "0x%016" PRIx64 " for " + "PortGID: 0x%016" PRIx64 " : " + "0x%016" PRIx64 "\n", + cl_ntoh64(p_sa_mad->comp_mask), + CL_NTOH64(JOIN_MC_COMP_MASK), + cl_ntoh64( p_recvd_mcmember_rec->mgid.unicast.prefix ), + cl_ntoh64( p_recvd_mcmember_rec->mgid.unicast.interface_id ), + cl_ntoh64( p_recvd_mcmember_rec->port_gid.unicast.prefix ), + cl_ntoh64( p_recvd_mcmember_rec->port_gid.unicast.interface_id ) ); + + osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status ); + goto Exit; + } + + /* + * Join or Create Multicast Group + */ + __osm_mcmr_rcv_join_mgrp(p_rcv, p_madw); + break; + case IB_MAD_METHOD_DELETE: + valid = __check_join_comp_mask(p_sa_mad->comp_mask); + if(!valid) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_mcmr_rcv_process: ERR 1B20: " + "component mask = 0x%016" PRIx64 ", " + "expected comp mask = 0x%016" PRIx64 "\n", + cl_ntoh64(p_sa_mad->comp_mask), + CL_NTOH64(JOIN_MC_COMP_MASK) ); + + osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status ); + goto Exit; + } + + /* + * Leave Multicast Group + */ + __osm_mcmr_rcv_leave_mgrp(p_rcv, p_madw); + break; + case IB_MAD_METHOD_GET: + case IB_MAD_METHOD_GETTABLE: + /* + * Querying a Multicast Group + */ + __osm_mcmr_query_mgrp(p_rcv, p_madw); + break; + default: + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_mcmr_rcv_process: ERR 1B21: " + "Unsupported Method (%s)\n", + ib_get_sa_method_str( p_sa_mad->method ) ); + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR ); + break; + } + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); + return; +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_mcmember_record_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_mcmember_record_ctrl.c new file mode 100644 index 00000000..ce6d88f7 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_mcmember_record_ctrl.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_mcmember_record_ctrl.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_mcmr_rcv_ctrl_t. + * This object represents the Multicast member record controller object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +__osm_mcmr_rcv_ctrl_disp_callback( + IN void *context, + IN void *p_data ) +{ + /* ignore return status when invoked via the dispatcher */ + osm_mcmr_rcv_process( ((osm_mcmr_rcv_ctrl_t*)context)->p_rcv, + (osm_madw_t*)p_data ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_mcmr_rcv_ctrl_construct( + IN osm_mcmr_rcv_ctrl_t* const p_ctrl ) +{ + memset( p_ctrl, 0, sizeof(*p_ctrl) ); + p_ctrl->h_disp = CL_DISP_INVALID_HANDLE; +} + +/********************************************************************** + **********************************************************************/ +void +osm_mcmr_rcv_ctrl_destroy( + IN osm_mcmr_rcv_ctrl_t* const p_ctrl ) +{ + CL_ASSERT( p_ctrl ); + cl_disp_unregister( p_ctrl->h_disp ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_mcmr_rcv_ctrl_init( + IN osm_mcmr_rcv_ctrl_t* const p_ctrl, + IN osm_mcmr_recv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_mcmr_rcv_ctrl_init ); + + osm_mcmr_rcv_ctrl_construct( p_ctrl ); + p_ctrl->p_log = p_log; + p_ctrl->p_rcv = p_rcv; + p_ctrl->p_disp = p_disp; + + p_ctrl->h_disp = cl_disp_register( + p_disp, + OSM_MSG_MAD_MCMEMBER_RECORD, + __osm_mcmr_rcv_ctrl_disp_callback, + p_ctrl ); + + if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_mcmr_rcv_ctrl_init: ERR 1C01: " + "Dispatcher registration failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return( status ); +} + + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_mft_record.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_mft_record.c new file mode 100644 index 00000000..5cd6efad --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_mft_record.c @@ -0,0 +1,547 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ + + +/* + * Abstract: + * Implementation of osm_mftr_rcv_t. + * This object represents the MulticastForwardingTable Receiver object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define OSM_MFTR_RCV_POOL_MIN_SIZE 32 +#define OSM_MFTR_RCV_POOL_GROW_SIZE 32 + +typedef struct _osm_mftr_item +{ + cl_pool_item_t pool_item; + ib_mft_record_t rec; +} osm_mftr_item_t; + +typedef struct _osm_mftr_search_ctxt +{ + const ib_mft_record_t* p_rcvd_rec; + ib_net64_t comp_mask; + cl_qlist_t* p_list; + osm_mftr_rcv_t* p_rcv; + const osm_physp_t* p_req_physp; +} osm_mftr_search_ctxt_t; + +/********************************************************************** + **********************************************************************/ +void +osm_mftr_rcv_construct( + IN osm_mftr_rcv_t* const p_rcv ) +{ + memset( p_rcv, 0, sizeof(*p_rcv) ); + cl_qlock_pool_construct( &p_rcv->pool ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_mftr_rcv_destroy( + IN osm_mftr_rcv_t* const p_rcv ) +{ + OSM_LOG_ENTER( p_rcv->p_log, osm_mftr_rcv_destroy ); + cl_qlock_pool_destroy( &p_rcv->pool ); + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_mftr_rcv_init( + IN osm_mftr_rcv_t* const p_rcv, + IN osm_sa_resp_t* const p_resp, + IN osm_mad_pool_t* const p_mad_pool, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ) +{ + ib_api_status_t status; + + OSM_LOG_ENTER( p_log, osm_mftr_rcv_init ); + + osm_mftr_rcv_construct( p_rcv ); + + p_rcv->p_log = p_log; + p_rcv->p_subn = p_subn; + p_rcv->p_lock = p_lock; + p_rcv->p_resp = p_resp; + p_rcv->p_mad_pool = p_mad_pool; + + status = cl_qlock_pool_init( &p_rcv->pool, + OSM_MFTR_RCV_POOL_MIN_SIZE, + 0, + OSM_MFTR_RCV_POOL_GROW_SIZE, + sizeof(osm_mftr_item_t), + NULL, NULL, NULL ); + + OSM_LOG_EXIT( p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +static ib_api_status_t +__osm_mftr_rcv_new_mftr( + IN osm_mftr_rcv_t* const p_rcv, + IN osm_switch_t* const p_sw, + IN cl_qlist_t* const p_list, + IN ib_net16_t const lid, + IN uint16_t const block, + IN uint8_t const position ) +{ + osm_mftr_item_t* p_rec_item; + ib_api_status_t status = IB_SUCCESS; + uint16_t position_block_num; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_mftr_rcv_new_mftr ); + + p_rec_item = (osm_mftr_item_t*)cl_qlock_pool_get( &p_rcv->pool ); + if( p_rec_item == NULL ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_mftr_rcv_new_mftr: ERR 4A02: " + "cl_qlock_pool_get failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_mftr_rcv_new_mftr: " + "New MulticastForwardingTable: sw 0x%016" PRIx64 + "\n\t\t\t\tblock %u position %u lid 0x%02X\n", + cl_ntoh64( osm_node_get_node_guid( p_sw->p_node ) ), + block, position, cl_ntoh16( lid ) + ); + } + + position_block_num = ((uint16_t)position << 12) | + (block & IB_MCAST_BLOCK_ID_MASK_HO); + + memset( &p_rec_item->rec, 0, sizeof(ib_mft_record_t) ); + + p_rec_item->rec.lid = lid; + p_rec_item->rec.position_block_num = cl_hton16( position_block_num ); + + /* copy the mft block */ + osm_switch_get_mft_block( p_sw, block, position, p_rec_item->rec.mft ); + + cl_qlist_insert_tail( p_list, (cl_list_item_t*)&p_rec_item->pool_item ); + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +static osm_port_t* +__osm_mftr_get_port_by_guid( + IN osm_mftr_rcv_t* const p_rcv, + IN uint64_t port_guid ) +{ + osm_port_t* p_port; + + CL_PLOCK_ACQUIRE(p_rcv->p_lock); + + p_port = (osm_port_t *)cl_qmap_get(&p_rcv->p_subn->port_guid_tbl, + port_guid); + if (p_port == (osm_port_t *)cl_qmap_end(&p_rcv->p_subn->port_guid_tbl)) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_mftr_get_port_by_guid ERR 4A04: " + "Invalid port GUID 0x%016" PRIx64 "\n", + port_guid ); + p_port = NULL; + } + + CL_PLOCK_RELEASE(p_rcv->p_lock); + return p_port; +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_mftr_rcv_by_comp_mask( + IN cl_map_item_t* const p_map_item, + IN void* context ) +{ + const osm_mftr_search_ctxt_t* const p_ctxt = + (osm_mftr_search_ctxt_t *)context; + osm_switch_t* const p_sw = (osm_switch_t*)p_map_item; + const ib_mft_record_t* const p_rcvd_rec = p_ctxt->p_rcvd_rec; + osm_mftr_rcv_t* const p_rcv = p_ctxt->p_rcv; + ib_net64_t const comp_mask = p_ctxt->comp_mask; + const osm_physp_t* const p_req_physp = p_ctxt->p_req_physp; + osm_port_t* p_port; + uint16_t min_lid_ho, max_lid_ho; + uint16_t position_block_num_ho; + uint16_t min_block, max_block, block; + const osm_physp_t* p_physp; + uint8_t min_position, max_position, position; + + /* In switches, the port guid is the node guid. */ + p_port = + __osm_mftr_get_port_by_guid( p_rcv, p_sw->p_node->node_info.port_guid ); + if (! p_port) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_mftr_rcv_by_comp_mask: ERR 4A05: " + "Failed to find Port by Node Guid:0x%016" PRIx64 + "\n", + cl_ntoh64( p_sw->p_node->node_info.node_guid ) + ); + return; + } + + /* check that the requester physp and the current physp are under + the same partition. */ + p_physp = osm_port_get_default_phys_ptr( p_port ); + if (! p_physp) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_mftr_rcv_by_comp_mask: ERR 4A06: " + "Failed to find default physical Port by Node Guid:0x%016" PRIx64 + "\n", + cl_ntoh64( p_sw->p_node->node_info.node_guid ) + ); + return; + } + if (! osm_physp_share_pkey( p_rcv->p_log, p_req_physp, p_physp )) + return; + + /* get the port 0 of the switch */ + osm_port_get_lid_range_ho( p_port, &min_lid_ho, &max_lid_ho ); + + /* compare the lids - if required */ + if( comp_mask & IB_MFTR_COMPMASK_LID ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_mftr_rcv_by_comp_mask: " + "Comparing lid:0x%02X to port lid range: 0x%02X .. 0x%02X\n", + cl_ntoh16( p_rcvd_rec->lid ), min_lid_ho, max_lid_ho + ); + /* ok we are ready for range check */ + if (min_lid_ho > cl_ntoh16(p_rcvd_rec->lid) || + max_lid_ho < cl_ntoh16(p_rcvd_rec->lid)) + return; + } + + if ( !osm_switch_supports_mcast ( p_sw ) ) + return; + + /* Are there any blocks in use ? */ + if ( osm_switch_get_mft_max_block_in_use( p_sw ) == -1 ) + return; + + position_block_num_ho = cl_ntoh16( p_rcvd_rec->position_block_num ); + + /* now we need to decide which blocks to output */ + if( comp_mask & IB_MFTR_COMPMASK_BLOCK ) + { + max_block = min_block = position_block_num_ho & IB_MCAST_BLOCK_ID_MASK_HO; + if ( max_block > osm_switch_get_mft_max_block_in_use( p_sw ) ) + return; + } + else + { + /* use as many blocks as needed */ + min_block = 0; + max_block = osm_switch_get_mft_max_block_in_use( p_sw ); + } + + /* need to decide which positions to output */ + if ( comp_mask & IB_MFTR_COMPMASK_POSITION ) + { + min_position = max_position = (position_block_num_ho & 0xF000) >> 12; + if (max_position > osm_switch_get_mft_max_position( p_sw ) ) + return; + } + else + { + /* use as many positions as needed */ + min_position = 0; + max_position = osm_switch_get_mft_max_position( p_sw ); + } + + /* so we can add these one by one ... */ + for (block = min_block; block <= max_block; block++) + for (position = min_position; position <= max_position; position++) + __osm_mftr_rcv_new_mftr( p_rcv, p_sw, p_ctxt->p_list, + osm_port_get_base_lid(p_port), + block, position ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_mftr_rcv_process( + IN osm_mftr_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ) +{ + const ib_sa_mad_t* p_rcvd_mad; + const ib_mft_record_t* p_rcvd_rec; + ib_mft_record_t* p_resp_rec; + cl_qlist_t rec_list; + osm_madw_t* p_resp_madw; + ib_sa_mad_t* p_resp_sa_mad; + uint32_t num_rec, pre_trim_num_rec; +#ifndef VENDOR_RMPP_SUPPORT + uint32_t trim_num_rec; +#endif + uint32_t i; + osm_mftr_search_ctxt_t context; + osm_mftr_item_t* p_rec_item; + ib_api_status_t status = IB_SUCCESS; + osm_physp_t* p_req_physp; + + CL_ASSERT( p_rcv ); + + OSM_LOG_ENTER( p_rcv->p_log, osm_mftr_rcv_process ); + + CL_ASSERT( p_madw ); + + p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw ); + p_rcvd_rec = (ib_mft_record_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad ); + + CL_ASSERT( p_rcvd_mad->attr_id == IB_MAD_ATTR_MFT_RECORD ); + + /* we only support SubnAdmGet and SubnAdmGetTable methods */ + if ( (p_rcvd_mad->method != IB_MAD_METHOD_GET) && + (p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) ) { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_mftr_rcv_process: ERR 4A08: " + "Unsupported Method (%s)\n", + ib_get_sa_method_str( p_rcvd_mad->method ) ); + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR ); + goto Exit; + } + + /* update the requester physical port. */ + p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log, + p_rcv->p_subn, + osm_madw_get_mad_addr_ptr(p_madw) ); + if (p_req_physp == NULL) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_mftr_rcv_process: ERR 4A07: " + "Cannot find requester physical port\n" ); + goto Exit; + } + + cl_qlist_init( &rec_list ); + + context.p_rcvd_rec = p_rcvd_rec; + context.p_list = &rec_list; + context.comp_mask = p_rcvd_mad->comp_mask; + context.p_rcv = p_rcv; + context.p_req_physp = p_req_physp; + + cl_plock_acquire( p_rcv->p_lock ); + + /* Go over all switches */ + cl_qmap_apply_func( &p_rcv->p_subn->sw_guid_tbl, + __osm_mftr_rcv_by_comp_mask, + &context ); + + cl_plock_release( p_rcv->p_lock ); + + num_rec = cl_qlist_count( &rec_list ); + + /* + * C15-0.1.30: + * If we do a SubnAdmGet and got more than one record it is an error ! + */ + if (p_rcvd_mad->method == IB_MAD_METHOD_GET) + { + if (num_rec == 0) + { + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS ); + goto Exit; + } + if (num_rec > 1) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_mftr_rcv_process: ERR 4A09: " + "Got more than one record for SubnAdmGet (%u)\n", + num_rec ); + osm_sa_send_error( p_rcv->p_resp, p_madw, + IB_SA_MAD_STATUS_TOO_MANY_RECORDS); + + /* need to set the mem free ... */ + p_rec_item = (osm_mftr_item_t*)cl_qlist_remove_head( &rec_list ); + while( p_rec_item != (osm_mftr_item_t*)cl_qlist_end( &rec_list ) ) + { + cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item ); + p_rec_item = (osm_mftr_item_t*)cl_qlist_remove_head( &rec_list ); + } + + goto Exit; + } + } + + pre_trim_num_rec = num_rec; +#ifndef VENDOR_RMPP_SUPPORT + /* we limit the number of records to a single packet */ + trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_mft_record_t); + if (trim_num_rec < num_rec) + { + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "osm_mftr_rcv_process: " + "Number of records:%u trimmed to:%u to fit in one MAD\n", + num_rec, trim_num_rec ); + num_rec = trim_num_rec; + } +#endif + + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "osm_mftr_rcv_process: " + "Returning %u records\n", num_rec ); + + if ((p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) && + (num_rec == 0)) + { + osm_sa_send_error( p_rcv->p_resp, p_madw, + IB_SA_MAD_STATUS_NO_RECORDS ); + goto Exit; + } + + /* + * Get a MAD to reply. Address of Mad is in the received mad_wrapper + */ + p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool, + p_madw->h_bind, + num_rec * sizeof(ib_mft_record_t) + IB_SA_MAD_HDR_SIZE, + &p_madw->mad_addr ); + + if( !p_resp_madw ) + { + osm_log(p_rcv->p_log, OSM_LOG_ERROR, + "osm_mftr_rcv_process: ERR 4A10: " + "osm_mad_pool_get failed\n" ); + + for( i = 0; i < num_rec; i++ ) + { + p_rec_item = (osm_mftr_item_t*)cl_qlist_remove_head( &rec_list ); + cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item ); + } + + osm_sa_send_error( p_rcv->p_resp, p_madw, + IB_SA_MAD_STATUS_NO_RESOURCES ); + + goto Exit; + } + + p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw ); + + /* + Copy the MAD header back into the response mad. + Set the 'R' bit and the payload length, + Then copy all records from the list into the response payload. + */ + + memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE ); + p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK; + /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */ + p_resp_sa_mad->sm_key = 0; + /* Fill in the offset (paylen will be done by the rmpp SAR) */ + p_resp_sa_mad->attr_offset = + ib_get_attr_offset( sizeof(ib_mft_record_t) ); + + p_resp_rec = (ib_mft_record_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad ); + +#ifndef VENDOR_RMPP_SUPPORT + /* we support only one packet RMPP - so we will set the first and + last flags for gettable */ + if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP) + { + p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA; + p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE; + } +#else + /* forcefully define the packet as RMPP one */ + if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP) + p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE; +#endif + + for( i = 0; i < pre_trim_num_rec; i++ ) + { + p_rec_item = (osm_mftr_item_t*)cl_qlist_remove_head( &rec_list ); + /* copy only if not trimmed */ + if (i < num_rec) + { + *p_resp_rec = p_rec_item->rec; + } + cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item ); + p_resp_rec++; + } + + CL_ASSERT( cl_is_qlist_empty( &rec_list ) ); + + status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE ); + if (status != IB_SUCCESS) + { + osm_log(p_rcv->p_log, OSM_LOG_ERROR, + "osm_mftr_rcv_process: ERR 4A11: " + "osm_vendor_send status = %s\n", + ib_get_err_str(status)); + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_mft_record_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_mft_record_ctrl.c new file mode 100644 index 00000000..3c0c39c7 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_mft_record_ctrl.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ + + +/* + * Abstract: + * Implementation of osm_mftr_rcv_ctrl_t. + * This object represents the MulticastForwardingTable request controller object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +__osm_mftr_rcv_ctrl_disp_callback( + IN void *context, + IN void *p_data ) +{ + /* ignore return status when invoked via the dispatcher */ + osm_mftr_rcv_process( ((osm_mftr_rcv_ctrl_t*)context)->p_rcv, + (osm_madw_t*)p_data ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_mftr_rcv_ctrl_construct( + IN osm_mftr_rcv_ctrl_t* const p_ctrl ) +{ + memset( p_ctrl, 0, sizeof(*p_ctrl) ); + p_ctrl->h_disp = CL_DISP_INVALID_HANDLE; +} + +/********************************************************************** + **********************************************************************/ +void +osm_mftr_rcv_ctrl_destroy( + IN osm_mftr_rcv_ctrl_t* const p_ctrl ) +{ + CL_ASSERT( p_ctrl ); + cl_disp_unregister( p_ctrl->h_disp ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_mftr_rcv_ctrl_init( + IN osm_mftr_rcv_ctrl_t* const p_ctrl, + IN osm_mftr_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_mftr_rcv_ctrl_init ); + + osm_mftr_rcv_ctrl_construct( p_ctrl ); + p_ctrl->p_log = p_log; + p_ctrl->p_rcv = p_rcv; + p_ctrl->p_disp = p_disp; + + p_ctrl->h_disp = cl_disp_register( + p_disp, + OSM_MSG_MAD_MFT_RECORD, + __osm_mftr_rcv_ctrl_disp_callback, + p_ctrl ); + + if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_mftr_rcv_ctrl_init: ERR 4A01: " + "Dispatcher registration failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return( status ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_multipath_record.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_multipath_record.c new file mode 100644 index 00000000..83404e0b --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_multipath_record.c @@ -0,0 +1,1652 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ + + +/* + * Abstract: + * Implementation of osm_mpr_rcv_t. + * This object represents the MultiPath Record Receiver object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + */ + +#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP) + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define OSM_MPR_RCV_POOL_MIN_SIZE 64 +#define OSM_MPR_RCV_POOL_GROW_SIZE 64 + +#define OSM_SA_MPR_MAX_NUM_PATH 127 + +typedef struct _osm_mpr_item +{ + cl_pool_item_t pool_item; + const osm_port_t *p_src_port; + const osm_port_t *p_dest_port; + int hops; + ib_path_rec_t path_rec; +} osm_mpr_item_t; + +typedef struct _osm_path_parms +{ + ib_net16_t pkey; + uint8_t mtu; + uint8_t rate; + uint8_t sl; + uint8_t pkt_life; + boolean_t reversible; + int hops; +} osm_path_parms_t; + +/********************************************************************** + **********************************************************************/ +void +osm_mpr_rcv_construct( + IN osm_mpr_rcv_t* const p_rcv ) +{ + memset( p_rcv, 0, sizeof(*p_rcv) ); + cl_qlock_pool_construct( &p_rcv->pr_pool ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_mpr_rcv_destroy( + IN osm_mpr_rcv_t* const p_rcv ) +{ + OSM_LOG_ENTER( p_rcv->p_log, osm_mpr_rcv_destroy ); + cl_qlock_pool_destroy( &p_rcv->pr_pool ); + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_mpr_rcv_init( + IN osm_mpr_rcv_t* const p_rcv, + IN osm_sa_resp_t* const p_resp, + IN osm_mad_pool_t* const p_mad_pool, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ) +{ + ib_api_status_t status; + + OSM_LOG_ENTER( p_log, osm_mpr_rcv_init ); + + osm_mpr_rcv_construct( p_rcv ); + + p_rcv->p_log = p_log; + p_rcv->p_subn = p_subn; + p_rcv->p_lock = p_lock; + p_rcv->p_resp = p_resp; + p_rcv->p_mad_pool = p_mad_pool; + + status = cl_qlock_pool_init( &p_rcv->pr_pool, + OSM_MPR_RCV_POOL_MIN_SIZE, + 0, + OSM_MPR_RCV_POOL_GROW_SIZE, + sizeof(osm_mpr_item_t), + NULL, NULL, NULL ); + + OSM_LOG_EXIT( p_rcv->p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +static inline boolean_t +__osm_sa_multipath_rec_is_tavor_port( + IN const osm_port_t* const p_port) +{ + osm_node_t const* p_node; + ib_net32_t vend_id; + + p_node = osm_port_get_parent_node( p_port ); + vend_id = ib_node_info_get_vendor_id( &p_node->node_info ); + + return( (p_node->node_info.device_id == CL_HTON16(23108)) && + ((vend_id == CL_HTON32(OSM_VENDOR_ID_MELLANOX)) || + (vend_id == CL_HTON32(OSM_VENDOR_ID_TOPSPIN)) || + (vend_id == CL_HTON32(OSM_VENDOR_ID_SILVERSTORM)) || + (vend_id == CL_HTON32(OSM_VENDOR_ID_VOLTAIRE))) ); +} + +/********************************************************************** + **********************************************************************/ +boolean_t + __osm_sa_multipath_rec_apply_tavor_mtu_limit( + IN const ib_multipath_rec_t* const p_mpr, + IN const osm_port_t* const p_src_port, + IN const osm_port_t* const p_dest_port, + IN const ib_net64_t comp_mask) +{ + uint8_t required_mtu; + + /* only if at least one of the ports is a Tavor device */ + if (! __osm_sa_multipath_rec_is_tavor_port(p_src_port) && + ! __osm_sa_multipath_rec_is_tavor_port(p_dest_port) ) + return( FALSE ); + + /* + we can apply the patch if either: + 1. No MTU required + 2. Required MTU < + 3. Required MTU = 1K or 512 or 256 + 4. Required MTU > 256 or 512 + */ + required_mtu = ib_multipath_rec_mtu( p_mpr ); + if ( ( comp_mask & IB_MPR_COMPMASK_MTUSELEC ) && + ( comp_mask & IB_PR_COMPMASK_MTU ) ) + { + switch( ib_multipath_rec_mtu_sel( p_mpr ) ) + { + case 0: /* must be greater than */ + case 2: /* exact match */ + if( IB_MTU_LEN_1024 < required_mtu ) + return(FALSE); + break; + + case 1: /* must be less than */ + /* can't be disqualified by this one */ + break; + + case 3: /* largest available */ + /* the ULP intentionally requested */ + /* the largest MTU possible */ + return(FALSE); + break; + + default: + /* if we're here, there's a bug in ib_multipath_rec_mtu_sel() */ + CL_ASSERT( FALSE ); + break; + } + } + + return(TRUE); +} + +/********************************************************************** + **********************************************************************/ +static ib_api_status_t +__osm_mpr_rcv_get_path_parms( + IN osm_mpr_rcv_t* const p_rcv, + IN const ib_multipath_rec_t* const p_mpr, + IN const osm_port_t* const p_src_port, + IN const osm_port_t* const p_dest_port, + IN const uint16_t dest_lid_ho, + IN const ib_net64_t comp_mask, + OUT osm_path_parms_t* const p_parms ) +{ + const osm_node_t* p_node; + const osm_physp_t* p_physp; + const osm_physp_t* p_dest_physp; + const osm_prtn_t* p_prtn; + const ib_port_info_t* p_pi; + ib_slvl_table_t* p_slvl_tbl; + ib_api_status_t status = IB_SUCCESS; + uint8_t mtu; + uint8_t rate; + uint8_t pkt_life; + uint8_t required_mtu; + uint8_t required_rate; + uint16_t required_pkey; + uint8_t required_sl; + uint8_t required_pkt_life; + ib_net16_t dest_lid; + int hops = 0; + int in_port_num = 0; + uint8_t vl; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_mpr_rcv_get_path_parms ); + + dest_lid = cl_hton16( dest_lid_ho ); + + p_dest_physp = osm_port_get_default_phys_ptr( p_dest_port ); + p_physp = osm_port_get_default_phys_ptr( p_src_port ); + p_pi = osm_physp_get_port_info_ptr( p_physp ); + + mtu = ib_port_info_get_mtu_cap( p_pi ); + rate = ib_port_info_compute_rate( p_pi ); + + /* + Mellanox Tavor device performance is better using 1K MTU. + If required MTU and MTU selector are such that 1K is OK + and at least one end of the path is Tavor we override the + port MTU with 1K. + */ + if ( p_rcv->p_subn->opt.enable_quirks && + __osm_sa_multipath_rec_apply_tavor_mtu_limit( + p_mpr, p_src_port, p_dest_port, comp_mask) ) + if (mtu > IB_MTU_LEN_1024) + { + mtu = IB_MTU_LEN_1024; + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_mpr_rcv_get_path_parms: " + "Optimized Path MTU to 1K for Mellanox Tavor device\n"); + } + + if ( comp_mask & IB_MPR_COMPMASK_RAWTRAFFIC && + cl_ntoh32( p_mpr->hop_flow_raw ) & ( 1<<31 ) ) + required_pkey = osm_physp_find_common_pkey( p_physp, p_dest_physp ); + else if ( comp_mask & IB_MPR_COMPMASK_PKEY ) { + required_pkey = p_mpr->pkey; + if( !osm_physp_share_this_pkey( p_physp, p_dest_physp, required_pkey ) ) { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_mpr_rcv_get_path_parms: ERR 4518: " + "Ports do not share specified PKey 0x%04x\n" + "\t\tsrc %" PRIx64 " dst %" PRIx64 "\n", + cl_ntoh16( required_pkey ), + cl_ntoh64( osm_physp_get_port_guid( p_physp ) ), + cl_ntoh64( osm_physp_get_port_guid( p_dest_physp ) ) ); + status = IB_NOT_FOUND; + goto Exit; + } + } else { + required_pkey = osm_physp_find_common_pkey( p_physp, p_dest_physp ); + if ( !required_pkey ) { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_mpr_rcv_get_path_parms: ERR 4519: " + "Ports do not have any shared PKeys\n" + "\t\tsrc %" PRIx64 " dst %" PRIx64 "\n", + cl_ntoh64( osm_physp_get_port_guid( p_physp ) ), + cl_ntoh64( osm_physp_get_port_guid( p_dest_physp ) ) ); + status = IB_NOT_FOUND; + goto Exit; + } + } + + required_sl = OSM_DEFAULT_SL; + + if (required_pkey) { + p_prtn = (osm_prtn_t *)cl_qmap_get(&p_rcv->p_subn->prtn_pkey_tbl, + required_pkey & cl_ntoh16((uint16_t)~0x8000)); + if ( p_prtn == (osm_prtn_t *)cl_qmap_end(&p_rcv->p_subn->prtn_pkey_tbl) ) + { + /* this may be possible when pkey tables are created somehow in + previous runs or things are going wrong here */ + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_mpr_rcv_get_path_parms: ERR 451A: " + "No partition found for PKey 0x%04x - using default SL %d\n", cl_ntoh16(required_pkey), required_sl ); + } + else + required_sl = p_prtn->sl; + + /* reset pkey when raw traffic */ + if( comp_mask & IB_PR_COMPMASK_RAWTRAFFIC && + cl_ntoh32( p_mpr->hop_flow_raw ) & ( 1<<31 ) ) + required_pkey = 0; + } + + if ( ( comp_mask & IB_MPR_COMPMASK_SL ) && ib_multipath_rec_sl( p_mpr ) != required_sl ) + { + status = IB_NOT_FOUND; + goto Exit; + } + + /* + Walk the subnet object from source to destination, + tracking the most restrictive rate and mtu values along the way... + + If source port node is a switch, then p_physp should + point to the port that routes the destination lid + */ + + p_node = osm_physp_get_node_ptr( p_physp ); + + if ( p_node->sw ) + { + + /* + * If the dest_lid_ho is equal to the lid of the switch pointed by + * p_sw then p_physp will be the physical port of the switch port zero. + */ + p_physp = osm_switch_get_route_by_lid( p_node->sw, cl_ntoh16( dest_lid_ho ) ); + if ( p_physp == 0 ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_mpr_rcv_get_path_parms: ERR 4514: " + "Can't find routing to LID 0x%X from switch for GUID 0x%016" PRIx64 "\n", + dest_lid_ho, + cl_ntoh64( osm_node_get_node_guid( p_node ) ) ); + status = IB_ERROR; + goto Exit; + } + } + + /* + * Same as above + */ + p_node = osm_physp_get_node_ptr( p_dest_physp ); + + if ( p_node->sw ) + { + + p_dest_physp = osm_switch_get_route_by_lid( p_node->sw, cl_ntoh16( dest_lid_ho ) ); + + if ( p_dest_physp == 0 ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_mpr_rcv_get_path_parms: ERR 4515: " + "Can't find routing to LID 0x%X from switch for GUID 0x%016" PRIx64 "\n", + dest_lid_ho, + cl_ntoh64( osm_node_get_node_guid( p_node ) ) ); + status = IB_ERROR; + goto Exit; + } + + } + + while ( p_physp != p_dest_physp ) + { + p_physp = osm_physp_get_remote( p_physp ); + + if ( p_physp == 0 ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_mpr_rcv_get_path_parms: ERR 4505: " + "Can't find remote phys port when routing to LID 0x%X from node GUID 0x%016" PRIx64 "\n", + dest_lid_ho, + cl_ntoh64( osm_node_get_node_guid( p_node ) ) ); + status = IB_ERROR; + goto Exit; + } + + hops++; + + /* + This is point to point case (no switch in between) + */ + if ( p_physp == p_dest_physp ) + break; + + p_node = osm_physp_get_node_ptr( p_physp ); + + if ( !p_node->sw ) + { + /* + There is some sort of problem in the subnet object! + If this isn't a switch, we should have reached + the destination by now! + */ + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_mpr_rcv_get_path_parms: ERR 4503: " + "Internal error, bad path\n" ); + status = IB_ERROR; + goto Exit; + } + + /* + Check parameters for the ingress port in this switch. + */ + p_pi = osm_physp_get_port_info_ptr( p_physp ); + + if ( mtu > ib_port_info_get_mtu_cap( p_pi ) ) + { + mtu = ib_port_info_get_mtu_cap( p_pi ); + if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_mpr_rcv_get_path_parms: " + "New smallest MTU = %u at intervening port 0x%016" PRIx64 + " port num 0x%X\n", + mtu, + cl_ntoh64( osm_physp_get_port_guid( p_physp ) ), + osm_physp_get_port_num( p_physp ) ); + } + } + + if ( rate > ib_port_info_compute_rate( p_pi ) ) + { + rate = ib_port_info_compute_rate( p_pi ); + if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_mpr_rcv_get_path_parms: " + "New smallest rate = %u at intervening port 0x%016" PRIx64 + " port num 0x%X\n", + rate, + cl_ntoh64( osm_physp_get_port_guid( p_physp ) ), + osm_physp_get_port_num( p_physp ) ); + } + } + + /* + Continue with the egress port on this switch. + */ + p_physp = osm_switch_get_route_by_lid( p_node->sw, dest_lid ); + + if ( p_physp == 0 ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_mpr_rcv_get_path_parms: ERR 4516: " + "Dead end on path to LID 0x%X from switch for GUID 0x%016" PRIx64 "\n", + dest_lid_ho, + cl_ntoh64( osm_node_get_node_guid( p_node ) ) ); + status = IB_ERROR; + goto Exit; + } + + CL_ASSERT( p_physp ); + CL_ASSERT( osm_physp_is_valid( p_physp ) ); + + if ( comp_mask & IB_MPR_COMPMASK_SL ) { + in_port_num = osm_physp_get_port_num( p_physp ); + p_slvl_tbl = osm_physp_get_slvl_tbl( p_physp, in_port_num ); + vl = ib_slvl_table_get( p_slvl_tbl, required_sl ); + if (vl == IB_DROP_VL) { /* discard packet */ + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "__osm_mpr_rcv_get_path_parms: Path not found for SL %d\n" + "\t\tin_port_num %d port_guid %" PRIx64 "\n", + required_sl, in_port_num, + cl_ntoh64( osm_physp_get_port_guid( p_physp ) ) ); + status = IB_NOT_FOUND; + goto Exit; + } + } + + p_pi = osm_physp_get_port_info_ptr( p_physp ); + + if ( mtu > ib_port_info_get_mtu_cap( p_pi ) ) + { + mtu = ib_port_info_get_mtu_cap( p_pi ); + if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_mpr_rcv_get_path_parms: " + "New smallest MTU = %u at intervening port 0x%016" PRIx64 + " port num 0x%X\n", + mtu, + cl_ntoh64( osm_physp_get_port_guid( p_physp ) ), + osm_physp_get_port_num( p_physp ) ); + } + } + + if ( rate > ib_port_info_compute_rate( p_pi ) ) + { + rate = ib_port_info_compute_rate( p_pi ); + if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_mpr_rcv_get_path_parms: " + "New smallest rate = %u at intervening port 0x%016" PRIx64 + " port num 0x%X\n", + rate, + cl_ntoh64( osm_physp_get_port_guid( p_physp ) ), + osm_physp_get_port_num( p_physp ) ); + } + } + + } + + /* + p_physp now points to the destination + */ + p_pi = osm_physp_get_port_info_ptr( p_physp ); + + if ( mtu > ib_port_info_get_mtu_cap( p_pi ) ) + { + mtu = ib_port_info_get_mtu_cap( p_pi ); + if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_mpr_rcv_get_path_parms: " + "New smallest MTU = %u at destination port 0x%016" PRIx64 "\n", + mtu, + cl_ntoh64( osm_physp_get_port_guid( p_physp ) ) ); + } + } + + if ( rate > ib_port_info_compute_rate( p_pi ) ) + { + rate = ib_port_info_compute_rate( p_pi ); + if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_mpr_rcv_get_path_parms: " + "New smallest rate = %u at destination port 0x%016" PRIx64 "\n", + rate, + cl_ntoh64( osm_physp_get_port_guid( p_physp ) ) ); + } + } + + if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_mpr_rcv_get_path_parms: " + "Path min MTU = %u, min rate = %u\n", mtu, rate ); + } + + /* + Determine if these values meet the user criteria + */ + + /* we silently ignore cases where only the MTU selector is defined */ + if ( ( comp_mask & IB_MPR_COMPMASK_MTUSELEC ) && + ( comp_mask & IB_MPR_COMPMASK_MTU ) ) + { + required_mtu = ib_multipath_rec_mtu( p_mpr ); + switch ( ib_multipath_rec_mtu_sel( p_mpr ) ) + { + case 0: /* must be greater than */ + if ( mtu <= required_mtu ) + status = IB_NOT_FOUND; + break; + + case 1: /* must be less than */ + if ( mtu >= required_mtu ) + { + /* adjust to use the highest mtu + lower then the required one */ + if ( required_mtu > 1 ) + mtu = required_mtu - 1; + else + status = IB_NOT_FOUND; + } + break; + + case 2: /* exact match */ + if ( mtu < required_mtu ) + status = IB_NOT_FOUND; + else + mtu = required_mtu; + break; + + case 3: /* largest available */ + /* can't be disqualified by this one */ + break; + + default: + /* if we're here, there's a bug in ib_multipath_rec_mtu_sel() */ + CL_ASSERT( FALSE ); + status = IB_ERROR; + break; + } + } + + /* we silently ignore cases where only the Rate selector is defined */ + if ( ( comp_mask & IB_MPR_COMPMASK_RATESELEC ) && + ( comp_mask & IB_PR_COMPMASK_RATE ) ) + { + required_rate = ib_multipath_rec_rate( p_mpr ); + switch ( ib_multipath_rec_rate_sel( p_mpr ) ) + { + case 0: /* must be greater than */ + if ( rate <= required_rate ) + status = IB_NOT_FOUND; + break; + + case 1: /* must be less than */ + if ( rate >= required_rate ) + { + /* adjust the rate to use the highest rate + lower then the required one */ + if ( required_rate > 2 ) + rate = required_rate - 1; + else + status = IB_NOT_FOUND; + } + break; + + case 2: /* exact match */ + if ( rate < required_rate ) + status = IB_NOT_FOUND; + else + rate = required_rate; + break; + + case 3: /* largest available */ + /* can't be disqualified by this one */ + break; + + default: + /* if we're here, there's a bug in ib_multipath_rec_mtu_sel() */ + CL_ASSERT( FALSE ); + status = IB_ERROR; + break; + } + } + + /* Verify the pkt_life_time */ + /* According to spec definition IBA 1.2 Table 205 PacketLifeTime description, + for loopback paths, packetLifeTime shall be zero. */ + if ( p_src_port == p_dest_port ) + pkt_life = 0; /* loopback */ + else + pkt_life = OSM_DEFAULT_SUBNET_TIMEOUT; + + /* we silently ignore cases where only the PktLife selector is defined */ + if ( ( comp_mask & IB_MPR_COMPMASK_PKTLIFETIMESELEC ) && + ( comp_mask & IB_MPR_COMPMASK_PKTLIFETIME ) ) + { + required_pkt_life = ib_multipath_rec_pkt_life( p_mpr ); + switch ( ib_multipath_rec_pkt_life_sel( p_mpr ) ) + { + case 0: /* must be greater than */ + if ( pkt_life <= required_pkt_life ) + status = IB_NOT_FOUND; + break; + + case 1: /* must be less than */ + if ( pkt_life >= required_pkt_life ) + { + /* adjust the lifetime to use the highest possible + lower then the required one */ + if ( required_pkt_life > 1 ) + pkt_life = required_pkt_life - 1; + else + status = IB_NOT_FOUND; + } + break; + + case 2: /* exact match */ + if ( pkt_life < required_pkt_life ) + status = IB_NOT_FOUND; + else + pkt_life = required_pkt_life; + break; + + case 3: /* smallest available */ + /* can't be disqualified by this one */ + break; + + default: + /* if we're here, there's a bug in ib_path_rec_pkt_life_sel() */ + CL_ASSERT( FALSE ); + status = IB_ERROR; + break; + } + } + + if (status != IB_SUCCESS) + goto Exit; + + p_parms->mtu = mtu; + p_parms->rate = rate; + p_parms->pkey = required_pkey; + p_parms->pkt_life = pkt_life; + p_parms->sl = required_sl; + p_parms->hops = hops; + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_mpr_rcv_build_pr( + IN osm_mpr_rcv_t* const p_rcv, + IN const osm_port_t* const p_src_port, + IN const osm_port_t* const p_dest_port, + IN const uint16_t src_lid_ho, + IN const uint16_t dest_lid_ho, + IN const uint8_t preference, + IN const osm_path_parms_t* const p_parms, + OUT ib_path_rec_t* const p_pr ) +{ + const osm_physp_t* p_src_physp; + const osm_physp_t* p_dest_physp; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_mpr_rcv_build_pr ); + + p_src_physp = osm_port_get_default_phys_ptr( p_src_port ); + p_dest_physp = osm_port_get_default_phys_ptr( p_dest_port ); + + p_pr->dgid.unicast.prefix = osm_physp_get_subnet_prefix( p_dest_physp ); + p_pr->dgid.unicast.interface_id = osm_physp_get_port_guid( p_dest_physp ); + + p_pr->sgid.unicast.prefix = osm_physp_get_subnet_prefix( p_src_physp ); + p_pr->sgid.unicast.interface_id = osm_physp_get_port_guid( p_src_physp ); + + p_pr->dlid = cl_hton16( dest_lid_ho ); + p_pr->slid = cl_hton16( src_lid_ho ); + + p_pr->hop_flow_raw &= cl_hton32(1<<31); + + p_pr->pkey = p_parms->pkey; + p_pr->sl = cl_hton16( p_parms->sl ); + p_pr->mtu = (uint8_t)( p_parms->mtu | 0x80 ); + p_pr->rate = (uint8_t)( p_parms->rate | 0x80 ); + + /* According to 1.2 spec definition Table 205 PacketLifeTime description, + for loopback paths, packetLifeTime shall be zero. */ + if ( p_src_port == p_dest_port ) + p_pr->pkt_life = 0x80; /* loopback */ + else + p_pr->pkt_life = (uint8_t)( p_parms->pkt_life | 0x80 ); + + p_pr->preference = preference; + + /* always return num_path = 0 so this is only the reversible component */ + if ( p_parms->reversible ) + p_pr->num_path = 0x80; + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +static osm_mpr_item_t* +__osm_mpr_rcv_get_lid_pair_path( + IN osm_mpr_rcv_t* const p_rcv, + IN const ib_multipath_rec_t* const p_mpr, + IN const osm_port_t* const p_src_port, + IN const osm_port_t* const p_dest_port, + IN const uint16_t src_lid_ho, + IN const uint16_t dest_lid_ho, + IN const ib_net64_t comp_mask, + IN const uint8_t preference ) +{ + osm_path_parms_t path_parms; + osm_path_parms_t rev_path_parms; + osm_mpr_item_t *p_pr_item; + ib_api_status_t status, rev_path_status; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_mpr_rcv_get_lid_pair_path ); + + if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_mpr_rcv_get_lid_pair_path: " + "Src LID 0x%X, Dest LID 0x%X\n", + src_lid_ho, dest_lid_ho ); + } + + p_pr_item = (osm_mpr_item_t*)cl_qlock_pool_get( &p_rcv->pr_pool ); + if ( p_pr_item == NULL ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_mpr_rcv_get_lid_pair_path: ERR 4501: " + "Unable to allocate path record\n" ); + goto Exit; + } + + status = __osm_mpr_rcv_get_path_parms( p_rcv, p_mpr, p_src_port, + p_dest_port, dest_lid_ho, + comp_mask, &path_parms ); + + if ( status != IB_SUCCESS ) + { + cl_qlock_pool_put( &p_rcv->pr_pool, &p_pr_item->pool_item ); + p_pr_item = NULL; + goto Exit; + } + + /* now try the reversible path */ + rev_path_status = __osm_mpr_rcv_get_path_parms( p_rcv, p_mpr, p_dest_port, + p_src_port, src_lid_ho, + comp_mask, &rev_path_parms ); + path_parms.reversible = ( rev_path_status == IB_SUCCESS ); + + /* did we get a Reversible Path compmask ? */ + /* + NOTE that if the reversible component = 0, it is a don't care + rather then requiring non-reversible paths ... + see Vol1 Ver1.2 p900 l16 + */ + if ( comp_mask & IB_MPR_COMPMASK_REVERSIBLE ) + { + if ( (! path_parms.reversible && ( p_mpr->num_path & 0x80 ) ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_mpr_rcv_get_lid_pair_path: " + "Requested reversible path but failed to get one\n"); + + cl_qlock_pool_put( &p_rcv->pr_pool, &p_pr_item->pool_item ); + p_pr_item = NULL; + goto Exit; + } + } + + p_pr_item->p_src_port = p_src_port; + p_pr_item->p_dest_port = p_dest_port; + p_pr_item->hops = path_parms.hops; + + __osm_mpr_rcv_build_pr( p_rcv, p_src_port, p_dest_port, src_lid_ho, + dest_lid_ho, preference, &path_parms, + &p_pr_item->path_rec ); + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); + return( p_pr_item ); +} + +/********************************************************************** + **********************************************************************/ +static uint32_t +__osm_mpr_rcv_get_port_pair_paths( + IN osm_mpr_rcv_t* const p_rcv, + IN const ib_multipath_rec_t* const p_mpr, + IN const osm_port_t* const p_req_port, + IN const osm_port_t* const p_src_port, + IN const osm_port_t* const p_dest_port, + IN const uint32_t rem_paths, + IN const ib_net64_t comp_mask, + IN cl_qlist_t* const p_list ) +{ + osm_mpr_item_t* p_pr_item; + uint16_t src_lid_min_ho; + uint16_t src_lid_max_ho; + uint16_t dest_lid_min_ho; + uint16_t dest_lid_max_ho; + uint16_t src_lid_ho; + uint16_t dest_lid_ho; + uint32_t path_num = 0; + uint8_t preference; + uintn_t src_offset; + uintn_t dest_offset; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_mpr_rcv_get_port_pair_paths ); + + if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_mpr_rcv_get_port_pair_paths: " + "Src port 0x%016" PRIx64 ", " + "Dst port 0x%016" PRIx64 "\n", + cl_ntoh64( osm_port_get_guid( p_src_port ) ), + cl_ntoh64( osm_port_get_guid( p_dest_port ) ) ); + } + + /* Check that the req_port, src_port and dest_port all share a + pkey. The check is done on the default physical port of the ports. */ + if ( osm_port_share_pkey(p_rcv->p_log, p_req_port, p_src_port ) == FALSE || + osm_port_share_pkey(p_rcv->p_log, p_req_port, p_dest_port ) == FALSE || + osm_port_share_pkey(p_rcv->p_log, p_src_port, p_dest_port ) == FALSE ) + { + /* One of the pairs doesn't share a pkey so the path is disqualified. */ + goto Exit; + } + + /* + We shouldn't be here if the paths are disqualified in some way... + Thus, we assume every possible connection is valid. + + We desire to return high-quality paths first. + In OpenSM, higher quality mean least overlap with other paths. + This is acheived in practice by returning paths with + different LID value on each end, which means these + paths are more redundant that paths with the same LID repeated + on one side. For example, in OpenSM the paths between two + endpoints with LMC = 1 might be as follows: + + Port A, LID 1 <-> Port B, LID 3 + Port A, LID 1 <-> Port B, LID 4 + Port A, LID 2 <-> Port B, LID 3 + Port A, LID 2 <-> Port B, LID 4 + + The OpenSM unicast routing algorithms attempt to disperse each path + to as varied a physical path as is reasonable. 1<->3 and 1<->4 have + more physical overlap (hence less redundancy) than 1<->3 and 2<->4. + + OpenSM ranks paths in three preference groups: + + Preference Value Description + ---------------- ------------------------------------------- + 0 Redundant in both directions with other + pref value = 0 paths + + 1 Redundant in one direction with other + pref value = 0 and pref value = 1 paths + + 2 Not redundant in either direction with + other paths + + 3-FF Unused + + + SA clients don't need to know these details, only that the lower + preference paths are preferred, as stated in the spec. The paths + may not actually be physically redundant depending on the topology + of the subnet, but the point of LMC > 0 is to offer redundancy, + so I assume the subnet is physically appropriate for the specified + LMC value. A more advanced implementation could inspect for physical + redundancy, but I'm not going to bother with that now. + */ + + osm_port_get_lid_range_ho( p_src_port, &src_lid_min_ho, &src_lid_max_ho ); + osm_port_get_lid_range_ho( p_dest_port, &dest_lid_min_ho, &dest_lid_max_ho ); + + if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_mpr_rcv_get_port_pair_paths: " + "Src LID [0x%X-0x%X], " + "Dest LID [0x%X-0x%X]\n", + src_lid_min_ho, src_lid_max_ho, + dest_lid_min_ho, dest_lid_max_ho ); + } + + src_lid_ho = src_lid_min_ho; + dest_lid_ho = dest_lid_min_ho; + + /* + Preferred paths come first in OpenSM + */ + preference = 0; + + while ( path_num < rem_paths ) + { + /* + These paths are "fully redundant" + */ + p_pr_item = __osm_mpr_rcv_get_lid_pair_path( p_rcv, p_mpr, + p_src_port, p_dest_port, + src_lid_ho, dest_lid_ho, + comp_mask, preference ); + + if ( p_pr_item ) + { + cl_qlist_insert_tail( p_list, + (cl_list_item_t*)&p_pr_item->pool_item ); + ++path_num; + } + + if ( ++src_lid_ho > src_lid_max_ho ) + break; + + if ( ++dest_lid_ho > dest_lid_max_ho ) + break; + } + + /* + Check if we've accumulated all the paths that the user cares to see + */ + if ( path_num == rem_paths ) + goto Exit; + + /* + Don't bother reporting preference 1 paths for now. + It's more trouble than it's worth and can only occur + if ports have different LMC values, which isn't supported + by OpenSM right now anyway. + */ + preference = 2; + src_lid_ho = src_lid_min_ho; + dest_lid_ho = dest_lid_min_ho; + src_offset = 0; + dest_offset = 0; + + /* + Iterate over the remaining paths + */ + while ( path_num < rem_paths ) + { + dest_offset++; + dest_lid_ho++; + + if ( dest_lid_ho > dest_lid_max_ho ) + { + src_offset++; + src_lid_ho++; + + if ( src_lid_ho > src_lid_max_ho ) + break; /* done */ + + dest_offset = 0; + dest_lid_ho = dest_lid_min_ho; + } + + /* + These paths are "fully non-redundant" with paths already + identified above and consequently not of much value. + + Don't return paths we already identified above, as indicated + by the offset values being equal. + */ + if ( src_offset == dest_offset ) + continue; /* already reported */ + + p_pr_item = __osm_mpr_rcv_get_lid_pair_path( p_rcv, p_mpr, + p_src_port, p_dest_port, + src_lid_ho, dest_lid_ho, + comp_mask, preference ); + + if ( p_pr_item ) + { + cl_qlist_insert_tail( p_list, + (cl_list_item_t*)&p_pr_item->pool_item ); + ++path_num; + } + } + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); + return path_num; +} + +#undef min +#define min(x,y) (((x) < (y)) ? (x) : (y)) + +/********************************************************************** + **********************************************************************/ +static osm_mpr_item_t* +__osm_mpr_rcv_get_apm_port_pair_paths( + IN osm_mpr_rcv_t* const p_rcv, + IN const ib_multipath_rec_t* const p_mpr, + IN const osm_port_t* const p_src_port, + IN const osm_port_t* const p_dest_port, + IN int base_offs, + IN const ib_net64_t comp_mask, + IN cl_qlist_t* const p_list ) +{ + osm_mpr_item_t* p_pr_item = 0; + uint16_t src_lid_min_ho; + uint16_t src_lid_max_ho; + uint16_t dest_lid_min_ho; + uint16_t dest_lid_max_ho; + uint16_t src_lid_ho; + uint16_t dest_lid_ho; + uintn_t iterations; + int src_lids, dest_lids; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_mpr_rcv_get_apm_port_pair_paths ); + + if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_mpr_rcv_get_apm_port_pair_paths: " + "Src port 0x%016" PRIx64 ", " + "Dst port 0x%016" PRIx64 ", base offs %d\n", + cl_ntoh64( osm_port_get_guid( p_src_port ) ), + cl_ntoh64( osm_port_get_guid( p_dest_port ) ), + base_offs ); + } + + osm_port_get_lid_range_ho( p_src_port, &src_lid_min_ho, &src_lid_max_ho ); + osm_port_get_lid_range_ho( p_dest_port, &dest_lid_min_ho, &dest_lid_max_ho ); + + src_lid_ho = src_lid_min_ho; + dest_lid_ho = dest_lid_min_ho; + + src_lids = src_lid_max_ho - src_lid_min_ho + 1; + dest_lids = dest_lid_max_ho - dest_lid_min_ho + 1; + + src_lid_ho += base_offs % src_lids; + dest_lid_ho += base_offs % dest_lids; + + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_mpr_rcv_get_apm_port_pair_paths: " + "Src LIDs [0x%X-0x%X] hashed %d, " + "Dest LIDs [0x%X-0x%X] hashed %d\n", + src_lid_min_ho, src_lid_max_ho, src_lid_ho, + dest_lid_min_ho, dest_lid_max_ho, dest_lid_ho ); + + iterations = min( src_lids, dest_lids ); + + while ( iterations-- ) + { + /* + These paths are "fully redundant" + */ + p_pr_item = __osm_mpr_rcv_get_lid_pair_path( p_rcv, p_mpr, + p_src_port, p_dest_port, + src_lid_ho, dest_lid_ho, + comp_mask, 0 ); + + if ( p_pr_item ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_mpr_rcv_get_apm_port_pair_paths: " + "Found matching path from Src LID 0x%X to Dest LID 0x%X with %d hops\n", + src_lid_ho, dest_lid_ho, p_pr_item->hops); + break; + } + + if ( ++src_lid_ho > src_lid_max_ho ) + src_lid_ho = src_lid_min_ho; + + if ( ++dest_lid_ho > dest_lid_max_ho ) + dest_lid_ho = dest_lid_min_ho; + } + + OSM_LOG_EXIT( p_rcv->p_log ); + return p_pr_item; +} + +/********************************************************************** + **********************************************************************/ +static ib_net16_t +__osm_mpr_rcv_get_gids( + IN osm_mpr_rcv_t* const p_rcv, + IN const ib_gid_t * gids, + IN int ngids, + IN int is_sgid, + OUT osm_port_t** pp_port ) +{ + osm_port_t *p_port; + ib_net16_t ib_status = IB_SUCCESS; + int i; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_mpr_rcv_get_gids ); + + for ( i = 0; i < ngids; i++, gids++ ) { + if ( !ib_gid_is_link_local ( gids ) ) { + if ( ( is_sgid && ib_gid_is_multicast( gids ) ) || + ( ib_gid_get_subnet_prefix ( gids ) != p_rcv->p_subn->opt.subnet_prefix ) ) { + /* + This 'error' is the client's fault (bad gid) so + don't enter it as an error in our own log. + Return an error response to the client. + */ + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "__osm_mpr_rcv_get_gids: ERR 451B: " + "Non local %sGID subnet prefix 0x%016" PRIx64 "\n", + is_sgid ? "S" : "D", + cl_ntoh64( gids->unicast.prefix ) ); + + ib_status = IB_SA_MAD_STATUS_INVALID_GID; + goto Exit; + } + } + + p_port = (osm_port_t *)cl_qmap_get( &p_rcv->p_subn->port_guid_tbl, + gids->unicast.interface_id ); + if ( !p_port || + p_port == (osm_port_t *)cl_qmap_end( &p_rcv->p_subn->port_guid_tbl ) ) { + /* + This 'error' is the client's fault (bad gid) so + don't enter it as an error in our own log. + Return an error response to the client. + */ + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_mpr_rcv_get_gids: ERR 4506: " + "No port with GUID 0x%016" PRIx64 "\n", + cl_ntoh64( gids->unicast.interface_id ) ); + + ib_status = IB_SA_MAD_STATUS_INVALID_GID; + goto Exit; + } + + pp_port[i] = p_port; + } + + Exit: + OSM_LOG_EXIT(p_rcv->p_log); + + return ib_status; +} + +/********************************************************************** + **********************************************************************/ +static ib_net16_t +__osm_mpr_rcv_get_end_points( + IN osm_mpr_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw, + OUT osm_port_t ** pp_ports, + OUT int * nsrc, + OUT int * ndest ) +{ + const ib_multipath_rec_t* p_mpr; + const ib_sa_mad_t* p_sa_mad; + ib_net64_t comp_mask; + ib_net16_t sa_status = IB_SA_MAD_STATUS_SUCCESS; + ib_gid_t * gids; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_mpr_rcv_get_end_points ); + + /* + Determine what fields are valid and then get a pointer + to the source and destination port objects, if possible. + */ + p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw ); + p_mpr = (ib_multipath_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad ); + gids = (ib_gid_t *)p_mpr->gids; + + comp_mask = p_sa_mad->comp_mask; + + /* + Check a few easy disqualifying cases up front before getting + into the endpoints. + */ + *nsrc = *ndest = 0; + + if ( comp_mask & IB_MPR_COMPMASK_SGIDCOUNT ) { + *nsrc = p_mpr->sgid_count; + if ( *nsrc > IB_MULTIPATH_MAX_GIDS ) + *nsrc = IB_MULTIPATH_MAX_GIDS; + sa_status = __osm_mpr_rcv_get_gids( p_rcv, gids, *nsrc, 1, pp_ports ); + if ( sa_status != IB_SUCCESS ) + goto Exit; + } + + if ( comp_mask & IB_MPR_COMPMASK_DGIDCOUNT ) { + *ndest = p_mpr->dgid_count; + if ( *ndest + *nsrc > IB_MULTIPATH_MAX_GIDS ) + *ndest = IB_MULTIPATH_MAX_GIDS - *nsrc; + sa_status = __osm_mpr_rcv_get_gids( p_rcv, gids + *nsrc, *ndest, 0, + pp_ports + *nsrc ); + } + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); + return( sa_status ); +} + +#define __hash_lids(a, b, lmc) \ + (((((a) >> (lmc)) << 4) | ((b) >> (lmc))) % 103) + +/********************************************************************** + **********************************************************************/ +static void +__osm_mpr_rcv_get_apm_paths( + IN osm_mpr_rcv_t* const p_rcv, + IN const ib_multipath_rec_t* const p_mpr, + IN const osm_port_t* const p_req_port, + IN osm_port_t ** _pp_ports, + IN const ib_net64_t comp_mask, + IN cl_qlist_t* const p_list ) +{ + osm_port_t *pp_ports[4]; + osm_mpr_item_t *matrix[2][2]; + int base_offs, src_lid_ho, dest_lid_ho; + int sumA, sumB, minA, minB; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_mpr_rcv_get_apm_paths ); + + /* + * We want to: + * 1. use different lid offsets (from base) for the resultant paths + * to increase the probability of redundant paths or in case + * of Clos - to ensure it (different offset => different spine!) + * 2. keep consistent paths no matter of direction and order of ports + * 3. distibute the lid offsets to balance the load + * So, we sort the ports (within the srcs, and within the dests), + * hash the lids of S0, D0 (after the sort), and call __osm_mpr_rcv_get_apm_port_pair_paths + * with base_lid for S0, D0 and base_lid + 1 for S1, D1. This way we will get + * always the same offsets - order indepentent, and make sure different spines are used. + * Note that the diagonals on a Clos have the same number of hops, so it doesn't + * really matter which diagonal we use. + */ + if ( _pp_ports[0]->guid < _pp_ports[1]->guid ) { + pp_ports[0] = _pp_ports[0]; + pp_ports[1] = _pp_ports[1]; + } + else + { + pp_ports[0] = _pp_ports[1]; + pp_ports[1] = _pp_ports[0]; + } + if ( _pp_ports[2]->guid < _pp_ports[3]->guid ) { + pp_ports[2] = _pp_ports[2]; + pp_ports[3] = _pp_ports[3]; + } + else + { + pp_ports[2] = _pp_ports[3]; + pp_ports[3] = _pp_ports[2]; + } + + src_lid_ho = osm_port_get_base_lid( pp_ports[0] ); + dest_lid_ho = osm_port_get_base_lid( pp_ports[2] ); + + base_offs = src_lid_ho < dest_lid_ho ? + __hash_lids( src_lid_ho, dest_lid_ho, p_rcv->p_subn->opt.lmc ) : + __hash_lids( dest_lid_ho, src_lid_ho, p_rcv->p_subn->opt.lmc ); + + matrix[0][0] = __osm_mpr_rcv_get_apm_port_pair_paths( p_rcv, p_mpr, pp_ports[0], + pp_ports[2], base_offs, comp_mask , p_list ); + matrix[0][1] = __osm_mpr_rcv_get_apm_port_pair_paths( p_rcv, p_mpr, pp_ports[0], + pp_ports[3], base_offs, comp_mask, p_list ); + matrix[1][0] = __osm_mpr_rcv_get_apm_port_pair_paths( p_rcv, p_mpr, pp_ports[1], + pp_ports[2], base_offs+1, comp_mask, p_list ); + matrix[1][1] = __osm_mpr_rcv_get_apm_port_pair_paths( p_rcv, p_mpr, pp_ports[1], + pp_ports[3], base_offs+1, comp_mask, p_list ); + + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, "__osm_mpr_rcv_get_apm_paths: " + "APM matrix:\n" + "\t{0,0} 0x%X->0x%X (%d)\t| {0,1} 0x%X->0x%X (%d)\n" + "\t{1,0} 0x%X->0x%X (%d)\t| {1,1} 0x%X->0x%X (%d)\n", + matrix[0][0]->path_rec.slid, matrix[0][0]->path_rec.dlid, matrix[0][0]->hops, + matrix[0][1]->path_rec.slid, matrix[0][1]->path_rec.dlid, matrix[0][1]->hops, + matrix[1][0]->path_rec.slid, matrix[1][0]->path_rec.dlid, matrix[1][0]->hops, + matrix[1][1]->path_rec.slid, matrix[1][1]->path_rec.dlid, matrix[1][1]->hops ); + + /* check diagonal A {(0,0), (1,1)} */ + sumA = matrix[0][0]->hops + matrix[1][1]->hops; + minA = min( matrix[0][0]->hops, matrix[1][1]->hops ); + + /* check diagonal B {(0,1), (1,0)} */ + sumB = matrix[0][1]->hops + matrix[1][0]->hops; + minB = min( matrix[0][1]->hops, matrix[1][0]->hops ); + + /* and the winner is... */ + if ( minA <= minB || ( minA == minB && sumA < sumB ) ) { + /* Diag A */ + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, "__osm_mpr_rcv_get_apm_paths: " + "Diag {0,0} & {1,1} is the best:\n" + "\t{0,0} 0x%X->0x%X (%d)\t & {1,1} 0x%X->0x%X (%d)\n", + matrix[0][0]->path_rec.slid, matrix[0][0]->path_rec.dlid, matrix[0][0]->hops, + matrix[1][1]->path_rec.slid, matrix[1][1]->path_rec.dlid, matrix[1][1]->hops ); + cl_qlist_insert_tail( p_list, + (cl_list_item_t*)&matrix[0][0]->pool_item ); + cl_qlist_insert_tail( p_list, + (cl_list_item_t*)&matrix[1][1]->pool_item ); + cl_qlock_pool_put( &p_rcv->pr_pool, &matrix[0][1]->pool_item ); + cl_qlock_pool_put( &p_rcv->pr_pool, &matrix[1][0]->pool_item ); + } + else + { + /* Diag B */ + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, "__osm_mpr_rcv_get_apm_paths: " + "Diag {0,1} & {1,0} is the best:\n" + "\t{0,1} 0x%X->0x%X (%d)\t & {1,0} 0x%X->0x%X (%d)\n", + matrix[0][1]->path_rec.slid, matrix[0][1]->path_rec.dlid, matrix[0][1]->hops, + matrix[1][0]->path_rec.slid, matrix[1][0]->path_rec.dlid, matrix[1][0]->hops ); + cl_qlist_insert_tail( p_list, + (cl_list_item_t*)&matrix[0][1]->pool_item ); + cl_qlist_insert_tail( p_list, + (cl_list_item_t*)&matrix[1][0]->pool_item ); + cl_qlock_pool_put( &p_rcv->pr_pool, &matrix[0][0]->pool_item ); + cl_qlock_pool_put( &p_rcv->pr_pool, &matrix[1][1]->pool_item ); + } + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_mpr_rcv_process_pairs( + IN osm_mpr_rcv_t* const p_rcv, + IN const ib_multipath_rec_t* const p_mpr, + IN osm_port_t* const p_req_port, + IN osm_port_t ** pp_ports, + IN const int nsrc, + IN const int ndest, + IN const ib_net64_t comp_mask, + IN cl_qlist_t* const p_list ) +{ + osm_port_t **pp_src_port, **pp_es; + osm_port_t **pp_dest_port, **pp_ed; + uint32_t max_paths, num_paths, total_paths = 0; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_mpr_rcv_process_pairs ); + + if ( comp_mask & IB_MPR_COMPMASK_NUMBPATH ) + max_paths = p_mpr->num_path & 0x7F; + else + max_paths = OSM_SA_MPR_MAX_NUM_PATH; + + for ( pp_src_port = pp_ports, pp_es = pp_ports + nsrc; pp_src_port < pp_es; pp_src_port++ ) + { + for ( pp_dest_port = pp_es, pp_ed = pp_es + ndest; pp_dest_port < pp_ed; pp_dest_port++ ) + { + num_paths = __osm_mpr_rcv_get_port_pair_paths( p_rcv, p_mpr, p_req_port, + *pp_src_port, *pp_dest_port, + max_paths - total_paths, + comp_mask, p_list ); + total_paths += num_paths; + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_mpr_rcv_process_pairs: " + "%d paths %d total paths %d max paths\n", + num_paths, total_paths, max_paths ); + /* Just take first NumbPaths found */ + if (total_paths >= max_paths) + goto Exit; + } + } + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_mpr_rcv_respond( + IN osm_mpr_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw, + IN cl_qlist_t* const p_list ) +{ + osm_madw_t* p_resp_madw; + const ib_sa_mad_t* p_sa_mad; + ib_sa_mad_t* p_resp_sa_mad; + size_t num_rec; + size_t mad_size; + ib_path_rec_t* p_resp_pr; + ib_multipath_rec_t* p_mpr; + ib_api_status_t status; + osm_mpr_item_t* p_mpr_item; + uint32_t i; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_mpr_rcv_respond ); + + p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw ); + p_mpr = (ib_multipath_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad ); + + num_rec = cl_qlist_count( p_list ); + + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_mpr_rcv_respond: " + "Generating response with %zu records\n", num_rec ); + + mad_size = IB_SA_MAD_HDR_SIZE + num_rec * sizeof(ib_path_rec_t); + + /* + Get a MAD to reply. Address of Mad is in the received mad_wrapper + */ + p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool, p_madw->h_bind, + mad_size, &p_madw->mad_addr ); + + if ( !p_resp_madw ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_mpr_rcv_respond: " + "ERR 4502: Unable to allocate MAD\n" ); + + for ( i = 0; i < num_rec; i++ ) + { + p_mpr_item = (osm_mpr_item_t*)cl_qlist_remove_head( p_list ); + cl_qlock_pool_put( &p_rcv->pr_pool, &p_mpr_item->pool_item ); + } + + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES ); + goto Exit; + } + + p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw ); + + memcpy( p_resp_sa_mad, p_sa_mad, IB_SA_MAD_HDR_SIZE ); + p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK; + /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */ + p_resp_sa_mad->sm_key = 0; + + /* + o15-0.2.7: If MultiPath is supported, then SA shall respond to a + SubnAdmGetMulti() containing a valid MultiPathRecord attribute with + a set of zero or more PathRecords satisfying the constraints indicated + in the MultiPathRecord received. The PathRecord Attribute ID shall be + used in the response. + */ + p_resp_sa_mad->attr_id = IB_MAD_ATTR_PATH_RECORD; + p_resp_sa_mad->attr_offset = ib_get_attr_offset( sizeof(ib_path_rec_t) ); + + p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE; + + p_resp_pr = (ib_path_rec_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad ); + + for ( i = 0; i < num_rec; i++ ) + { + p_mpr_item = (osm_mpr_item_t*)cl_qlist_remove_head( p_list ); + + /* Copy the Path Records from the list into the MAD */ + *p_resp_pr = p_mpr_item->path_rec; + + cl_qlock_pool_put( &p_rcv->pr_pool, &p_mpr_item->pool_item ); + p_resp_pr++; + } + + CL_ASSERT( cl_is_qlist_empty( p_list ) ); + + osm_dump_sa_mad( p_rcv->p_log, p_resp_sa_mad, OSM_LOG_FRAMES ); + + status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE ); + + if ( status != IB_SUCCESS ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_mpr_rcv_respond: ERR 4507: " + "Unable to send MAD (%s)\n", ib_get_err_str( status ) ); + /* osm_mad_pool_put( p_rcv->p_mad_pool, p_resp_madw ); */ + } + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_mpr_rcv_process( + IN osm_mpr_rcv_t* const p_rcv, + IN osm_madw_t* const p_madw ) +{ + const ib_multipath_rec_t* p_mpr; + const ib_sa_mad_t* p_sa_mad; + osm_port_t* requester_port; + osm_port_t* pp_ports[IB_MULTIPATH_MAX_GIDS]; + cl_qlist_t pr_list; + ib_net16_t sa_status; + int nsrc, ndest; + + OSM_LOG_ENTER( p_rcv->p_log, osm_mpr_rcv_process ); + + CL_ASSERT( p_madw ); + + p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw ); + p_mpr = (ib_multipath_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad ); + + CL_ASSERT( p_sa_mad->attr_id == IB_MAD_ATTR_MULTIPATH_RECORD ); + + if ( ( p_sa_mad->rmpp_flags & IB_RMPP_FLAG_ACTIVE ) != IB_RMPP_FLAG_ACTIVE ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_mpr_rcv_process: ERR 4510: " + "Invalid request since RMPP_FLAG_ACTIVE is not set\n" ); + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_REQ_INVALID ); + goto Exit; + } + + /* we only support SubnAdmGetMulti method */ + if ( p_sa_mad->method != IB_MAD_METHOD_GETMULTI ) { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_mpr_rcv_process: ERR 4513: " + "Unsupported Method (%s)\n", + ib_get_sa_method_str( p_sa_mad->method ) ); + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR ); + goto Exit; + } + + /* update the requester physical port. */ + requester_port = osm_get_port_by_mad_addr( p_rcv->p_log, p_rcv->p_subn, + osm_madw_get_mad_addr_ptr( p_madw ) ); + if ( requester_port == NULL ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_mpr_rcv_process: ERR 4517: " + "Cannot find requester physical port\n" ); + goto Exit; + } + + if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + osm_dump_multipath_record( p_rcv->p_log, p_mpr, OSM_LOG_DEBUG ); + + cl_qlist_init( &pr_list ); + + /* + Most SA functions (including this one) are read-only on the + subnet object, so we grab the lock non-exclusively. + */ + cl_plock_acquire( p_rcv->p_lock ); + + sa_status = __osm_mpr_rcv_get_end_points( p_rcv, p_madw, pp_ports, + &nsrc, &ndest ); + + if ( sa_status != IB_SA_MAD_STATUS_SUCCESS || !nsrc || !ndest ) + { + if ( sa_status == IB_SA_MAD_STATUS_SUCCESS && ( !nsrc || !ndest ) ) + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_mpr_rcv_process_cb: ERR 4512: " + "__osm_mpr_rcv_get_end_points failed, not enough GIDs " + "(nsrc %d ndest %d)\n", + nsrc, ndest); + cl_plock_release( p_rcv->p_lock ); + if ( sa_status == IB_SA_MAD_STATUS_SUCCESS ) + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_REQ_INVALID ); + else + osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status ); + goto Exit; + } + + /* APM request */ + if ( nsrc == 2 && ndest == 2 && ( p_mpr->num_path & 0x7F ) == 2 ) + __osm_mpr_rcv_get_apm_paths( p_rcv, p_mpr, requester_port, pp_ports, + p_sa_mad->comp_mask, &pr_list ); + else + __osm_mpr_rcv_process_pairs( p_rcv, p_mpr, requester_port, pp_ports, + nsrc, ndest, + p_sa_mad->comp_mask, &pr_list ); + + cl_plock_release( p_rcv->p_lock ); + __osm_mpr_rcv_respond( p_rcv, p_madw, &pr_list ); + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} +#endif + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_multipath_record_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_multipath_record_ctrl.c new file mode 100644 index 00000000..6a30be92 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_multipath_record_ctrl.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ + + + +/* + * Abstract: + * Implementation of osm_mpr_rcv_ctrl_t. + * This object represents the MultiPathRecord request controller object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + */ + +#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP) + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +static void +__osm_mpr_rcv_ctrl_disp_callback( + IN void *context, + IN void *p_data ) +{ + /* ignore return status when invoked via the dispatcher */ + osm_mpr_rcv_process( ((osm_mpr_rcv_ctrl_t*)context)->p_rcv, + (osm_madw_t*)p_data ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_mpr_rcv_ctrl_construct( + IN osm_mpr_rcv_ctrl_t* const p_ctrl ) +{ + memset( p_ctrl, 0, sizeof(*p_ctrl) ); + p_ctrl->h_disp = CL_DISP_INVALID_HANDLE; +} + +/********************************************************************** + **********************************************************************/ +void +osm_mpr_rcv_ctrl_destroy( + IN osm_mpr_rcv_ctrl_t* const p_ctrl ) +{ + CL_ASSERT( p_ctrl ); + cl_disp_unregister( p_ctrl->h_disp ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_mpr_rcv_ctrl_init( + IN osm_mpr_rcv_ctrl_t* const p_ctrl, + IN osm_mpr_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_mpr_rcv_ctrl_init ); + + osm_mpr_rcv_ctrl_construct( p_ctrl ); + p_ctrl->p_log = p_log; + p_ctrl->p_rcv = p_rcv; + p_ctrl->p_disp = p_disp; + + p_ctrl->h_disp = cl_disp_register( + p_disp, + OSM_MSG_MAD_MULTIPATH_RECORD, + __osm_mpr_rcv_ctrl_disp_callback, + p_ctrl ); + + if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_mpr_rcv_ctrl_init: ERR 4B01: " + "Dispatcher registration failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return( status ); +} + +#endif + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_node_record.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_node_record.c new file mode 100644 index 00000000..1d78ee86 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_node_record.c @@ -0,0 +1,600 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_node_record.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Implementation of osm_nr_rcv_t. + * This object represents the NodeInfo Receiver object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.8 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define OSM_NR_RCV_POOL_MIN_SIZE 32 +#define OSM_NR_RCV_POOL_GROW_SIZE 32 + +typedef struct _osm_nr_item +{ + cl_pool_item_t pool_item; + ib_node_record_t rec; +} osm_nr_item_t; + +typedef struct _osm_nr_search_ctxt +{ + const ib_node_record_t* p_rcvd_rec; + ib_net64_t comp_mask; + cl_qlist_t* p_list; + osm_nr_rcv_t* p_rcv; + const osm_physp_t* p_req_physp; +} osm_nr_search_ctxt_t; + +/********************************************************************** + **********************************************************************/ +void +osm_nr_rcv_construct( + IN osm_nr_rcv_t* const p_rcv ) +{ + memset( p_rcv, 0, sizeof(*p_rcv) ); + cl_qlock_pool_construct( &p_rcv->pool ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_nr_rcv_destroy( + IN osm_nr_rcv_t* const p_rcv ) +{ + OSM_LOG_ENTER( p_rcv->p_log, osm_nr_rcv_destroy ); + cl_qlock_pool_destroy( &p_rcv->pool ); + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_nr_rcv_init( + IN osm_nr_rcv_t* const p_rcv, + IN osm_sa_resp_t* const p_resp, + IN osm_mad_pool_t* const p_mad_pool, + IN const osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ) +{ + ib_api_status_t status; + + OSM_LOG_ENTER( p_log, osm_nr_rcv_init ); + + osm_nr_rcv_construct( p_rcv ); + + p_rcv->p_log = p_log; + p_rcv->p_subn = p_subn; + p_rcv->p_lock = p_lock; + p_rcv->p_resp = p_resp; + p_rcv->p_mad_pool = p_mad_pool; + + status = cl_qlock_pool_init( &p_rcv->pool, + OSM_NR_RCV_POOL_MIN_SIZE, + 0, + OSM_NR_RCV_POOL_GROW_SIZE, + sizeof(osm_nr_item_t), + NULL, NULL, NULL ); + + OSM_LOG_EXIT( p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +static ib_api_status_t +__osm_nr_rcv_new_nr( + IN osm_nr_rcv_t* const p_rcv, + IN const osm_node_t* const p_node, + IN cl_qlist_t* const p_list, + IN ib_net64_t const port_guid, + IN ib_net16_t const lid ) +{ + osm_nr_item_t* p_rec_item; + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_nr_rcv_new_nr ); + + p_rec_item = (osm_nr_item_t*)cl_qlock_pool_get( &p_rcv->pool ); + if( p_rec_item == NULL ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_nr_rcv_new_nr: ERR 1D02: " + "cl_qlock_pool_get failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_nr_rcv_new_nr: " + "New NodeRecord: node 0x%016" PRIx64 + "\n\t\t\t\tport 0x%016" PRIx64 ", lid 0x%X\n", + cl_ntoh64( osm_node_get_node_guid( p_node ) ), + cl_ntoh64( port_guid ), cl_ntoh16( lid ) + ); + } + + memset( &p_rec_item->rec, 0, sizeof(ib_node_record_t) ); + + p_rec_item->rec.lid = lid; + + p_rec_item->rec.node_info = p_node->node_info; + p_rec_item->rec.node_info.port_guid = port_guid; + memcpy(&(p_rec_item->rec.node_desc), &(p_node->node_desc), + IB_NODE_DESCRIPTION_SIZE); + cl_qlist_insert_tail( p_list, (cl_list_item_t*)&p_rec_item->pool_item ); + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_nr_rcv_create_nr( + IN osm_nr_rcv_t* const p_rcv, + IN const osm_node_t* const p_node, + IN cl_qlist_t* const p_list, + IN ib_net64_t const match_port_guid, + IN ib_net16_t const match_lid, + IN const osm_physp_t* const p_req_physp ) +{ + const osm_physp_t* p_physp; + uint8_t port_num; + uint8_t num_ports; + uint16_t match_lid_ho; + ib_net16_t base_lid; + ib_net16_t base_lid_ho; + ib_net16_t max_lid_ho; + uint8_t lmc; + ib_net64_t port_guid; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_nr_rcv_create_nr ); + + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_nr_rcv_create_nr: " + "Looking for NodeRecord with LID: 0x%X GUID:0x%016" PRIx64 "\n", + cl_ntoh16( match_lid ), + cl_ntoh64( match_port_guid ) + ); + } + + /* + For switches, do not return the NodeInfo record + for each port on the switch, just for port 0. + */ + if( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH ) + num_ports = 1; + else + num_ports = osm_node_get_num_physp( p_node ); + + for( port_num = 0; port_num < num_ports; port_num++ ) + { + p_physp = osm_node_get_physp_ptr( p_node, port_num ); + + if( !osm_physp_is_valid( p_physp ) ) + continue; + + /* Check to see if the found p_physp and the requester physp + share a pkey. If not - continue */ + if (!osm_physp_share_pkey( p_rcv->p_log, p_physp, p_req_physp ) ) + continue; + + port_guid = osm_physp_get_port_guid( p_physp ); + + if( match_port_guid && ( port_guid != match_port_guid ) ) + continue; + + base_lid = osm_physp_get_base_lid( p_physp ); + base_lid_ho = cl_ntoh16( base_lid ); + lmc = osm_physp_get_lmc( p_physp ); + max_lid_ho = (uint16_t)( base_lid_ho + (1 << lmc) - 1 ); + match_lid_ho = cl_ntoh16( match_lid ); + + if( match_lid_ho ) + { + /* + We validate that the lid belongs to this node. + */ + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_nr_rcv_create_nr: " + "Comparing LID: 0x%X <= 0x%X <= 0x%X\n", + base_lid_ho, match_lid_ho, max_lid_ho + ); + } + + if ( match_lid_ho < base_lid_ho || match_lid_ho > max_lid_ho ) + continue; + } + + __osm_nr_rcv_new_nr( p_rcv, p_node, p_list, port_guid, base_lid ); + + } + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_nr_rcv_by_comp_mask( + IN cl_map_item_t* const p_map_item, + IN void* context ) +{ + const osm_nr_search_ctxt_t* const p_ctxt = (osm_nr_search_ctxt_t *)context; + const osm_node_t* const p_node = (osm_node_t*)p_map_item; + const ib_node_record_t* const p_rcvd_rec = p_ctxt->p_rcvd_rec; + const osm_physp_t* const p_req_physp = p_ctxt->p_req_physp; + osm_nr_rcv_t* const p_rcv = p_ctxt->p_rcv; + ib_net64_t const comp_mask = p_ctxt->comp_mask; + ib_net64_t match_port_guid = 0; + ib_net16_t match_lid = 0; + + OSM_LOG_ENTER( p_ctxt->p_rcv->p_log, __osm_nr_rcv_by_comp_mask ); + + osm_dump_node_info( + p_ctxt->p_rcv->p_log, + &p_node->node_info, + OSM_LOG_VERBOSE ); + + if( comp_mask & IB_NR_COMPMASK_LID ) + match_lid = p_rcvd_rec->lid; + + if( comp_mask & IB_NR_COMPMASK_NODEGUID) + { + /* + DEBUG TOP + */ + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_nr_rcv_by_comp_mask: " + "Looking for node 0x%016" PRIx64 + ", found 0x%016" PRIx64 "\n", + cl_ntoh64( p_rcvd_rec->node_info.node_guid ), + cl_ntoh64( osm_node_get_node_guid( p_node ) ) + ); + } + /* + DEBUG BOTTOM + */ + if( (p_node->node_info.node_guid != p_rcvd_rec->node_info.node_guid) ) + goto Exit; + } + if( comp_mask & IB_NR_COMPMASK_PORTGUID ) + { + match_port_guid = p_rcvd_rec->node_info.port_guid; + } + if( comp_mask & IB_NR_COMPMASK_SYSIMAGEGUID ) + { + if( (p_node->node_info.sys_guid != p_rcvd_rec->node_info.sys_guid) ) + goto Exit; + } + if( comp_mask & IB_NR_COMPMASK_BASEVERSION ) + { + if( (p_node->node_info.base_version != p_rcvd_rec->node_info.base_version) ) + goto Exit; + } + if( comp_mask & IB_NR_COMPMASK_CLASSVERSION ) + { + if( (p_node->node_info.class_version != p_rcvd_rec->node_info.class_version) ) + goto Exit; + } + if( comp_mask & IB_NR_COMPMASK_NODETYPE ) + { + if( (p_node->node_info.node_type != p_rcvd_rec->node_info.node_type) ) + goto Exit; + } + if( comp_mask & IB_NR_COMPMASK_NUMPORTS ) + { + if( (p_node->node_info.num_ports != p_rcvd_rec->node_info.num_ports) ) + goto Exit; + } + if( comp_mask & IB_NR_COMPMASK_PARTCAP ) + { + if( (p_node->node_info.partition_cap != p_rcvd_rec->node_info.partition_cap) ) + goto Exit; + } + if( comp_mask & IB_NR_COMPMASK_DEVID ) + { + if( (p_node->node_info.device_id != p_rcvd_rec->node_info.device_id) ) + goto Exit; + } + if( comp_mask & IB_NR_COMPMASK_REV ) + { + if( (p_node->node_info.revision != p_rcvd_rec->node_info.revision) ) + goto Exit; + } + if( comp_mask & IB_NR_COMPMASK_PORTNUM ) + { + if( ib_node_info_get_local_port_num(&p_node->node_info) != + ib_node_info_get_local_port_num(&p_rcvd_rec->node_info) ) + goto Exit; + } + if( comp_mask & IB_NR_COMPMASK_VENDID ) + { + if( ib_node_info_get_vendor_id(&p_node->node_info) != + ib_node_info_get_vendor_id(&p_rcvd_rec->node_info) ) + goto Exit; + } + if( comp_mask & IB_NR_COMPMASK_NODEDESC ) + { + if( strncmp((char*) &p_node->node_desc, + (char*) &p_rcvd_rec->node_desc, sizeof(ib_node_desc_t)) ) + goto Exit; + } + + __osm_nr_rcv_create_nr( p_rcv, p_node, p_ctxt->p_list, + match_port_guid, match_lid, p_req_physp ); + + Exit: + OSM_LOG_EXIT( p_ctxt->p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_nr_rcv_process( + IN osm_nr_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ) +{ + const ib_sa_mad_t* p_rcvd_mad; + const ib_node_record_t* p_rcvd_rec; + ib_node_record_t* p_resp_rec; + cl_qlist_t rec_list; + osm_madw_t* p_resp_madw; + ib_sa_mad_t* p_resp_sa_mad; + uint32_t num_rec, pre_trim_num_rec; +#ifndef VENDOR_RMPP_SUPPORT + uint32_t trim_num_rec; +#endif + uint32_t i; + osm_nr_search_ctxt_t context; + osm_nr_item_t* p_rec_item; + ib_api_status_t status; + osm_physp_t* p_req_physp; + + CL_ASSERT( p_rcv ); + + OSM_LOG_ENTER( p_rcv->p_log, osm_nr_rcv_process ); + + CL_ASSERT( p_madw ); + + p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw ); + p_rcvd_rec = (ib_node_record_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad ); + + CL_ASSERT( p_rcvd_mad->attr_id == IB_MAD_ATTR_NODE_RECORD ); + + /* we only support SubnAdmGet and SubnAdmGetTable methods */ + if ( (p_rcvd_mad->method != IB_MAD_METHOD_GET) && + (p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) ) { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_nr_rcv_process: ERR 1D05: " + "Unsupported Method (%s)\n", + ib_get_sa_method_str( p_rcvd_mad->method ) ); + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR ); + goto Exit; + } + + /* update the requester physical port. */ + p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log, + p_rcv->p_subn, + osm_madw_get_mad_addr_ptr(p_madw) ); + if (p_req_physp == NULL) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_nr_rcv_process: ERR 1D04: " + "Cannot find requester physical port\n" ); + goto Exit; + } + + if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + osm_dump_node_record( p_rcv->p_log, p_rcvd_rec, OSM_LOG_DEBUG ); + + cl_qlist_init( &rec_list ); + + context.p_rcvd_rec = p_rcvd_rec; + context.p_list = &rec_list; + context.comp_mask = p_rcvd_mad->comp_mask; + context.p_rcv = p_rcv; + context.p_req_physp = p_req_physp; + + cl_plock_acquire( p_rcv->p_lock ); + + cl_qmap_apply_func( &p_rcv->p_subn->node_guid_tbl, + __osm_nr_rcv_by_comp_mask, + &context ); + + cl_plock_release( p_rcv->p_lock ); + + num_rec = cl_qlist_count( &rec_list ); + + /* + * C15-0.1.30: + * If we do a SubnAdmGet and got more than one record it is an error ! + */ + if ( (p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec > 1) ) { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_nr_rcv_process: ERR 1D03: " + "Got more than one record for SubnAdmGet (%u)\n", + num_rec ); + osm_sa_send_error( p_rcv->p_resp, p_madw, + IB_SA_MAD_STATUS_TOO_MANY_RECORDS ); + + /* need to set the mem free ... */ + p_rec_item = (osm_nr_item_t*)cl_qlist_remove_head( &rec_list ); + while( p_rec_item != (osm_nr_item_t*)cl_qlist_end( &rec_list ) ) + { + cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item ); + p_rec_item = (osm_nr_item_t*)cl_qlist_remove_head( &rec_list ); + } + + goto Exit; + } + + pre_trim_num_rec = num_rec; +#ifndef VENDOR_RMPP_SUPPORT + /* we limit the number of records to a single packet */ + trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_node_record_t); + if (trim_num_rec < num_rec) + { + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "osm_nr_rcv_process: " + "Number of records:%u trimmed to:%u to fit in one MAD\n", + num_rec, trim_num_rec ); + num_rec = trim_num_rec; + } +#endif + + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "osm_nr_rcv_process: " + "Returning %u records\n", num_rec ); + + if ((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0)) + { + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS ); + goto Exit; + } + + /* + * Get a MAD to reply. Address of Mad is in the received mad_wrapper + */ + p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool, + p_madw->h_bind, + num_rec * sizeof(ib_node_record_t) + IB_SA_MAD_HDR_SIZE, + &p_madw->mad_addr ); + + if( !p_resp_madw ) + { + osm_log(p_rcv->p_log, OSM_LOG_ERROR, + "osm_nr_rcv_process: ERR 1D06: " + "osm_mad_pool_get failed\n" ); + + for( i = 0; i < num_rec; i++ ) + { + p_rec_item = (osm_nr_item_t*)cl_qlist_remove_head( &rec_list ); + cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item ); + } + + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES ); + goto Exit; + } + + p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw ); + + /* + Copy the MAD header back into the response mad. + Set the 'R' bit and the payload length, + Then copy all records from the list into the response payload. + */ + + memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE ); + p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK; + /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */ + p_resp_sa_mad->sm_key = 0; + /* Fill in the offset (paylen will be done by the rmpp SAR) */ + p_resp_sa_mad->attr_offset = + ib_get_attr_offset( sizeof(ib_node_record_t) ); + + p_resp_rec = (ib_node_record_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad ); + +#ifndef VENDOR_RMPP_SUPPORT + /* we support only one packet RMPP - so we will set the first and + last flags for gettable */ + if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP) + { + p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA; + p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE; + } +#else + /* forcefully define the packet as RMPP one */ + if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP) + p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE; +#endif + + for( i = 0; i < pre_trim_num_rec; i++ ) + { + p_rec_item = (osm_nr_item_t*)cl_qlist_remove_head( &rec_list ); + /* copy only if not trimmed */ + if (i < num_rec) + { + *p_resp_rec = p_rec_item->rec; + } + cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item ); + p_resp_rec++; + } + + CL_ASSERT( cl_is_qlist_empty( &rec_list ) ); + + status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE ); + if (status != IB_SUCCESS) + { + osm_log(p_rcv->p_log, OSM_LOG_ERROR, + "osm_nr_rcv_process: ERR 1D07: " + "osm_vendor_send status = %s\n", + ib_get_err_str(status)); + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_node_record_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_node_record_ctrl.c new file mode 100644 index 00000000..d40c1315 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_node_record_ctrl.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_node_record_ctrl.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_nr_rcv_ctrl_t. + * This object represents the Node Record controller object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +__osm_nr_ctrl_disp_callback( + IN void *context, + IN void *p_data ) +{ + /* ignore return status when invoked via the dispatcher */ + osm_nr_rcv_process( ((osm_nr_rcv_ctrl_t*)context)->p_rcv, + (osm_madw_t*)p_data ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_nr_rcv_ctrl_construct( + IN osm_nr_rcv_ctrl_t* const p_ctrl ) +{ + memset( p_ctrl, 0, sizeof(*p_ctrl) ); + p_ctrl->h_disp = CL_DISP_INVALID_HANDLE; +} + +/********************************************************************** + **********************************************************************/ +void +osm_nr_rcv_ctrl_destroy( + IN osm_nr_rcv_ctrl_t* const p_ctrl ) +{ + CL_ASSERT( p_ctrl ); + cl_disp_unregister( p_ctrl->h_disp ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_nr_rcv_ctrl_init( + IN osm_nr_rcv_ctrl_t* const p_ctrl, + IN osm_nr_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_nr_rcv_ctrl_init ); + + osm_nr_rcv_ctrl_construct( p_ctrl ); + p_ctrl->p_log = p_log; + p_ctrl->p_rcv = p_rcv; + p_ctrl->p_disp = p_disp; + + p_ctrl->h_disp = cl_disp_register( + p_disp, + OSM_MSG_MAD_NODE_RECORD, + __osm_nr_ctrl_disp_callback, + p_ctrl ); + + if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_nr_rcv_ctrl_init: ERR 1E01: " + "Dispatcher registration failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return( status ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_path_record.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_path_record.c new file mode 100644 index 00000000..9377fdab --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_path_record.c @@ -0,0 +1,2006 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_path_record.c 1929 2009-02-04 15:24:59Z tzachid $ + */ + + +/* + * 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 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 ) +{ + memset( p_rcv, 0, 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 inline boolean_t +__osm_sa_path_rec_is_tavor_port( + IN const osm_port_t* const p_port) +{ + osm_node_t const* p_node; + ib_net32_t vend_id; + + p_node = osm_port_get_parent_node( p_port ); + vend_id = ib_node_info_get_vendor_id( &p_node->node_info ); + + return( (p_node->node_info.device_id == CL_HTON16(23108)) && + ((vend_id == CL_HTON32(OSM_VENDOR_ID_MELLANOX)) || + (vend_id == CL_HTON32(OSM_VENDOR_ID_TOPSPIN)) || + (vend_id == CL_HTON32(OSM_VENDOR_ID_SILVERSTORM)) || + (vend_id == CL_HTON32(OSM_VENDOR_ID_VOLTAIRE))) ); +} + +/********************************************************************** + **********************************************************************/ +static boolean_t + __osm_sa_path_rec_apply_tavor_mtu_limit( + 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 ib_net64_t comp_mask) +{ + uint8_t required_mtu; + + /* only if at least one of the ports is a Tavor device */ + if (! __osm_sa_path_rec_is_tavor_port(p_src_port) && + ! __osm_sa_path_rec_is_tavor_port(p_dest_port) ) + return( FALSE ); + + /* + we can apply the patch if either: + 1. No MTU required + 2. Required MTU < + 3. Required MTU = 1K or 512 or 256 + 4. Required MTU > 256 or 512 + */ + required_mtu = ib_path_rec_mtu( p_pr ); + if ( ( comp_mask & IB_PR_COMPMASK_MTUSELEC ) && + ( comp_mask & IB_PR_COMPMASK_MTU ) ) + { + switch( ib_path_rec_mtu_sel( p_pr ) ) + { + case 0: /* must be greater than */ + case 2: /* exact match */ + if( IB_MTU_LEN_1024 < required_mtu ) + return(FALSE); + break; + + case 1: /* must be less than */ + /* can't be disqualified by this one */ + break; + + case 3: /* largest available */ + /* the ULP intentionally requested */ + /* the largest MTU possible */ + return(FALSE); + break; + + default: + /* if we're here, there's a bug in ib_path_rec_mtu_sel() */ + CL_ASSERT( FALSE ); + break; + } + } + + return(TRUE); +} + +/********************************************************************** + **********************************************************************/ +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 ) +{ + const osm_node_t* p_node; + const osm_physp_t* p_physp; + const osm_physp_t* p_dest_physp; + const osm_prtn_t* p_prtn; + const ib_port_info_t* p_pi; + ib_api_status_t status = IB_SUCCESS; + ib_net16_t pkey; + uint8_t mtu; + uint8_t rate; + uint8_t pkt_life; + uint8_t required_mtu; + uint8_t required_rate; + uint8_t required_pkt_life; + uint8_t sl; + 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 ); + + mtu = ib_port_info_get_mtu_cap( p_pi ); + rate = ib_port_info_compute_rate( p_pi ); + + /* + Mellanox Tavor device performance is better using 1K MTU. + If required MTU and MTU selector are such that 1K is OK + and at least one end of the path is Tavor we override the + port MTU with 1K. + */ + if ( p_rcv->p_subn->opt.enable_quirks && + __osm_sa_path_rec_apply_tavor_mtu_limit( + p_pr, p_src_port, p_dest_port, comp_mask) ) + if (mtu > IB_MTU_LEN_1024) + { + mtu = IB_MTU_LEN_1024; + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_pr_rcv_get_path_parms: " + "Optimized Path MTU to 1K for Mellanox Tavor device\n"); + } + + /* + Walk the subnet object from source to destination, + tracking the most restrictive rate and mtu values along the way... + + If source port node is a switch, then p_physp should + point to the port that routes the destination lid + */ + + p_node = osm_physp_get_node_ptr( p_physp ); + + if( p_node->sw ) + { + /* + * If the dest_lid_ho is equal to the lid of the switch pointed by + * p_sw then p_physp will be the physical port of the switch port zero. + */ + p_physp = osm_switch_get_route_by_lid(p_node->sw, cl_ntoh16( dest_lid_ho ) ); + if ( p_physp == 0 ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_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( p_node->sw ) + { + p_dest_physp = osm_switch_get_route_by_lid( p_node->sw, cl_ntoh16( dest_lid_ho ) ); + + if ( p_dest_physp == 0 ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_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( !p_node->sw ) + { + /* + There is some sort of problem in the subnet object! + If this isn't a switch, we should have reached + the destination by now! + */ + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_pr_rcv_get_path_parms: ERR 1F06: " + "Internal error, bad path\n" ); + status = IB_ERROR; + goto Exit; + } + + /* + Check parameters for the ingress port in this switch. + */ + p_pi = osm_physp_get_port_info_ptr( p_physp ); + + if( mtu > ib_port_info_get_mtu_cap( p_pi ) ) + { + mtu = ib_port_info_get_mtu_cap( p_pi ); + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_pr_rcv_get_path_parms: " + "New smallest MTU = %u at intervening port 0x%016" PRIx64 + " port num 0x%X\n", + mtu, + cl_ntoh64( osm_physp_get_port_guid( p_physp ) ), + osm_physp_get_port_num( p_physp ) ); + } + } + + if( rate > ib_port_info_compute_rate( p_pi ) ) + { + rate = ib_port_info_compute_rate( p_pi ); + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_pr_rcv_get_path_parms: " + "New smallest rate = %u at intervening port 0x%016" PRIx64 + " port num 0x%X\n", + rate, + cl_ntoh64( osm_physp_get_port_guid( p_physp ) ), + osm_physp_get_port_num( p_physp ) ); + } + } + + /* + Continue with the egress port on this switch. + */ + p_physp = osm_switch_get_route_by_lid( p_node->sw, dest_lid ); + + if ( p_physp == 0 ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_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( osm_node_get_node_guid( p_node ) ) ); + 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 + " port num 0x%X\n", + mtu, + cl_ntoh64( osm_physp_get_port_guid( p_physp ) ), + osm_physp_get_port_num( p_physp ) ); + } + } + + if( rate > ib_port_info_compute_rate( p_pi ) ) + { + rate = ib_port_info_compute_rate( p_pi ); + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_pr_rcv_get_path_parms: " + "New smallest rate = %u at intervening port 0x%016" PRIx64 + " port num 0x%X\n", + rate, + cl_ntoh64( osm_physp_get_port_guid( p_physp ) ), + osm_physp_get_port_num( p_physp ) ); + } + } + + } + + /* + p_physp now points to the destination + */ + p_pi = osm_physp_get_port_info_ptr( p_physp ); + + if( mtu > ib_port_info_get_mtu_cap( p_pi ) ) + { + mtu = ib_port_info_get_mtu_cap( p_pi ); + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_pr_rcv_get_path_parms: " + "New smallest MTU = %u at destination port 0x%016" PRIx64 "\n", + mtu, + cl_ntoh64(osm_physp_get_port_guid( p_physp )) ); + } + } + + if( rate > ib_port_info_compute_rate( p_pi ) ) + { + rate = ib_port_info_compute_rate( p_pi ); + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_pr_rcv_get_path_parms: " + "New smallest rate = %u at destination port 0x%016" PRIx64 "\n", + rate, + cl_ntoh64(osm_physp_get_port_guid( p_physp )) ); + } + } + + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_pr_rcv_get_path_parms: " + "Path min MTU = %u, min rate = %u\n", mtu, rate ); + } + + /* + Determine if these values meet the user criteria + and adjust appropriately + */ + + /* 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 ) + { + /* adjust to use the highest mtu + lower then the required one */ + if( required_mtu > 1 ) + mtu = required_mtu - 1; + else + status = IB_NOT_FOUND; + } + break; + + case 2: /* exact match */ + if( mtu < required_mtu ) + status = IB_NOT_FOUND; + else + mtu = required_mtu; + break; + + case 3: /* largest available */ + /* can't be disqualified by this one */ + break; + + default: + /* if we're here, there's a bug in ib_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 ) + { + /* adjust the rate to use the highest rate + lower then the required one */ + if( required_rate > 2 ) + rate = required_rate - 1; + else + status = IB_NOT_FOUND; + } + break; + + case 2: /* exact match */ + if( rate < required_rate ) + status = IB_NOT_FOUND; + else + rate = required_rate; + break; + + case 3: /* largest available */ + /* can't be disqualified by this one */ + break; + + default: + /* if we're here, there's a bug in ib_path_rec_mtu_sel() */ + CL_ASSERT( FALSE ); + status = IB_ERROR; + break; + } + } + + /* Verify the pkt_life_time */ + /* According to spec definition IBA 1.2 Table 205 PacketLifeTime description, + for loopback paths, packetLifeTime shall be zero. */ + if ( p_src_port == p_dest_port ) + pkt_life = 0; /* loopback */ + else + pkt_life = OSM_DEFAULT_SUBNET_TIMEOUT; + + /* we silently ignore cases where only the PktLife selector is defined */ + if ( ( comp_mask & IB_PR_COMPMASK_PKTLIFETIMESELEC ) && + ( comp_mask & IB_PR_COMPMASK_PKTLIFETIME ) ) + { + required_pkt_life = ib_path_rec_pkt_life( p_pr ); + switch( ib_path_rec_pkt_life_sel( p_pr ) ) + { + case 0: /* must be greater than */ + if( pkt_life <= required_pkt_life ) + status = IB_NOT_FOUND; + break; + + case 1: /* must be less than */ + if( pkt_life >= required_pkt_life ) + { + /* adjust the lifetime to use the highest possible + lower then the required one */ + if( required_pkt_life > 1 ) + pkt_life = required_pkt_life - 1; + else + status = IB_NOT_FOUND; + } + break; + + case 2: /* exact match */ + if( pkt_life < required_pkt_life ) + status = IB_NOT_FOUND; + else + pkt_life = required_pkt_life; + break; + + case 3: /* smallest available */ + /* can't be disqualified by this one */ + break; + + default: + /* if we're here, there's a bug in ib_path_rec_pkt_life_sel() */ + CL_ASSERT( FALSE ); + status = IB_ERROR; + break; + } + } + + if (status != IB_SUCCESS) + goto Exit; + + p_parms->mtu = mtu; + p_parms->rate = rate; + p_parms->pkt_life = pkt_life; + + if( comp_mask & IB_PR_COMPMASK_RAWTRAFFIC && + cl_ntoh32( p_pr->hop_flow_raw ) & ( 1<<31 ) ) + pkey = osm_physp_find_common_pkey( p_physp, p_dest_physp ); + else if( comp_mask & IB_PR_COMPMASK_PKEY ) + { + pkey = p_pr->pkey; + if( !osm_physp_share_this_pkey( p_physp, p_dest_physp, pkey ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_pr_rcv_get_path_parms: ERR 1F1A: " + "Ports do not share specified PKey 0x%04x\n", cl_ntoh16(pkey)); + status = IB_NOT_FOUND; + goto Exit; + } + } + else + { + pkey = osm_physp_find_common_pkey( p_physp, p_dest_physp ); + if ( !pkey ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_pr_rcv_get_path_parms: ERR 1F1B: " + "Ports do not have any shared PKeys\n"); + status = IB_NOT_FOUND; + goto Exit; + } + } + + sl = OSM_DEFAULT_SL; + + if (pkey) { + p_prtn = (osm_prtn_t *)cl_qmap_get(&p_rcv->p_subn->prtn_pkey_tbl, + pkey & cl_ntoh16((uint16_t)~0x8000)); + if ( p_prtn == (osm_prtn_t *)cl_qmap_end(&p_rcv->p_subn->prtn_pkey_tbl) ) + { + /* this may be possible when pkey tables are created somehow in + previous runs or things are going wrong here */ + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_pr_rcv_get_path_parms: ERR 1F1C: " + "No partition found for PKey 0x%04x - using default SL %d\n", + cl_ntoh16(pkey), sl ); + } + else + sl = p_prtn->sl; + + /* reset pkey when raw traffic */ + if( comp_mask & IB_PR_COMPMASK_RAWTRAFFIC && + cl_ntoh32( p_pr->hop_flow_raw ) & ( 1<<31 ) ) + pkey = 0; + } + + if ( ( comp_mask & IB_PR_COMPMASK_SL ) && ib_path_rec_sl( p_pr ) != sl ) + { + status = IB_NOT_FOUND; + goto Exit; + } + + p_parms->pkey = pkey; + p_parms->sl = 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->hop_flow_raw &= cl_hton32(1<<31); + + p_pr->pkey = p_parms->pkey; + p_pr->qos_class_sl = cl_hton16(p_parms->sl); + p_pr->mtu = (uint8_t)(p_parms->mtu | 0x80); + p_pr->rate = (uint8_t)(p_parms->rate | 0x80); + + /* According to 1.2 spec definition Table 205 PacketLifeTime description, + for loopback paths, packetLifeTime shall be zero. */ + if ( p_src_port == p_dest_port ) + p_pr->pkt_life = 0x80; /* loopback */ + else + p_pr->pkt_life = (uint8_t)(p_parms->pkt_life | 0x80); + + p_pr->preference = preference; + + /* always return num_path = 0 so this is only the reversible component */ + if (p_parms->reversible) + p_pr->num_path = 0x80; + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +static osm_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 osm_madw_t* const p_madw, + 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 ) +{ + const ib_path_rec_t* p_pr; + const ib_sa_mad_t* p_sa_mad; + 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 doesn't share a pkey so the path is disqualified. */ + 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 ); + + /* + 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 means least overlap with other paths. + This is acheived in practice by returning paths with + different LID value on each end, which means these + paths are more redundant that paths with the same LID repeated + on one side. For example, in OpenSM the paths between two + endpoints with LMC = 1 might be as follows: + + Port A, LID 1 <-> Port B, LID 3 + Port A, LID 1 <-> Port B, LID 4 + Port A, LID 2 <-> Port B, LID 3 + Port A, LID 2 <-> Port B, LID 4 + + The OpenSM unicast routing algorithms attempt to disperse each path + to as varied a physical path as is reasonable. 1<->3 and 1<->4 have + more physical overlap (hence less redundancy) than 1<->3 and 2<->4. + + OpenSM ranks paths in three preference groups: + + Preference Value Description + ---------------- ------------------------------------------- + 0 Redundant in both directions with other + pref value = 0 paths + + 1 Redundant in one direction with other + pref value = 0 and pref value = 1 paths + + 2 Not redundant in either direction with + other paths + + 3-FF Unused + + + SA clients don't need to know these details, only that the lower + preference paths are preferred, as stated in the spec. The paths + may not actually be physically redundant depending on the topology + of the subnet, but the point of LMC > 0 is to offer redundancy, + so it is assumed that the subnet is physically appropriate for the + specified LMC value. A more advanced implementation would 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 ( src_lid_min_ho == 0 ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_pr_rcv_get_port_pair_paths: ERR 1F20:" + "Obtained source LID of 0. No such LID possible\n"); + goto Exit; + } + + if ( dest_lid_min_ho == 0 ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_pr_rcv_get_port_pair_paths: ERR 1F21:" + "Obtained destination LID of 0. No such LID possible\n"); + goto Exit; + } + + 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 SubnAdmGet, assume NumbPaths 1 (1.2 erratum) */ + if( p_sa_mad->method != IB_MAD_METHOD_GET ) + if( comp_mask & IB_PR_COMPMASK_NUMBPATH ) + iterations = ib_path_rec_num_path( p_pr ); + else + iterations = (uintn_t)(-1); + else + iterations = 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 paths that 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_SGID ) + { + if ( ! ib_gid_is_link_local ( &p_pr->sgid ) ) + { + if ( ib_gid_get_subnet_prefix ( &p_pr->sgid ) != p_rcv->p_subn->opt.subnet_prefix ) + { + /* + This 'error' is the client's fault (bad gid) so + don't enter it as an error in our own log. + Return an error response to the client. + */ + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "__osm_pr_rcv_get_end_points: " + "Non local SGID subnet prefix 0x%016" PRIx64 "\n", + cl_ntoh64( p_pr->sgid.unicast.prefix ) ); + + sa_status = IB_SA_MAD_STATUS_INVALID_GID; + goto Exit; + } + } + + *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( 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) ) + { + /* + 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( comp_mask & IB_PR_COMPMASK_DGID ) + { + if ( ! ib_gid_is_link_local ( &p_pr->dgid ) ) + { + if ( ! ib_gid_is_multicast ( &p_pr->dgid ) && + ib_gid_get_subnet_prefix ( &p_pr->dgid ) != p_rcv->p_subn->opt.subnet_prefix ) + { + /* + This 'error' is the client's fault (bad gid) so + don't enter it as an error in our own log. + Return an error response to the client. + */ + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "__osm_pr_rcv_get_end_points: " + "Non local DGID subnet prefix 0x%016" PRIx64 "\n", + cl_ntoh64( p_pr->dgid.unicast.prefix ) ); + + sa_status = IB_SA_MAD_STATUS_INVALID_GID; + goto Exit; + } + } + + *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( 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) ) + { + /* + 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 osm_madw_t* const p_madw, + IN const osm_port_t* const requester_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_madw, requester_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 osm_madw_t* const p_madw, + IN const osm_port_t* const requester_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_madw , requester_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_madw, requester_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 osm_madw_t* const p_madw, + IN const osm_port_t* const requester_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_madw, requester_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; + + /* ignore groups marked for deletion */ + if ( p_mgrp->to_be_deleted ) + return; + + /* compare entire MGID so different scope will not sneak in for + the same MGID */ + if ( memcmp( &p_mgrp->mcmember_rec.mgid, + p_recvd_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 MC groups 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 member of MC group */ + /* Also, MTU, rate, packet lifetime, and raw traffic requested are not currently checked */ + 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( ib_path_rec_sl( p_pr ) != sl ) + goto Exit; + } + + /* If SubnAdmGet, assume NumbPaths of 1 (1.2 erratum) */ + if( ( comp_mask & IB_PR_COMPMASK_NUMBPATH ) && + ( p_sa_mad->method != IB_MAD_METHOD_GET ) ) + { + if( ib_path_rec_num_path( p_pr ) == 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 int +__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; + int is_multicast = 0; + + 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 = 1; + 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" ); + is_multicast = -1; + } + } + + 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, pre_trim_num_rec; +#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; + uint32_t i; + + 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 SubnAdmGet and got more than one record it is an error ! + */ + if (p_rcvd_mad->method == IB_MAD_METHOD_GET) + { + if (num_rec == 0) + { + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS ); + goto Exit; + } + if (num_rec > 1) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_pr_rcv_respond: ERR 1F13: " + "Got more than one record for SubnAdmGet (%zu)\n", + num_rec ); + osm_sa_send_error( p_rcv->p_resp, p_madw, + IB_SA_MAD_STATUS_TOO_MANY_RECORDS ); + /* need to set the mem free ... */ + p_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; + } + } + + pre_trim_num_rec = num_rec; +#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 + + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_pr_rcv_respond: " + "Generating response with %zu 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_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" ); + + for( i = 0; i < num_rec; i++ ) + { + p_pr_item = (osm_pr_item_t*)cl_qlist_remove_head( p_list ); + cl_qlock_pool_put( &p_rcv->pr_pool, &p_pr_item->pool_item ); + } + + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES ); + goto Exit; + } + + p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw ); + p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw ); + + memcpy( p_resp_sa_mad, p_sa_mad, IB_SA_MAD_HDR_SIZE ); + p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK; + /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */ + p_resp_sa_mad->sm_key = 0; + /* 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) ); + + p_resp_pr = (ib_path_rec_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_pr_item = (osm_pr_item_t*)cl_qlist_remove_head( p_list ); + /* copy only if not trimmed */ + if (i < num_rec) + *p_resp_pr = p_pr_item->path_rec; + + cl_qlock_pool_put( &p_rcv->pr_pool, &p_pr_item->pool_item ); + p_resp_pr++; + } + + CL_ASSERT( cl_is_qlist_empty( 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 ); */ + } + + 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* requester_port; + int ret; + + OSM_LOG_ENTER( p_rcv->p_log, osm_pr_rcv_process ); + + CL_ASSERT( p_madw ); + + 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 ); + + /* 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_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_MAD_STATUS_UNSUP_METHOD_ATTR ); + goto Exit; + } + + /* update the requester physical port. */ + requester_port = osm_get_port_by_mad_addr( p_rcv->p_log, p_rcv->p_subn, + osm_madw_get_mad_addr_ptr( p_madw ) ); + if( requester_port == NULL ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_pr_rcv_process: ERR 1F16: " + "Cannot find requester physical port\n" ); + 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( (ret = __osm_pr_rcv_check_mcast_dest( p_rcv, p_madw )) < 0 ) + { + /* Multicast DGID with unicast DLID */ + cl_plock_release( p_rcv->p_lock ); + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_INVALID_FIELD ); + goto Exit; + } + + if(ret > 0) + 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 ) + { + /* + 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_madw, requester_port, + p_src_port, p_dest_port, + p_sa_mad->comp_mask, &pr_list ); + else + __osm_pr_rcv_process_half( p_rcv, p_madw, requester_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_madw, requester_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_madw, requester_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" ); + { + 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; + + /* 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.qos_class_sl = cl_hton16( 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" ); + } + } + } + + Unlock: + cl_plock_release( p_rcv->p_lock ); + + /* Now, (finally) respond to the PathRecord request */ + __osm_pr_rcv_respond( p_rcv, p_madw, &pr_list ); + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_path_record_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_path_record_ctrl.c new file mode 100644 index 00000000..2a9bc772 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_path_record_ctrl.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_path_record_ctrl.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_pr_rcv_ctrl_t. + * This object represents the PathRecord request controller object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +static void +__osm_pr_rcv_ctrl_disp_callback( + IN void *context, + IN void *p_data ) +{ + /* ignore return status when invoked via the dispatcher */ + osm_pr_rcv_process( ((osm_pr_rcv_ctrl_t*)context)->p_rcv, + (osm_madw_t*)p_data ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_pr_rcv_ctrl_construct( + IN osm_pr_rcv_ctrl_t* const p_ctrl ) +{ + memset( p_ctrl, 0, sizeof(*p_ctrl) ); + p_ctrl->h_disp = CL_DISP_INVALID_HANDLE; +} + +/********************************************************************** + **********************************************************************/ +void +osm_pr_rcv_ctrl_destroy( + IN osm_pr_rcv_ctrl_t* const p_ctrl ) +{ + CL_ASSERT( p_ctrl ); + cl_disp_unregister( p_ctrl->h_disp ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_pr_rcv_ctrl_init( + IN osm_pr_rcv_ctrl_t* const p_ctrl, + IN osm_pr_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_pr_rcv_ctrl_init ); + + osm_pr_rcv_ctrl_construct( p_ctrl ); + p_ctrl->p_log = p_log; + p_ctrl->p_rcv = p_rcv; + p_ctrl->p_disp = p_disp; + + p_ctrl->h_disp = cl_disp_register( + p_disp, + OSM_MSG_MAD_PATH_RECORD, + __osm_pr_rcv_ctrl_disp_callback, + p_ctrl ); + + if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_pr_rcv_ctrl_init: ERR 2001: " + "Dispatcher registration failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return( status ); +} + + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_pkey_record.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_pkey_record.c new file mode 100644 index 00000000..0e5ffee4 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_pkey_record.c @@ -0,0 +1,590 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_pkey_record.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define OSM_PKEY_REC_RCV_POOL_MIN_SIZE 32 +#define OSM_PKEY_REC_RCV_POOL_GROW_SIZE 32 + +typedef struct _osm_pkey_item +{ + cl_pool_item_t pool_item; + ib_pkey_table_record_t rec; +} osm_pkey_item_t; + +typedef struct _osm_pkey_search_ctxt +{ + const ib_pkey_table_record_t* p_rcvd_rec; + ib_net64_t comp_mask; + uint16_t block_num; + cl_qlist_t* p_list; + osm_pkey_rec_rcv_t* p_rcv; + const osm_physp_t* p_req_physp; +} osm_pkey_search_ctxt_t; + +/********************************************************************** + **********************************************************************/ +void +osm_pkey_rec_rcv_construct( + IN osm_pkey_rec_rcv_t* const p_rcv ) +{ + memset( p_rcv, 0, sizeof(*p_rcv) ); + cl_qlock_pool_construct( &p_rcv->pool ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_pkey_rec_rcv_destroy( + IN osm_pkey_rec_rcv_t* const p_rcv ) +{ + OSM_LOG_ENTER( p_rcv->p_log, osm_pkey_rec_rcv_destroy ); + cl_qlock_pool_destroy( &p_rcv->pool ); + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_pkey_rec_rcv_init( + IN osm_pkey_rec_rcv_t* const p_rcv, + IN osm_sa_resp_t* const p_resp, + IN osm_mad_pool_t* const p_mad_pool, + IN const osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ) +{ + ib_api_status_t status; + + OSM_LOG_ENTER( p_log, osm_pkey_rec_rcv_init ); + + osm_pkey_rec_rcv_construct( p_rcv ); + + p_rcv->p_log = p_log; + p_rcv->p_subn = p_subn; + p_rcv->p_lock = p_lock; + p_rcv->p_resp = p_resp; + p_rcv->p_mad_pool = p_mad_pool; + + /* used for matching records collection */ + status = cl_qlock_pool_init( &p_rcv->pool, + OSM_PKEY_REC_RCV_POOL_MIN_SIZE, + 0, + OSM_PKEY_REC_RCV_POOL_GROW_SIZE, + sizeof(osm_pkey_item_t), + NULL, NULL, NULL ); + + OSM_LOG_EXIT( p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +void +__osm_sa_pkey_create( + IN osm_pkey_rec_rcv_t* const p_rcv, + IN osm_physp_t* const p_physp, + IN osm_pkey_search_ctxt_t* const p_ctxt, + IN uint16_t block ) +{ + osm_pkey_item_t* p_rec_item; + uint16_t lid; + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_pkey_create ); + + p_rec_item = (osm_pkey_item_t*)cl_qlock_pool_get( &p_rcv->pool ); + if( p_rec_item == NULL ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_sa_pkey_create: ERR 4602: " + "cl_qlock_pool_get failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + if (p_physp->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH) + { + lid = osm_physp_get_port_info_ptr( p_physp )->base_lid; + } + else + { + lid = osm_node_get_base_lid( p_physp->p_node, 0 ); + } + + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_sa_pkey_create: " + "New P_Key table for: port 0x%016" PRIx64 + ", lid 0x%X, port# 0x%X Block:%u\n", + cl_ntoh64( osm_physp_get_port_guid( p_physp ) ), + cl_ntoh16( lid ), osm_physp_get_port_num( p_physp ), + block + ); + } + + memset( &p_rec_item->rec, 0, sizeof( p_rec_item->rec ) ); + + p_rec_item->rec.lid = lid; + p_rec_item->rec.block_num = block; + p_rec_item->rec.port_num = osm_physp_get_port_num( p_physp ); + p_rec_item->rec.pkey_tbl = + *(osm_pkey_tbl_block_get(osm_physp_get_pkey_tbl(p_physp), block)); + + cl_qlist_insert_tail( p_ctxt->p_list, + (cl_list_item_t*)&p_rec_item->pool_item ); + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +void +__osm_sa_pkey_check_physp( + IN osm_pkey_rec_rcv_t* const p_rcv, + IN osm_physp_t* const p_physp, + osm_pkey_search_ctxt_t* const p_ctxt ) +{ + ib_net64_t comp_mask = p_ctxt->comp_mask; + uint16_t block, num_blocks; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_pkey_check_physp ); + + /* we got here with the phys port - all is left is to get the right block */ + if ( comp_mask & IB_PKEY_COMPMASK_BLOCK ) + { + __osm_sa_pkey_create( p_rcv, p_physp, p_ctxt, p_ctxt->block_num); + } + else + { + num_blocks = + osm_pkey_tbl_get_num_blocks( osm_physp_get_pkey_tbl( p_physp )); + for (block = 0; block < num_blocks; block++) { + __osm_sa_pkey_create( p_rcv, p_physp, p_ctxt, block ); + } + } + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_sa_pkey_by_comp_mask( + IN osm_pkey_rec_rcv_t* const p_rcv, + IN const osm_port_t* const p_port, + osm_pkey_search_ctxt_t* const p_ctxt ) +{ + const ib_pkey_table_record_t* p_rcvd_rec; + ib_net64_t comp_mask; + osm_physp_t * p_physp; + uint8_t port_num; + uint8_t num_ports; + const osm_physp_t* p_req_physp; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_pkey_by_comp_mask ); + + p_rcvd_rec = p_ctxt->p_rcvd_rec; + comp_mask = p_ctxt->comp_mask; + port_num = p_rcvd_rec->port_num; + p_req_physp = p_ctxt->p_req_physp; + + /* if this is a switch port we can search all ports + otherwise we must be looking on port 0 */ + if ( p_port->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH ) + { + /* we put it in the comp mask and port num */ + port_num = p_port->default_port_num; + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_sa_pkey_by_comp_mask: " + "Using Physical Default Port Number: 0x%X (for End Node)\n", + port_num); + comp_mask |= IB_PKEY_COMPMASK_PORT; + } + + if( comp_mask & IB_PKEY_COMPMASK_PORT ) + { + if (port_num < osm_port_get_num_physp( p_port )) + { + p_physp = osm_port_get_phys_ptr( p_port, port_num ); + /* Check that the p_physp is valid, and that is shares a pkey + with the p_req_physp. */ + if( p_physp && osm_physp_is_valid( p_physp ) && + (osm_physp_share_pkey(p_rcv->p_log, p_req_physp, p_physp)) ) + __osm_sa_pkey_check_physp( p_rcv, p_physp, p_ctxt ); + } + else + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_sa_pkey_by_comp_mask: ERR 4603: " + "Given Physical Port Number: 0x%X is out of range should be < 0x%X\n", + port_num, osm_port_get_num_physp( p_port )); + goto Exit; + } + } + else + { + num_ports = osm_port_get_num_physp( p_port ); + for( port_num = 0; port_num < num_ports; port_num++ ) + { + p_physp = osm_port_get_phys_ptr( p_port, port_num ); + if( p_physp == NULL ) + continue; + + if( !osm_physp_is_valid( p_physp ) ) + continue; + + /* if the requester and the p_physp don't share a pkey - + continue */ + if (!osm_physp_share_pkey(p_rcv->p_log, p_req_physp, p_physp ) ) + continue; + + __osm_sa_pkey_check_physp( p_rcv, p_physp, p_ctxt ); + } + } + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_sa_pkey_by_comp_mask_cb( + IN cl_map_item_t* const p_map_item, + IN void* context ) +{ + const osm_port_t* const p_port = (osm_port_t*)p_map_item; + osm_pkey_search_ctxt_t* const p_ctxt = (osm_pkey_search_ctxt_t *)context; + + __osm_sa_pkey_by_comp_mask( p_ctxt->p_rcv, p_port, p_ctxt ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_pkey_rec_rcv_process( + IN osm_pkey_rec_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ) +{ + const ib_sa_mad_t* p_rcvd_mad; + const ib_pkey_table_record_t* p_rcvd_rec; + const cl_ptr_vector_t* p_tbl; + const osm_port_t* p_port = NULL; + const ib_pkey_table_t* p_pkey; + cl_qlist_t rec_list; + osm_madw_t* p_resp_madw; + ib_sa_mad_t* p_resp_sa_mad; + ib_pkey_table_record_t* p_resp_rec; + uint32_t num_rec, pre_trim_num_rec; +#ifndef VENDOR_RMPP_SUPPORT + uint32_t trim_num_rec; +#endif + uint32_t i; + osm_pkey_search_ctxt_t context; + osm_pkey_item_t* p_rec_item; + ib_api_status_t status = IB_SUCCESS; + ib_net64_t comp_mask; + osm_physp_t* p_req_physp; + + CL_ASSERT( p_rcv ); + + OSM_LOG_ENTER( p_rcv->p_log, osm_pkey_rec_rcv_process ); + + CL_ASSERT( p_madw ); + + p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw ); + p_rcvd_rec = (ib_pkey_table_record_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad ); + comp_mask = p_rcvd_mad->comp_mask; + + CL_ASSERT( p_rcvd_mad->attr_id == IB_MAD_ATTR_PKEY_TBL_RECORD ); + + /* we only support SubnAdmGet and SubnAdmGetTable methods */ + if ( (p_rcvd_mad->method != IB_MAD_METHOD_GET) && + (p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_pkey_rec_rcv_process: ERR 4605: " + "Unsupported Method (%s)\n", + ib_get_sa_method_str( p_rcvd_mad->method ) ); + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR ); + goto Exit; + } + + /* + p922 - P_KeyTableRecords shall only be provided in response + to trusted requests. + Check that the requester is a trusted one. + */ + if ( p_rcvd_mad->sm_key != p_rcv->p_subn->opt.sm_key ) + { + /* This is not a trusted requester! */ + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_pkey_rec_rcv_process ERR 4608: " + "Request from non-trusted requester: " + "Given SM_Key:0x%016" PRIx64 "\n", + cl_ntoh64(p_rcvd_mad->sm_key) ); + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_REQ_INVALID ); + goto Exit; + } + + /* update the requester physical port. */ + p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log, + p_rcv->p_subn, + osm_madw_get_mad_addr_ptr(p_madw) ); + if (p_req_physp == NULL) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_pkey_rec_rcv_process: ERR 4604: " + "Cannot find requester physical port\n" ); + goto Exit; + } + + p_pkey = (ib_pkey_table_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad ); + + cl_qlist_init( &rec_list ); + + context.p_rcvd_rec = p_rcvd_rec; + context.p_list = &rec_list; + context.comp_mask = p_rcvd_mad->comp_mask; + context.p_rcv = p_rcv; + context.block_num = p_rcvd_rec->block_num; + context.p_req_physp = p_req_physp; + + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "osm_pkey_rec_rcv_process: " + "Got Query Lid:0x%04X(%02X), Block:0x%02X(%02X), Port:0x%02X(%02X)\n", + cl_ntoh16(p_rcvd_rec->lid), (comp_mask & IB_PKEY_COMPMASK_LID) != 0, + p_rcvd_rec->port_num, (comp_mask & IB_PKEY_COMPMASK_PORT) != 0, + p_rcvd_rec->block_num, (comp_mask & IB_PKEY_COMPMASK_BLOCK) != 0 ); + + cl_plock_acquire( p_rcv->p_lock ); + + /* + If the user specified a LID, it obviously narrows our + work load, since we don't have to search every port + */ + if( comp_mask & IB_PKEY_COMPMASK_LID ) + { + + p_tbl = &p_rcv->p_subn->port_lid_tbl; + + CL_ASSERT( cl_ptr_vector_get_size(p_tbl) < 0x10000 ); + + status = osm_get_port_by_base_lid( p_rcv->p_subn, p_rcvd_rec->lid, &p_port ); + if ( ( status != IB_SUCCESS ) || ( p_port == NULL ) ) + { + status = IB_NOT_FOUND; + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_pkey_rec_rcv_process: ERR 460B: " + "No port found with LID 0x%x\n", + cl_ntoh16(p_rcvd_rec->lid) ); + } + } + + if ( status == IB_SUCCESS ) + { + /* if we got a unique port - no need for a port search */ + if( p_port ) + /* this does the loop on all the port phys ports */ + __osm_sa_pkey_by_comp_mask( p_rcv, p_port, &context ); + else + { + cl_qmap_apply_func( &p_rcv->p_subn->port_guid_tbl, + __osm_sa_pkey_by_comp_mask_cb, + &context ); + } + } + + cl_plock_release( p_rcv->p_lock ); + + num_rec = cl_qlist_count( &rec_list ); + + /* + * C15-0.1.30: + * If we do a SubnAdmGet and got more than one record it is an error ! + */ + if (p_rcvd_mad->method == IB_MAD_METHOD_GET) + { + if (num_rec == 0) + { + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS ); + goto Exit; + } + if (num_rec > 1) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_pkey_rec_rcv_process: ERR 460A: " + "Got more than one record for SubnAdmGet (%u)\n", + num_rec ); + osm_sa_send_error( p_rcv->p_resp, p_madw, + IB_SA_MAD_STATUS_TOO_MANY_RECORDS); + + /* need to set the mem free ... */ + p_rec_item = (osm_pkey_item_t*)cl_qlist_remove_head( &rec_list ); + while( p_rec_item != (osm_pkey_item_t*)cl_qlist_end( &rec_list ) ) + { + cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item ); + p_rec_item = (osm_pkey_item_t*)cl_qlist_remove_head( &rec_list ); + } + + goto Exit; + } + } + + pre_trim_num_rec = num_rec; +#ifndef VENDOR_RMPP_SUPPORT + trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_pkey_table_record_t); + if (trim_num_rec < num_rec) + { + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "osm_pkey_rec_rcv_process: " + "Number of records:%u trimmed to:%u to fit in one MAD\n", + num_rec, trim_num_rec ); + num_rec = trim_num_rec; + } +#endif + + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "osm_pkey_rec_rcv_process: " + "Returning %u records\n", num_rec ); + + if((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0)) + { + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS ); + goto Exit; + } + + /* + * Get a MAD to reply. Address of Mad is in the received mad_wrapper + */ + p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool, + p_madw->h_bind, + num_rec * sizeof(ib_pkey_table_record_t) + IB_SA_MAD_HDR_SIZE, + &p_madw->mad_addr ); + + if( !p_resp_madw ) + { + osm_log(p_rcv->p_log, OSM_LOG_ERROR, + "osm_pkey_rec_rcv_process: ERR 4606: " + "osm_mad_pool_get failed\n" ); + + for( i = 0; i < num_rec; i++ ) + { + p_rec_item = (osm_pkey_item_t*)cl_qlist_remove_head( &rec_list ); + cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item ); + } + + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES ); + goto Exit; + } + + p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw ); + + /* + Copy the MAD header back into the response mad. + Set the 'R' bit and the payload length, + Then copy all records from the list into the response payload. + */ + + memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE ); + p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK; + /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */ + p_resp_sa_mad->sm_key = 0; + + /* Fill in the offset (paylen will be done by the rmpp SAR) */ + p_resp_sa_mad->attr_offset = + ib_get_attr_offset( sizeof(ib_pkey_table_record_t) ); + + p_resp_rec = (ib_pkey_table_record_t*) + ib_sa_mad_get_payload_ptr( p_resp_sa_mad ); + +#ifndef VENDOR_RMPP_SUPPORT + /* we support only one packet RMPP - so we will set the first and + last flags for gettable */ + if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP) + { + p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA; + p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE; + } +#else + /* forcefully define the packet as RMPP one */ + if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP) + p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE; +#endif + + for( i = 0; i < pre_trim_num_rec; i++ ) + { + p_rec_item = (osm_pkey_item_t*)cl_qlist_remove_head( &rec_list ); + /* copy only if not trimmed */ + if (i < num_rec) + { + *p_resp_rec = p_rec_item->rec; + } + cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item ); + p_resp_rec++; + } + + CL_ASSERT( cl_is_qlist_empty( &rec_list ) ); + + status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE); + if (status != IB_SUCCESS) + { + osm_log(p_rcv->p_log, OSM_LOG_ERROR, + "osm_pkey_rec_rcv_process: ERR 4607: " + "osm_vendor_send status = %s\n", + ib_get_err_str(status)); + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_pkey_record_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_pkey_record_ctrl.c new file mode 100644 index 00000000..0aefe391 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_pkey_record_ctrl.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_pkey_record_ctrl.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +__osm_pkey_rec_rcv_ctrl_disp_callback( + IN void *context, + IN void *p_data ) +{ + /* ignore return status when invoked via the dispatcher */ + osm_pkey_rec_rcv_process( ((osm_pkey_rec_rcv_ctrl_t*)context)->p_rcv, + (osm_madw_t*)p_data ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_pkey_rec_rcv_ctrl_construct( + IN osm_pkey_rec_rcv_ctrl_t* const p_ctrl ) +{ + memset( p_ctrl, 0, sizeof(*p_ctrl) ); + p_ctrl->h_disp = CL_DISP_INVALID_HANDLE; +} + +/********************************************************************** + **********************************************************************/ +void +osm_pkey_rec_rcv_ctrl_destroy( + IN osm_pkey_rec_rcv_ctrl_t* const p_ctrl ) +{ + CL_ASSERT( p_ctrl ); + cl_disp_unregister( p_ctrl->h_disp ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_pkey_rec_rcv_ctrl_init( + IN osm_pkey_rec_rcv_ctrl_t* const p_ctrl, + IN osm_pkey_rec_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_pkey_rec_rcv_ctrl_init ); + + osm_pkey_rec_rcv_ctrl_construct( p_ctrl ); + p_ctrl->p_log = p_log; + p_ctrl->p_rcv = p_rcv; + p_ctrl->p_disp = p_disp; + + p_ctrl->h_disp = cl_disp_register( + p_disp, + OSM_MSG_MAD_PKEY_TBL_RECORD, + __osm_pkey_rec_rcv_ctrl_disp_callback, + p_ctrl ); + + if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_pkey_rec_rcv_ctrl_init: ERR 4701: " + "Dispatcher registration failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return( status ); +} + + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_portinfo_record.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_portinfo_record.c new file mode 100644 index 00000000..29bf18ba --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_portinfo_record.c @@ -0,0 +1,878 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_portinfo_record.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_pir_rcv_t. + * This object represents the PortInfoRecord Receiver object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.10 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define OSM_PIR_RCV_POOL_MIN_SIZE 32 +#define OSM_PIR_RCV_POOL_GROW_SIZE 32 + +typedef struct _osm_pir_item +{ + cl_pool_item_t pool_item; + ib_portinfo_record_t rec; +} osm_pir_item_t; + +typedef struct _osm_pir_search_ctxt +{ + const ib_portinfo_record_t* p_rcvd_rec; + ib_net64_t comp_mask; + cl_qlist_t* p_list; + osm_pir_rcv_t* p_rcv; + const osm_physp_t* p_req_physp; + boolean_t is_enhanced_comp_mask; +} osm_pir_search_ctxt_t; + +/********************************************************************** + **********************************************************************/ +void +osm_pir_rcv_construct( + IN osm_pir_rcv_t* const p_rcv ) +{ + memset( p_rcv, 0, sizeof(*p_rcv) ); + cl_qlock_pool_construct( &p_rcv->pool ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_pir_rcv_destroy( + IN osm_pir_rcv_t* const p_rcv ) +{ + OSM_LOG_ENTER( p_rcv->p_log, osm_pir_rcv_destroy ); + cl_qlock_pool_destroy( &p_rcv->pool ); + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_pir_rcv_init( + IN osm_pir_rcv_t* const p_rcv, + IN osm_sa_resp_t* const p_resp, + IN osm_mad_pool_t* const p_mad_pool, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ) +{ + ib_api_status_t status; + + OSM_LOG_ENTER( p_log, osm_pir_rcv_init ); + + osm_pir_rcv_construct( p_rcv ); + + p_rcv->p_log = p_log; + p_rcv->p_subn = p_subn; + p_rcv->p_lock = p_lock; + p_rcv->p_resp = p_resp; + p_rcv->p_mad_pool = p_mad_pool; + + status = cl_qlock_pool_init( &p_rcv->pool, + OSM_PIR_RCV_POOL_MIN_SIZE, + 0, + OSM_PIR_RCV_POOL_GROW_SIZE, + sizeof(osm_pir_item_t), + NULL, NULL, NULL ); + + OSM_LOG_EXIT( p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +static ib_api_status_t +__osm_pir_rcv_new_pir( + IN osm_pir_rcv_t* const p_rcv, + IN const osm_physp_t* const p_physp, + IN cl_qlist_t* const p_list, + IN ib_net16_t const lid ) +{ + osm_pir_item_t* p_rec_item; + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_pir_rcv_new_pir ); + + p_rec_item = (osm_pir_item_t*)cl_qlock_pool_get( &p_rcv->pool ); + if( p_rec_item == NULL ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_pir_rcv_new_pir: ERR 2102: " + "cl_qlock_pool_get failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_pir_rcv_new_pir: " + "New PortInfoRecord: port 0x%016" PRIx64 + ", lid 0x%X, port# 0x%X\n", + cl_ntoh64( osm_physp_get_port_guid( p_physp ) ), + cl_ntoh16( lid ), osm_physp_get_port_num( p_physp ) ); + } + + memset( &p_rec_item->rec, 0, sizeof( p_rec_item->rec ) ); + + p_rec_item->rec.lid = lid; + p_rec_item->rec.port_info = *osm_physp_get_port_info_ptr( p_physp ); + p_rec_item->rec.port_num = osm_physp_get_port_num( p_physp ); + + cl_qlist_insert_tail( p_list, (cl_list_item_t*)&p_rec_item->pool_item ); + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +void +__osm_sa_pir_create( + IN osm_pir_rcv_t* const p_rcv, + IN const osm_physp_t* const p_physp, + IN osm_pir_search_ctxt_t* const p_ctxt ) +{ + uint8_t lmc; + uint16_t max_lid_ho; + uint16_t base_lid_ho; + uint16_t match_lid_ho; + osm_physp_t *p_node_physp; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_pir_create ); + + if (p_physp->p_node->sw) + { + p_node_physp = osm_node_get_physp_ptr( p_physp->p_node, 0 ); + base_lid_ho = cl_ntoh16( osm_physp_get_base_lid( p_node_physp ) ); + lmc = osm_switch_sp0_is_lmc_capable(p_physp->p_node->sw, p_rcv->p_subn) ? + osm_physp_get_lmc( p_node_physp ) : 0; + } + else + { + lmc = osm_physp_get_lmc( p_physp ); + base_lid_ho = cl_ntoh16( osm_physp_get_base_lid( p_physp ) ); + } + max_lid_ho = (uint16_t)( base_lid_ho + (1 << lmc) - 1 ); + + if( p_ctxt->comp_mask & IB_PIR_COMPMASK_LID ) + { + match_lid_ho = cl_ntoh16( p_ctxt->p_rcvd_rec->lid ); + + /* + We validate that the lid belongs to this node. + */ + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_sa_pir_create: " + "Comparing LID: 0x%X <= 0x%X <= 0x%X\n", + base_lid_ho, match_lid_ho, max_lid_ho + ); + } + + if ( match_lid_ho < base_lid_ho || match_lid_ho > max_lid_ho ) + goto Exit; + } + + __osm_pir_rcv_new_pir( p_rcv, p_physp, p_ctxt->p_list, + cl_hton16( base_lid_ho ) ); + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +void +__osm_sa_pir_check_physp( + IN osm_pir_rcv_t* const p_rcv, + IN const osm_physp_t* const p_physp, + osm_pir_search_ctxt_t* const p_ctxt ) +{ + const ib_portinfo_record_t* p_rcvd_rec; + ib_net64_t comp_mask; + const ib_port_info_t* p_comp_pi; + const ib_port_info_t* p_pi; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_pir_check_physp ); + + p_rcvd_rec = p_ctxt->p_rcvd_rec; + comp_mask = p_ctxt->comp_mask; + p_comp_pi = &p_rcvd_rec->port_info; + p_pi = osm_physp_get_port_info_ptr( p_physp ); + + osm_dump_port_info( + p_rcv->p_log, + osm_node_get_node_guid( p_physp->p_node ), + p_physp->port_guid, + p_physp->port_num, + &p_physp->port_info, + OSM_LOG_DEBUG ); + + /* We have to re-check the base_lid, since if the given + base_lid in p_pi is zero - we are comparing on all ports. */ + if( comp_mask & IB_PIR_COMPMASK_BASELID ) + { + if( p_comp_pi->base_lid != p_pi->base_lid ) + goto Exit; + } + if( comp_mask & IB_PIR_COMPMASK_MKEY ) + { + if( p_comp_pi->m_key != p_pi->m_key ) + goto Exit; + } + if( comp_mask & IB_PIR_COMPMASK_GIDPRE ) + { + if( p_comp_pi->subnet_prefix != p_pi->subnet_prefix ) + goto Exit; + } + if( comp_mask & IB_PIR_COMPMASK_SMLID ) + { + if( p_comp_pi->master_sm_base_lid != p_pi->master_sm_base_lid ) + goto Exit; + } + + /* IBTA 1.2 errata provides support for bitwise compare if the bit 31 + of the attribute modifier of the Get/GetTable is set */ + if( comp_mask & IB_PIR_COMPMASK_CAPMASK ) + { + if (p_ctxt->is_enhanced_comp_mask) + { + if ( ( ( p_comp_pi->capability_mask & p_pi->capability_mask ) != p_comp_pi->capability_mask) ) + goto Exit; + } + else + { + if( p_comp_pi->capability_mask != p_pi->capability_mask ) + goto Exit; + } + } + + if( comp_mask & IB_PIR_COMPMASK_DIAGCODE ) + { + if( p_comp_pi->diag_code != p_pi->diag_code ) + goto Exit; + } + if( comp_mask & IB_PIR_COMPMASK_MKEYLEASEPRD ) + { + if( p_comp_pi->m_key_lease_period != p_pi->m_key_lease_period ) + goto Exit; + } + if( comp_mask & IB_PIR_COMPMASK_LOCALPORTNUM ) + { + if( p_comp_pi->local_port_num != p_pi->local_port_num ) + goto Exit; + } + if( comp_mask & IB_PIR_COMPMASK_LNKWIDTHSUPPORT ) + { + if( p_comp_pi->link_width_supported != p_pi->link_width_supported ) + goto Exit; + } + if( comp_mask & IB_PIR_COMPMASK_LNKWIDTHACTIVE ) + { + if( p_comp_pi->link_width_active != p_pi->link_width_active ) + goto Exit; + } + if( comp_mask & IB_PIR_COMPMASK_LINKWIDTHENABLED ) + { + if( p_comp_pi->link_width_enabled != p_pi->link_width_enabled ) + goto Exit; + } + if( comp_mask & IB_PIR_COMPMASK_LNKSPEEDSUPPORT ) + { + if( ib_port_info_get_link_speed_sup( p_comp_pi )!= + ib_port_info_get_link_speed_sup( p_pi) ) + goto Exit; + } + if( comp_mask & IB_PIR_COMPMASK_PORTSTATE ) + { + if( ib_port_info_get_port_state( p_comp_pi ) != + ib_port_info_get_port_state( p_pi ) ) + goto Exit; + } + if ( comp_mask & IB_PIR_COMPMASK_PORTPHYSTATE ) + { + if ( ib_port_info_get_port_phys_state( p_comp_pi ) != + ib_port_info_get_port_phys_state( p_pi ) ) + goto Exit; + } + if ( comp_mask & IB_PIR_COMPMASK_LINKDWNDFLTSTATE ) + { + if ( ib_port_info_get_link_down_def_state( p_comp_pi ) != + ib_port_info_get_link_down_def_state( p_pi ) ) + goto Exit; + } + if ( comp_mask & IB_PIR_COMPMASK_MKEYPROTBITS ) + { + if( ib_port_info_get_mpb( p_comp_pi ) != + ib_port_info_get_mpb( p_pi ) ) + goto Exit; + } + if( comp_mask & IB_PIR_COMPMASK_LMC ) + { + if( ib_port_info_get_lmc( p_comp_pi ) != + ib_port_info_get_lmc( p_pi ) ) + goto Exit; + } + if ( comp_mask & IB_PIR_COMPMASK_LINKSPEEDACTIVE ) + { + if ( ib_port_info_get_link_speed_active( p_comp_pi ) != + ib_port_info_get_link_speed_active( p_pi ) ) + goto Exit; + } + if ( comp_mask & IB_PIR_COMPMASK_LINKSPEEDENABLE ) + { + if ( ib_port_info_get_link_speed_enabled( p_comp_pi ) != + ib_port_info_get_link_speed_enabled( p_pi ) ) + goto Exit; + } + if( comp_mask & IB_PIR_COMPMASK_NEIGHBORMTU ) + { + if( ib_port_info_get_neighbor_mtu( p_comp_pi ) != + ib_port_info_get_neighbor_mtu( p_pi ) ) + goto Exit; + } + if( comp_mask & IB_PIR_COMPMASK_MASTERSMSL ) + { + if( ib_port_info_get_master_smsl( p_comp_pi ) != + ib_port_info_get_master_smsl( p_pi ) ) + goto Exit; + } + if( comp_mask & IB_PIR_COMPMASK_VLCAP ) + { + if( ib_port_info_get_vl_cap( p_comp_pi ) != + ib_port_info_get_vl_cap( p_pi ) ) + goto Exit; + } + if( comp_mask & IB_PIR_COMPMASK_INITTYPE ) + { + if( ib_port_info_get_init_type( p_comp_pi ) != + ib_port_info_get_init_type( p_pi ) ) + goto Exit; + } + if( comp_mask & IB_PIR_COMPMASK_VLHIGHLIMIT ) + { + if( p_comp_pi->vl_high_limit != p_pi->vl_high_limit ) + goto Exit; + } + if( comp_mask & IB_PIR_COMPMASK_VLARBHIGHCAP ) + { + if( p_comp_pi->vl_arb_high_cap != p_pi->vl_arb_high_cap ) + goto Exit; + } + if( comp_mask & IB_PIR_COMPMASK_VLARBLOWCAP ) + { + if( p_comp_pi->vl_arb_low_cap != p_pi->vl_arb_low_cap ) + goto Exit; + } + if( comp_mask & IB_PIR_COMPMASK_MTUCAP ) + { + if( ib_port_info_get_mtu_cap( p_comp_pi ) != + ib_port_info_get_mtu_cap( p_pi ) ) + goto Exit; + } + if( comp_mask & IB_PIR_COMPMASK_VLSTALLCNT ) + { + if( ib_port_info_get_vl_stall_count( p_comp_pi ) != + ib_port_info_get_vl_stall_count( p_pi ) ) + goto Exit; + } + if (comp_mask & IB_PIR_COMPMASK_HOQLIFE ) + { + if ((p_comp_pi->vl_stall_life & 0x1F) != (p_pi->vl_stall_life & 0x1F) ) + goto Exit; + } + if (comp_mask & IB_PIR_COMPMASK_OPVLS ) + { + if ((p_comp_pi->vl_enforce & 0xF0) != (p_pi->vl_enforce & 0xF0) ) + goto Exit; + } + if (comp_mask & IB_PIR_COMPMASK_PARENFIN ) + { + if ((p_comp_pi->vl_enforce & 0x08) != (p_pi->vl_enforce & 0x08) ) + goto Exit; + } + if (comp_mask & IB_PIR_COMPMASK_PARENFOUT ) + { + if ((p_comp_pi->vl_enforce & 0x04) != (p_pi->vl_enforce & 0x04) ) + goto Exit; + } + if (comp_mask & IB_PIR_COMPMASK_FILTERRAWIN ) + { + if ((p_comp_pi->vl_enforce & 0x02) != (p_pi->vl_enforce & 0x02) ) + goto Exit; + } + if (comp_mask & IB_PIR_COMPMASK_FILTERRAWOUT ) + { + if ((p_comp_pi->vl_enforce & 0x01) != (p_pi->vl_enforce & 0x01) ) + goto Exit; + } + if (comp_mask & IB_PIR_COMPMASK_MKEYVIO ) + { + if (p_comp_pi->m_key_violations != p_pi->m_key_violations ) + goto Exit; + } + if (comp_mask & IB_PIR_COMPMASK_PKEYVIO ) + { + if (p_comp_pi->p_key_violations != p_pi->p_key_violations ) + goto Exit; + } + if (comp_mask & IB_PIR_COMPMASK_QKEYVIO ) + { + if (p_comp_pi->q_key_violations != p_pi->q_key_violations ) + goto Exit; + } + if (comp_mask & IB_PIR_COMPMASK_GUIDCAP ) + { + if (p_comp_pi->guid_cap != p_pi->guid_cap ) + goto Exit; + } + if (comp_mask & IB_PIR_COMPMASK_SUBNTO ) + { + if (ib_port_info_get_timeout(p_comp_pi) != ib_port_info_get_timeout(p_pi)) + goto Exit; + } + if (comp_mask & IB_PIR_COMPMASK_RESPTIME ) + { + if ((p_comp_pi->resp_time_value & 0x1F) != (p_pi->resp_time_value &0x1F) ) + goto Exit; + } + if (comp_mask & IB_PIR_COMPMASK_LOCALPHYERR ) + { + if( ib_port_info_get_local_phy_err_thd( p_comp_pi ) != + ib_port_info_get_local_phy_err_thd( p_pi ) ) + goto Exit; + } + if (comp_mask & IB_PIR_COMPMASK_OVERRUNERR) + { + if( ib_port_info_get_overrun_err_thd( p_comp_pi ) != + ib_port_info_get_overrun_err_thd( p_pi ) ) + goto Exit; + } + + __osm_sa_pir_create( p_rcv, p_physp, p_ctxt ); + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_sa_pir_by_comp_mask( + IN osm_pir_rcv_t* const p_rcv, + IN const osm_port_t* const p_port, + osm_pir_search_ctxt_t* const p_ctxt ) +{ + const ib_portinfo_record_t* p_rcvd_rec; + ib_net64_t comp_mask; + const osm_physp_t* p_physp; + uint8_t port_num; + uint8_t num_ports; + const osm_physp_t* p_req_physp; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_pir_by_comp_mask ); + + p_rcvd_rec = p_ctxt->p_rcvd_rec; + comp_mask = p_ctxt->comp_mask; + p_req_physp = p_ctxt->p_req_physp; + + num_ports = osm_port_get_num_physp( p_port ); + + if( comp_mask & IB_PIR_COMPMASK_PORTNUM ) + { + if (p_rcvd_rec->port_num < num_ports) + { + p_physp = osm_port_get_phys_ptr( p_port, p_rcvd_rec->port_num ); + /* Check that the p_physp is valid, and that the p_physp and the + p_req_physp share a pkey. */ + if( p_physp && osm_physp_is_valid( p_physp ) && + osm_physp_share_pkey(p_rcv->p_log, p_req_physp, p_physp)) + __osm_sa_pir_check_physp( p_rcv, p_physp, p_ctxt ); + } + } + else + { + for( port_num = 0; port_num < num_ports; port_num++ ) + { + p_physp = osm_port_get_phys_ptr( p_port, port_num ); + if( p_physp == NULL ) + continue; + + if( !osm_physp_is_valid( p_physp ) ) + continue; + + /* if the requester and the p_physp don't share a pkey - + continue */ + if (!osm_physp_share_pkey(p_rcv->p_log, p_req_physp, p_physp ) ) + continue; + + __osm_sa_pir_check_physp( p_rcv, p_physp, p_ctxt ); + } + } + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_sa_pir_by_comp_mask_cb( + IN cl_map_item_t* const p_map_item, + IN void* context ) +{ + const osm_port_t* const p_port = (osm_port_t*)p_map_item; + osm_pir_search_ctxt_t* const p_ctxt = (osm_pir_search_ctxt_t *)context; + + __osm_sa_pir_by_comp_mask( p_ctxt->p_rcv, p_port, p_ctxt ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_pir_rcv_process( + IN osm_pir_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ) +{ + const ib_sa_mad_t* p_rcvd_mad; + const ib_portinfo_record_t* p_rcvd_rec; + const cl_ptr_vector_t* p_tbl; + const osm_port_t* p_port = NULL; + const ib_port_info_t* p_pi; + cl_qlist_t rec_list; + osm_madw_t* p_resp_madw; + ib_sa_mad_t* p_resp_sa_mad; + ib_portinfo_record_t* p_resp_rec; + uint32_t num_rec, pre_trim_num_rec; +#ifndef VENDOR_RMPP_SUPPORT + uint32_t trim_num_rec; +#endif + uint32_t i; + osm_pir_search_ctxt_t context; + osm_pir_item_t* p_rec_item; + ib_api_status_t status = IB_SUCCESS; + ib_net64_t comp_mask; + osm_physp_t* p_req_physp; + boolean_t trusted_req = TRUE; + + CL_ASSERT( p_rcv ); + + OSM_LOG_ENTER( p_rcv->p_log, osm_pir_rcv_process ); + + CL_ASSERT( p_madw ); + + p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw ); + p_rcvd_rec = (ib_portinfo_record_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad ); + comp_mask = p_rcvd_mad->comp_mask; + + CL_ASSERT( p_rcvd_mad->attr_id == IB_MAD_ATTR_PORTINFO_RECORD ); + + /* we only support SubnAdmGet and SubnAdmGetTable methods */ + if ( (p_rcvd_mad->method != IB_MAD_METHOD_GET) && + (p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_pir_rcv_process: ERR 2105: " + "Unsupported Method (%s)\n", + ib_get_sa_method_str( p_rcvd_mad->method ) ); + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR ); + goto Exit; + } + + /* update the requester physical port. */ + p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log, + p_rcv->p_subn, + osm_madw_get_mad_addr_ptr(p_madw) ); + if (p_req_physp == NULL) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_pir_rcv_process: ERR 2104: " + "Cannot find requester physical port\n" ); + goto Exit; + } + + if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + osm_dump_portinfo_record( p_rcv->p_log, p_rcvd_rec, OSM_LOG_DEBUG ); + + p_tbl = &p_rcv->p_subn->port_lid_tbl; + p_pi = &p_rcvd_rec->port_info; + + cl_qlist_init( &rec_list ); + + context.p_rcvd_rec = p_rcvd_rec; + context.p_list = &rec_list; + context.comp_mask = p_rcvd_mad->comp_mask; + context.p_rcv = p_rcv; + context.p_req_physp = p_req_physp; + context.is_enhanced_comp_mask = cl_ntoh32(p_rcvd_mad->attr_mod) & (1 << 31); + + cl_plock_acquire( p_rcv->p_lock ); + + CL_ASSERT( cl_ptr_vector_get_size(p_tbl) < 0x10000 ); + + /* + If the user specified a LID, it obviously narrows our + work load, since we don't have to search every port + */ + if( comp_mask & IB_PIR_COMPMASK_LID ) + { + status = osm_get_port_by_base_lid( p_rcv->p_subn, p_rcvd_rec->lid, &p_port ); + if ( ( status != IB_SUCCESS ) || ( p_port == NULL ) ) + { + status = IB_NOT_FOUND; + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_pir_rcv_process: ERR 2109: " + "No port found with LID 0x%x\n", + cl_ntoh16(p_rcvd_rec->lid) ); + } + } + else + { + if( comp_mask & IB_PIR_COMPMASK_BASELID ) + { + if ((uint16_t)cl_ptr_vector_get_size(p_tbl) > cl_ntoh16(p_pi->base_lid)) + { + p_port = cl_ptr_vector_get( p_tbl, cl_ntoh16(p_pi->base_lid) ); + } + else + { + status = IB_NOT_FOUND; + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_pir_rcv_process: ERR 2103: " + "Given LID (0x%X) is out of range:0x%X\n", + cl_ntoh16(p_pi->base_lid), cl_ptr_vector_get_size(p_tbl)); + } + } + } + + if ( status == IB_SUCCESS ) + { + if( p_port ) + __osm_sa_pir_by_comp_mask( p_rcv, p_port, &context ); + else + { + cl_qmap_apply_func( &p_rcv->p_subn->port_guid_tbl, + __osm_sa_pir_by_comp_mask_cb, + &context ); + } + } + + cl_plock_release( p_rcv->p_lock ); + + num_rec = cl_qlist_count( &rec_list ); + + /* + * C15-0.1.30: + * If we do a SubnAdmGet and got more than one record it is an error ! + */ + if (p_rcvd_mad->method == IB_MAD_METHOD_GET) + { + if (num_rec == 0) + { + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS ); + goto Exit; + } + if (num_rec > 1) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_pir_rcv_process: ERR 2108: " + "Got more than one record for SubnAdmGet (%u)\n", + num_rec ); + osm_sa_send_error( p_rcv->p_resp, p_madw, + IB_SA_MAD_STATUS_TOO_MANY_RECORDS); + + /* need to set the mem free ... */ + p_rec_item = (osm_pir_item_t*)cl_qlist_remove_head( &rec_list ); + while( p_rec_item != (osm_pir_item_t*)cl_qlist_end( &rec_list ) ) + { + cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item ); + p_rec_item = (osm_pir_item_t*)cl_qlist_remove_head( &rec_list ); + } + + goto Exit; + } + } + + pre_trim_num_rec = num_rec; +#ifndef VENDOR_RMPP_SUPPORT + trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_portinfo_record_t); + if (trim_num_rec < num_rec) + { + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "osm_pir_rcv_process: " + "Number of records:%u trimmed to:%u to fit in one MAD\n", + num_rec, trim_num_rec ); + num_rec = trim_num_rec; + } +#endif + + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "osm_pir_rcv_process: " + "Returning %u records\n", num_rec ); + + if ((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0)) + { + osm_sa_send_error( p_rcv->p_resp, p_madw, + IB_SA_MAD_STATUS_NO_RECORDS ); + goto Exit; + } + + /* + * Get a MAD to reply. Address of Mad is in the received mad_wrapper + */ + p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool, + p_madw->h_bind, + num_rec * sizeof(ib_portinfo_record_t) + IB_SA_MAD_HDR_SIZE, + &p_madw->mad_addr ); + + if( !p_resp_madw ) + { + osm_log(p_rcv->p_log, OSM_LOG_ERROR, + "osm_pir_rcv_process: ERR 2106: " + "osm_mad_pool_get failed\n" ); + + for( i = 0; i < num_rec; i++ ) + { + p_rec_item = (osm_pir_item_t*)cl_qlist_remove_head( &rec_list ); + cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item ); + } + + osm_sa_send_error( p_rcv->p_resp, p_madw, + IB_SA_MAD_STATUS_NO_RESOURCES ); + + goto Exit; + } + + p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw ); + + /* + Copy the MAD header back into the response mad. + Set the 'R' bit and the payload length, + Then copy all records from the list into the response payload. + */ + + memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE ); + p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK; + /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */ + p_resp_sa_mad->sm_key = 0; + /* Fill in the offset (paylen will be done by the rmpp SAR) */ + p_resp_sa_mad->attr_offset = + ib_get_attr_offset( sizeof(ib_portinfo_record_t) ); + + p_resp_rec = (ib_portinfo_record_t*) + ib_sa_mad_get_payload_ptr( p_resp_sa_mad ); + +#ifndef VENDOR_RMPP_SUPPORT + /* we support only one packet RMPP - so we will set the first and + last flags for gettable */ + if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP) + { + p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA; + p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE; + } +#else + /* forcefully define the packet as RMPP one */ + if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP) + p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE; +#endif + + /* + p922 - The M_Key returned shall be zero, except in the case of a + trusted request. + Note: In the mad controller we check that the SM_Key received on + the mad is valid. Meaning - is either zero or equal to the local + sm_key. + */ + if (p_rcvd_mad->sm_key == 0) + trusted_req = FALSE; + + for( i = 0; i < pre_trim_num_rec; i++ ) + { + p_rec_item = (osm_pir_item_t*)cl_qlist_remove_head( &rec_list ); + /* copy only if not trimmed */ + if (i < num_rec) + { + *p_resp_rec = p_rec_item->rec; + if (trusted_req == FALSE) + p_resp_rec->port_info.m_key = 0; + } + cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item ); + p_resp_rec++; + } + + CL_ASSERT( cl_is_qlist_empty( &rec_list ) ); + + status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE); + if (status != IB_SUCCESS) + { + osm_log(p_rcv->p_log, OSM_LOG_ERROR, + "osm_pir_rcv_process: ERR 2107: " + "osm_vendor_send status = %s\n", + ib_get_err_str(status)); + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_portinfo_record_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_portinfo_record_ctrl.c new file mode 100644 index 00000000..80bb937b --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_portinfo_record_ctrl.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_portinfo_record_ctrl.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_pir_rcv_ctrl_t. + * This object represents the PortInfoRecord request controller object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +__osm_pir_rcv_ctrl_disp_callback( + IN void *context, + IN void *p_data ) +{ + /* ignore return status when invoked via the dispatcher */ + osm_pir_rcv_process( ((osm_pir_rcv_ctrl_t*)context)->p_rcv, + (osm_madw_t*)p_data ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_pir_rcv_ctrl_construct( + IN osm_pir_rcv_ctrl_t* const p_ctrl ) +{ + memset( p_ctrl, 0, sizeof(*p_ctrl) ); + p_ctrl->h_disp = CL_DISP_INVALID_HANDLE; +} + +/********************************************************************** + **********************************************************************/ +void +osm_pir_rcv_ctrl_destroy( + IN osm_pir_rcv_ctrl_t* const p_ctrl ) +{ + CL_ASSERT( p_ctrl ); + cl_disp_unregister( p_ctrl->h_disp ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_pir_rcv_ctrl_init( + IN osm_pir_rcv_ctrl_t* const p_ctrl, + IN osm_pir_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_pir_rcv_ctrl_init ); + + osm_pir_rcv_ctrl_construct( p_ctrl ); + p_ctrl->p_log = p_log; + p_ctrl->p_rcv = p_rcv; + p_ctrl->p_disp = p_disp; + + p_ctrl->h_disp = cl_disp_register( + p_disp, + OSM_MSG_MAD_PORTINFO_RECORD, + __osm_pir_rcv_ctrl_disp_callback, + p_ctrl ); + + if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_pir_rcv_ctrl_init: ERR 2201: " + "Dispatcher registration failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return( status ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_response.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_response.c new file mode 100644 index 00000000..3d242d87 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_response.c @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_response.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Implementation of osm_sa_resp_t. + * This object represents the SA query responder. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.6 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +osm_sa_resp_construct( + IN osm_sa_resp_t* const p_resp ) +{ + memset( p_resp, 0, sizeof(*p_resp) ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_sa_resp_destroy( + IN osm_sa_resp_t* const p_resp ) +{ + CL_ASSERT( p_resp ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_sa_resp_init( + IN osm_sa_resp_t* const p_resp, + IN osm_mad_pool_t* const p_pool, + IN osm_log_t* const p_log ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_sa_resp_init ); + + osm_sa_resp_construct( p_resp ); + + p_resp->p_log = p_log; + p_resp->p_pool = p_pool; + + OSM_LOG_EXIT( p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_sa_send_error( + IN osm_sa_resp_t* const p_resp, + IN const osm_madw_t* const p_madw, + IN const ib_net16_t sa_status ) +{ + osm_madw_t* p_resp_madw; + ib_sa_mad_t* p_resp_sa_mad; + ib_sa_mad_t* p_sa_mad; + ib_api_status_t status; + + OSM_LOG_ENTER( p_resp->p_log, osm_sa_send_error ); + + /* avoid races - if we are exiting - exit */ + if (osm_exit_flag) + { + osm_log( p_resp->p_log, OSM_LOG_DEBUG, + "osm_sa_send_error: " + "Ignoring requested send after exit\n" ); + goto Exit; + } + + p_resp_madw = osm_mad_pool_get( p_resp->p_pool, + p_madw->h_bind, MAD_BLOCK_SIZE, &p_madw->mad_addr ); + + if( p_resp_madw == NULL ) + { + osm_log( p_resp->p_log, OSM_LOG_ERROR, + "osm_sa_send_error: ERR 2301: " + "Unable to acquire response MAD\n" ); + goto Exit; + } + + p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw ); + p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw ); + + /* Copy the MAD header back into the response mad */ + *p_resp_sa_mad = *p_sa_mad; + p_resp_sa_mad->status = sa_status; + + if( p_resp_sa_mad->method == IB_MAD_METHOD_SET ) + p_resp_sa_mad->method = IB_MAD_METHOD_GET; + + p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK; + + /* + * C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) + */ + p_resp_sa_mad->sm_key = 0; + + /* + * o15-0.2.7 - The PathRecord Attribute ID shall be used in + * the response (to a SubnAdmGetMulti(MultiPathRecord) + */ + if( p_resp_sa_mad->attr_id == IB_MAD_ATTR_MULTIPATH_RECORD ) + p_resp_sa_mad->attr_id = IB_MAD_ATTR_PATH_RECORD; + + if( osm_log_is_active( p_resp->p_log, OSM_LOG_FRAMES ) ) + osm_dump_sa_mad( p_resp->p_log, p_resp_sa_mad, OSM_LOG_FRAMES ); + + status = osm_vendor_send( osm_madw_get_bind_handle( p_resp_madw ), + p_resp_madw, FALSE ); + + if( status != IB_SUCCESS ) + { + osm_log( p_resp->p_log, OSM_LOG_ERROR, + "osm_sa_send_error: ERR 2302: " + "Error sending MAD (%s)\n", ib_get_err_str( status ) ); + /* osm_mad_pool_put( p_resp->p_pool, p_resp_madw ); */ + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_resp->p_log ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_service_record.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_service_record.c new file mode 100644 index 00000000..97595d0f --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_service_record.c @@ -0,0 +1,1204 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_service_record.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Implementation of osm_sr_rcv_t. + * This object represents the ServiceRecord Receiver object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.9 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define OSM_SR_RCV_POOL_MIN_SIZE 64 +#define OSM_SR_RCV_POOL_GROW_SIZE 64 + +typedef struct _osm_sr_item +{ + cl_pool_item_t pool_item; + ib_service_record_t service_rec; +} osm_sr_item_t; + +typedef struct osm_sr_match_item { + cl_qlist_t sr_list; + ib_service_record_t* p_service_rec; + ib_net64_t comp_mask; + osm_sr_rcv_t* p_rcv; + +} osm_sr_match_item_t; + +typedef struct _osm_sr_search_ctxt +{ + osm_sr_match_item_t * p_sr_item; + const osm_physp_t* p_req_physp; +} osm_sr_search_ctxt_t; + +/********************************************************************** + **********************************************************************/ +void +osm_sr_rcv_construct( + IN osm_sr_rcv_t* const p_rcv ) +{ + memset( p_rcv, 0, sizeof(*p_rcv) ); + cl_qlock_pool_construct( &p_rcv->sr_pool ); + cl_timer_construct(&p_rcv->sr_timer ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_sr_rcv_destroy( + IN osm_sr_rcv_t* const p_rcv ) +{ + OSM_LOG_ENTER( p_rcv->p_log, osm_sr_rcv_destroy ); + cl_qlock_pool_destroy( &p_rcv->sr_pool ); + cl_timer_trim(&p_rcv->sr_timer, 1); + cl_timer_destroy(&p_rcv->sr_timer ); + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_sr_rcv_init( + IN osm_sr_rcv_t* const p_rcv, + IN osm_sa_resp_t* const p_resp, + IN osm_mad_pool_t* const p_mad_pool, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ) +{ + ib_api_status_t status = IB_ERROR; + cl_status_t cl_status; + + OSM_LOG_ENTER( p_log, osm_sr_rcv_init ); + + osm_sr_rcv_construct( p_rcv ); + + p_rcv->p_log = p_log; + p_rcv->p_subn = p_subn; + p_rcv->p_lock = p_lock; + p_rcv->p_resp = p_resp; + p_rcv->p_mad_pool = p_mad_pool; + + cl_status = cl_qlock_pool_init( &p_rcv->sr_pool, + OSM_SR_RCV_POOL_MIN_SIZE, + 0, + OSM_SR_RCV_POOL_GROW_SIZE, + sizeof(osm_sr_item_t), + NULL, NULL, NULL ); + if(cl_status != CL_SUCCESS) + goto Exit; + + status = cl_timer_init(&p_rcv->sr_timer, + osm_sr_rcv_lease_cb, + p_rcv ); + if(cl_status != CL_SUCCESS) + goto Exit; + + status = IB_SUCCESS; + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +static boolean_t +__match_service_pkey_with_ports_pkey( + IN osm_sr_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw, + ib_service_record_t * const p_service_rec, + ib_net64_t const comp_mask ) +{ + boolean_t valid = TRUE; + osm_physp_t * p_req_physp; + ib_net64_t service_guid; + osm_port_t * service_port; + + /* update the requester physical port. */ + p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log, + p_rcv->p_subn, + osm_madw_get_mad_addr_ptr(p_madw)); + if (p_req_physp == NULL) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__match_service_pkey_with_ports_pkey: ERR 2404: " + "Cannot find requester physical port\n" ); + valid = FALSE; + goto Exit; + } + + if((comp_mask & IB_SR_COMPMASK_SPKEY) == IB_SR_COMPMASK_SPKEY) + { + /* We have a ServiceP_Key - check matching on requester port, and + ServiceGid port (if such exists) */ + /* Make sure it matches the p_req_physp */ + if (!osm_physp_has_pkey(p_rcv->p_log, p_service_rec->service_pkey, p_req_physp)) + { + valid = FALSE; + goto Exit; + } + + /* Make sure it matches the port of the ServiceGid */ + if((comp_mask & IB_SR_COMPMASK_SGID) == IB_SR_COMPMASK_SGID) + { + service_guid = p_service_rec->service_gid.unicast.interface_id; + service_port = (osm_port_t*)cl_qmap_get( &p_rcv->p_subn->port_guid_tbl, service_guid ); + if (service_port == (osm_port_t*)cl_qmap_end( &p_rcv->p_subn->port_guid_tbl )) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__match_service_pkey_with_ports_pkey: ERR 2405: " + "No port object for port 0x%016" PRIx64 "\n", + cl_ntoh64( service_guid ) ); + valid = FALSE; + goto Exit; + } + /* check on the table of the default physical port of the service port */ + if ( !osm_physp_has_pkey( p_rcv->p_log, + p_service_rec->service_pkey, + osm_port_get_default_phys_ptr(service_port) ) ) + { + valid = FALSE; + goto Exit; + } + } + } + + Exit: + return valid; +} + +/********************************************************************** + **********************************************************************/ +boolean_t +__match_name_to_key_association( + IN osm_sr_rcv_t* const p_rcv, + ib_service_record_t* p_service_rec, + ib_net64_t comp_mask ) +{ + UNUSED_PARAM( p_service_rec ); + UNUSED_PARAM( p_rcv ); + + if( (comp_mask & (IB_SR_COMPMASK_SKEY | IB_SR_COMPMASK_SNAME)) == + (IB_SR_COMPMASK_SKEY | IB_SR_COMPMASK_SNAME) ) + { + /* For now, we are not maintaining the ServiceAssociation record + * so just return TRUE + */ + return TRUE; + } + + return TRUE; +} + +/********************************************************************** + **********************************************************************/ +static boolean_t +__validate_sr( + IN osm_sr_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ) +{ + boolean_t valid = TRUE; + ib_sa_mad_t * p_sa_mad; + ib_service_record_t* p_recvd_service_rec; + + OSM_LOG_ENTER( p_rcv->p_log, __validate_sr ); + + p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw ); + p_recvd_service_rec = + (ib_service_record_t*)ib_sa_mad_get_payload_ptr( p_sa_mad ); + + valid = __match_service_pkey_with_ports_pkey( + p_rcv, + p_madw, + p_recvd_service_rec, + p_sa_mad->comp_mask ); + + if(!valid) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__validate_sr: " + "No Match for Service Pkey\n" ); + valid = FALSE; + goto Exit; + } + + valid = __match_name_to_key_association( + p_rcv, + p_recvd_service_rec, + p_sa_mad->comp_mask ); + + if(!valid) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__validate_sr: " + "Service Record Name to key matching failed\n" ); + valid = FALSE; + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); + return valid; +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_sr_rcv_respond( + IN osm_sr_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw, + IN cl_qlist_t* const p_list ) +{ + osm_madw_t* p_resp_madw; + const ib_sa_mad_t* p_sa_mad; + ib_sa_mad_t* p_resp_sa_mad; + uint32_t num_rec, num_copied; +#ifndef VENDOR_RMPP_SUPPORT + uint32_t trim_num_rec; +#endif + ib_service_record_t* p_resp_sr; + ib_api_status_t status; + osm_sr_item_t* p_sr_item; + const ib_sa_mad_t* p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw ); + boolean_t trusted_req = TRUE; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_sr_rcv_respond ); + + num_rec = cl_qlist_count( p_list ); + + /* + * C15-0.1.30: + * If we do a SubnAdmGet and got more than one record it is an error ! + */ + if ( (p_rcvd_mad->method == IB_MAD_METHOD_GET) && + (num_rec > 1)) { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_sr_rcv_respond: ERR 2406: " + "Got more than one record for SubnAdmGet (%u).\n", + num_rec ); + osm_sa_send_error( p_rcv->p_resp, p_madw, + IB_SA_MAD_STATUS_TOO_MANY_RECORDS ); + + /* need to set the mem free ... */ + p_sr_item = (osm_sr_item_t*)cl_qlist_remove_head( p_list ); + while( p_sr_item != (osm_sr_item_t*)cl_qlist_end( p_list ) ) + { + cl_qlock_pool_put( &p_rcv->sr_pool, &p_sr_item->pool_item ); + p_sr_item = (osm_sr_item_t*)cl_qlist_remove_head( p_list ); + } + + goto Exit; + } + +#ifndef VENDOR_RMPP_SUPPORT + trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_service_record_t); + if (trim_num_rec < num_rec) + { + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "__osm_sr_rcv_respond: " + "Number of records:%u trimmed to:%u to fit in one MAD\n", + num_rec, trim_num_rec ); + num_rec = trim_num_rec; + } +#endif + + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_sr_rcv_respond: " + "Generating response with %u records\n", num_rec ); + } + + /* + Get a MAD to reply. Address of Mad is in the received mad_wrapper + */ + p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool, + p_madw->h_bind, + num_rec * sizeof(ib_service_record_t) + IB_SA_MAD_HDR_SIZE, + &p_madw->mad_addr ); + if( !p_resp_madw ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_sr_rcv_respond: ERR 2402: " + "Unable to allocate MAD\n" ); + /* Release the quick pool items */ + p_sr_item = (osm_sr_item_t*)cl_qlist_remove_head( p_list ); + while( p_sr_item != (osm_sr_item_t*)cl_qlist_end( p_list ) ) + { + cl_qlock_pool_put( &p_rcv->sr_pool, &p_sr_item->pool_item ); + p_sr_item = (osm_sr_item_t*)cl_qlist_remove_head( p_list ); + } + + goto Exit; + } + + p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw ); + p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw ); + + memcpy( p_resp_sa_mad, p_sa_mad, IB_SA_MAD_HDR_SIZE ); + + /* but what if it was a SET ? setting the response bit is not enough */ + if (p_rcvd_mad->method == IB_MAD_METHOD_SET) + { + p_resp_sa_mad->method = IB_MAD_METHOD_GET; + } + p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK; + /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */ + p_resp_sa_mad->sm_key = 0; + + /* Fill in the offset (paylen will be done by the rmpp SAR) */ + p_resp_sa_mad->attr_offset = + ib_get_attr_offset( sizeof(ib_service_record_t) ); + +#ifndef VENDOR_RMPP_SUPPORT + /* we support only one packet RMPP - so we will set the first and + last flags for gettable */ + if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP) + { + p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA; + p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE; + } +#else + /* forcefully define the packet as RMPP one */ + if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP) + p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE; +#endif + + p_resp_sr = (ib_service_record_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad ); + + if( (p_resp_sa_mad->method != IB_MAD_METHOD_GETTABLE_RESP) && + (num_rec == 0)) + { + p_resp_sa_mad->status = IB_SA_MAD_STATUS_NO_RECORDS; + memset( p_resp_sr, 0, sizeof(*p_resp_sr) ); + } + else + { + /* + p923 - The ServiceKey shall be set to 0, except in the case of a trusted + request. + Note: In the mad controller we check that the SM_Key received on + the mad is valid. Meaning - is either zero or equal to the local + sm_key. + */ + if (p_sa_mad->sm_key == 0) + trusted_req = FALSE; + + p_sr_item = (osm_sr_item_t*)cl_qlist_remove_head( p_list ); + + /* we need to track the number of copied items so we can + * stop the copy - but clear them all + */ + num_copied = 0; + while( p_sr_item != (osm_sr_item_t*)cl_qlist_end( p_list ) ) + { + /* Copy the Link Records from the list into the MAD */ + if (num_copied < num_rec) + { + *p_resp_sr = p_sr_item->service_rec; + if (trusted_req == FALSE) + memset(p_resp_sr->service_key, 0, sizeof(p_resp_sr->service_key)); + + num_copied++; + } + cl_qlock_pool_put( &p_rcv->sr_pool, &p_sr_item->pool_item ); + p_resp_sr++; + p_sr_item = (osm_sr_item_t*)cl_qlist_remove_head( p_list ); + } + } + + status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE ); + + if( status != IB_SUCCESS ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_sr_rcv_respond: ERR 2407: " + "Unable to send MAD (%s)\n", ib_get_err_str( status ) ); + /* osm_mad_pool_put( p_rcv->p_mad_pool, p_resp_madw ); */ + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +static void +__get_matching_sr( + IN cl_list_item_t* const p_list_item, + IN void* context ) +{ + osm_sr_search_ctxt_t* const p_ctxt = (osm_sr_search_ctxt_t*)context; + osm_svcr_t * p_svcr = (osm_svcr_t*)p_list_item; + osm_sr_item_t* p_sr_pool_item; + osm_sr_match_item_t* p_sr_item =p_ctxt->p_sr_item; + ib_net64_t comp_mask = p_sr_item->comp_mask; + const osm_physp_t* p_req_physp = p_ctxt->p_req_physp; + + if((comp_mask & IB_SR_COMPMASK_SID) == IB_SR_COMPMASK_SID) + { + if(p_sr_item->p_service_rec->service_id != + p_svcr->service_record.service_id) + return; + } + if((comp_mask & IB_SR_COMPMASK_SGID) == IB_SR_COMPMASK_SGID) + { + if( + memcmp(&p_sr_item->p_service_rec->service_gid, + &p_svcr->service_record.service_gid, + sizeof(p_svcr->service_record.service_gid)) != 0) + return; + } + if((comp_mask & IB_SR_COMPMASK_SPKEY) == IB_SR_COMPMASK_SPKEY ) + { + if(p_sr_item->p_service_rec->service_pkey != + p_svcr->service_record.service_pkey) + return; + } + + if((comp_mask & IB_SR_COMPMASK_SKEY) == IB_SR_COMPMASK_SKEY) + { + if(memcmp(p_sr_item->p_service_rec->service_key , + p_svcr->service_record.service_key, + 16*sizeof(uint8_t))) + return; + } + if((comp_mask & IB_SR_COMPMASK_SNAME) == IB_SR_COMPMASK_SNAME) + { + if( + memcmp(p_sr_item->p_service_rec->service_name, + p_svcr->service_record.service_name, + sizeof(p_svcr->service_record.service_name)) != 0 + ) + return; + } + if((comp_mask & IB_SR_COMPMASK_SDATA8_0) == IB_SR_COMPMASK_SDATA8_0) + { + if(p_sr_item->p_service_rec->service_data8[0] != + p_svcr->service_record.service_data8[0]) + return; + } + + if((comp_mask & IB_SR_COMPMASK_SDATA8_1) == IB_SR_COMPMASK_SDATA8_1) + { + if(p_sr_item->p_service_rec->service_data8[1] != + p_svcr->service_record.service_data8[1]) + return; + } + if((comp_mask & IB_SR_COMPMASK_SDATA8_2) == IB_SR_COMPMASK_SDATA8_2) + { + if(p_sr_item->p_service_rec->service_data8[2] != + p_svcr->service_record.service_data8[2]) + return; + } + if((comp_mask & IB_SR_COMPMASK_SDATA8_3) == IB_SR_COMPMASK_SDATA8_3) + { + if(p_sr_item->p_service_rec->service_data8[3] != + p_svcr->service_record.service_data8[3]) + return; + } + if((comp_mask & IB_SR_COMPMASK_SDATA8_4)== IB_SR_COMPMASK_SDATA8_4) + { + if(p_sr_item->p_service_rec->service_data8[4] != + p_svcr->service_record.service_data8[4]) + return; + } + if((comp_mask & IB_SR_COMPMASK_SDATA8_5)== IB_SR_COMPMASK_SDATA8_5) + { + if(p_sr_item->p_service_rec->service_data8[5] != + p_svcr->service_record.service_data8[5]) + return; + } + if((comp_mask & IB_SR_COMPMASK_SDATA8_6)== IB_SR_COMPMASK_SDATA8_6) + { + if(p_sr_item->p_service_rec->service_data8[6]!= + p_svcr->service_record.service_data8[6]) + return; + } + + if((comp_mask & IB_SR_COMPMASK_SDATA8_7)== IB_SR_COMPMASK_SDATA8_7) + { + if(p_sr_item->p_service_rec->service_data8[7]!= + p_svcr->service_record.service_data8[7]) + return; + } + + if((comp_mask & IB_SR_COMPMASK_SDATA8_8)== IB_SR_COMPMASK_SDATA8_8) + { + if(p_sr_item->p_service_rec->service_data8[8]!= + p_svcr->service_record.service_data8[8]) + return; + } + + if((comp_mask & IB_SR_COMPMASK_SDATA8_9)== IB_SR_COMPMASK_SDATA8_9) + { + if(p_sr_item->p_service_rec->service_data8[9]!= + p_svcr->service_record.service_data8[9]) + return; + } + + if((comp_mask & IB_SR_COMPMASK_SDATA8_10)== IB_SR_COMPMASK_SDATA8_10) + { + if(p_sr_item->p_service_rec->service_data8[10]!= + p_svcr->service_record.service_data8[10]) + return; + } + + if((comp_mask & IB_SR_COMPMASK_SDATA8_11)== IB_SR_COMPMASK_SDATA8_11) + { + if(p_sr_item->p_service_rec->service_data8[11]!= + p_svcr->service_record.service_data8[11]) + return; + } + + if((comp_mask & IB_SR_COMPMASK_SDATA8_12)== IB_SR_COMPMASK_SDATA8_12) + { + if(p_sr_item->p_service_rec->service_data8[12]!= + p_svcr->service_record.service_data8[12]) + return; + } + if((comp_mask & IB_SR_COMPMASK_SDATA8_13)== IB_SR_COMPMASK_SDATA8_13) + { + if(p_sr_item->p_service_rec->service_data8[13]!= + p_svcr->service_record.service_data8[13]) + return; + } + if((comp_mask & IB_SR_COMPMASK_SDATA8_14)== IB_SR_COMPMASK_SDATA8_14) + { + if(p_sr_item->p_service_rec->service_data8[14]!= + p_svcr->service_record.service_data8[14]) + return; + } + if((comp_mask & IB_SR_COMPMASK_SDATA8_15)== IB_SR_COMPMASK_SDATA8_15) + { + if(p_sr_item->p_service_rec->service_data8[15]!= + p_svcr->service_record.service_data8[15]) + return; + } + if((comp_mask & IB_SR_COMPMASK_SDATA16_0)== IB_SR_COMPMASK_SDATA16_0) + { + if(p_sr_item->p_service_rec->service_data16[0]!= + p_svcr->service_record.service_data16[0]) + return; + } + if((comp_mask & IB_SR_COMPMASK_SDATA16_1)== IB_SR_COMPMASK_SDATA16_1) + { + if(p_sr_item->p_service_rec->service_data16[1]!= + p_svcr->service_record.service_data16[1]) + return; + } + if((comp_mask & IB_SR_COMPMASK_SDATA16_2)== IB_SR_COMPMASK_SDATA16_2) + { + if(p_sr_item->p_service_rec->service_data16[2]!= + p_svcr->service_record.service_data16[2]) + return; + } + if((comp_mask & IB_SR_COMPMASK_SDATA16_3)== IB_SR_COMPMASK_SDATA16_3) + { + if(p_sr_item->p_service_rec->service_data16[3]!= + p_svcr->service_record.service_data16[3]) + return; + } + if((comp_mask & IB_SR_COMPMASK_SDATA16_4)== IB_SR_COMPMASK_SDATA16_4) + { + if(p_sr_item->p_service_rec->service_data16[4]!= + p_svcr->service_record.service_data16[4]) + return; + } + if((comp_mask & IB_SR_COMPMASK_SDATA16_5)== IB_SR_COMPMASK_SDATA16_5) + { + if(p_sr_item->p_service_rec->service_data16[5]!= + p_svcr->service_record.service_data16[5]) + return; + } + if((comp_mask & IB_SR_COMPMASK_SDATA16_6)== IB_SR_COMPMASK_SDATA16_6) + { + if(p_sr_item->p_service_rec->service_data16[6]!= + p_svcr->service_record.service_data16[6]) + return; + } + if((comp_mask & IB_SR_COMPMASK_SDATA16_7)== IB_SR_COMPMASK_SDATA16_7) + { + if(p_sr_item->p_service_rec->service_data16[7]!= + p_svcr->service_record.service_data16[7]) + return; + } + if((comp_mask & IB_SR_COMPMASK_SDATA32_0)== IB_SR_COMPMASK_SDATA32_0) + { + if(p_sr_item->p_service_rec->service_data32[0]!= + p_svcr->service_record.service_data32[0]) + return; + } + if((comp_mask & IB_SR_COMPMASK_SDATA32_1)== IB_SR_COMPMASK_SDATA32_1) + { + if(p_sr_item->p_service_rec->service_data32[1]!= + p_svcr->service_record.service_data32[1]) + return; + } + if((comp_mask & IB_SR_COMPMASK_SDATA32_2)== IB_SR_COMPMASK_SDATA32_2) + { + if(p_sr_item->p_service_rec->service_data32[2]!= + p_svcr->service_record.service_data32[2]) + return; + } + if((comp_mask & IB_SR_COMPMASK_SDATA32_3)== IB_SR_COMPMASK_SDATA32_3) + { + if(p_sr_item->p_service_rec->service_data32[3]!= + p_svcr->service_record.service_data32[3]) + return; + } + + if((comp_mask & IB_SR_COMPMASK_SDATA64_0)== IB_SR_COMPMASK_SDATA64_0) + { + if(p_sr_item->p_service_rec->service_data64[0]!= + p_svcr->service_record.service_data64[0]) + return; + } + if((comp_mask & IB_SR_COMPMASK_SDATA64_1)== IB_SR_COMPMASK_SDATA64_1) + { + if(p_sr_item->p_service_rec->service_data64[1]!= + p_svcr->service_record.service_data64[1]) + return; + } + + /* Check that the requester port has the pkey which is the service_pkey. + If not - then it cannot receive this ServiceRecord. */ + /* The check is relevant only if the service_pkey is valid */ + if (!ib_pkey_is_invalid(p_svcr->service_record.service_pkey)) + { + if (!osm_physp_has_pkey( p_sr_item->p_rcv->p_log, + p_svcr->service_record.service_pkey, + p_req_physp ) ) + { + osm_log( p_sr_item->p_rcv->p_log, OSM_LOG_VERBOSE, + "__get_matching_sr: " + "requester port doesn't have the service_pkey: 0x%X\n", + cl_ntoh16(p_svcr->service_record.service_pkey) ); + return; + } + } + + p_sr_pool_item = (osm_sr_item_t*)cl_qlock_pool_get( &p_sr_item->p_rcv->sr_pool ); + + if( p_sr_pool_item == NULL ) + { + osm_log( p_sr_item->p_rcv->p_log, OSM_LOG_ERROR, + "__get_matching_sr: ERR 2408: " + "Unable to acquire Service Record from pool\n" ); + goto Exit; + } + + p_sr_pool_item->service_rec = p_svcr->service_record; + + cl_qlist_insert_tail( &p_sr_item->sr_list, + (cl_list_item_t*)&p_sr_pool_item->pool_item ); + + Exit: + return; +} + +/********************************************************************** + **********************************************************************/ +static void +osm_sr_rcv_process_get_method( + IN osm_sr_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ) +{ + ib_sa_mad_t * p_sa_mad; + ib_service_record_t* p_recvd_service_rec; + osm_sr_match_item_t sr_match_item; + osm_sr_search_ctxt_t context; + osm_physp_t* p_req_physp; + + OSM_LOG_ENTER( p_rcv->p_log, osm_sr_rcv_process_get_method ); + + CL_ASSERT( p_madw ); + + /* update the requester physical port. */ + p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log, + p_rcv->p_subn, + osm_madw_get_mad_addr_ptr(p_madw) ); + if (p_req_physp == NULL) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_sr_rcv_process_get_method: ERR 2409: " + "Cannot find requester physical port\n" ); + goto Exit; + } + + p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw ); + p_recvd_service_rec = + (ib_service_record_t*)ib_sa_mad_get_payload_ptr( p_sa_mad ); + + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_dump_service_record( p_rcv->p_log, + p_recvd_service_rec, + OSM_LOG_DEBUG ); + } + + cl_qlist_init(&sr_match_item.sr_list); + sr_match_item.p_service_rec = p_recvd_service_rec; + sr_match_item.comp_mask = p_sa_mad->comp_mask; + sr_match_item.p_rcv = p_rcv; + + context.p_sr_item = &sr_match_item; + context.p_req_physp = p_req_physp; + + /* Grab the lock */ + cl_plock_excl_acquire(p_rcv->p_lock); + + cl_qlist_apply_func(&p_rcv->p_subn->sa_sr_list, + __get_matching_sr, + &context); + + cl_plock_release(p_rcv->p_lock); + + if ((p_sa_mad->method == IB_MAD_METHOD_GET) && + (cl_qlist_count( &sr_match_item.sr_list ) == 0)) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "osm_sr_rcv_process_get_method: " + "No records matched the Service Record query\n"); + + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS ); + goto Exit; + } + + __osm_sr_rcv_respond( p_rcv, p_madw, &sr_match_item.sr_list ); + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); + return; +} + +/********************************************************************** + **********************************************************************/ +static void +osm_sr_rcv_process_set_method( + IN osm_sr_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ) +{ + ib_sa_mad_t * p_sa_mad; + ib_net16_t sa_status = IB_SA_MAD_STATUS_REQ_INVALID; + ib_service_record_t* p_recvd_service_rec; + ib_net64_t comp_mask; + osm_svcr_t* p_svcr; + osm_sr_item_t* p_sr_item; + cl_qlist_t sr_list; + + OSM_LOG_ENTER( p_rcv->p_log, osm_sr_rcv_process_set_method ); + + CL_ASSERT( p_madw ); + + p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw ); + p_recvd_service_rec = + (ib_service_record_t*)ib_sa_mad_get_payload_ptr( p_sa_mad ); + + comp_mask = p_sa_mad->comp_mask; + + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_dump_service_record( p_rcv->p_log, + p_recvd_service_rec, + OSM_LOG_DEBUG ); + } + + if( (comp_mask & ( IB_SR_COMPMASK_SID | IB_SR_COMPMASK_SGID )) != + (IB_SR_COMPMASK_SID | IB_SR_COMPMASK_SGID )) + { + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "osm_sr_rcv_process_set_method: " + "Component Mask RID check failed for METHOD_SET\n"); + osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status ); + goto Exit; + } + + /* if we were not provided with a service lease make it + infinite */ + if( (comp_mask & IB_SR_COMPMASK_SLEASE) != IB_SR_COMPMASK_SLEASE) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "osm_sr_rcv_process_set_method: " + "ServiceLease Component Mask not set - using infinite lease\n"); + p_recvd_service_rec->service_lease = 0xFFFFFFFF; + } + + /* Grab the lock */ + cl_plock_excl_acquire(p_rcv->p_lock); + + /* If Record exists with matching RID */ + p_svcr = osm_svcr_get_by_rid( + p_rcv->p_subn, + p_rcv->p_log, + p_recvd_service_rec ); + + if(p_svcr == NULL) + { + /* Create the instance of the osm_svcr_t object */ + p_svcr = osm_svcr_new(p_recvd_service_rec); + if(p_svcr == NULL) + { + cl_plock_release(p_rcv->p_lock); + + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_sr_rcv_process_set_method: ERR 2411: " + "osm_svcr_get_by_rid failed\n" ); + + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES ); + goto Exit; + } + + /* Add this new osm_svcr_t object to subnet object */ + osm_svcr_insert_to_db( + p_rcv->p_subn, + p_rcv->p_log, + p_svcr ); + + } + else + { + /* Update the old instance of the osm_svcr_t object */ + osm_svcr_init(p_svcr, p_recvd_service_rec); + } + + cl_plock_release(p_rcv->p_lock); + + if( p_recvd_service_rec->service_lease != 0xFFFFFFFF ) + { +#if 0 + cl_timer_trim(&p_rcv->sr_timer, + p_recvd_service_rec->service_lease * 1000); +#endif + /* This was a bug since no check was made to see if too long */ + /* just make sure the timer works - get a call back within a second */ + cl_timer_trim(&p_rcv->sr_timer, 1000); + p_svcr->modified_time = cl_get_time_stamp_sec(); + } + + p_sr_item = (osm_sr_item_t*)cl_qlock_pool_get( &p_rcv->sr_pool ); + if( p_sr_item == NULL ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_sr_rcv_process_set_method: ERR 2412: " + "Unable to acquire Service record\n" ); + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES ); + goto Exit; + } + + if( (comp_mask & IB_SR_COMPMASK_SPKEY) != IB_SR_COMPMASK_SPKEY) + { + /* Set the Default Service P_Key in the response */ + p_recvd_service_rec->service_pkey = IB_DEFAULT_PKEY; + } + + p_sr_item->service_rec = *p_recvd_service_rec; + cl_qlist_init(&sr_list); + + cl_qlist_insert_tail( &sr_list, (cl_list_item_t*)&p_sr_item->pool_item ); + + __osm_sr_rcv_respond( p_rcv, p_madw, &sr_list ); + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); + return; +} + +/********************************************************************** + **********************************************************************/ +static void +osm_sr_rcv_process_delete_method( + IN osm_sr_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ) +{ + ib_sa_mad_t * p_sa_mad; + ib_service_record_t* p_recvd_service_rec; + ib_net64_t comp_mask; + osm_svcr_t* p_svcr; + osm_sr_item_t* p_sr_item; + cl_qlist_t sr_list; + + OSM_LOG_ENTER( p_rcv->p_log, osm_sr_rcv_process_delete_method ); + + CL_ASSERT( p_madw ); + + p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw ); + p_recvd_service_rec = + (ib_service_record_t*)ib_sa_mad_get_payload_ptr( p_sa_mad ); + + comp_mask = p_sa_mad->comp_mask; + + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_dump_service_record( p_rcv->p_log, + p_recvd_service_rec, + OSM_LOG_DEBUG ); + } + + /* Grab the lock */ + cl_plock_excl_acquire(p_rcv->p_lock); + + /* If Record exists with matching RID */ + p_svcr = osm_svcr_get_by_rid( + p_rcv->p_subn, + p_rcv->p_log, + p_recvd_service_rec ); + + if(p_svcr == NULL) + { + cl_plock_release(p_rcv->p_lock); + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "osm_sr_rcv_process_delete_method: " + "No records matched the RID\n"); + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS ); + goto Exit; + } + else + { + osm_svcr_remove_from_db(p_rcv->p_subn, + p_rcv->p_log, + p_svcr ); + } + + cl_plock_release(p_rcv->p_lock); + + p_sr_item = (osm_sr_item_t*)cl_qlock_pool_get( &p_rcv->sr_pool ); + if( p_sr_item == NULL ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_sr_rcv_process_delete_method: ERR 2413: " + "Unable to acquire Service record\n"); + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES ); + goto Exit; + } + + /* provide back the copy of the record */ + p_sr_item->service_rec = p_svcr->service_record; + cl_qlist_init(&sr_list); + + cl_qlist_insert_tail( &sr_list, (cl_list_item_t*)&p_sr_item->pool_item ); + + if(p_svcr) + osm_svcr_destroy(p_svcr); + + __osm_sr_rcv_respond( p_rcv, p_madw, &sr_list ); + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); + return; +} + +/********************************************************************** + **********************************************************************/ +void +osm_sr_rcv_process( + IN osm_sr_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ) +{ + ib_sa_mad_t * p_sa_mad; + ib_net16_t sa_status = IB_SA_MAD_STATUS_REQ_INVALID; + boolean_t valid; + + OSM_LOG_ENTER( p_rcv->p_log, osm_sr_rcv_process ); + + CL_ASSERT( p_madw ); + + p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw ); + + CL_ASSERT( p_sa_mad->attr_id == IB_MAD_ATTR_SERVICE_RECORD ); + + switch (p_sa_mad->method) + { + case IB_MAD_METHOD_SET: + valid = __validate_sr(p_rcv, p_madw); + if(!valid) + { + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "osm_sr_rcv_process: " + "Component Mask check failed for set request\n" ); + osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status ); + goto Exit; + } + osm_sr_rcv_process_set_method(p_rcv, p_madw); + break; + case IB_MAD_METHOD_DELETE: + valid = __validate_sr(p_rcv, p_madw); + if(!valid) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "osm_sr_rcv_process: " + "Component Mask check failed for delete request\n" ); + osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status ); + goto Exit; + } + osm_sr_rcv_process_delete_method(p_rcv, p_madw); + break; + case IB_MAD_METHOD_GET: + case IB_MAD_METHOD_GETTABLE: + osm_sr_rcv_process_get_method(p_rcv, p_madw); + break; + default: + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "osm_sr_rcv_process: " + "Unsupported Method (%s)\n", + ib_get_sa_method_str( p_sa_mad->method ) ); + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR ); + break; + } + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); + return; +} + +/********************************************************************** + **********************************************************************/ +void +osm_sr_rcv_lease_cb( + IN void* context ) +{ + osm_sr_rcv_t* p_rcv = (osm_sr_rcv_t*)context; + cl_list_item_t* p_list_item; + cl_list_item_t* p_next_list_item; + osm_svcr_t* p_svcr; + uint32_t curr_time; + uint32_t elapsed_time; + uint32_t trim_time = 20; /* maxiaml timer refresh is 20 seconds */ + + OSM_LOG_ENTER( p_rcv->p_log, osm_sr_rcv_lease_cb ); + + cl_plock_excl_acquire(p_rcv->p_lock); + + p_list_item = cl_qlist_head(&p_rcv->p_subn->sa_sr_list); + + while( p_list_item != cl_qlist_end(&p_rcv->p_subn->sa_sr_list) ) + { + p_svcr = (osm_svcr_t*)p_list_item; + + if(p_svcr->service_record.service_lease == 0xFFFFFFFF) + { + p_list_item = cl_qlist_next(p_list_item); + continue; + } + + /* current time in seconds */ + curr_time = cl_get_time_stamp_sec(); + /* elapsed time from last modify */ + elapsed_time = curr_time - p_svcr->modified_time; + /* but it can not be less then 1 */ + if (elapsed_time < 1) elapsed_time = 1; + + if(elapsed_time < p_svcr->lease_period) + { + /* + Just update the service lease period + note: for simplicity we work with a uint32_t field + external to the network order lease_period of the MAD + */ + p_svcr->lease_period -= elapsed_time; + + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "osm_sr_rcv_lease_cb: " + "Remaining time for Service Name:%s is:0x%X\n", + p_svcr->service_record.service_name, + p_svcr->lease_period ); + + p_svcr->modified_time = curr_time; + + /* Update the trim timer */ + if(trim_time > p_svcr->lease_period) + { + trim_time = p_svcr->lease_period; + if (trim_time < 1) trim_time = 1; + } + + p_list_item = cl_qlist_next(p_list_item); + continue; + + } + else + { + p_next_list_item = cl_qlist_next(p_list_item); + + /* Remove the service Record */ + osm_svcr_remove_from_db(p_rcv->p_subn, + p_rcv->p_log, + p_svcr); + + osm_svcr_destroy(p_svcr); + + p_list_item = p_next_list_item; + continue; + } + } + + /* Release the Lock */ + cl_plock_release(p_rcv->p_lock); + + if(trim_time != 0xFFFFFFFF) + { + cl_timer_trim(&p_rcv->sr_timer, + trim_time * 1000); /* Convert to milli seconds */ + } + + OSM_LOG_EXIT( p_rcv->p_log ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_service_record_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_service_record_ctrl.c new file mode 100644 index 00000000..1aa5c474 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_service_record_ctrl.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_service_record_ctrl.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_sr_rcv_ctrl_t. + * This object represents the ServiceRecord request controller object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +static void +__osm_sr_rcv_ctrl_disp_callback( + IN void *context, + IN void *p_data ) +{ + /* ignore return status when invoked via the dispatcher */ + osm_sr_rcv_process( ((osm_sr_rcv_ctrl_t*)context)->p_rcv, + (osm_madw_t*)p_data ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_sr_rcv_ctrl_construct( + IN osm_sr_rcv_ctrl_t* const p_ctrl ) +{ + memset( p_ctrl, 0, sizeof(*p_ctrl) ); + p_ctrl->h_disp = CL_DISP_INVALID_HANDLE; +} + +/********************************************************************** + **********************************************************************/ +void +osm_sr_rcv_ctrl_destroy( + IN osm_sr_rcv_ctrl_t* const p_ctrl ) +{ + CL_ASSERT( p_ctrl ); + cl_disp_unregister( p_ctrl->h_disp ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_sr_rcv_ctrl_init( + IN osm_sr_rcv_ctrl_t* const p_ctrl, + IN osm_sr_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_sr_rcv_ctrl_init ); + + osm_sr_rcv_ctrl_construct( p_ctrl ); + p_ctrl->p_log = p_log; + p_ctrl->p_rcv = p_rcv; + p_ctrl->p_disp = p_disp; + + p_ctrl->h_disp = cl_disp_register( + p_disp, + OSM_MSG_MAD_SERVICE_RECORD, + __osm_sr_rcv_ctrl_disp_callback, + p_ctrl ); + + if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_sr_rcv_ctrl_init: ERR 2501: " + "Dispatcher registration failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return( status ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_slvl_record.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_slvl_record.c new file mode 100644 index 00000000..b3a2c883 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_slvl_record.c @@ -0,0 +1,557 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_slvl_record.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Implementation of osm_slvl_rec_rcv_t. + * This object represents the SLtoVL Mapping Query Receiver object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.6 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define OSM_SLVL_REC_RCV_POOL_MIN_SIZE 32 +#define OSM_SLVL_REC_RCV_POOL_GROW_SIZE 32 + +typedef struct _osm_slvl_item +{ + cl_pool_item_t pool_item; + ib_slvl_table_record_t rec; +} osm_slvl_item_t; + +typedef struct _osm_slvl_search_ctxt +{ + const ib_slvl_table_record_t* p_rcvd_rec; + ib_net64_t comp_mask; + uint8_t in_port_num; + cl_qlist_t* p_list; + osm_slvl_rec_rcv_t* p_rcv; + const osm_physp_t* p_req_physp; +} osm_slvl_search_ctxt_t; + +/********************************************************************** + **********************************************************************/ +void +osm_slvl_rec_rcv_construct( + IN osm_slvl_rec_rcv_t* const p_rcv ) +{ + memset( p_rcv, 0, sizeof(*p_rcv) ); + cl_qlock_pool_construct( &p_rcv->pool ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_slvl_rec_rcv_destroy( + IN osm_slvl_rec_rcv_t* const p_rcv ) +{ + OSM_LOG_ENTER( p_rcv->p_log, osm_slvl_rec_rcv_destroy ); + cl_qlock_pool_destroy( &p_rcv->pool ); + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_slvl_rec_rcv_init( + IN osm_slvl_rec_rcv_t* const p_rcv, + IN osm_sa_resp_t* const p_resp, + IN osm_mad_pool_t* const p_mad_pool, + IN const osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ) +{ + ib_api_status_t status; + + OSM_LOG_ENTER( p_log, osm_slvl_rec_rcv_init ); + + osm_slvl_rec_rcv_construct( p_rcv ); + + p_rcv->p_log = p_log; + p_rcv->p_subn = p_subn; + p_rcv->p_lock = p_lock; + p_rcv->p_resp = p_resp; + p_rcv->p_mad_pool = p_mad_pool; + + /* used for matching records collection */ + status = cl_qlock_pool_init( &p_rcv->pool, + OSM_SLVL_REC_RCV_POOL_MIN_SIZE, + 0, + OSM_SLVL_REC_RCV_POOL_GROW_SIZE, + sizeof(osm_slvl_item_t), + NULL, NULL, NULL ); + + OSM_LOG_EXIT( p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +void +__osm_sa_slvl_create( + IN osm_slvl_rec_rcv_t* const p_rcv, + IN const osm_physp_t* const p_physp, + IN osm_slvl_search_ctxt_t* const p_ctxt, + IN uint8_t in_port_idx ) +{ + osm_slvl_item_t* p_rec_item; + uint16_t lid; + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_slvl_create ); + + p_rec_item = (osm_slvl_item_t*)cl_qlock_pool_get( &p_rcv->pool ); + if( p_rec_item == NULL ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_sa_slvl_create: ERR 2602: " + "cl_qlock_pool_get failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + if (p_physp->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH) + { + lid = osm_physp_get_port_info_ptr( p_physp )->base_lid; + } + else + { + lid = osm_node_get_base_lid( p_physp->p_node, 0 ); + } + + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_sa_slvl_create: " + "New SLtoVL Map for: OUT port 0x%016" PRIx64 + ", lid 0x%X, port# 0x%X to In Port:%u\n", + cl_ntoh64( osm_physp_get_port_guid( p_physp ) ), + cl_ntoh16( lid ), osm_physp_get_port_num( p_physp ), + in_port_idx + ); + } + + memset( &p_rec_item->rec, 0, sizeof( p_rec_item->rec ) ); + + p_rec_item->rec.lid = lid; + p_rec_item->rec.out_port_num = osm_physp_get_port_num( p_physp ); + p_rec_item->rec.in_port_num = in_port_idx; + p_rec_item->rec.slvl_tbl = *(osm_physp_get_slvl_tbl(p_physp,in_port_idx)); + + cl_qlist_insert_tail( p_ctxt->p_list, (cl_list_item_t*)&p_rec_item->pool_item ); + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +void +__osm_sa_slvl_by_comp_mask( + IN osm_slvl_rec_rcv_t* const p_rcv, + IN const osm_port_t* const p_port, + osm_slvl_search_ctxt_t* const p_ctxt ) +{ + const ib_slvl_table_record_t* p_rcvd_rec; + ib_net64_t comp_mask; + const osm_physp_t* p_out_physp, *p_in_physp; + uint8_t in_port_num, out_port_num; + uint8_t num_ports; + uint8_t in_port_start, in_port_end; + uint8_t out_port_start, out_port_end; + const osm_physp_t* p_req_physp; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_slvl_by_comp_mask ); + + p_rcvd_rec = p_ctxt->p_rcvd_rec; + comp_mask = p_ctxt->comp_mask; + num_ports = osm_port_get_num_physp( p_port ); + in_port_start = 0; + in_port_end = num_ports; + out_port_start = 0; + out_port_end = num_ports; + p_req_physp = p_ctxt->p_req_physp; + + if ( p_port->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_sa_slvl_by_comp_mask: " + "Using Physical Default Port Number: 0x%X (for End Node)\n", + p_port->default_port_num ); + p_out_physp = osm_port_get_phys_ptr( p_port, p_port->default_port_num ); + /* check that the p_out_physp and the p_req_physp share a pkey */ + if (osm_physp_share_pkey( p_rcv->p_log, p_req_physp, p_out_physp )) + __osm_sa_slvl_create( p_rcv, p_out_physp, p_ctxt, 0 ); + } + else + { + if ( comp_mask & IB_SLVL_COMPMASK_OUT_PORT ) + { + out_port_start = out_port_end = p_rcvd_rec->out_port_num; + } + if ( comp_mask & IB_SLVL_COMPMASK_IN_PORT ) + { + in_port_start = in_port_end = p_rcvd_rec->in_port_num; + } + + for( out_port_num = out_port_start; out_port_num <= out_port_end; out_port_num++ ) { + p_out_physp = osm_port_get_phys_ptr( p_port, out_port_num ); + if( p_out_physp == NULL ) + continue; + + if( !osm_physp_is_valid( p_out_physp ) ) + continue; + + for( in_port_num = in_port_start; in_port_num <= in_port_end; in_port_num++ ) { +#if 0 + if (out_port_num && out_port_num == in_port_num) + continue; +#endif + + p_in_physp = osm_port_get_phys_ptr( p_port, in_port_num ); + if( p_in_physp == NULL ) + continue; + + if( !osm_physp_is_valid( p_in_physp ) ) + continue; + + /* if the requester and the p_out_physp don't share a pkey - + continue */ + if (!osm_physp_share_pkey(p_rcv->p_log, p_req_physp, p_out_physp ) ) + continue; + + __osm_sa_slvl_create(p_rcv, p_out_physp, p_ctxt, in_port_num); + } + } + } + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +void +__osm_sa_slvl_by_comp_mask_cb( + IN cl_map_item_t* const p_map_item, + IN void* context ) +{ + const osm_port_t* const p_port = (osm_port_t*)p_map_item; + osm_slvl_search_ctxt_t* const p_ctxt = (osm_slvl_search_ctxt_t *)context; + + __osm_sa_slvl_by_comp_mask( p_ctxt->p_rcv, p_port, p_ctxt ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_slvl_rec_rcv_process( + IN osm_slvl_rec_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ) +{ + const ib_sa_mad_t* p_rcvd_mad; + const ib_slvl_table_record_t* p_rcvd_rec; + const cl_ptr_vector_t* p_tbl; + const osm_port_t* p_port = NULL; + const ib_slvl_table_t* p_slvl_tbl; + cl_qlist_t rec_list; + osm_madw_t* p_resp_madw; + ib_sa_mad_t* p_resp_sa_mad; + ib_slvl_table_record_t* p_resp_rec; + uint32_t num_rec, pre_trim_num_rec; +#ifndef VENDOR_RMPP_SUPPORT + uint32_t trim_num_rec; +#endif + uint32_t i; + osm_slvl_search_ctxt_t context; + osm_slvl_item_t* p_rec_item; + ib_api_status_t status = IB_SUCCESS; + ib_net64_t comp_mask; + osm_physp_t* p_req_physp; + + CL_ASSERT( p_rcv ); + + OSM_LOG_ENTER( p_rcv->p_log, osm_slvl_rec_rcv_process ); + + CL_ASSERT( p_madw ); + + p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw ); + p_rcvd_rec = (ib_slvl_table_record_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad ); + comp_mask = p_rcvd_mad->comp_mask; + + CL_ASSERT( p_rcvd_mad->attr_id == IB_MAD_ATTR_SLVL_RECORD ); + + /* we only support SubnAdmGet and SubnAdmGetTable methods */ + if ( (p_rcvd_mad->method != IB_MAD_METHOD_GET) && + (p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_slvl_rec_rcv_process: ERR 2604: " + "Unsupported Method (%s)\n", + ib_get_sa_method_str( p_rcvd_mad->method ) ); + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR ); + goto Exit; + } + + /* update the requester physical port. */ + p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log, + p_rcv->p_subn, + osm_madw_get_mad_addr_ptr(p_madw) ); + if (p_req_physp == NULL) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_slvl_rec_rcv_process: ERR 2603: " + "Cannot find requester physical port\n" ); + goto Exit; + } + + p_slvl_tbl = (ib_slvl_table_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad ); + + cl_qlist_init( &rec_list ); + + context.p_rcvd_rec = p_rcvd_rec; + context.p_list = &rec_list; + context.comp_mask = p_rcvd_mad->comp_mask; + context.p_rcv = p_rcv; + context.in_port_num = p_rcvd_rec->in_port_num; + context.p_req_physp = p_req_physp; + + cl_plock_acquire( p_rcv->p_lock ); + + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "osm_slvl_rec_rcv_process: " + "Got Query Lid:0x%04X(%02X), In-Port:0x%02X(%02X), Out-Port:0x%02X(%02X)\n", + cl_ntoh16(p_rcvd_rec->lid), (comp_mask & IB_SLVL_COMPMASK_LID) != 0, + p_rcvd_rec->in_port_num, (comp_mask & IB_SLVL_COMPMASK_IN_PORT) != 0, + p_rcvd_rec->out_port_num, (comp_mask & IB_SLVL_COMPMASK_OUT_PORT) != 0 ); + + /* + If the user specified a LID, it obviously narrows our + work load, since we don't have to search every port + */ + if( comp_mask & IB_SLVL_COMPMASK_LID ) + { + + p_tbl = &p_rcv->p_subn->port_lid_tbl; + + CL_ASSERT( cl_ptr_vector_get_size(p_tbl) < 0x10000 ); + + status = osm_get_port_by_base_lid( p_rcv->p_subn, p_rcvd_rec->lid, &p_port ); + if ( ( status != IB_SUCCESS ) || ( p_port == NULL ) ) + { + status = IB_NOT_FOUND; + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_slvl_rec_rcv_process: ERR 2608: " + "No port found with LID 0x%x\n", + cl_ntoh16(p_rcvd_rec->lid) ); + } + } + + if ( status == IB_SUCCESS ) + { + /* if we have a unique port - no need for a port search */ + if( p_port ) + /* this does the loop on all the port phys ports */ + __osm_sa_slvl_by_comp_mask( p_rcv, p_port, &context ); + else + { + cl_qmap_apply_func( &p_rcv->p_subn->port_guid_tbl, + __osm_sa_slvl_by_comp_mask_cb, + &context ); + } + } + + cl_plock_release( p_rcv->p_lock ); + + num_rec = cl_qlist_count( &rec_list ); + + /* + * C15-0.1.30: + * If we do a SubnAdmGet and got more than one record it is an error ! + */ + if (p_rcvd_mad->method == IB_MAD_METHOD_GET) + { + if (num_rec == 0) + { + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS ); + goto Exit; + } + if (num_rec > 1) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_slvl_rec_rcv_process: ERR 2607: " + "Got more than one record for SubnAdmGet (%u)\n", + num_rec ); + osm_sa_send_error( p_rcv->p_resp, p_madw, + IB_SA_MAD_STATUS_TOO_MANY_RECORDS ); + + /* need to set the mem free ... */ + p_rec_item = (osm_slvl_item_t*)cl_qlist_remove_head( &rec_list ); + while( p_rec_item != (osm_slvl_item_t*)cl_qlist_end( &rec_list ) ) + { + cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item ); + p_rec_item = (osm_slvl_item_t*)cl_qlist_remove_head( &rec_list ); + } + + goto Exit; + } + } + + pre_trim_num_rec = num_rec; +#ifndef VENDOR_RMPP_SUPPORT + trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_slvl_table_record_t); + if (trim_num_rec < num_rec) + { + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "osm_slvl_rec_rcv_process: " + "Number of records:%u trimmed to:%u to fit in one MAD\n", + num_rec, trim_num_rec ); + num_rec = trim_num_rec; + } +#endif + + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "osm_slvl_rec_rcv_process: " + "Returning %u records\n", num_rec ); + + if ((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0)) + { + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS ); + goto Exit; + } + + /* + * Get a MAD to reply. Address of Mad is in the received mad_wrapper + */ + p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool, + p_madw->h_bind, + num_rec * sizeof(ib_slvl_table_record_t) + IB_SA_MAD_HDR_SIZE, + &p_madw->mad_addr ); + + if( !p_resp_madw ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_slvl_rec_rcv_process: ERR 2605: " + "osm_mad_pool_get failed\n" ); + + for( i = 0; i < num_rec; i++ ) + { + p_rec_item = (osm_slvl_item_t*)cl_qlist_remove_head( &rec_list ); + cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item ); + } + + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES ); + goto Exit; + } + + p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw ); + + /* + Copy the MAD header back into the response mad. + Set the 'R' bit and the payload length, + Then copy all records from the list into the response payload. + */ + + memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE ); + p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK; + /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */ + p_resp_sa_mad->sm_key = 0; + + /* Fill in the offset (paylen will be done by the rmpp SAR) */ + p_resp_sa_mad->attr_offset = + ib_get_attr_offset( sizeof(ib_slvl_table_record_t) ); + + p_resp_rec = (ib_slvl_table_record_t*) + ib_sa_mad_get_payload_ptr( p_resp_sa_mad ); + +#ifndef VENDOR_RMPP_SUPPORT + /* we support only one packet RMPP - so we will set the first and + last flags for gettable */ + if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP) + { + p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA; + p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE; + } +#else + /* forcefully define the packet as RMPP one */ + if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP) + p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE; +#endif + + for( i = 0; i < pre_trim_num_rec; i++ ) + { + p_rec_item = (osm_slvl_item_t*)cl_qlist_remove_head( &rec_list ); + /* copy only if not trimmed */ + if (i < num_rec) + { + *p_resp_rec = p_rec_item->rec; + } + cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item ); + p_resp_rec++; + } + + CL_ASSERT( cl_is_qlist_empty( &rec_list ) ); + + status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE); + if(status != IB_SUCCESS) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_slvl_rec_rcv_process: ERR 2606: " + "osm_vendor_send status = %s\n", + ib_get_err_str(status) ); + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_slvl_record_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_slvl_record_ctrl.c new file mode 100644 index 00000000..42d305cf --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_slvl_record_ctrl.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_slvl_record_ctrl.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_slvl_rec_rcv_ctrl_t. + * This object represents the SLtoVL Map Record SA request controller object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +__osm_slvl_rec_rcv_ctrl_disp_callback( + IN void *context, + IN void *p_data ) +{ + /* ignore return status when invoked via the dispatcher */ + osm_slvl_rec_rcv_process( ((osm_slvl_rec_rcv_ctrl_t*)context)->p_rcv, + (osm_madw_t*)p_data ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_slvl_rec_rcv_ctrl_construct( + IN osm_slvl_rec_rcv_ctrl_t* const p_ctrl ) +{ + memset( p_ctrl, 0, sizeof(*p_ctrl) ); + p_ctrl->h_disp = CL_DISP_INVALID_HANDLE; +} + +/********************************************************************** + **********************************************************************/ +void +osm_slvl_rec_rcv_ctrl_destroy( + IN osm_slvl_rec_rcv_ctrl_t* const p_ctrl ) +{ + CL_ASSERT( p_ctrl ); + cl_disp_unregister( p_ctrl->h_disp ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_slvl_rec_rcv_ctrl_init( + IN osm_slvl_rec_rcv_ctrl_t* const p_ctrl, + IN osm_slvl_rec_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_slvl_rec_rcv_ctrl_init ); + + osm_slvl_rec_rcv_ctrl_construct( p_ctrl ); + p_ctrl->p_log = p_log; + p_ctrl->p_rcv = p_rcv; + p_ctrl->p_disp = p_disp; + + p_ctrl->h_disp = cl_disp_register( + p_disp, + OSM_MSG_MAD_SLVL_TBL_RECORD, + __osm_slvl_rec_rcv_ctrl_disp_callback, + p_ctrl ); + + if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_slvl_rec_rcv_ctrl_init: ERR 2701: " + "Dispatcher registration failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return( status ); +} + + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_sminfo_record.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_sminfo_record.c new file mode 100644 index 00000000..77582e62 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_sminfo_record.c @@ -0,0 +1,583 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_sminfo_record.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Implementation of osm_smir_rcv_t. + * This object represents the SMInfo Receiver object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.7 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define OSM_SMIR_RCV_POOL_MIN_SIZE 32 +#define OSM_SMIR_RCV_POOL_GROW_SIZE 32 + +typedef struct _osm_smir_item +{ + cl_pool_item_t pool_item; + ib_sminfo_record_t rec; +} osm_smir_item_t; + +typedef struct _osm_smir_search_ctxt +{ + const ib_sminfo_record_t* p_rcvd_rec; + ib_net64_t comp_mask; + cl_qlist_t* p_list; + osm_smir_rcv_t* p_rcv; + const osm_physp_t* p_req_physp; +} osm_smir_search_ctxt_t; + +/********************************************************************** + **********************************************************************/ +void +osm_smir_rcv_construct( + IN osm_smir_rcv_t* const p_rcv ) +{ + memset( p_rcv, 0, sizeof(*p_rcv) ); + cl_qlock_pool_construct( &p_rcv->pool ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_smir_rcv_destroy( + IN osm_smir_rcv_t* const p_rcv ) +{ + CL_ASSERT( p_rcv ); + + OSM_LOG_ENTER( p_rcv->p_log, osm_smir_rcv_destroy ); + cl_qlock_pool_destroy( &p_rcv->pool ); + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_smir_rcv_init( + IN osm_smir_rcv_t* const p_rcv, + IN osm_sa_resp_t* const p_resp, + IN osm_mad_pool_t* const p_mad_pool, + IN osm_subn_t* const p_subn, + IN osm_stats_t* const p_stats, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_smir_rcv_init ); + + osm_smir_rcv_construct( p_rcv ); + + p_rcv->p_log = p_log; + p_rcv->p_subn = p_subn; + p_rcv->p_lock = p_lock; + p_rcv->p_resp = p_resp; + p_rcv->p_stats = p_stats; + p_rcv->p_mad_pool = p_mad_pool; + + status = cl_qlock_pool_init( &p_rcv->pool, + OSM_SMIR_RCV_POOL_MIN_SIZE, + 0, + OSM_SMIR_RCV_POOL_GROW_SIZE, + sizeof(osm_smir_item_t), + NULL, NULL, NULL ); + + OSM_LOG_EXIT( p_rcv->p_log ); + return( status ); +} + +static ib_api_status_t +__osm_smir_rcv_new_smir( + IN osm_smir_rcv_t* const p_rcv, + IN const osm_port_t* const p_port, + IN cl_qlist_t* const p_list, + IN ib_net64_t const guid, + IN ib_net32_t const act_count, + IN uint8_t const pri_state, + IN const osm_physp_t* const p_req_physp ) +{ + osm_smir_item_t* p_rec_item; + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_smir_rcv_new_smir ); + + p_rec_item = (osm_smir_item_t*)cl_qlock_pool_get( &p_rcv->pool ); + if( p_rec_item == NULL ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_smir_rcv_new_smir: ERR 2801: " + "cl_qlock_pool_get failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_smir_rcv_new_smir: " + "New SMInfo: GUID 0x%016" PRIx64 "\n", + cl_ntoh64( guid ) + ); + } + + memset( &p_rec_item->rec, 0, sizeof(ib_sminfo_record_t) ); + + p_rec_item->rec.lid = osm_port_get_base_lid( p_port ); + p_rec_item->rec.sm_info.guid = guid; + p_rec_item->rec.sm_info.act_count = act_count; + p_rec_item->rec.sm_info.pri_state = pri_state; + + cl_qlist_insert_tail( p_list, (cl_list_item_t*)&p_rec_item->pool_item ); + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_sa_smir_by_comp_mask( + IN osm_smir_rcv_t* const p_rcv, + IN const osm_remote_sm_t* const p_rem_sm, + osm_smir_search_ctxt_t* const p_ctxt ) +{ + const ib_sminfo_record_t* const p_rcvd_rec = p_ctxt->p_rcvd_rec; + const osm_physp_t* const p_req_physp = p_ctxt->p_req_physp; + ib_net64_t const comp_mask = p_ctxt->comp_mask; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_smir_by_comp_mask ); + + if ( comp_mask & IB_SMIR_COMPMASK_GUID ) + { + if ( p_rem_sm->smi.guid != p_rcvd_rec->sm_info.guid ) + goto Exit; + } + + if ( comp_mask & IB_SMIR_COMPMASK_PRIORITY ) + { + if ( ib_sminfo_get_priority( &p_rem_sm->smi ) != + ib_sminfo_get_priority( &p_rcvd_rec->sm_info ) ) + goto Exit; + } + + if ( comp_mask & IB_SMIR_COMPMASK_SMSTATE ) + { + if ( ib_sminfo_get_state( &p_rem_sm->smi ) != + ib_sminfo_get_state( &p_rcvd_rec->sm_info ) ) + goto Exit; + } + + /* Implement any other needed search cases */ + + __osm_smir_rcv_new_smir( p_rcv, p_rem_sm->p_port, p_ctxt->p_list, + p_rem_sm->smi.guid, + p_rem_sm->smi.act_count, + p_rem_sm->smi.pri_state, + p_req_physp ); + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_sa_smir_by_comp_mask_cb( + IN cl_map_item_t* const p_map_item, + IN void* context ) +{ + const osm_remote_sm_t* const p_rem_sm = (osm_remote_sm_t*)p_map_item; + osm_smir_search_ctxt_t* const p_ctxt = (osm_smir_search_ctxt_t *)context; + + __osm_sa_smir_by_comp_mask( p_ctxt->p_rcv, p_rem_sm, p_ctxt ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_smir_rcv_process( + IN osm_smir_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ) +{ + const ib_sa_mad_t* p_rcvd_mad; + const ib_sminfo_record_t* p_rcvd_rec; + const cl_qmap_t* p_tbl; + const osm_port_t* p_port = NULL; + const ib_sm_info_t* p_smi; + cl_qlist_t rec_list; + osm_madw_t* p_resp_madw; + ib_sa_mad_t* p_resp_sa_mad; + ib_sminfo_record_t* p_resp_rec; + uint32_t num_rec, pre_trim_num_rec; +#ifndef VENDOR_RMPP_SUPPORT + uint32_t trim_num_rec; +#endif + uint32_t i; + osm_smir_search_ctxt_t context; + osm_smir_item_t* p_rec_item; + ib_api_status_t status = IB_SUCCESS; + ib_net64_t comp_mask; + ib_net64_t port_guid; + osm_physp_t* p_req_physp; + osm_port_t* local_port; + osm_remote_sm_t* p_rem_sm; + cl_qmap_t* p_sm_guid_tbl; + uint8_t pri_state; + + CL_ASSERT( p_rcv ); + + OSM_LOG_ENTER( p_rcv->p_log, osm_smir_rcv_process ); + + CL_ASSERT( p_madw ); + + p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw ); + p_rcvd_rec = (ib_sminfo_record_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad ); + comp_mask = p_rcvd_mad->comp_mask; + + CL_ASSERT( p_rcvd_mad->attr_id == IB_MAD_ATTR_SMINFO_RECORD ); + + /* we only support SubnAdmGet and SubnAdmGetTable methods */ + if ( (p_rcvd_mad->method != IB_MAD_METHOD_GET) && + (p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_smir_rcv_process: ERR 2804: " + "Unsupported Method (%s)\n", + ib_get_sa_method_str( p_rcvd_mad->method ) ); + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR ); + goto Exit; + } + + /* update the requester physical port. */ + p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log, + p_rcv->p_subn, + osm_madw_get_mad_addr_ptr(p_madw) ); + if (p_req_physp == NULL) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_smir_rcv_process: ERR 2803: " + "Cannot find requester physical port\n" ); + goto Exit; + } + + if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + osm_dump_sm_info_record( p_rcv->p_log, p_rcvd_rec, OSM_LOG_DEBUG ); + + p_tbl = &p_rcv->p_subn->sm_guid_tbl; + p_smi = &p_rcvd_rec->sm_info; + + cl_qlist_init( &rec_list ); + + context.p_rcvd_rec = p_rcvd_rec; + context.p_list = &rec_list; + context.comp_mask = p_rcvd_mad->comp_mask; + context.p_rcv = p_rcv; + context.p_req_physp = p_req_physp; + + cl_plock_acquire( p_rcv->p_lock ); + + /* + If the user specified a LID, it obviously narrows our + work load, since we don't have to search every port + */ + if( comp_mask & IB_SMIR_COMPMASK_LID ) + { + status = osm_get_port_by_base_lid( p_rcv->p_subn, p_rcvd_rec->lid, &p_port ); + if ( ( status != IB_SUCCESS ) || ( p_port == NULL ) ) + { + status = IB_NOT_FOUND; + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_smir_rcv_process: ERR 2806: " + "No port found with LID 0x%x\n", + cl_ntoh16(p_rcvd_rec->lid) ); + } + } + + if ( status == IB_SUCCESS ) + { + /* Handle our own SM first */ + local_port = osm_get_port_by_guid( p_rcv->p_subn, p_rcv->p_subn->sm_port_guid ); + if ( !local_port ) + { + cl_plock_release( p_rcv->p_lock ); + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_smir_rcv_process: ERR 2809: " + "No port found with GUID 0x%016" PRIx64 "\n", + cl_ntoh64(p_rcv->p_subn->sm_port_guid ) ); + goto Exit; + } + + if ( !p_port || local_port == p_port ) + { + if (FALSE == + osm_physp_share_pkey( p_rcv->p_log, p_req_physp, + osm_port_get_default_phys_ptr( local_port ) ) ) + { + cl_plock_release( p_rcv->p_lock ); + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_smir_rcv_process: ERR 2805: " + "Cannot get SMInfo record due to pkey violation\n" ); + goto Exit; + } + + /* Check that other search components specified match */ + if ( comp_mask & IB_SMIR_COMPMASK_GUID ) + { + if ( p_rcv->p_subn->sm_port_guid != p_smi->guid ) + goto Remotes; + } + if ( comp_mask & IB_SMIR_COMPMASK_PRIORITY ) + { + if ( p_rcv->p_subn->opt.sm_priority != ib_sminfo_get_priority( p_smi ) ) + goto Remotes; + } + if ( comp_mask & IB_SMIR_COMPMASK_SMSTATE ) + { + if ( p_rcv->p_subn->sm_state != ib_sminfo_get_state( p_smi ) ) + goto Remotes; + } + + /* Now, add local SMInfo to list */ + pri_state = p_rcv->p_subn->sm_state & 0x0F; + pri_state |= (p_rcv->p_subn->opt.sm_priority & 0x0F) << 4; + __osm_smir_rcv_new_smir( p_rcv, local_port, context.p_list, + p_rcv->p_subn->sm_port_guid, + cl_ntoh32( p_rcv->p_stats->qp0_mads_sent ), + pri_state, + p_req_physp ); + } + + Remotes: + if( p_port && p_port != local_port ) + { + /* Find remote SM corresponding to p_port */ + port_guid = osm_port_get_guid( p_port ); + p_sm_guid_tbl = &p_rcv->p_subn->sm_guid_tbl; + p_rem_sm = (osm_remote_sm_t*)cl_qmap_get( p_sm_guid_tbl, port_guid ); + if (p_rem_sm != (osm_remote_sm_t*)cl_qmap_end( p_sm_guid_tbl ) ) + __osm_sa_smir_by_comp_mask( p_rcv, p_rem_sm, &context ); + else + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_smir_rcv_process: ERR 280A: " + "No remote SM for GUID 0x%016" PRIx64 "\n", + cl_ntoh64( port_guid ) ); + } + } + else + { + /* Go over all other known (remote) SMs */ + cl_qmap_apply_func( &p_rcv->p_subn->sm_guid_tbl, + __osm_sa_smir_by_comp_mask_cb, + &context ); + } + } + + cl_plock_release( p_rcv->p_lock ); + + num_rec = cl_qlist_count( &rec_list ); + + /* + * C15-0.1.30: + * If we do a SubnAdmGet and got more than one record it is an error ! + */ + if (p_rcvd_mad->method == IB_MAD_METHOD_GET) + { + if (num_rec == 0) + { + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS ); + goto Exit; + } + if (num_rec > 1) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_smir_rcv_process: ERR 2808: " + "Got more than one record for SubnAdmGet (%u)\n", + num_rec ); + osm_sa_send_error( p_rcv->p_resp, p_madw, + IB_SA_MAD_STATUS_TOO_MANY_RECORDS); + + /* need to set the mem free ... */ + p_rec_item = (osm_smir_item_t*)cl_qlist_remove_head( &rec_list ); + while( p_rec_item != (osm_smir_item_t*)cl_qlist_end( &rec_list ) ) + { + cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item ); + p_rec_item = (osm_smir_item_t*)cl_qlist_remove_head( &rec_list ); + } + + goto Exit; + } + } + + pre_trim_num_rec = num_rec; +#ifndef VENDOR_RMPP_SUPPORT + trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_sminfo_record_t); + if (trim_num_rec < num_rec) + { + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "osm_smir_rcv_process: " + "Number of records:%u trimmed to:%u to fit in one MAD\n", + num_rec, trim_num_rec ); + num_rec = trim_num_rec; + } +#endif + + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "osm_smir_rcv_process: " + "Returning %u records\n", num_rec ); + + if ((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0)) + { + osm_sa_send_error( p_rcv->p_resp, p_madw, + IB_SA_MAD_STATUS_NO_RECORDS ); + goto Exit; + } + + /* + * Get a MAD to reply. Address of Mad is in the received mad_wrapper + */ + p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool, + p_madw->h_bind, + num_rec * sizeof(ib_sminfo_record_t) + IB_SA_MAD_HDR_SIZE, + &p_madw->mad_addr ); + + if( !p_resp_madw ) + { + osm_log(p_rcv->p_log, OSM_LOG_ERROR, + "osm_smir_rcv_process: ERR 2807: " + "osm_mad_pool_get failed\n" ); + + for( i = 0; i < num_rec; i++ ) + { + p_rec_item = (osm_smir_item_t*)cl_qlist_remove_head( &rec_list ); + cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item ); + } + + osm_sa_send_error( p_rcv->p_resp, p_madw, + IB_SA_MAD_STATUS_NO_RESOURCES ); + + goto Exit; + } + + p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw ); + + /* + Copy the MAD header back into the response mad. + Set the 'R' bit and the payload length, + Then copy all records from the list into the response payload. + */ + + memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE ); + p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK; + /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */ + p_resp_sa_mad->sm_key = 0; + /* Fill in the offset (paylen will be done by the rmpp SAR) */ + p_resp_sa_mad->attr_offset = + ib_get_attr_offset( sizeof(ib_sminfo_record_t) ); + + p_resp_rec = (ib_sminfo_record_t*) + ib_sa_mad_get_payload_ptr( p_resp_sa_mad ); + +#ifndef VENDOR_RMPP_SUPPORT + /* we support only one packet RMPP - so we will set the first and + last flags for gettable */ + if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP) + { + p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA; + p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE; + } +#else + /* forcefully define the packet as RMPP one */ + if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP) + p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE; +#endif + + for( i = 0; i < pre_trim_num_rec; i++ ) + { + p_rec_item = (osm_smir_item_t*)cl_qlist_remove_head( &rec_list ); + /* copy only if not trimmed */ + if (i < num_rec) + { + *p_resp_rec = p_rec_item->rec; + p_resp_rec->sm_info.sm_key = 0; + } + cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item ); + p_resp_rec++; + } + + CL_ASSERT( cl_is_qlist_empty( &rec_list ) ); + + status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE ); + if( status != IB_SUCCESS ) + { + osm_log(p_rcv->p_log, OSM_LOG_ERROR, + "osm_smir_rcv_process: ERR 2802: " + "Error sending MAD (%s)\n", + ib_get_err_str( status ) ); + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_sminfo_record_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_sminfo_record_ctrl.c new file mode 100644 index 00000000..f6172746 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_sminfo_record_ctrl.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_sminfo_record_ctrl.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_smir_ctrl_t. + * This object represents the SMInfo request controller object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +__osm_smir_ctrl_disp_callback( + IN void *context, + IN void *p_data ) +{ + /* ignore return status when invoked via the dispatcher */ + osm_smir_rcv_process( ((osm_smir_ctrl_t*)context)->p_rcv, + (osm_madw_t*)p_data ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_smir_ctrl_construct( + IN osm_smir_ctrl_t* const p_ctrl ) +{ + memset( p_ctrl, 0, sizeof(*p_ctrl) ); + p_ctrl->h_disp = CL_DISP_INVALID_HANDLE; +} + +/********************************************************************** + **********************************************************************/ +void +osm_smir_ctrl_destroy( + IN osm_smir_ctrl_t* const p_ctrl ) +{ + CL_ASSERT( p_ctrl ); + cl_disp_unregister( p_ctrl->h_disp ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_smir_ctrl_init( + IN osm_smir_ctrl_t* const p_ctrl, + IN osm_smir_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_smir_ctrl_init ); + + osm_smir_ctrl_construct( p_ctrl ); + p_ctrl->p_log = p_log; + p_ctrl->p_rcv = p_rcv; + p_ctrl->p_disp = p_disp; + + p_ctrl->h_disp = cl_disp_register( + p_disp, + OSM_MSG_MAD_SMINFO_RECORD, + __osm_smir_ctrl_disp_callback, + p_ctrl ); + + if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_smir_ctrl_init: ERR 2901: " + "Dispatcher registration failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return( status ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_sw_info_record.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_sw_info_record.c new file mode 100644 index 00000000..8c893ad3 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_sw_info_record.c @@ -0,0 +1,535 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ + + +/* + * Abstract: + * Implementation of osm_sir_rcv_t. + * This object represents the SwitchInfo Receiver object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define OSM_SIR_RCV_POOL_MIN_SIZE 32 +#define OSM_SIR_RCV_POOL_GROW_SIZE 32 + +typedef struct _osm_sir_item +{ + cl_pool_item_t pool_item; + ib_switch_info_record_t rec; +} osm_sir_item_t; + +typedef struct _osm_sir_search_ctxt +{ + const ib_switch_info_record_t* p_rcvd_rec; + ib_net64_t comp_mask; + cl_qlist_t* p_list; + osm_sir_rcv_t* p_rcv; + const osm_physp_t* p_req_physp; +} osm_sir_search_ctxt_t; + +/********************************************************************** + **********************************************************************/ +void +osm_sir_rcv_construct( + IN osm_sir_rcv_t* const p_rcv ) +{ + memset( p_rcv, 0, sizeof(*p_rcv) ); + cl_qlock_pool_construct( &p_rcv->pool ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_sir_rcv_destroy( + IN osm_sir_rcv_t* const p_rcv ) +{ + OSM_LOG_ENTER( p_rcv->p_log, osm_sir_rcv_destroy ); + cl_qlock_pool_destroy( &p_rcv->pool ); + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_sir_rcv_init( + IN osm_sir_rcv_t* const p_rcv, + IN osm_sa_resp_t* const p_resp, + IN osm_mad_pool_t* const p_mad_pool, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ) +{ + ib_api_status_t status; + + OSM_LOG_ENTER( p_log, osm_sir_rcv_init ); + + osm_sir_rcv_construct( p_rcv ); + + p_rcv->p_log = p_log; + p_rcv->p_subn = p_subn; + p_rcv->p_lock = p_lock; + p_rcv->p_resp = p_resp; + p_rcv->p_mad_pool = p_mad_pool; + + status = cl_qlock_pool_init( &p_rcv->pool, + OSM_SIR_RCV_POOL_MIN_SIZE, + 0, + OSM_SIR_RCV_POOL_GROW_SIZE, + sizeof(osm_sir_item_t), + NULL, NULL, NULL ); + + OSM_LOG_EXIT( p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +static ib_api_status_t +__osm_sir_rcv_new_sir( + IN osm_sir_rcv_t* const p_rcv, + IN const osm_switch_t* const p_sw, + IN cl_qlist_t* const p_list, + IN ib_net16_t const lid ) +{ + osm_sir_item_t* p_rec_item; + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_sir_rcv_new_sir ); + + p_rec_item = (osm_sir_item_t*)cl_qlock_pool_get( &p_rcv->pool ); + if( p_rec_item == NULL ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_sir_rcv_new_sir: ERR 5308: " + "cl_qlock_pool_get failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_sir_rcv_new_sir: " + "New SwitchInfoRecord: lid 0x%X\n", + cl_ntoh16( lid ) + ); + } + + memset( &p_rec_item->rec, 0, sizeof(ib_switch_info_record_t) ); + + p_rec_item->rec.lid = lid; + p_rec_item->rec.switch_info = p_sw->switch_info; + + cl_qlist_insert_tail( p_list, (cl_list_item_t*)&p_rec_item->pool_item ); + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +static osm_port_t* +__osm_sir_get_port_by_guid( + IN osm_sir_rcv_t* const p_rcv, + IN uint64_t port_guid ) +{ + osm_port_t* p_port; + + CL_PLOCK_ACQUIRE(p_rcv->p_lock); + + p_port = (osm_port_t *)cl_qmap_get(&p_rcv->p_subn->port_guid_tbl, + port_guid); + if (p_port == (osm_port_t *)cl_qmap_end(&p_rcv->p_subn->port_guid_tbl)) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_sir_get_port_by_guid ERR 5309: " + "Invalid port GUID 0x%016" PRIx64 "\n", + port_guid ); + p_port = NULL; + } + + CL_PLOCK_RELEASE(p_rcv->p_lock); + return p_port; +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_sir_rcv_create_sir( + IN osm_sir_rcv_t* const p_rcv, + IN const osm_switch_t* const p_sw, + IN cl_qlist_t* const p_list, + IN ib_net16_t const match_lid, + IN const osm_physp_t* const p_req_physp ) +{ + osm_port_t* p_port; + const osm_physp_t* p_physp; + uint16_t match_lid_ho; + ib_net16_t min_lid_ho; + ib_net16_t max_lid_ho; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_sir_rcv_create_sir ); + + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_sir_rcv_create_sir: " + "Looking for SwitchInfoRecord with LID: 0x%X\n", + cl_ntoh16( match_lid ) + ); + } + + /* In switches, the port guid is the node guid. */ + p_port = + __osm_sir_get_port_by_guid( p_rcv, p_sw->p_node->node_info.port_guid ); + if (! p_port) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_sir_rcv_create_sir: ERR 530A: " + "Failed to find Port by Node Guid:0x%016" PRIx64 + "\n", + cl_ntoh64( p_sw->p_node->node_info.node_guid ) + ); + goto Exit; + } + + /* check that the requester physp and the current physp are under + the same partition. */ + p_physp = osm_port_get_default_phys_ptr( p_port ); + if (! p_physp) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_sir_rcv_create_sir: ERR 530B: " + "Failed to find default physical Port by Node Guid:0x%016" PRIx64 + "\n", + cl_ntoh64( p_sw->p_node->node_info.node_guid ) + ); + goto Exit; + } + if (! osm_physp_share_pkey( p_rcv->p_log, p_req_physp, p_physp )) + goto Exit; + + /* get the port 0 of the switch */ + osm_port_get_lid_range_ho( p_port, &min_lid_ho, &max_lid_ho ); + + match_lid_ho = cl_ntoh16( match_lid ); + if( match_lid_ho ) + { + /* + We validate that the lid belongs to this switch. + */ + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_sir_rcv_create_sir: " + "Comparing LID: 0x%X <= 0x%X <= 0x%X\n", + min_lid_ho, match_lid_ho, max_lid_ho + ); + } + + if ( match_lid_ho < min_lid_ho || match_lid_ho > max_lid_ho ) + goto Exit; + + } + + __osm_sir_rcv_new_sir( p_rcv, p_sw, p_list, osm_port_get_base_lid(p_port) ); + +Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_sir_rcv_by_comp_mask( + IN cl_map_item_t* const p_map_item, + IN void* context ) +{ + const osm_sir_search_ctxt_t* const p_ctxt = (osm_sir_search_ctxt_t *)context; + const osm_switch_t* const p_sw = (osm_switch_t*)p_map_item; + const ib_switch_info_record_t* const p_rcvd_rec = p_ctxt->p_rcvd_rec; + const osm_physp_t* const p_req_physp = p_ctxt->p_req_physp; + osm_sir_rcv_t* const p_rcv = p_ctxt->p_rcv; + ib_net64_t const comp_mask = p_ctxt->comp_mask; + ib_net16_t match_lid = 0; + + OSM_LOG_ENTER( p_ctxt->p_rcv->p_log, __osm_sir_rcv_by_comp_mask ); + + osm_dump_switch_info( + p_ctxt->p_rcv->p_log, + &p_sw->switch_info, + OSM_LOG_VERBOSE ); + + if( comp_mask & IB_SWIR_COMPMASK_LID ) + { + match_lid = p_rcvd_rec->lid; + if (!match_lid) + goto Exit; + } + + __osm_sir_rcv_create_sir( p_rcv, p_sw, p_ctxt->p_list, + match_lid, p_req_physp ); + +Exit: + OSM_LOG_EXIT( p_ctxt->p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_sir_rcv_process( + IN osm_sir_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ) +{ + const ib_sa_mad_t* p_rcvd_mad; + const ib_switch_info_record_t* p_rcvd_rec; + ib_switch_info_record_t* p_resp_rec; + cl_qlist_t rec_list; + osm_madw_t* p_resp_madw; + ib_sa_mad_t* p_resp_sa_mad; + uint32_t num_rec, pre_trim_num_rec; +#ifndef VENDOR_RMPP_SUPPORT + uint32_t trim_num_rec; +#endif + uint32_t i; + osm_sir_search_ctxt_t context; + osm_sir_item_t* p_rec_item; + ib_api_status_t status; + osm_physp_t* p_req_physp; + + CL_ASSERT( p_rcv ); + + OSM_LOG_ENTER( p_rcv->p_log, osm_sir_rcv_process ); + + CL_ASSERT( p_madw ); + + p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw ); + p_rcvd_rec = (ib_switch_info_record_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad ); + + CL_ASSERT( p_rcvd_mad->attr_id == IB_MAD_ATTR_SWITCH_INFO_RECORD ); + + /* we only support SubnAdmGet and SubnAdmGetTable methods */ + if ( (p_rcvd_mad->method != IB_MAD_METHOD_GET) && + (p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) ) { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_sir_rcv_process: ERR 5305: " + "Unsupported Method (%s)\n", + ib_get_sa_method_str( p_rcvd_mad->method ) ); + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR ); + goto Exit; + } + + /* update the requester physical port. */ + p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log, + p_rcv->p_subn, + osm_madw_get_mad_addr_ptr(p_madw) ); + if (p_req_physp == NULL) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_sir_rcv_process: ERR 5304: " + "Cannot find requester physical port\n" ); + goto Exit; + } + + if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + osm_dump_switch_info_record( p_rcv->p_log, p_rcvd_rec, OSM_LOG_DEBUG ); + + cl_qlist_init( &rec_list ); + + context.p_rcvd_rec = p_rcvd_rec; + context.p_list = &rec_list; + context.comp_mask = p_rcvd_mad->comp_mask; + context.p_rcv = p_rcv; + context.p_req_physp = p_req_physp; + + cl_plock_acquire( p_rcv->p_lock ); + + /* Go over all switches */ + cl_qmap_apply_func( &p_rcv->p_subn->sw_guid_tbl, + __osm_sir_rcv_by_comp_mask, + &context ); + + cl_plock_release( p_rcv->p_lock ); + + num_rec = cl_qlist_count( &rec_list ); + + /* + * C15-0.1.30: + * If we do a SubnAdmGet and got more than one record it is an error ! + */ + if ( (p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec > 1) ) { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_sir_rcv_process: ERR 5303: " + "Got more than one record for SubnAdmGet (%u)\n", + num_rec ); + osm_sa_send_error( p_rcv->p_resp, p_madw, + IB_SA_MAD_STATUS_TOO_MANY_RECORDS ); + + /* need to set the mem free ... */ + p_rec_item = (osm_sir_item_t*)cl_qlist_remove_head( &rec_list ); + while( p_rec_item != (osm_sir_item_t*)cl_qlist_end( &rec_list ) ) + { + cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item ); + p_rec_item = (osm_sir_item_t*)cl_qlist_remove_head( &rec_list ); + } + + goto Exit; + } + + pre_trim_num_rec = num_rec; +#ifndef VENDOR_RMPP_SUPPORT + /* we limit the number of records to a single packet */ + trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_switch_info_record_t); + if (trim_num_rec < num_rec) + { + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "osm_sir_rcv_process: " + "Number of records:%u trimmed to:%u to fit in one MAD\n", + num_rec, trim_num_rec ); + num_rec = trim_num_rec; + } +#endif + + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "osm_sir_rcv_process: " + "Returning %u records\n", num_rec ); + + if ((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0)) + { + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS ); + goto Exit; + } + + /* + * Get a MAD to reply. Address of Mad is in the received mad_wrapper + */ + p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool, + p_madw->h_bind, + num_rec * sizeof(ib_switch_info_record_t) + IB_SA_MAD_HDR_SIZE, + &p_madw->mad_addr ); + + if( !p_resp_madw ) + { + osm_log(p_rcv->p_log, OSM_LOG_ERROR, + "osm_sir_rcv_process: ERR 5306: " + "osm_mad_pool_get failed\n" ); + + for( i = 0; i < num_rec; i++ ) + { + p_rec_item = (osm_sir_item_t*)cl_qlist_remove_head( &rec_list ); + cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item ); + } + + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES ); + goto Exit; + } + + p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw ); + + /* + Copy the MAD header back into the response mad. + Set the 'R' bit and the payload length, + Then copy all records from the list into the response payload. + */ + + memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE ); + p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK; + /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */ + p_resp_sa_mad->sm_key = 0; + /* Fill in the offset (paylen will be done by the rmpp SAR) */ + p_resp_sa_mad->attr_offset = + ib_get_attr_offset( sizeof(ib_switch_info_record_t) ); + + p_resp_rec = (ib_switch_info_record_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad ); + +#ifndef VENDOR_RMPP_SUPPORT + /* we support only one packet RMPP - so we will set the first and + last flags for gettable */ + if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP) + { + p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA; + p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE; + } +#else + /* forcefully define the packet as RMPP one */ + if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP) + p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE; +#endif + + for( i = 0; i < pre_trim_num_rec; i++ ) + { + p_rec_item = (osm_sir_item_t*)cl_qlist_remove_head( &rec_list ); + /* copy only if not trimmed */ + if (i < num_rec) + { + *p_resp_rec = p_rec_item->rec; + } + cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item ); + p_resp_rec++; + } + + CL_ASSERT( cl_is_qlist_empty( &rec_list ) ); + + status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE ); + if (status != IB_SUCCESS) + { + osm_log(p_rcv->p_log, OSM_LOG_ERROR, + "osm_sir_rcv_process: ERR 5307: " + "osm_vendor_send status = %s\n", + ib_get_err_str(status)); + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_sw_info_record_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_sw_info_record_ctrl.c new file mode 100644 index 00000000..726cd40a --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_sw_info_record_ctrl.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ + + +/* + * Abstract: + * Implementation of osm_sir_rcv_ctrl_t. + * This object represents the SwitchInfo Record controller object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +__osm_sir_ctrl_disp_callback( + IN void *context, + IN void *p_data ) +{ + /* ignore return status when invoked via the dispatcher */ + osm_sir_rcv_process( ((osm_sir_rcv_ctrl_t*)context)->p_rcv, + (osm_madw_t*)p_data ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_sir_rcv_ctrl_construct( + IN osm_sir_rcv_ctrl_t* const p_ctrl ) +{ + memset( p_ctrl, 0, sizeof(*p_ctrl) ); + p_ctrl->h_disp = CL_DISP_INVALID_HANDLE; +} + +/********************************************************************** + **********************************************************************/ +void +osm_sir_rcv_ctrl_destroy( + IN osm_sir_rcv_ctrl_t* const p_ctrl ) +{ + CL_ASSERT( p_ctrl ); + cl_disp_unregister( p_ctrl->h_disp ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_sir_rcv_ctrl_init( + IN osm_sir_rcv_ctrl_t* const p_ctrl, + IN osm_sir_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_sir_rcv_ctrl_init ); + + osm_sir_rcv_ctrl_construct( p_ctrl ); + p_ctrl->p_log = p_log; + p_ctrl->p_rcv = p_rcv; + p_ctrl->p_disp = p_disp; + + p_ctrl->h_disp = cl_disp_register( + p_disp, + OSM_MSG_MAD_SWITCH_INFO_RECORD, + __osm_sir_ctrl_disp_callback, + p_ctrl ); + + if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_sir_rcv_ctrl_init: ERR 5301: " + "Dispatcher registration failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return( status ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_vlarb_record.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_vlarb_record.c new file mode 100644 index 00000000..6d29936d --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_vlarb_record.c @@ -0,0 +1,577 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_vlarb_record.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Implementation of osm_vlarb_rec_rcv_t. + * This object represents the VLArbitrationRecord Receiver object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.7 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define OSM_VLARB_REC_RCV_POOL_MIN_SIZE 32 +#define OSM_VLARB_REC_RCV_POOL_GROW_SIZE 32 + +typedef struct _osm_vl_arb_item +{ + cl_pool_item_t pool_item; + ib_vl_arb_table_record_t rec; +} osm_vl_arb_item_t; + +typedef struct _osm_vl_arb_search_ctxt +{ + const ib_vl_arb_table_record_t* p_rcvd_rec; + ib_net64_t comp_mask; + uint8_t block_num; + cl_qlist_t* p_list; + osm_vlarb_rec_rcv_t* p_rcv; + const osm_physp_t* p_req_physp; +} osm_vl_arb_search_ctxt_t; + +/********************************************************************** + **********************************************************************/ +void +osm_vlarb_rec_rcv_construct( + IN osm_vlarb_rec_rcv_t* const p_rcv ) +{ + memset( p_rcv, 0, sizeof(*p_rcv) ); + cl_qlock_pool_construct( &p_rcv->pool ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_vlarb_rec_rcv_destroy( + IN osm_vlarb_rec_rcv_t* const p_rcv ) +{ + OSM_LOG_ENTER( p_rcv->p_log, osm_vlarb_rec_rcv_destroy ); + cl_qlock_pool_destroy( &p_rcv->pool ); + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_vlarb_rec_rcv_init( + IN osm_vlarb_rec_rcv_t* const p_rcv, + IN osm_sa_resp_t* const p_resp, + IN osm_mad_pool_t* const p_mad_pool, + IN const osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ) +{ + ib_api_status_t status; + + OSM_LOG_ENTER( p_log, osm_vlarb_rec_rcv_init ); + + osm_vlarb_rec_rcv_construct( p_rcv ); + + p_rcv->p_log = p_log; + p_rcv->p_subn = p_subn; + p_rcv->p_lock = p_lock; + p_rcv->p_resp = p_resp; + p_rcv->p_mad_pool = p_mad_pool; + + /* used for matching records collection */ + status = cl_qlock_pool_init( &p_rcv->pool, + OSM_VLARB_REC_RCV_POOL_MIN_SIZE, + 0, + OSM_VLARB_REC_RCV_POOL_GROW_SIZE, + sizeof(osm_vl_arb_item_t), + NULL, NULL, NULL ); + + OSM_LOG_EXIT( p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +void +__osm_sa_vl_arb_create( + IN osm_vlarb_rec_rcv_t* const p_rcv, + IN osm_physp_t* const p_physp, + IN osm_vl_arb_search_ctxt_t* const p_ctxt, + IN uint8_t block ) +{ + osm_vl_arb_item_t* p_rec_item; + uint16_t lid; + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_vl_arb_create ); + + p_rec_item = (osm_vl_arb_item_t*)cl_qlock_pool_get( &p_rcv->pool ); + if( p_rec_item == NULL ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_sa_vl_arb_create: ERR 2A02: " + "cl_qlock_pool_get failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + if (p_physp->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH) + { + lid = osm_physp_get_port_info_ptr( p_physp )->base_lid; + } + else + { + lid = osm_node_get_base_lid( p_physp->p_node, 0 ); + } + + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_sa_vl_arb_create: " + "New VLArbitration for: port 0x%016" PRIx64 + ", lid 0x%X, port# 0x%X Block:%u\n", + cl_ntoh64( osm_physp_get_port_guid( p_physp ) ), + cl_ntoh16( lid ), osm_physp_get_port_num( p_physp ), + block + ); + } + + memset( &p_rec_item->rec, 0, sizeof( p_rec_item->rec ) ); + + p_rec_item->rec.lid = lid; + p_rec_item->rec.port_num = osm_physp_get_port_num( p_physp ); + p_rec_item->rec.block_num = block; + p_rec_item->rec.vl_arb_tbl = *(osm_physp_get_vla_tbl(p_physp, block)); + + cl_qlist_insert_tail( p_ctxt->p_list, (cl_list_item_t*)&p_rec_item->pool_item ); + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +void +__osm_sa_vl_arb_check_physp( + IN osm_vlarb_rec_rcv_t* const p_rcv, + IN osm_physp_t* const p_physp, + osm_vl_arb_search_ctxt_t* const p_ctxt ) +{ + ib_net64_t comp_mask = p_ctxt->comp_mask; + uint8_t block; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_vl_arb_check_physp ); + + /* we got here with the phys port - all that's left is to get the right block */ + for (block = 1; block <= 4; block++) { + if (!(comp_mask & IB_VLA_COMPMASK_BLOCK) || block == p_ctxt->block_num) + { + __osm_sa_vl_arb_create( p_rcv, p_physp, p_ctxt, block ); + } + } + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +void +__osm_sa_vl_arb_by_comp_mask( + IN osm_vlarb_rec_rcv_t* const p_rcv, + IN const osm_port_t* const p_port, + osm_vl_arb_search_ctxt_t* const p_ctxt ) +{ + const ib_vl_arb_table_record_t* p_rcvd_rec; + ib_net64_t comp_mask; + osm_physp_t * p_physp; + uint8_t port_num; + uint8_t num_ports; + const osm_physp_t* p_req_physp; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_vl_arb_by_comp_mask ); + + p_rcvd_rec = p_ctxt->p_rcvd_rec; + comp_mask = p_ctxt->comp_mask; + port_num = p_rcvd_rec->port_num; + p_req_physp = p_ctxt->p_req_physp; + + /* if this is a switch port we can search all ports + otherwise we must be looking on port 0 */ + if ( p_port->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH) + { + /* we put it in the comp mask and port num */ + port_num = p_port->default_port_num; + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_sa_vl_arb_by_comp_mask: " + "Using Physical Default Port Number: 0x%X (for End Node)\n", + port_num ); + comp_mask |= IB_VLA_COMPMASK_OUT_PORT; + } + + if( comp_mask & IB_VLA_COMPMASK_OUT_PORT ) + { + if (port_num < osm_port_get_num_physp( p_port )) + { + p_physp = osm_port_get_phys_ptr( p_port, port_num ); + /* check that the p_physp is valid, and that the requester + and the p_physp share a pkey. */ + if( p_physp && osm_physp_is_valid( p_physp ) && + osm_physp_share_pkey(p_rcv->p_log, p_req_physp, p_physp) ) + __osm_sa_vl_arb_check_physp( p_rcv, p_physp, p_ctxt ); + } + else + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_sa_vl_arb_by_comp_mask: ERR 2A03: " + "Given Physical Port Number: 0x%X is out of range should be < 0x%X\n", + port_num, osm_port_get_num_physp( p_port ) ); + goto Exit; + } + } + else + { + num_ports = osm_port_get_num_physp( p_port ); + for( port_num = 0; port_num < num_ports; port_num++ ) + { + p_physp = osm_port_get_phys_ptr( p_port, port_num ); + if( p_physp == NULL ) + continue; + + if( !osm_physp_is_valid( p_physp ) ) + continue; + + /* if the requester and the p_physp don't share a pkey - + continue */ + if (!osm_physp_share_pkey(p_rcv->p_log, p_req_physp, p_physp)) + continue; + + __osm_sa_vl_arb_check_physp( p_rcv, p_physp, p_ctxt ); + } + } + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +void +__osm_sa_vl_arb_by_comp_mask_cb( + IN cl_map_item_t* const p_map_item, + IN void* context ) +{ + const osm_port_t* const p_port = (osm_port_t*)p_map_item; + osm_vl_arb_search_ctxt_t* const p_ctxt = (osm_vl_arb_search_ctxt_t *)context; + + __osm_sa_vl_arb_by_comp_mask( p_ctxt->p_rcv, p_port, p_ctxt ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_vlarb_rec_rcv_process( + IN osm_vlarb_rec_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ) +{ + const ib_sa_mad_t* p_rcvd_mad; + const ib_vl_arb_table_record_t* p_rcvd_rec; + const cl_ptr_vector_t* p_tbl; + const osm_port_t* p_port = NULL; + const ib_vl_arb_table_t* p_vl_arb; + cl_qlist_t rec_list; + osm_madw_t* p_resp_madw; + ib_sa_mad_t* p_resp_sa_mad; + ib_vl_arb_table_record_t* p_resp_rec; + uint32_t num_rec, pre_trim_num_rec; +#ifndef VENDOR_RMPP_SUPPORT + uint32_t trim_num_rec; +#endif + uint32_t i; + osm_vl_arb_search_ctxt_t context; + osm_vl_arb_item_t* p_rec_item; + ib_api_status_t status = IB_SUCCESS; + ib_net64_t comp_mask; + osm_physp_t* p_req_physp; + + CL_ASSERT( p_rcv ); + + OSM_LOG_ENTER( p_rcv->p_log, osm_vlarb_rec_rcv_process ); + + CL_ASSERT( p_madw ); + + p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw ); + p_rcvd_rec = (ib_vl_arb_table_record_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad ); + comp_mask = p_rcvd_mad->comp_mask; + + CL_ASSERT( p_rcvd_mad->attr_id == IB_MAD_ATTR_VLARB_RECORD ); + + /* we only support SubnAdmGet and SubnAdmGetTable methods */ + if ( (p_rcvd_mad->method != IB_MAD_METHOD_GET) && + (p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_vlarb_rec_rcv_process: ERR 2A05: " + "Unsupported Method (%s)\n", + ib_get_sa_method_str( p_rcvd_mad->method ) ); + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR ); + goto Exit; + } + + /* update the requester physical port. */ + p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log, + p_rcv->p_subn, + osm_madw_get_mad_addr_ptr(p_madw) ); + if (p_req_physp == NULL) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_vlarb_rec_rcv_process: ERR 2A04: " + "Cannot find requester physical port\n" ); + goto Exit; + } + + p_vl_arb = (ib_vl_arb_table_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad ); + + cl_qlist_init( &rec_list ); + + context.p_rcvd_rec = p_rcvd_rec; + context.p_list = &rec_list; + context.comp_mask = p_rcvd_mad->comp_mask; + context.p_rcv = p_rcv; + context.block_num = p_rcvd_rec->block_num; + context.p_req_physp = p_req_physp; + + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "osm_vlarb_rec_rcv_process: " + "Got Query Lid:0x%04X(%02X), Port:0x%02X(%02X), Block:0x%02X(%02X)\n", + cl_ntoh16(p_rcvd_rec->lid), (comp_mask & IB_VLA_COMPMASK_LID) != 0, + p_rcvd_rec->port_num, (comp_mask & IB_VLA_COMPMASK_OUT_PORT) != 0, + p_rcvd_rec->block_num, (comp_mask & IB_VLA_COMPMASK_BLOCK) != 0 ); + + cl_plock_acquire( p_rcv->p_lock ); + + /* + If the user specified a LID, it obviously narrows our + work load, since we don't have to search every port + */ + if( comp_mask & IB_VLA_COMPMASK_LID ) + { + + p_tbl = &p_rcv->p_subn->port_lid_tbl; + + CL_ASSERT( cl_ptr_vector_get_size(p_tbl) < 0x10000 ); + + status = osm_get_port_by_base_lid( p_rcv->p_subn, p_rcvd_rec->lid, &p_port ); + if ( ( status != IB_SUCCESS ) || ( p_port == NULL ) ) + { + status = IB_NOT_FOUND; + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_vlarb_rec_rcv_process: ERR 2A09: " + "No port found with LID 0x%x\n", + cl_ntoh16(p_rcvd_rec->lid) ); + } + } + + if ( status == IB_SUCCESS ) + { + /* if we got a unique port - no need for a port search */ + if( p_port ) + /* this does the loop on all the port phys ports */ + __osm_sa_vl_arb_by_comp_mask( p_rcv, p_port, &context ); + else + { + cl_qmap_apply_func( &p_rcv->p_subn->port_guid_tbl, + __osm_sa_vl_arb_by_comp_mask_cb, + &context ); + } + } + + cl_plock_release( p_rcv->p_lock ); + + num_rec = cl_qlist_count( &rec_list ); + + /* + * C15-0.1.30: + * If we do a SubnAdmGet and got more than one record it is an error ! + */ + if (p_rcvd_mad->method == IB_MAD_METHOD_GET) + { + if (num_rec == 0) + { + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS ); + goto Exit; + } + if (num_rec > 1) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_vlarb_rec_rcv_process: ERR 2A08: " + "Got more than one record for SubnAdmGet (%u)\n", + num_rec ); + osm_sa_send_error( p_rcv->p_resp, p_madw, + IB_SA_MAD_STATUS_TOO_MANY_RECORDS ); + + /* need to set the mem free ... */ + p_rec_item = (osm_vl_arb_item_t*)cl_qlist_remove_head( &rec_list ); + while( p_rec_item != (osm_vl_arb_item_t*)cl_qlist_end( &rec_list ) ) + { + cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item ); + p_rec_item = (osm_vl_arb_item_t*)cl_qlist_remove_head( &rec_list ); + } + + goto Exit; + } + } + + pre_trim_num_rec = num_rec; +#ifndef VENDOR_RMPP_SUPPORT + trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_vl_arb_table_record_t); + if (trim_num_rec < num_rec) + { + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "osm_vlarb_rec_rcv_process: " + "Number of records:%u trimmed to:%u to fit in one MAD\n", + num_rec, trim_num_rec ); + num_rec = trim_num_rec; + } +#endif + + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "osm_vlarb_rec_rcv_process: " + "Returning %u records\n", num_rec ); + + if ((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0)) + { + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS ); + goto Exit; + } + + /* + * Get a MAD to reply. Address of Mad is in the received mad_wrapper + */ + p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool, + p_madw->h_bind, + num_rec * sizeof(ib_vl_arb_table_record_t) + IB_SA_MAD_HDR_SIZE, + &p_madw->mad_addr ); + + if( !p_resp_madw ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_vlarb_rec_rcv_process: ERR 2A06: " + "osm_mad_pool_get failed\n" ); + + for( i = 0; i < num_rec; i++ ) + { + p_rec_item = (osm_vl_arb_item_t*)cl_qlist_remove_head( &rec_list ); + cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item ); + } + + osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES ); + goto Exit; + } + + p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw ); + + /* + Copy the MAD header back into the response mad. + Set the 'R' bit and the payload length, + Then copy all records from the list into the response payload. + */ + + memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE ); + p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK; + /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */ + p_resp_sa_mad->sm_key = 0; + + /* Fill in the offset (paylen will be done by the rmpp SAR) */ + p_resp_sa_mad->attr_offset = + ib_get_attr_offset( sizeof(ib_vl_arb_table_record_t) ); + + p_resp_rec = (ib_vl_arb_table_record_t*) + ib_sa_mad_get_payload_ptr( p_resp_sa_mad ); + +#ifndef VENDOR_RMPP_SUPPORT + /* we support only one packet RMPP - so we will set the first and + last flags for gettable */ + if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP) + { + p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA; + p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE; + } +#else + /* forcefully define the packet as RMPP one */ + if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP) + p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE; +#endif + + for( i = 0; i < pre_trim_num_rec; i++ ) + { + p_rec_item = (osm_vl_arb_item_t*)cl_qlist_remove_head( &rec_list ); + /* copy only if not trimmed */ + if (i < num_rec) + { + *p_resp_rec = p_rec_item->rec; + } + cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item ); + p_resp_rec++; + } + + CL_ASSERT( cl_is_qlist_empty( &rec_list ) ); + + status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE ); + if(status != IB_SUCCESS) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_vlarb_rec_rcv_process: ERR 2A07: " + "osm_vendor_send status = %s\n", + ib_get_err_str(status) ); + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_vlarb_record_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_vlarb_record_ctrl.c new file mode 100644 index 00000000..cc57ae8f --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_vlarb_record_ctrl.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sa_vlarb_record_ctrl.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_vlarb_rec_rcv_ctrl_t. + * This object represents the VL Arbitration Record SA request controller object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +__osm_vlarb_rec_rcv_ctrl_disp_callback( + IN void *context, + IN void *p_data ) +{ + /* ignore return status when invoked via the dispatcher */ + osm_vlarb_rec_rcv_process( ((osm_vlarb_rec_rcv_ctrl_t*)context)->p_rcv, + (osm_madw_t*)p_data ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_vlarb_rec_rcv_ctrl_construct( + IN osm_vlarb_rec_rcv_ctrl_t* const p_ctrl ) +{ + memset( p_ctrl, 0, sizeof(*p_ctrl) ); + p_ctrl->h_disp = CL_DISP_INVALID_HANDLE; +} + +/********************************************************************** + **********************************************************************/ +void +osm_vlarb_rec_rcv_ctrl_destroy( + IN osm_vlarb_rec_rcv_ctrl_t* const p_ctrl ) +{ + CL_ASSERT( p_ctrl ); + cl_disp_unregister( p_ctrl->h_disp ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_vlarb_rec_rcv_ctrl_init( + IN osm_vlarb_rec_rcv_ctrl_t* const p_ctrl, + IN osm_vlarb_rec_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_vlarb_rec_rcv_ctrl_init ); + + osm_vlarb_rec_rcv_ctrl_construct( p_ctrl ); + p_ctrl->p_log = p_log; + p_ctrl->p_rcv = p_rcv; + p_ctrl->p_disp = p_disp; + + p_ctrl->h_disp = cl_disp_register( + p_disp, + OSM_MSG_MAD_VL_ARB_RECORD, + __osm_vlarb_rec_rcv_ctrl_disp_callback, + p_ctrl ); + + if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_vlarb_rec_rcv_ctrl_init: ERR 2B01: " + "Dispatcher registration failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return( status ); +} + + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_service.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_service.c new file mode 100644 index 00000000..64d3e0c9 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_service.c @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_service.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of service record functions. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.7 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +osm_svcr_construct( + IN osm_svcr_t* const p_svcr ) +{ + memset( p_svcr, 0, sizeof(*p_svcr) ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_svcr_destroy( + IN osm_svcr_t* const p_svcr ) +{ + free( p_svcr); +} + +/********************************************************************** + **********************************************************************/ +void +osm_svcr_init( + IN osm_svcr_t* const p_svcr, + IN const ib_service_record_t *p_svc_rec ) +{ + CL_ASSERT( p_svcr ); + + p_svcr->modified_time = cl_get_time_stamp_sec(); + + /* We track the time left for this service in + an external field to avoid extra cl_ntoh/hton + required for working with the MAD field */ + p_svcr->lease_period = cl_ntoh32(p_svc_rec->service_lease); + p_svcr->service_record = *p_svc_rec; +} + +/********************************************************************** + **********************************************************************/ +osm_svcr_t* +osm_svcr_new( + IN const ib_service_record_t *p_svc_rec ) +{ + osm_svcr_t* p_svcr; + + CL_ASSERT(p_svc_rec); + + p_svcr = (osm_svcr_t*)malloc( sizeof(*p_svcr) ); + if( p_svcr ) + { + osm_svcr_construct( p_svcr ); + osm_svcr_init( p_svcr, p_svc_rec ); + } + + return( p_svcr ); +} + +/********************************************************************** + **********************************************************************/ +static +cl_status_t +__match_rid_of_svc_rec( + + IN const cl_list_item_t* const p_list_item, + IN void* context ) +{ + ib_service_record_t* p_svc_rec = (ib_service_record_t *)context; + osm_svcr_t* p_svcr = (osm_svcr_t*)p_list_item; + int32_t count; + + count = memcmp( + &p_svcr->service_record, + p_svc_rec, + sizeof(p_svc_rec->service_id) + + sizeof(p_svc_rec->service_gid) + + sizeof(p_svc_rec->service_pkey) ); + + if(count == 0) + return CL_SUCCESS; + else + return CL_NOT_FOUND; + +} + +/********************************************************************** + **********************************************************************/ +osm_svcr_t* +osm_svcr_get_by_rid( + IN osm_subn_t const *p_subn, + IN osm_log_t *p_log, + IN ib_service_record_t* const p_svc_rec ) +{ + cl_list_item_t* p_list_item; + + OSM_LOG_ENTER( p_log, osm_svcr_get_by_rid ); + + p_list_item = cl_qlist_find_from_head( + &p_subn->sa_sr_list, + __match_rid_of_svc_rec, + p_svc_rec); + + if( p_list_item == cl_qlist_end( &p_subn->sa_sr_list ) ) + p_list_item = NULL; + + OSM_LOG_EXIT( p_log ); + return (osm_svcr_t*)p_list_item; +} + +/********************************************************************** + **********************************************************************/ +void +osm_svcr_insert_to_db( + IN osm_subn_t *p_subn, + IN osm_log_t *p_log, + IN osm_svcr_t *p_svcr) +{ + OSM_LOG_ENTER( p_log, osm_svcr_insert_to_db ); + + osm_log( p_log, OSM_LOG_DEBUG, + "osm_svcr_insert_to_db: " + "Inserting new Service Record into Database\n"); + + cl_qlist_insert_head(&p_subn->sa_sr_list, + &p_svcr->list_item); + + OSM_LOG_EXIT( p_log ); +} + +void +osm_svcr_remove_from_db( + IN osm_subn_t *p_subn, + IN osm_log_t *p_log, + IN osm_svcr_t *p_svcr) +{ + OSM_LOG_ENTER( p_log, osm_svcr_remove_from_db ); + + osm_log( p_log, OSM_LOG_DEBUG, + "osm_svcr_remove_from_db: " + "Removing Service Record Name:%s ID:0x%016" PRIx64" from Database\n", + p_svcr->service_record.service_name, p_svcr->service_record.service_id + ); + + cl_qlist_remove_item(&p_subn->sa_sr_list, + &p_svcr->list_item); + + OSM_LOG_EXIT( p_log ); +} + + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_slvl_map_rcv.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_slvl_map_rcv.c new file mode 100644 index 00000000..8621849a --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_slvl_map_rcv.c @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_slvl_map_rcv.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_slvl_rcv_t. + * This object represents the SLtoVL Receiver object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +osm_slvl_rcv_construct( + IN osm_slvl_rcv_t* const p_rcv ) +{ + memset( p_rcv, 0, sizeof(*p_rcv) ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_slvl_rcv_destroy( + IN osm_slvl_rcv_t* const p_rcv ) +{ + CL_ASSERT( p_rcv ); + + OSM_LOG_ENTER( p_rcv->p_log, osm_slvl_rcv_destroy ); + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_slvl_rcv_init( + IN osm_slvl_rcv_t* const p_rcv, + IN osm_req_t* const p_req, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_slvl_rcv_init ); + + osm_slvl_rcv_construct( p_rcv ); + + p_rcv->p_log = p_log; + p_rcv->p_subn = p_subn; + p_rcv->p_lock = p_lock; + p_rcv->p_req = p_req; + + OSM_LOG_EXIT( p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +/* + * WE MIGHT ONLY RECEIVE A GET or SET responses + */ +void +osm_slvl_rcv_process( + IN const osm_slvl_rcv_t* const p_rcv, + IN osm_madw_t* const p_madw ) +{ + cl_qmap_t *p_guid_tbl; + ib_slvl_table_t *p_slvl_tbl; + ib_smp_t *p_smp; + osm_port_t *p_port; + osm_physp_t *p_physp; + osm_node_t *p_node; + osm_slvl_context_t *p_context; + ib_net64_t port_guid; + ib_net64_t node_guid; + uint8_t out_port_num, in_port_num; + + CL_ASSERT( p_rcv ); + + OSM_LOG_ENTER( p_rcv->p_log, osm_slvl_rcv_process ); + + CL_ASSERT( p_madw ); + + p_smp = osm_madw_get_smp_ptr( p_madw ); + p_context = osm_madw_get_slvl_context_ptr( p_madw ); + p_slvl_tbl = (ib_slvl_table_t*)ib_smp_get_payload_ptr( p_smp ); + + port_guid = p_context->port_guid; + node_guid = p_context->node_guid; + + CL_ASSERT( p_smp->attr_id == IB_MAD_ATTR_SLVL_TABLE ); + + p_guid_tbl = &p_rcv->p_subn->port_guid_tbl; + cl_plock_excl_acquire( p_rcv->p_lock ); + p_port = (osm_port_t*)cl_qmap_get( p_guid_tbl, port_guid ); + + if( p_port == (osm_port_t*)cl_qmap_end( p_guid_tbl) ) + { + cl_plock_release( p_rcv->p_lock ); + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_slvl_rcv_process: ERR 2C06: " + "No port object for port with GUID 0x%" PRIx64 + "\n\t\t\t\tfor parent node GUID 0x%" PRIx64 + ", TID 0x%" PRIx64 "\n", + cl_ntoh64( port_guid ), + cl_ntoh64( node_guid ), + cl_ntoh64( p_smp->trans_id ) ); + goto Exit; + } + + p_node = osm_port_get_parent_node( p_port ); + CL_ASSERT( p_node ); + + /* in case of a non switch node the attr modifier should be ignored */ + if (osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH) + { + out_port_num = (uint8_t)cl_ntoh32( p_smp->attr_mod & 0xFF000000); + in_port_num = (uint8_t)cl_ntoh32( (p_smp->attr_mod & 0x00FF0000) << 8); + p_physp = osm_node_get_physp_ptr( p_node, out_port_num ); + } + else + { + p_physp = osm_port_get_default_phys_ptr(p_port); + out_port_num = p_port->default_port_num; + in_port_num = 0; + } + + CL_ASSERT( p_physp ); + + /* + We do not mind if this is a result of a set or get - all we want is to update + the subnet. + */ + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "osm_slvl_rcv_process: " + "Got SLtoVL get response in_port_num %u out_port_num %u with GUID 0x%" PRIx64 + " for parent node GUID 0x%" PRIx64 + ", TID 0x%" PRIx64 "\n", + in_port_num, out_port_num, + cl_ntoh64( port_guid ), + cl_ntoh64( node_guid ), + cl_ntoh64( p_smp->trans_id ) ); + } + + /* + Determine if we encountered a new Physical Port. + If so, Ignore it. + */ + if( !osm_physp_is_valid( p_physp ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_slvl_rcv_process: " + "Got invalid port number 0x%X\n", + out_port_num ); + goto Exit; + } + + osm_dump_slvl_map_table( p_rcv->p_log, + port_guid, in_port_num, + out_port_num, p_slvl_tbl, + OSM_LOG_DEBUG ); + + osm_physp_set_slvl_tbl( p_physp, p_slvl_tbl, in_port_num); + + Exit: + cl_plock_release( p_rcv->p_lock ); + + OSM_LOG_EXIT( p_rcv->p_log ); +} + + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_slvl_map_rcv_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_slvl_map_rcv_ctrl.c new file mode 100644 index 00000000..040eddd7 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_slvl_map_rcv_ctrl.c @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_slvl_map_rcv_ctrl.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_slvl_rcv_ctrl_t. + * This object represents the SLtoVL request controller object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +__osm_slvl_rcv_ctrl_disp_callback( + IN void *context, + IN void *p_data ) +{ + /* ignore return status when invoked via the dispatcher */ + osm_slvl_rcv_process( ((osm_slvl_rcv_ctrl_t*)context)->p_rcv, + (osm_madw_t*)p_data ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_slvl_rcv_ctrl_construct( + IN osm_slvl_rcv_ctrl_t* const p_ctrl ) +{ + memset( p_ctrl, 0, sizeof(*p_ctrl) ); + p_ctrl->h_disp = CL_DISP_INVALID_HANDLE; +} + +/********************************************************************** + **********************************************************************/ +void +osm_slvl_rcv_ctrl_destroy( + IN osm_slvl_rcv_ctrl_t* const p_ctrl ) +{ + CL_ASSERT( p_ctrl ); + cl_disp_unregister( p_ctrl->h_disp ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_slvl_rcv_ctrl_init( + IN osm_slvl_rcv_ctrl_t* const p_ctrl, + IN osm_slvl_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_slvl_rcv_ctrl_init ); + + osm_slvl_rcv_ctrl_construct( p_ctrl ); + p_ctrl->p_log = p_log; + + p_ctrl->p_rcv = p_rcv; + p_ctrl->p_disp = p_disp; + + p_ctrl->h_disp = cl_disp_register( + p_disp, + OSM_MSG_MAD_SLVL, + __osm_slvl_rcv_ctrl_disp_callback, + p_ctrl ); + + if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_slvl_rcv_ctrl_init: ERR 2D01: " + "Dispatcher registration failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return( status ); +} + + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sm.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sm.c new file mode 100644 index 00000000..e2988772 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sm.c @@ -0,0 +1,824 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sm.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Implementation of osm_sm_t. + * This object represents the SM Receiver object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.9 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define OSM_SM_INITIAL_TID_VALUE 0x1233 + +/********************************************************************** + **********************************************************************/ +void +__osm_sm_sweeper( + IN void *p_ptr ) +{ + ib_api_status_t status; + osm_sm_t *const p_sm = ( osm_sm_t * ) p_ptr; + + OSM_LOG_ENTER( p_sm->p_log, __osm_sm_sweeper ); + + if( p_sm->thread_state == OSM_THREAD_STATE_INIT ) + { + p_sm->thread_state = OSM_THREAD_STATE_RUN; + } + + /* If the sweep interval was updated before - then run only if + * it is not zero. */ + while( p_sm->thread_state == OSM_THREAD_STATE_RUN && + p_sm->p_subn->opt.sweep_interval != 0 ) + { + /* do the sweep only if we are in MASTER state */ + if( p_sm->p_subn->sm_state == IB_SMINFO_STATE_MASTER || + p_sm->p_subn->sm_state == IB_SMINFO_STATE_DISCOVERING ) + osm_state_mgr_process( &p_sm->state_mgr, OSM_SIGNAL_SWEEP ); + + /* + * Wait on the event with a timeout. + * Sweeps may be initiated "off schedule" by simply + * signaling the event. + */ + status = cl_event_wait_on( &p_sm->signal, + p_sm->p_subn->opt.sweep_interval * 1000000, + TRUE ); + + if( status == CL_SUCCESS ) + { + if( osm_log_is_active( p_sm->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_sm->p_log, OSM_LOG_DEBUG, + "__osm_sm_sweeper: " "Off schedule sweep signalled\n" ); + } + } + else + { + if( status != CL_TIMEOUT ) + { + osm_log( p_sm->p_log, OSM_LOG_ERROR, + "__osm_sm_sweeper: ERR 2E01: " + "Event wait failed (%s)\n", CL_STATUS_MSG( status ) ); + } + } + } + + OSM_LOG_EXIT( p_sm->p_log ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_sm_construct( + IN osm_sm_t * const p_sm ) +{ + memset( p_sm, 0, sizeof( *p_sm ) ); + p_sm->thread_state = OSM_THREAD_STATE_NONE; + p_sm->sm_trans_id = OSM_SM_INITIAL_TID_VALUE; + cl_event_construct( &p_sm->signal ); + cl_event_construct( &p_sm->subnet_up_event ); + cl_thread_construct( &p_sm->sweeper ); + osm_req_construct( &p_sm->req ); + osm_req_ctrl_construct( &p_sm->req_ctrl ); + osm_resp_construct( &p_sm->resp ); + osm_ni_rcv_construct( &p_sm->ni_rcv ); + osm_ni_rcv_ctrl_construct( &p_sm->ni_rcv_ctrl ); + osm_pi_rcv_construct( &p_sm->pi_rcv ); + osm_pi_rcv_ctrl_construct( &p_sm->pi_rcv_ctrl ); + osm_nd_rcv_construct( &p_sm->nd_rcv ); + osm_nd_rcv_ctrl_construct( &p_sm->nd_rcv_ctrl ); + osm_sm_mad_ctrl_construct( &p_sm->mad_ctrl ); + osm_si_rcv_construct( &p_sm->si_rcv ); + osm_si_rcv_ctrl_construct( &p_sm->si_rcv_ctrl ); + osm_lid_mgr_construct( &p_sm->lid_mgr ); + osm_ucast_mgr_construct( &p_sm->ucast_mgr ); + osm_link_mgr_construct( &p_sm->link_mgr ); + osm_state_mgr_construct( &p_sm->state_mgr ); + osm_state_mgr_ctrl_construct( &p_sm->state_mgr_ctrl ); + osm_drop_mgr_construct( &p_sm->drop_mgr ); + osm_lft_rcv_construct( &p_sm->lft_rcv ); + osm_lft_rcv_ctrl_construct( &p_sm->lft_rcv_ctrl ); + osm_mft_rcv_construct( &p_sm->mft_rcv ); + osm_mft_rcv_ctrl_construct( &p_sm->mft_rcv_ctrl ); + osm_sweep_fail_ctrl_construct( &p_sm->sweep_fail_ctrl ); + osm_sminfo_rcv_construct( &p_sm->sm_info_rcv ); + osm_sminfo_rcv_ctrl_construct( &p_sm->sm_info_rcv_ctrl ); + osm_trap_rcv_construct( &p_sm->trap_rcv ); + osm_trap_rcv_ctrl_construct( &p_sm->trap_rcv_ctrl ); + osm_sm_state_mgr_construct( &p_sm->sm_state_mgr ); + osm_slvl_rcv_construct( &p_sm->slvl_rcv ); + osm_slvl_rcv_ctrl_construct( &p_sm->slvl_rcv_ctrl ); + osm_vla_rcv_construct( &p_sm->vla_rcv ); + osm_vla_rcv_ctrl_construct( &p_sm->vla_rcv_ctrl ); + osm_pkey_rcv_construct( &p_sm->pkey_rcv ); + osm_pkey_rcv_ctrl_construct( &p_sm->pkey_rcv_ctrl ); + osm_mcast_mgr_construct( &p_sm->mcast_mgr ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_sm_shutdown( + IN osm_sm_t * const p_sm ) +{ + boolean_t signal_event = FALSE; + + OSM_LOG_ENTER( p_sm->p_log, osm_sm_shutdown ); + + /* + * Signal our threads that we're leaving. + */ + if( p_sm->thread_state != OSM_THREAD_STATE_NONE ) + signal_event = TRUE; + + p_sm->thread_state = OSM_THREAD_STATE_EXIT; + + /* + * Don't trigger unless event has been initialized. + * Destroy the thread before we tear down the other objects. + */ + if( signal_event ) + cl_event_signal( &p_sm->signal ); + + cl_thread_destroy( &p_sm->sweeper ); + + /* + * Always destroy controllers before the corresponding + * receiver to guarantee that all callbacks from the + * dispatcher are complete. + */ + osm_sm_mad_ctrl_destroy( &p_sm->mad_ctrl ); + osm_trap_rcv_ctrl_destroy( &p_sm->trap_rcv_ctrl ); + osm_sminfo_rcv_ctrl_destroy( &p_sm->sm_info_rcv_ctrl ); + osm_req_ctrl_destroy( &p_sm->req_ctrl ); + osm_ni_rcv_ctrl_destroy( &p_sm->ni_rcv_ctrl ); + osm_pi_rcv_ctrl_destroy( &p_sm->pi_rcv_ctrl ); + osm_si_rcv_ctrl_destroy( &p_sm->si_rcv_ctrl ); + osm_nd_rcv_ctrl_destroy( &p_sm->nd_rcv_ctrl ); + osm_lft_rcv_ctrl_destroy( &p_sm->lft_rcv_ctrl ); + osm_mft_rcv_ctrl_destroy( &p_sm->mft_rcv_ctrl ); + osm_slvl_rcv_ctrl_destroy( &p_sm->slvl_rcv_ctrl ); + osm_vla_rcv_ctrl_destroy( &p_sm->vla_rcv_ctrl ); + osm_pkey_rcv_ctrl_destroy( &p_sm->pkey_rcv_ctrl ); + osm_sweep_fail_ctrl_destroy( &p_sm->sweep_fail_ctrl ); + osm_state_mgr_ctrl_destroy( &p_sm->state_mgr_ctrl ); + + OSM_LOG_EXIT( p_sm->p_log ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_sm_destroy( + IN osm_sm_t * const p_sm ) +{ + OSM_LOG_ENTER( p_sm->p_log, osm_sm_destroy ); + osm_trap_rcv_destroy( &p_sm->trap_rcv ); + osm_sminfo_rcv_destroy( &p_sm->sm_info_rcv ); + osm_req_destroy( &p_sm->req ); + osm_resp_destroy( &p_sm->resp ); + osm_ni_rcv_destroy( &p_sm->ni_rcv ); + osm_pi_rcv_destroy( &p_sm->pi_rcv ); + osm_si_rcv_destroy( &p_sm->si_rcv ); + osm_nd_rcv_destroy( &p_sm->nd_rcv ); + osm_lid_mgr_destroy( &p_sm->lid_mgr ); + osm_ucast_mgr_destroy( &p_sm->ucast_mgr ); + osm_link_mgr_destroy( &p_sm->link_mgr ); + osm_drop_mgr_destroy( &p_sm->drop_mgr ); + osm_lft_rcv_destroy( &p_sm->lft_rcv ); + osm_mft_rcv_destroy( &p_sm->mft_rcv ); + osm_slvl_rcv_destroy( &p_sm->slvl_rcv ); + osm_vla_rcv_destroy( &p_sm->vla_rcv ); + osm_pkey_rcv_destroy( &p_sm->pkey_rcv ); + osm_state_mgr_destroy( &p_sm->state_mgr ); + osm_sm_state_mgr_destroy( &p_sm->sm_state_mgr ); + osm_mcast_mgr_destroy( &p_sm->mcast_mgr ); + cl_event_destroy( &p_sm->signal ); + cl_event_destroy( &p_sm->subnet_up_event ); + + osm_log( p_sm->p_log, OSM_LOG_SYS, "Exiting SM\n" ); /* Format Waived */ + OSM_LOG_EXIT( p_sm->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_sm_init( + IN osm_sm_t * const p_sm, + IN osm_subn_t * const p_subn, + IN osm_db_t * const p_db, + IN osm_vendor_t * const p_vendor, + IN osm_mad_pool_t * const p_mad_pool, + IN osm_vl15_t * const p_vl15, + IN osm_log_t * const p_log, + IN osm_stats_t * const p_stats, + IN cl_dispatcher_t * const p_disp, + IN cl_plock_t * const p_lock ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_sm_init ); + + p_sm->p_subn = p_subn; + p_sm->p_db = p_db; + p_sm->p_vendor = p_vendor; + p_sm->p_mad_pool = p_mad_pool; + p_sm->p_vl15 = p_vl15; + p_sm->p_log = p_log; + p_sm->p_disp = p_disp; + p_sm->p_lock = p_lock; + + status = cl_event_init( &p_sm->signal, FALSE ); + if( status != CL_SUCCESS ) + goto Exit; + + status = cl_event_init( &p_sm->subnet_up_event, FALSE ); + if( status != CL_SUCCESS ) + goto Exit; + + status = osm_sm_mad_ctrl_init( &p_sm->mad_ctrl, + p_sm->p_subn, + p_sm->p_mad_pool, + p_sm->p_vl15, + p_sm->p_vendor, + p_log, p_stats, p_lock, p_disp ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_req_init( &p_sm->req, + p_mad_pool, + p_vl15, p_subn, p_log, &p_sm->sm_trans_id ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_req_ctrl_init( &p_sm->req_ctrl, &p_sm->req, p_log, p_disp ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_resp_init( &p_sm->resp, p_mad_pool, p_vl15, p_subn, p_log ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_ni_rcv_init( &p_sm->ni_rcv, + &p_sm->req, + p_subn, p_log, &p_sm->state_mgr, p_lock ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_ni_rcv_ctrl_init( &p_sm->ni_rcv_ctrl, + &p_sm->ni_rcv, p_log, p_disp ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_pi_rcv_init( &p_sm->pi_rcv, + &p_sm->req, + p_subn, p_log, &p_sm->state_mgr, p_lock ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_pi_rcv_ctrl_init( &p_sm->pi_rcv_ctrl, + &p_sm->pi_rcv, p_log, p_disp ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_si_rcv_init( &p_sm->si_rcv, + p_sm->p_subn, + p_sm->p_log, + &p_sm->req, &p_sm->state_mgr, p_sm->p_lock ); + + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_si_rcv_ctrl_init( &p_sm->si_rcv_ctrl, + &p_sm->si_rcv, p_sm->p_log, p_sm->p_disp ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_nd_rcv_init( &p_sm->nd_rcv, p_subn, p_log, p_lock ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_nd_rcv_ctrl_init( &p_sm->nd_rcv_ctrl, + &p_sm->nd_rcv, p_log, p_disp ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_lid_mgr_init( &p_sm->lid_mgr, + &p_sm->req, + p_sm->p_subn, + p_sm->p_db, p_sm->p_log, p_sm->p_lock ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_ucast_mgr_init( &p_sm->ucast_mgr, + &p_sm->req, + p_sm->p_subn, + p_sm->p_log, p_sm->p_lock ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_link_mgr_init( &p_sm->link_mgr, + &p_sm->req, + p_sm->p_subn, p_sm->p_log, p_sm->p_lock ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_state_mgr_init( &p_sm->state_mgr, + p_sm->p_subn, + &p_sm->lid_mgr, + &p_sm->ucast_mgr, + &p_sm->mcast_mgr, + &p_sm->link_mgr, + &p_sm->drop_mgr, + &p_sm->req, + p_stats, + &p_sm->sm_state_mgr, + &p_sm->mad_ctrl, + p_sm->p_lock, + &p_sm->subnet_up_event, + p_sm->p_log ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_state_mgr_ctrl_init( &p_sm->state_mgr_ctrl, + &p_sm->state_mgr, + p_sm->p_log, p_sm->p_disp ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_drop_mgr_init( &p_sm->drop_mgr, + p_sm->p_subn, + p_sm->p_log, &p_sm->req, p_sm->p_lock ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_lft_rcv_init( &p_sm->lft_rcv, p_subn, p_log, p_lock ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_lft_rcv_ctrl_init( &p_sm->lft_rcv_ctrl, + &p_sm->lft_rcv, p_log, p_disp ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_mft_rcv_init( &p_sm->mft_rcv, p_subn, p_log, p_lock ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_mft_rcv_ctrl_init( &p_sm->mft_rcv_ctrl, + &p_sm->mft_rcv, p_log, p_disp ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_sweep_fail_ctrl_init( &p_sm->sweep_fail_ctrl, + p_log, &p_sm->state_mgr, p_disp ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_sminfo_rcv_init( &p_sm->sm_info_rcv, + p_subn, + p_stats, + &p_sm->resp, + p_log, + &p_sm->state_mgr, + &p_sm->sm_state_mgr, p_lock ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_sminfo_rcv_ctrl_init( &p_sm->sm_info_rcv_ctrl, + &p_sm->sm_info_rcv, + p_sm->p_log, p_disp ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_trap_rcv_init( &p_sm->trap_rcv, + p_subn, + p_stats, + &p_sm->resp, p_log, &p_sm->state_mgr, p_lock ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_trap_rcv_ctrl_init( &p_sm->trap_rcv_ctrl, + &p_sm->trap_rcv, p_sm->p_log, p_disp ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_sm_state_mgr_init( &p_sm->sm_state_mgr, + &p_sm->state_mgr, + p_sm->p_subn, &p_sm->req, p_sm->p_log ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_mcast_mgr_init( &p_sm->mcast_mgr, + &p_sm->req, p_subn, p_log, p_lock ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_slvl_rcv_init( &p_sm->slvl_rcv, + &p_sm->req, p_subn, p_log, p_lock ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_slvl_rcv_ctrl_init( &p_sm->slvl_rcv_ctrl, + &p_sm->slvl_rcv, p_sm->p_log, p_disp ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_vla_rcv_init( &p_sm->vla_rcv, + &p_sm->req, p_subn, p_log, p_lock ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_vla_rcv_ctrl_init( &p_sm->vla_rcv_ctrl, + &p_sm->vla_rcv, p_sm->p_log, p_disp ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_pkey_rcv_init( &p_sm->pkey_rcv, + &p_sm->req, p_subn, p_log, p_lock ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_pkey_rcv_ctrl_init( &p_sm->pkey_rcv_ctrl, + &p_sm->pkey_rcv, p_sm->p_log, p_disp ); + if( status != IB_SUCCESS ) + goto Exit; + + /* + * Now that the component objects are initialized, start + * the sweeper thread if the user wants sweeping. + */ + if( p_sm->p_subn->opt.sweep_interval ) + { + p_sm->thread_state = OSM_THREAD_STATE_INIT; + status = cl_thread_init( &p_sm->sweeper, __osm_sm_sweeper, p_sm, + "opensm sweeper" ); + if( status != IB_SUCCESS ) + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return ( status ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_sm_sweep( + IN osm_sm_t * const p_sm ) +{ + OSM_LOG_ENTER( p_sm->p_log, osm_sm_sweep ); + osm_state_mgr_process( &p_sm->state_mgr, OSM_SIGNAL_SWEEP ); + OSM_LOG_EXIT( p_sm->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_sm_bind( + IN osm_sm_t * const p_sm, + IN const ib_net64_t port_guid ) +{ + ib_api_status_t status; + + OSM_LOG_ENTER( p_sm->p_log, osm_sm_bind ); + + status = osm_sm_mad_ctrl_bind( &p_sm->mad_ctrl, port_guid ); + + if( status != IB_SUCCESS ) + { + osm_log( p_sm->p_log, OSM_LOG_ERROR, + "osm_sm_bind: ERR 2E10: " + "SM MAD Controller bind failed (%s)\n", + ib_get_err_str( status ) ); + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_sm->p_log ); + return ( status ); +} + +/********************************************************************** + **********************************************************************/ +static ib_api_status_t +__osm_sm_mgrp_connect( + IN osm_sm_t * const p_sm, + IN osm_mgrp_t * const p_mgrp, + IN const ib_net64_t port_guid, + IN osm_mcast_req_type_t req_type ) +{ + ib_api_status_t status; + osm_mcast_mgr_ctxt_t *ctx2; + + OSM_LOG_ENTER( p_sm->p_log, __osm_sm_mgrp_connect ); + + /* + * 'Schedule' all the QP0 traffic for when the state manager + * isn't busy trying to do something else. + */ + ctx2 = + ( osm_mcast_mgr_ctxt_t * ) malloc( sizeof( osm_mcast_mgr_ctxt_t ) ); + memcpy( &ctx2->mlid, &p_mgrp->mlid, sizeof( p_mgrp->mlid ) ); + ctx2->req_type = req_type; + ctx2->port_guid = port_guid; + + status = osm_state_mgr_process_idle( &p_sm->state_mgr, + osm_mcast_mgr_process_mgrp_cb, + NULL, &p_sm->mcast_mgr, + ( void * )ctx2 ); + + OSM_LOG_EXIT( p_sm->p_log ); + return ( status ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_sm_mgrp_disconnect( + IN osm_sm_t * const p_sm, + IN osm_mgrp_t * const p_mgrp, + IN const ib_net64_t port_guid ) +{ + ib_api_status_t status; + osm_mcast_mgr_ctxt_t *ctx2; + + OSM_LOG_ENTER( p_sm->p_log, __osm_sm_mgrp_disconnect ); + + /* + * 'Schedule' all the QP0 traffic for when the state manager + * isn't busy trying to do something else. + */ + ctx2 = + ( osm_mcast_mgr_ctxt_t * ) malloc( sizeof( osm_mcast_mgr_ctxt_t ) ); + memcpy( &ctx2->mlid, &p_mgrp->mlid, sizeof( p_mgrp->mlid ) ); + ctx2->req_type = OSM_MCAST_REQ_TYPE_LEAVE; + ctx2->port_guid = port_guid; + + status = osm_state_mgr_process_idle( &p_sm->state_mgr, + osm_mcast_mgr_process_mgrp_cb, + NULL, &p_sm->mcast_mgr, ctx2 ); + if( status != IB_SUCCESS ) + { + osm_log( p_sm->p_log, OSM_LOG_ERROR, + "__osm_sm_mgrp_disconnect: ERR 2E11: " + "Failure processing multicast group (%s)\n", + ib_get_err_str( status ) ); + } + + OSM_LOG_EXIT( p_sm->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_sm_mcgrp_join( + IN osm_sm_t * const p_sm, + IN const ib_net16_t mlid, + IN const ib_net64_t port_guid, + IN osm_mcast_req_type_t req_type ) +{ + osm_mgrp_t *p_mgrp; + osm_port_t *p_port; + cl_qmap_t *p_tbl; + ib_api_status_t status = IB_SUCCESS; + osm_mcm_info_t *p_mcm; + + OSM_LOG_ENTER( p_sm->p_log, osm_sm_mcgrp_join ); + + osm_log( p_sm->p_log, OSM_LOG_VERBOSE, + "osm_sm_mcgrp_join: " + "Port 0x%016" PRIx64 " joining MLID 0x%X\n", + cl_ntoh64( port_guid ), cl_ntoh16( mlid ) ); + + /* + * Acquire the port object for the port joining this group. + */ + CL_PLOCK_EXCL_ACQUIRE( p_sm->p_lock ); + p_port = ( osm_port_t * ) cl_qmap_get( &p_sm->p_subn->port_guid_tbl, + port_guid ); + if( p_port == + ( osm_port_t * ) cl_qmap_end( &p_sm->p_subn->port_guid_tbl ) ) + { + CL_PLOCK_RELEASE( p_sm->p_lock ); + osm_log( p_sm->p_log, OSM_LOG_ERROR, + "osm_sm_mcgrp_join: ERR 2E05: " + "No port object for port 0x%016" PRIx64 "\n", + cl_ntoh64( port_guid ) ); + status = IB_INVALID_PARAMETER; + goto Exit; + } + + /* + * If this multicast group does not already exist, create it. + */ + p_tbl = &p_sm->p_subn->mgrp_mlid_tbl; + p_mgrp = ( osm_mgrp_t * ) cl_qmap_get( p_tbl, mlid ); + if( p_mgrp == ( osm_mgrp_t * ) cl_qmap_end( p_tbl ) ) + { + osm_log( p_sm->p_log, OSM_LOG_VERBOSE, + "osm_sm_mcgrp_join: " + "Creating group, MLID 0x%X\n", cl_ntoh16( mlid ) ); + + p_mgrp = osm_mgrp_new( mlid ); + if( p_mgrp == NULL ) + { + CL_PLOCK_RELEASE( p_sm->p_lock ); + osm_log( p_sm->p_log, OSM_LOG_ERROR, + "osm_sm_mcgrp_join: ERR 2E06: " + "Unable to allocate multicast group object\n" ); + status = IB_INSUFFICIENT_MEMORY; + goto Exit; + } + + cl_qmap_insert( p_tbl, mlid, &p_mgrp->map_item ); + } + else + { + /* + * The group already exists. If the port is not a + * member of the group, then fail immediately. + * This can happen since the spinlock is released briefly + * before the SA calls this function. + */ + if( !osm_mgrp_is_guid( p_mgrp, port_guid ) ) + { + CL_PLOCK_RELEASE( p_sm->p_lock ); + osm_log( p_sm->p_log, OSM_LOG_ERROR, + "osm_sm_mcgrp_join: ERR 2E12: " + "Port 0x%016" PRIx64 " not in mcast group 0x%X\n", + cl_ntoh64( port_guid ), cl_ntoh16( mlid ) ); + status = IB_NOT_FOUND; + goto Exit; + } + } + + /* + * Check if the object (according to mlid) already exists on this port. + * If it does - then no need to update it again, and no need to + * create the mc tree again. Just goto Exit. + */ + p_mcm = ( osm_mcm_info_t * ) cl_qlist_head( &p_port->mcm_list ); + while( p_mcm != ( osm_mcm_info_t * ) cl_qlist_end( &p_port->mcm_list ) ) + { + if( p_mcm->mlid == mlid ) + { + CL_PLOCK_RELEASE( p_sm->p_lock ); + osm_log( p_sm->p_log, OSM_LOG_DEBUG, + "osm_sm_mcgrp_join: " + "Found mlid object for Port:" + "0x%016" PRIx64 " lid:0x%X\n", + cl_ntoh64( port_guid ), cl_ntoh16( mlid ) ); + goto Exit; + } + p_mcm = ( osm_mcm_info_t * ) cl_qlist_next( &p_mcm->list_item ); + } + + status = osm_port_add_mgrp( p_port, mlid ); + if( status != IB_SUCCESS ) + { + CL_PLOCK_RELEASE( p_sm->p_lock ); + osm_log( p_sm->p_log, OSM_LOG_ERROR, + "osm_sm_mcgrp_join: ERR 2E03: " + "Unable to associate port 0x%" PRIx64 " to mlid 0x%X\n", + cl_ntoh64( osm_port_get_guid( p_port ) ), + cl_ntoh16( osm_mgrp_get_mlid( p_mgrp ) ) ); + goto Exit; + } + + CL_PLOCK_RELEASE( p_sm->p_lock ); + status = __osm_sm_mgrp_connect( p_sm, p_mgrp, port_guid, req_type ); + + Exit: + OSM_LOG_EXIT( p_sm->p_log ); + return ( status ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_sm_mcgrp_leave( + IN osm_sm_t * const p_sm, + IN const ib_net16_t mlid, + IN const ib_net64_t port_guid ) +{ + osm_mgrp_t *p_mgrp; + osm_port_t *p_port; + cl_qmap_t *p_tbl; + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_sm->p_log, osm_sm_mcgrp_leave ); + + osm_log( p_sm->p_log, OSM_LOG_VERBOSE, + "osm_sm_mcgrp_leave: " + "Port 0x%" PRIx64 " leaving MLID 0x%X\n", + cl_ntoh64( port_guid ), cl_ntoh16( mlid ) ); + + /* + * Acquire the port object for the port leaving this group. + */ + /* note: p_sm->p_lock is locked by caller, but will be released later + this function */ + p_port = ( osm_port_t * ) cl_qmap_get( &p_sm->p_subn->port_guid_tbl, + port_guid ); + if( p_port == + ( osm_port_t * ) cl_qmap_end( &p_sm->p_subn->port_guid_tbl ) ) + { + CL_PLOCK_RELEASE( p_sm->p_lock ); + osm_log( p_sm->p_log, OSM_LOG_ERROR, + "osm_sm_mcgrp_leave: ERR 2E04: " + "No port object for port 0x%" PRIx64 "\n", + cl_ntoh64( port_guid ) ); + status = IB_INVALID_PARAMETER; + goto Exit; + } + + /* + * Get the multicast group object for this group. + */ + p_tbl = &p_sm->p_subn->mgrp_mlid_tbl; + p_mgrp = ( osm_mgrp_t * ) cl_qmap_get( p_tbl, mlid ); + if( p_mgrp == ( osm_mgrp_t * ) cl_qmap_end( p_tbl ) ) + { + CL_PLOCK_RELEASE( p_sm->p_lock ); + osm_log( p_sm->p_log, OSM_LOG_ERROR, + "osm_sm_mcgrp_leave: ERR 2E08: " + "No multicast group for MLID 0x%X\n", cl_ntoh16( mlid ) ); + status = IB_INVALID_PARAMETER; + goto Exit; + } + + /* + * Walk the list of ports in the group, and remove the appropriate one. + */ + osm_mgrp_remove_port( p_sm->p_subn, p_sm->p_log, p_mgrp, port_guid ); + + osm_port_remove_mgrp( p_port, mlid ); + + CL_PLOCK_RELEASE( p_sm->p_lock ); + + __osm_sm_mgrp_disconnect( p_sm, p_mgrp, port_guid ); + + Exit: + OSM_LOG_EXIT( p_sm->p_log ); + return ( status ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sm_mad_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sm_mad_ctrl.c new file mode 100644 index 00000000..87b56422 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sm_mad_ctrl.c @@ -0,0 +1,1049 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sm_mad_ctrl.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Implementation of osm_sm_mad_ctrl_t. + * This object represents the SM MAD request controller object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.7 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/****f* opensm: SM/__osm_sm_mad_ctrl_retire_trans_mad + * NAME + * __osm_sm_mad_ctrl_retire_trans_mad + * + * DESCRIPTION + * This function handles clean-up of MADs associated with the SM's + * outstanding transactions on the wire. + * + * SYNOPSIS + */ +static void +__osm_sm_mad_ctrl_retire_trans_mad( + IN osm_sm_mad_ctrl_t* const p_ctrl, + IN osm_madw_t* const p_madw ) +{ + uint32_t outstanding; + cl_status_t status; + + OSM_LOG_ENTER( p_ctrl->p_log, __osm_sm_mad_ctrl_retire_trans_mad ); + + CL_ASSERT( p_madw ); + /* + Return the MAD & wrapper to the pool. + */ + if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_ctrl->p_log, OSM_LOG_DEBUG, + "__osm_sm_mad_ctrl_retire_trans_mad: " + "Retiring MAD with TID 0x%" PRIx64 "\n", + cl_ntoh64( osm_madw_get_smp_ptr( p_madw )->trans_id ) ); + } + + osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw ); + + outstanding = cl_atomic_dec( &p_ctrl->p_stats->qp0_mads_outstanding ); + + if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_ctrl->p_log, OSM_LOG_DEBUG, + "__osm_sm_mad_ctrl_retire_trans_mad: " + "%u QP0 MADs outstanding\n", + p_ctrl->p_stats->qp0_mads_outstanding ); + } + + if( outstanding == 0 ) + { + /* + The wire is clean. + Signal the state manager. + */ + if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_ctrl->p_log, OSM_LOG_DEBUG, + "__osm_sm_mad_ctrl_retire_trans_mad: " + "Posting Dispatcher message %s\n", + osm_get_disp_msg_str( OSM_MSG_NO_SMPS_OUTSTANDING ) ); + } + + status = cl_disp_post( p_ctrl->h_disp, + OSM_MSG_NO_SMPS_OUTSTANDING, + (void *)OSM_SIGNAL_NO_PENDING_TRANSACTIONS, + NULL, + NULL ); + + if( status != CL_SUCCESS ) + { + osm_log( p_ctrl->p_log, OSM_LOG_ERROR, + "__osm_sm_mad_ctrl_retire_trans_mad: ERR 3101: " + "Dispatcher post message failed (%s)\n", + CL_STATUS_MSG( status ) ); + goto Exit; + } + } + + Exit: + OSM_LOG_EXIT( p_ctrl->p_log ); +} +/************/ + +/****f* opensm: SM/__osm_sm_mad_ctrl_disp_done_callback + * NAME + * __osm_sm_mad_ctrl_disp_done_callback + * + * DESCRIPTION + * This function is the Dispatcher callback that indicates + * a received MAD has been processed by the recipient. + * + * SYNOPSIS + */ +static void +__osm_sm_mad_ctrl_disp_done_callback( + IN void* context, + IN void* p_data ) +{ + osm_sm_mad_ctrl_t* const p_ctrl = (osm_sm_mad_ctrl_t*)context; + osm_madw_t* const p_madw = (osm_madw_t*)p_data; + ib_smp_t *p_smp; + + OSM_LOG_ENTER( p_ctrl->p_log, __osm_sm_mad_ctrl_disp_done_callback ); + + /* + If the MAD that just finished processing was a response, + then retire the transaction, since we must have generated + the request. + + Otherwise, retire the transaction if a response was expected, + as in the case of a send failure. If a response was not expected, + just put the MAD back in the pool, because the MAD was a query + from some outside agent, e.g. Get(SMInfo) from another SM. + */ + p_smp = osm_madw_get_smp_ptr( p_madw ); + if( ib_smp_is_response( p_smp ) ) + { + CL_ASSERT( p_madw->resp_expected == FALSE ); + __osm_sm_mad_ctrl_retire_trans_mad( p_ctrl, p_madw ); + } + else + { + if( p_madw->resp_expected == TRUE ) + __osm_sm_mad_ctrl_retire_trans_mad( p_ctrl, p_madw ); + else + osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw ); + } + + OSM_LOG_EXIT( p_ctrl->p_log ); +} +/************/ + +/****f* opensm: SM/__osm_sm_mad_ctrl_update_wire_stats + * NAME + * __osm_sm_mad_ctrl_update_wire_stats + * + * DESCRIPTION + * Updates wire stats for outstanding MADs and calls the VL15 poller. + * + * SYNOPSIS + */ +static void +__osm_sm_mad_ctrl_update_wire_stats( + IN osm_sm_mad_ctrl_t* const p_ctrl ) +{ + uint32_t mads_on_wire; + + OSM_LOG_ENTER( p_ctrl->p_log, __osm_sm_mad_ctrl_update_wire_stats ); + + mads_on_wire = cl_atomic_dec( + &p_ctrl->p_stats->qp0_mads_outstanding_on_wire ); + + if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_ctrl->p_log, OSM_LOG_DEBUG, + "__osm_sm_mad_ctrl_update_wire_stats: " + "%u SMPs on the wire, %u outstanding\n", mads_on_wire, + p_ctrl->p_stats->qp0_mads_outstanding ); + } + + /* + We can signal the VL15 controller to send another MAD + if any are waiting for transmission. + */ + osm_vl15_poll( p_ctrl->p_vl15 ); + OSM_LOG_EXIT( p_ctrl->p_log ); +} + +/****f* opensm: SM/__osm_sm_mad_ctrl_process_get_resp + * NAME + * __osm_sm_mad_ctrl_process_get_resp + * + * DESCRIPTION + * This function handles method GetResp() for received MADs. + * This is the most common path for QP0 MADs. + * + * SYNOPSIS + */ +static void +__osm_sm_mad_ctrl_process_get_resp( + IN osm_sm_mad_ctrl_t* const p_ctrl, + IN osm_madw_t *p_madw, + IN void* transaction_context ) +{ + ib_smp_t* p_smp; + cl_status_t status; + osm_madw_t* p_old_madw; + cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE; + + OSM_LOG_ENTER( p_ctrl->p_log, __osm_sm_mad_ctrl_process_get_resp ); + + CL_ASSERT( p_madw ); + CL_ASSERT( transaction_context ); + + p_smp = osm_madw_get_smp_ptr( p_madw ); + + if( p_smp->mgmt_class == IB_MCLASS_SUBN_DIR ) + { + if( !ib_smp_is_d( p_smp ) ) + { + osm_log( p_ctrl->p_log, OSM_LOG_ERROR, + "__osm_sm_mad_ctrl_process_get_resp: ERR 3102: " + "'D' bit not set in returned SMP\n" ); + osm_dump_dr_smp( p_ctrl->p_log, p_smp, OSM_LOG_ERROR ); + } + } + + p_old_madw = (osm_madw_t*)transaction_context; + + __osm_sm_mad_ctrl_update_wire_stats( p_ctrl ); + + /* + Copy the MAD Wrapper context from the requesting MAD + to the new MAD. This mechanism allows the recipient + controller to recover its own context regarding this + MAD transaction. Once we've copied the context, we + can return the original MAD to the pool. + */ + osm_madw_copy_context( p_madw, p_old_madw ); + osm_mad_pool_put( p_ctrl->p_mad_pool, p_old_madw ); + + /* + Note that attr_id (like the rest of the MAD) is in + network byte order. + */ + switch( p_smp->attr_id ) + { + case IB_MAD_ATTR_NODE_DESC: + msg_id = OSM_MSG_MAD_NODE_DESC; + break; + case IB_MAD_ATTR_NODE_INFO: + msg_id = OSM_MSG_MAD_NODE_INFO; + break; + case IB_MAD_ATTR_SWITCH_INFO: + msg_id = OSM_MSG_MAD_SWITCH_INFO; + break; + case IB_MAD_ATTR_PORT_INFO: + msg_id = OSM_MSG_MAD_PORT_INFO; + break; + case IB_MAD_ATTR_LIN_FWD_TBL: + msg_id = OSM_MSG_MAD_LFT; + break; + case IB_MAD_ATTR_MCAST_FWD_TBL: + msg_id = OSM_MSG_MAD_MFT; + break; + case IB_MAD_ATTR_SM_INFO: + msg_id = OSM_MSG_MAD_SM_INFO; + break; + case IB_MAD_ATTR_SLVL_TABLE: + msg_id = OSM_MSG_MAD_SLVL; + break; + case IB_MAD_ATTR_VL_ARBITRATION: + msg_id = OSM_MSG_MAD_VL_ARB; + break; + case IB_MAD_ATTR_P_KEY_TABLE: + msg_id = OSM_MSG_MAD_PKEY; + break; + + case IB_MAD_ATTR_GUID_INFO: + case IB_MAD_ATTR_CLASS_PORT_INFO: + case IB_MAD_ATTR_NOTICE: + case IB_MAD_ATTR_INFORM_INFO: + default: + osm_log( p_ctrl->p_log, OSM_LOG_ERROR, + "__osm_sm_mad_ctrl_process_get_resp: ERR 3103: " + "Unsupported attribute = 0x%X\n", + cl_ntoh16( p_smp->attr_id ) ); + osm_dump_dr_smp( p_ctrl->p_log, p_smp, OSM_LOG_ERROR ); + goto Exit; + } + + if( msg_id != CL_DISP_MSGID_NONE ) + { + /* + Post this MAD to the dispatcher for asynchronous + processing by the appropriate controller. + */ + + if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_ctrl->p_log, OSM_LOG_DEBUG, + "__osm_sm_mad_ctrl_process_get_resp: " + "Posting Dispatcher message %s\n", + osm_get_disp_msg_str( msg_id ) ); + } + + status = cl_disp_post( p_ctrl->h_disp, + msg_id, + p_madw, + __osm_sm_mad_ctrl_disp_done_callback, + p_ctrl ); + + if( status != CL_SUCCESS ) + { + osm_log( p_ctrl->p_log, OSM_LOG_ERROR, + "__osm_sm_mad_ctrl_process_get_resp: ERR 3104: " + "Dispatcher post message failed (%s) for attribute = 0x%X\n", + CL_STATUS_MSG( status ), + cl_ntoh16( p_smp->attr_id ) ); + goto Exit; + } + } + + Exit: + OSM_LOG_EXIT( p_ctrl->p_log ); +} + +/****f* opensm: SM/__osm_sm_mad_ctrl_process_get + * NAME + * __osm_sm_mad_ctrl_process_get + * + * DESCRIPTION + * This function handles method Get() for received MADs. + * + * SYNOPSIS + */ +static void +__osm_sm_mad_ctrl_process_get( + IN osm_sm_mad_ctrl_t* const p_ctrl, + IN osm_madw_t *p_madw ) +{ + ib_smp_t* p_smp; + cl_status_t status; + cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE; + + OSM_LOG_ENTER( p_ctrl->p_log, __osm_sm_mad_ctrl_process_get ); + + p_smp = osm_madw_get_smp_ptr( p_madw ); + + /* + Note that attr_id (like the rest of the MAD) is in + network byte order. + */ + switch( p_smp->attr_id ) + { + case IB_MAD_ATTR_SM_INFO: + msg_id = OSM_MSG_MAD_SM_INFO; + break; + + default: + osm_log( p_ctrl->p_log, OSM_LOG_VERBOSE, + "__osm_sm_mad_ctrl_process_get: " + "Ignoring SubnGet MAD - unsupported attribute = 0x%X\n", + cl_ntoh16( p_smp->attr_id ) ); + break; + } + + if( msg_id != CL_DISP_MSGID_NONE ) + { + /* + Post this MAD to the dispatcher for asynchronous + processing by the appropriate controller. + */ + + if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_ctrl->p_log, OSM_LOG_DEBUG, + "__osm_sm_mad_ctrl_process_get: " + "Posting Dispatcher message %s\n", + osm_get_disp_msg_str( msg_id ) ); + } + + status = cl_disp_post( p_ctrl->h_disp, + msg_id, + p_madw, + __osm_sm_mad_ctrl_disp_done_callback, + p_ctrl ); + + if( status != CL_SUCCESS ) + { + osm_log( p_ctrl->p_log, OSM_LOG_ERROR, + "__osm_sm_mad_ctrl_process_get: ERR 3106: " + "Dispatcher post message failed (%s)\n", + CL_STATUS_MSG( status ) ); + goto Exit; + } + } + else + { + /* + There is an unknown MAD attribute type for which there is + no recipient. Simply retire the MAD here. + */ + osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw ); + } + + Exit: + OSM_LOG_EXIT( p_ctrl->p_log ); +} +/* + * PARAMETERS + * + * RETURN VALUES + * + * NOTES + * + * SEE ALSO + *********/ + +/****f* opensm: SM/__osm_sm_mad_ctrl_process_set + * NAME + * __osm_sm_mad_ctrl_process_set + * + * DESCRIPTION + * This function handles method Set() for received MADs. + * + * SYNOPSIS + */ +static void +__osm_sm_mad_ctrl_process_set( + IN osm_sm_mad_ctrl_t* const p_ctrl, + IN osm_madw_t *p_madw ) +{ + ib_smp_t* p_smp; + cl_status_t status; + cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE; + + OSM_LOG_ENTER( p_ctrl->p_log, __osm_sm_mad_ctrl_process_set ); + + p_smp = osm_madw_get_smp_ptr( p_madw ); + + /* + Note that attr_id (like the rest of the MAD) is in + network byte order. + */ + switch( p_smp->attr_id ) + { + case IB_MAD_ATTR_SM_INFO: + msg_id = OSM_MSG_MAD_SM_INFO; + break; + + default: + osm_log( p_ctrl->p_log, OSM_LOG_ERROR, + "__osm_sm_mad_ctrl_process_set: ERR 3107: " + "Unsupported attribute = 0x%X\n", + cl_ntoh16( p_smp->attr_id ) ); + osm_dump_dr_smp( p_ctrl->p_log, p_smp, OSM_LOG_ERROR ); + break; + } + + if( msg_id != CL_DISP_MSGID_NONE ) + { + /* + Post this MAD to the dispatcher for asynchronous + processing by the appropriate controller. + */ + + if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_ctrl->p_log, OSM_LOG_DEBUG, + "__osm_sm_mad_ctrl_process_set: " + "Posting Dispatcher message %s\n", + osm_get_disp_msg_str( msg_id ) ); + } + + status = cl_disp_post( p_ctrl->h_disp, + msg_id, + p_madw, + __osm_sm_mad_ctrl_disp_done_callback, + p_ctrl ); + + if( status != CL_SUCCESS ) + { + osm_log( p_ctrl->p_log, OSM_LOG_ERROR, + "__osm_sm_mad_ctrl_process_set: ERR 3108: " + "Dispatcher post message failed (%s)\n", + CL_STATUS_MSG( status ) ); + goto Exit; + } + } + else + { + /* + There is an unknown MAD attribute type for which there is + no recipient. Simply retire the MAD here. + */ + osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw ); + } + + Exit: + OSM_LOG_EXIT( p_ctrl->p_log ); +} +/* + * PARAMETERS + * + * RETURN VALUES + * + * NOTES + * + * SEE ALSO + *********/ + +/****f* opensm: SM/__osm_sm_mad_ctrl_process_trap + * NAME + * __osm_sm_mad_ctrl_process_trap + * + * DESCRIPTION + * This function handles method Trap() for received MADs. + * + * SYNOPSIS + */ +static void +__osm_sm_mad_ctrl_process_trap( + IN osm_sm_mad_ctrl_t* const p_ctrl, + IN osm_madw_t *p_madw ) +{ + ib_smp_t* p_smp; + cl_status_t status; + cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE; + + OSM_LOG_ENTER( p_ctrl->p_log, __osm_sm_mad_ctrl_process_trap ); + + p_smp = osm_madw_get_smp_ptr( p_madw ); + + /* Make sure OpenSM is master. If not - then we should not process the trap */ + if (p_ctrl->p_subn->sm_state != IB_SMINFO_STATE_MASTER) + { + osm_log( p_ctrl->p_log, OSM_LOG_DEBUG, + "__osm_sm_mad_ctrl_process_trap: " + "Received trap but OpenSM is not in MASTER state. " + "Dropping mad\n"); + osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw ); + goto Exit; + } + + /* + Note that attr_id (like the rest of the MAD) is in + network byte order. + */ + switch( p_smp->attr_id ) + { + case IB_MAD_ATTR_NOTICE: + msg_id = OSM_MSG_MAD_NOTICE; + break; + + default: + osm_log( p_ctrl->p_log, OSM_LOG_ERROR, + "__osm_sm_mad_ctrl_process_trap: ERR 3109: " + "Unsupported attribute = 0x%X\n", + cl_ntoh16( p_smp->attr_id ) ); + osm_dump_dr_smp( p_ctrl->p_log, p_smp, OSM_LOG_ERROR ); + break; + } + + if( msg_id != CL_DISP_MSGID_NONE ) + { + /* + Post this MAD to the dispatcher for asynchronous + processing by the appropriate controller. + */ + + if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_ctrl->p_log, OSM_LOG_DEBUG, + "__osm_sm_mad_ctrl_process_trap: " + "Posting Dispatcher message %s\n", + osm_get_disp_msg_str( msg_id ) ); + } + + status = cl_disp_post( p_ctrl->h_disp, + msg_id, + p_madw, + __osm_sm_mad_ctrl_disp_done_callback, + p_ctrl ); + + if( status != CL_SUCCESS ) + { + osm_log( p_ctrl->p_log, OSM_LOG_ERROR, + "__osm_sm_mad_ctrl_process_trap: ERR 3110: " + "Dispatcher post message failed (%s)\n", + CL_STATUS_MSG( status ) ); + goto Exit; + } + } + else + { + /* + There is an unknown MAD attribute type for which there is + no recipient. Simply retire the MAD here. + */ + osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw ); + } + + Exit: + OSM_LOG_EXIT( p_ctrl->p_log ); +} +/* + * PARAMETERS + * + * RETURN VALUES + * + * NOTES + * + * SEE ALSO + *********/ + +/****f* opensm: SM/__osm_sm_mad_ctrl_rcv_callback + * NAME + * __osm_sm_mad_ctrl_rcv_callback + * + * DESCRIPTION + * This is the callback from the transport layer for received MADs. + * + * SYNOPSIS + */ +void +__osm_sm_mad_ctrl_rcv_callback( + IN osm_madw_t *p_madw, + IN void *bind_context, + IN osm_madw_t *p_req_madw ) +{ + osm_sm_mad_ctrl_t* p_ctrl = (osm_sm_mad_ctrl_t*)bind_context; + ib_smp_t* p_smp; + ib_net16_t status; + + OSM_LOG_ENTER( p_ctrl->p_log, __osm_sm_mad_ctrl_rcv_callback ); + + CL_ASSERT( p_madw ); + + /* + A MAD was received from the wire, possibly in response to a request. + */ + cl_atomic_inc( &p_ctrl->p_stats->qp0_mads_rcvd ); + + if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_ctrl->p_log, OSM_LOG_DEBUG, + "__osm_sm_mad_ctrl_rcv_callback: " + "%u QP0 MADs received\n", + p_ctrl->p_stats->qp0_mads_rcvd ); + } + + p_smp = osm_madw_get_smp_ptr( p_madw ); + + /* if we are closing down simply do nothing */ + if (osm_exit_flag) + { + osm_log( p_ctrl->p_log, OSM_LOG_ERROR, + "__osm_sm_mad_ctrl_rcv_callback: " + "Ignoring received mad - since we are exiting\n"); + + osm_dump_dr_smp( p_ctrl->p_log, p_smp, OSM_LOG_DEBUG ); + + /* retire the mad or put it back */ + if( ib_smp_is_response( p_smp ) || + (p_smp->method == IB_MAD_METHOD_TRAP_REPRESS)) + { + CL_ASSERT( p_madw->resp_expected == FALSE ); + __osm_sm_mad_ctrl_retire_trans_mad( p_ctrl, p_madw ); + } + else + { + if( p_madw->resp_expected == TRUE ) + __osm_sm_mad_ctrl_retire_trans_mad( p_ctrl, p_madw ); + else + osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw ); + } + + goto Exit; + } + + if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_FRAMES ) ) + osm_dump_dr_smp( p_ctrl->p_log, p_smp, OSM_LOG_FRAMES ); + + if( p_smp->mgmt_class == IB_MCLASS_SUBN_DIR ) + { + status = ib_smp_get_status( p_smp ); + } + else + { + status = p_smp->status; + } + + if( status != 0 ) + { + osm_log( p_ctrl->p_log, OSM_LOG_ERROR, + "__osm_sm_mad_ctrl_rcv_callback: ERR 3111: " + "Error status = 0x%X\n", status ); + osm_dump_dr_smp( p_ctrl->p_log, p_smp, OSM_LOG_ERROR ); + } + + switch( p_smp->method ) + { + case IB_MAD_METHOD_GET_RESP: + CL_ASSERT( p_req_madw != NULL ); + __osm_sm_mad_ctrl_process_get_resp( p_ctrl, p_madw, p_req_madw ); + break; + + case IB_MAD_METHOD_GET: + CL_ASSERT( p_req_madw == NULL ); + __osm_sm_mad_ctrl_process_get( p_ctrl, p_madw ); + break; + + case IB_MAD_METHOD_TRAP: + CL_ASSERT( p_req_madw == NULL ); + __osm_sm_mad_ctrl_process_trap( p_ctrl, p_madw ); + break; + + case IB_MAD_METHOD_SET: + CL_ASSERT( p_req_madw == NULL ); + __osm_sm_mad_ctrl_process_set( p_ctrl, p_madw ); + break; + + case IB_MAD_METHOD_SEND: + case IB_MAD_METHOD_REPORT: + case IB_MAD_METHOD_REPORT_RESP: + case IB_MAD_METHOD_TRAP_REPRESS: + default: + osm_log( p_ctrl->p_log, OSM_LOG_ERROR, + "__osm_sm_mad_ctrl_rcv_callback: ERR 3112: " + "Unsupported method = 0x%X\n", p_smp->method ); + osm_dump_dr_smp( p_ctrl->p_log, p_smp, OSM_LOG_ERROR ); + osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw ); + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_ctrl->p_log ); +} +/* + * PARAMETERS + * + * RETURN VALUES + * + * NOTES + * + * SEE ALSO + *********/ + +/****f* opensm: SM/__osm_sm_mad_ctrl_send_err_cb + * NAME + * __osm_sm_mad_ctrl_send_err_cb + * + * DESCRIPTION + * This is the callback from the transport layer for send errors + * on MADs that were expecting a response. + * + * SYNOPSIS + */ +void +__osm_sm_mad_ctrl_send_err_cb( + IN void *bind_context, + IN osm_madw_t *p_madw ) +{ + osm_sm_mad_ctrl_t* p_ctrl = (osm_sm_mad_ctrl_t*)bind_context; +#if 0 + osm_physp_t* p_physp; +#endif + ib_api_status_t status; + ib_smp_t* p_smp; + + OSM_LOG_ENTER( p_ctrl->p_log, __osm_sm_mad_ctrl_send_err_cb ); + + CL_ASSERT( p_madw ); + + osm_log( p_ctrl->p_log, OSM_LOG_ERROR, + "__osm_sm_mad_ctrl_send_err_cb: ERR 3113: " + "MAD completed in error (%s)\n", + ib_get_err_str( p_madw->status ) ); + + /* + If this was a SubnSet MAD, then this error might indicate a problem + in configuring the subnet. In this case - need to mark that there was + such a problem. The subnet will not be up, and the next sweep should + be a heavy sweep as well. + */ + p_smp = osm_madw_get_smp_ptr( p_madw ); + if (p_smp->method == IB_MAD_METHOD_SET && + ( p_smp->attr_id == IB_MAD_ATTR_PORT_INFO || + p_smp->attr_id == IB_MAD_ATTR_MCAST_FWD_TBL || + p_smp->attr_id == IB_MAD_ATTR_SWITCH_INFO || + p_smp->attr_id == IB_MAD_ATTR_LIN_FWD_TBL ) ) + { + osm_log( p_ctrl->p_log, OSM_LOG_ERROR, + "__osm_sm_mad_ctrl_send_err_cb: ERR 3119: " + "Set method failed\n" ); + p_ctrl->p_subn->subnet_initialization_error = TRUE; + } + + /* + Since we did not get any response we suspect the DR path + used for the target port. + Find it and replace it with an alternate path. + This is true only if the destination lid is not 0xFFFF, since + then we are aiming for a specific path and not specific destination + lid. + */ + /* For now - do not add the alternate dr path to the release */ +#if 0 + if ( p_madw->mad_addr.dest_lid != 0xFFFF ) + { + p_physp = + osm_get_physp_by_mad_addr(p_ctrl->p_log, + p_ctrl->p_subn, + &(p_madw->mad_addr)); + if (!p_physp) + { + osm_log( p_ctrl->p_log, OSM_LOG_ERROR, + "__osm_sm_mad_ctrl_send_err_cb: ERR 3114: " + "Failed to find the corresponding phys port\n"); + } + else + { + osm_physp_replace_dr_path_with_alternate_dr_path( + p_ctrl->p_log, p_ctrl->p_subn, p_physp, p_madw->h_bind ); + } + } +#endif + + /* + An error occurred. No response was received to a request MAD. + Retire the original request MAD. + */ + + osm_dump_dr_smp( p_ctrl->p_log, osm_madw_get_smp_ptr( p_madw ), + OSM_LOG_ERROR ); + + __osm_sm_mad_ctrl_update_wire_stats( p_ctrl ); + + if( osm_madw_get_err_msg( p_madw ) != CL_DISP_MSGID_NONE ) + { + if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_ctrl->p_log, OSM_LOG_DEBUG, + "__osm_sm_mad_ctrl_send_err_cb: " + "Posting Dispatcher message %s\n", + osm_get_disp_msg_str( osm_madw_get_err_msg( p_madw ) ) ); + } + + status = cl_disp_post( p_ctrl->h_disp, + osm_madw_get_err_msg( p_madw ), + p_madw, + __osm_sm_mad_ctrl_disp_done_callback, + p_ctrl ); + if( status != CL_SUCCESS ) + { + osm_log( p_ctrl->p_log, OSM_LOG_ERROR, + "__osm_sm_mad_ctrl_send_err_cb: ERR 3115: " + "Dispatcher post message failed (%s)\n", + CL_STATUS_MSG( status ) ); + } + } + else + { + /* + No error message was provided, just retire the MAD. + */ + __osm_sm_mad_ctrl_retire_trans_mad( p_ctrl, p_madw ); + } + + OSM_LOG_EXIT( p_ctrl->p_log ); +} +/* + * PARAMETERS + * + * RETURN VALUES + * + * NOTES + * + * SEE ALSO + *********/ + +/********************************************************************** + **********************************************************************/ +void +osm_sm_mad_ctrl_construct( + IN osm_sm_mad_ctrl_t* const p_ctrl ) +{ + CL_ASSERT( p_ctrl ); + memset( p_ctrl, 0, sizeof(*p_ctrl) ); + p_ctrl->h_disp = CL_DISP_INVALID_HANDLE; +} + +/********************************************************************** + **********************************************************************/ +void +osm_sm_mad_ctrl_destroy( + IN osm_sm_mad_ctrl_t* const p_ctrl ) +{ + CL_ASSERT( p_ctrl ); + + if (p_ctrl->h_bind != CL_DISP_INVALID_HANDLE) + { + osm_vendor_unbind( p_ctrl->h_bind ); + } + cl_disp_unregister( p_ctrl->h_disp ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_sm_mad_ctrl_init( + IN osm_sm_mad_ctrl_t* const p_ctrl, + IN osm_subn_t* const p_subn, + IN osm_mad_pool_t* const p_mad_pool, + IN osm_vl15_t* const p_vl15, + IN osm_vendor_t* const p_vendor, + IN osm_log_t* const p_log, + IN osm_stats_t* const p_stats, + IN cl_plock_t* const p_lock, + IN cl_dispatcher_t* const p_disp ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_sm_mad_ctrl_init ); + + osm_sm_mad_ctrl_construct( p_ctrl ); + + p_ctrl->p_subn = p_subn; + p_ctrl->p_log = p_log; + p_ctrl->p_disp = p_disp; + p_ctrl->p_mad_pool = p_mad_pool; + p_ctrl->p_vendor = p_vendor; + p_ctrl->p_stats = p_stats; + p_ctrl->p_lock = p_lock; + p_ctrl->p_vl15 = p_vl15; + + p_ctrl->h_disp = cl_disp_register( + p_disp, + CL_DISP_MSGID_NONE, + NULL, + NULL ); + + if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_sm_mad_ctrl_init: ERR 3116: " + "Dispatcher registration failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_sm_mad_ctrl_bind( + IN osm_sm_mad_ctrl_t* const p_ctrl, + IN const ib_net64_t port_guid ) +{ + osm_bind_info_t bind_info; + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_ctrl->p_log, osm_sm_mad_ctrl_bind ); + + if( p_ctrl->h_bind != OSM_BIND_INVALID_HANDLE ) + { + osm_log( p_ctrl->p_log, OSM_LOG_ERROR, + "osm_sm_mad_ctrl_bind: ERR 3117: " + "Multiple binds not allowed\n" ); + status = IB_ERROR; + goto Exit; + } + + bind_info.class_version = 1; + bind_info.is_report_processor = FALSE; + bind_info.is_responder = TRUE; + bind_info.is_trap_processor = TRUE; + bind_info.mad_class = IB_MCLASS_SUBN_DIR; + bind_info.port_guid = port_guid; + bind_info.recv_q_size = OSM_SM_DEFAULT_QP0_RCV_SIZE; + bind_info.send_q_size = OSM_SM_DEFAULT_QP0_SEND_SIZE; + + osm_log( p_ctrl->p_log, OSM_LOG_VERBOSE, + "osm_sm_mad_ctrl_bind: " + "Binding to port 0x%" PRIx64 "\n", + cl_ntoh64( port_guid ) ); + + p_ctrl->h_bind = osm_vendor_bind( p_ctrl->p_vendor, + &bind_info, + p_ctrl->p_mad_pool, + __osm_sm_mad_ctrl_rcv_callback, + __osm_sm_mad_ctrl_send_err_cb, + p_ctrl ); + + if( p_ctrl->h_bind == OSM_BIND_INVALID_HANDLE ) + { + status = IB_ERROR; + osm_log( p_ctrl->p_log, OSM_LOG_ERROR, + "osm_sm_mad_ctrl_bind: ERR 3118: " + "Vendor specific bind failed\n" ); + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_ctrl->p_log ); + return( status ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sm_state_mgr.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sm_state_mgr.c new file mode 100644 index 00000000..9a0b87f9 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sm_state_mgr.c @@ -0,0 +1,872 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sm_state_mgr.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_state_mgr_t. + * This file implements the SM State Manager object. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.7 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +static void +__osm_sm_state_mgr_standby_msg( + IN const osm_sm_state_mgr_t * p_sm_mgr ) +{ + osm_log( p_sm_mgr->p_log, OSM_LOG_SYS, "Entering STANDBY state\n" ); /* Format Waived */ + + if( osm_log_is_active( p_sm_mgr->p_log, OSM_LOG_VERBOSE ) ) + { + osm_log( p_sm_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_sm_state_mgr_standby_msg: " + "\n\n\n********************************" + "**********************************\n" + "******************** ENTERING SM STANDBY" + " STATE *******************\n" + "**************************************" + "****************************\n\n\n" ); + } +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_sm_state_mgr_master_msg( + IN const osm_sm_state_mgr_t * p_sm_mgr ) +{ + osm_log( p_sm_mgr->p_log, OSM_LOG_SYS, "Entering MASTER state\n" ); /* Format Waived */ + + if( osm_log_is_active( p_sm_mgr->p_log, OSM_LOG_VERBOSE ) ) + { + osm_log( p_sm_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_sm_state_mgr_master_msg: " + "\n\n\n********************************" + "**********************************\n" + "******************** ENTERING SM MASTER" + " STATE ********************\n" + "**************************************" + "****************************\n\n\n" ); + } +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_sm_state_mgr_discovering_msg( + IN const osm_sm_state_mgr_t * p_sm_mgr ) +{ + if( osm_log_is_active( p_sm_mgr->p_log, OSM_LOG_VERBOSE ) ) + { + osm_log( p_sm_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_sm_state_mgr_discovering_msg: " + "\n\n\n********************************" + "**********************************\n" + "******************** ENTERING SM DISCOVERING" + " STATE ***************\n" + "**************************************" + "****************************\n\n\n" ); + } +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_sm_state_mgr_notactive_msg( + IN const osm_sm_state_mgr_t * p_sm_mgr ) +{ + if( osm_log_is_active( p_sm_mgr->p_log, OSM_LOG_VERBOSE ) ) + { + osm_log( p_sm_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_sm_state_mgr_notactive_msg: " + "\n\n\n********************************" + "**********************************\n" + "******************** ENTERING SM NOT-ACTIVE" + " STATE **********************\n" + "**************************************" + "****************************\n\n\n" ); + } +} + +#if 0 +/********************************************************************** + **********************************************************************/ +static void +__osm_sm_state_mgr_send_local_port_info_req( + IN osm_sm_state_mgr_t * p_sm_mgr ) +{ + osm_madw_context_t context; + osm_port_t *p_port; + ib_net64_t port_guid = p_sm_mgr->p_subn->sm_port_guid; + ib_api_status_t status; + + OSM_LOG_ENTER( p_sm_mgr->p_log, + __osm_sm_state_mgr_send_local_port_info_req ); + /* + * Send a query of SubnGet(PortInfo) to our own port, in order to + * update the master_sm_base_lid of the subnet. + */ + memset( &context, 0, sizeof( context ) ); + p_port = ( osm_port_t * ) cl_qmap_get( &p_sm_mgr->p_subn->port_guid_tbl, + port_guid ); + if( p_port == + ( osm_port_t * ) cl_qmap_end( &p_sm_mgr->p_subn->port_guid_tbl ) ) + { + osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR, + "__osm_sm_state_mgr_send_local_port_info_req: ERR 3205: " + "No port object for port 0x%016" PRIx64 "\n", + cl_ntoh64( port_guid ) ); + goto Exit; + } + + context.pi_context.port_guid = port_guid; + context.pi_context.node_guid = p_port->p_node->node_info.node_guid; + context.pi_context.set_method = FALSE; + context.pi_context.ignore_errors = FALSE; + /* mark the update_master_sm_base_lid with TRUE - we want to update it */ + /* with the new master lid value. */ + context.pi_context.update_master_sm_base_lid = TRUE; + context.pi_context.light_sweep = FALSE; + context.pi_context.active_transition = FALSE; + + status = osm_req_get( p_sm_mgr->p_req, + osm_physp_get_dr_path_ptr + ( osm_port_get_default_phys_ptr( p_port ) ), + IB_MAD_ATTR_PORT_INFO, + cl_hton32( p_port->default_port_num ), + CL_DISP_MSGID_NONE, &context ); + + if( status != IB_SUCCESS ) + { + osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR, + "__osm_sm_state_mgr_send_local_port_info_req: ERR 3202: " + "Failure requesting PortInfo (%s)\n", + ib_get_err_str( status ) ); + } + + Exit: + OSM_LOG_EXIT( p_sm_mgr->p_log ); +} +#endif + +/********************************************************************** + **********************************************************************/ +static void +__osm_sm_state_mgr_send_master_sm_info_req( + IN osm_sm_state_mgr_t * p_sm_mgr ) +{ + osm_madw_context_t context; + const osm_port_t *p_port; + ib_api_status_t status; + + OSM_LOG_ENTER( p_sm_mgr->p_log, + __osm_sm_state_mgr_send_master_sm_info_req ); + + memset( &context, 0, sizeof( context ) ); + if( p_sm_mgr->p_subn->sm_state == IB_SMINFO_STATE_STANDBY ) + { + /* + * We are in STANDBY state - this means we need to poll on the master + * SM (according to master_guid) + * Send a query of SubnGet(SMInfo) to the subn master_sm_base_lid object. + */ + p_port = ( osm_port_t * ) cl_qmap_get( &p_sm_mgr->p_subn->port_guid_tbl, + p_sm_mgr->master_guid ); + } + else + { + /* + * We are not in STANDBY - this means we are in MASTER state - so we need + * to poll on the SM that is saved in p_polling_sm under p_sm_mgr. + * Send a query of SubnGet(SMInfo) to that SM. + */ + p_port = p_sm_mgr->p_polling_sm->p_port; + } + if( p_port == NULL ) + { + osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR, + "__osm_sm_state_mgr_send_master_sm_info_req: ERR 3203: " + "No port object for GUID 0x%016" PRIx64 "\n", + cl_ntoh64(p_sm_mgr->master_guid) ); + goto Exit; + } + + context.smi_context.port_guid = p_port->guid; + context.smi_context.set_method = FALSE; + + status = osm_req_get( p_sm_mgr->p_req, + osm_physp_get_dr_path_ptr + ( osm_port_get_default_phys_ptr( p_port ) ), + IB_MAD_ATTR_SM_INFO, 0, CL_DISP_MSGID_NONE, + &context ); + + if( status != IB_SUCCESS ) + { + osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR, + "__osm_sm_state_mgr_send_master_sm_info_req: ERR 3204: " + "Failure rquesting SMInfo (%s)\n", ib_get_err_str( status ) ); + } + + Exit: + OSM_LOG_EXIT( p_sm_mgr->p_log ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_sm_state_mgr_start_polling( + IN osm_sm_state_mgr_t * p_sm_mgr ) +{ + uint32_t sminfo_polling_timeout = + p_sm_mgr->p_subn->opt.sminfo_polling_timeout; + cl_status_t cl_status; + + OSM_LOG_ENTER( p_sm_mgr->p_log, __osm_sm_state_mgr_start_polling ); + + /* + * Init the retry_nubmer back to zero - need to restart counting + */ + p_sm_mgr->retry_number = 0; + + /* + * Send a SubnGet(SMInfo) query to the current (or new) master found. + */ + __osm_sm_state_mgr_send_master_sm_info_req( p_sm_mgr ); + + /* + * Start a timer that will wake up every sminfo_polling_timeout milliseconds. + * The callback of the timer will send a SubnGet(SMInfo) to the Master SM + * and restart the timer + */ + cl_status = cl_timer_start( &p_sm_mgr->polling_timer, + sminfo_polling_timeout ); + if( cl_status != CL_SUCCESS ) + { + osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR, + "__osm_sm_state_mgr_start_polling : ERR 3210: " + "Failed to start timer\n" ); + } + + OSM_LOG_EXIT( p_sm_mgr->p_log ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_sm_state_mgr_polling_callback( + IN void *context ) +{ + osm_sm_state_mgr_t *p_sm_mgr = ( osm_sm_state_mgr_t * ) context; + uint32_t sminfo_polling_timeout = + p_sm_mgr->p_subn->opt.sminfo_polling_timeout; + cl_status_t cl_status; + + OSM_LOG_ENTER( p_sm_mgr->p_log, __osm_sm_state_mgr_polling_callback ); + + /* + * We can be here in one of two cases: + * 1. We are a STANDBY sm polling on the master SM. + * 2. We are a MASTER sm, waiting for a handover from a remote master sm. + * If we are not in one of these cases - don't need to restart the poller. + */ + if( !( ( p_sm_mgr->p_subn->sm_state == IB_SMINFO_STATE_MASTER && + p_sm_mgr->p_polling_sm != NULL ) || + ( p_sm_mgr->p_subn->sm_state == IB_SMINFO_STATE_STANDBY ) ) ) + { + goto Exit; + } + + /* + * If we are a STANDBY sm and the osm_exit_flag is 1, then let's signal + * the subnet_up. This is relevant for the case of running only once. In that + * case - the program is stuck until this signal is received. In other + * cases - it is not relevant whether or not the signal is on - since we are + * currently in exit flow + */ + if( p_sm_mgr->p_subn->sm_state == IB_SMINFO_STATE_STANDBY && + osm_exit_flag == 1 ) + { + osm_log( p_sm_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_sm_state_mgr_polling_callback : " + "Signalling subnet_up_event\n" ); + cl_event_signal( p_sm_mgr->p_state_mgr->p_subnet_up_event ); + goto Exit; + } + + /* + * Incr the retry number. + * If it reached the max_retry_number in the subnet opt - call + * osm_sm_state_mgr_process with signal OSM_SM_SIGNAL_POLLING_TIMEOUT + */ + p_sm_mgr->retry_number++; + osm_log( p_sm_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_sm_state_mgr_polling_callback : " + "Retry number:%d\n", p_sm_mgr->retry_number ); + + if( p_sm_mgr->retry_number >= p_sm_mgr->p_subn->opt.polling_retry_number ) + { + osm_log( p_sm_mgr->p_log, OSM_LOG_DEBUG, + "__osm_sm_state_mgr_polling_callback : " + "Reached polling_retry_number value in retry_number. " + "Go to DISCOVERY state\n" ); + osm_sm_state_mgr_process( p_sm_mgr, OSM_SM_SIGNAL_POLLING_TIMEOUT ); + goto Exit; + } + + /* Send a SubnGet(SMInfo) request to the remote sm (depends on our state) */ + __osm_sm_state_mgr_send_master_sm_info_req( p_sm_mgr ); + + /* restart the timer */ + cl_status = cl_timer_start( &p_sm_mgr->polling_timer, + sminfo_polling_timeout ); + if( cl_status != CL_SUCCESS ) + { + osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR, + "__osm_sm_state_mgr_polling_callback : ERR 3211: " + "Failed to restart timer\n" ); + } + + Exit: + OSM_LOG_EXIT( p_sm_mgr->p_log ); + return; +} + +/********************************************************************** + **********************************************************************/ +void +osm_sm_state_mgr_construct( + IN osm_sm_state_mgr_t * const p_sm_mgr ) +{ + memset( p_sm_mgr, 0, sizeof( *p_sm_mgr ) ); + cl_spinlock_construct( &p_sm_mgr->state_lock ); + cl_timer_construct( &p_sm_mgr->polling_timer ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_sm_state_mgr_destroy( + IN osm_sm_state_mgr_t * const p_sm_mgr ) +{ + CL_ASSERT( p_sm_mgr ); + + OSM_LOG_ENTER( p_sm_mgr->p_log, osm_sm_state_mgr_destroy ); + + cl_spinlock_destroy( &p_sm_mgr->state_lock ); + cl_timer_destroy( &p_sm_mgr->polling_timer ); + + OSM_LOG_EXIT( p_sm_mgr->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_sm_state_mgr_init( + IN osm_sm_state_mgr_t * const p_sm_mgr, + IN osm_state_mgr_t * const p_state_mgr, + IN osm_subn_t * const p_subn, + IN osm_req_t * const p_req, + IN osm_log_t * const p_log ) +{ + cl_status_t status; + + OSM_LOG_ENTER( p_log, osm_sm_state_mgr_init ); + + CL_ASSERT( p_subn ); + CL_ASSERT( p_state_mgr ); + CL_ASSERT( p_req ); + + osm_sm_state_mgr_construct( p_sm_mgr ); + + p_sm_mgr->p_log = p_log; + p_sm_mgr->p_req = p_req; + p_sm_mgr->p_subn = p_subn; + p_sm_mgr->p_state_mgr = p_state_mgr; + + /* init the state of the SM to idle */ + p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_INIT; + + status = cl_spinlock_init( &p_sm_mgr->state_lock ); + if( status != CL_SUCCESS ) + { + osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR, + "osm_sm_state_mgr_init: ERR 3201: " + "Spinlock init failed (%s)\n", CL_STATUS_MSG( status ) ); + } + + status = cl_timer_init( &p_sm_mgr->polling_timer, + __osm_sm_state_mgr_polling_callback, p_sm_mgr ); + + if( status != CL_SUCCESS ) + { + osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR, + "osm_sm_state_mgr_init: ERR 3206: " + "Timer init failed (%s)\n", CL_STATUS_MSG( status ) ); + } + + OSM_LOG_EXIT( p_sm_mgr->p_log ); + return ( status ); +} + +/********************************************************************** + **********************************************************************/ +void +__osm_sm_state_mgr_signal_error( + IN const osm_sm_state_mgr_t * const p_sm_mgr, + IN const osm_sm_signal_t signal ) +{ + osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR, + "__osm_sm_state_mgr_signal_error: ERR 3207: " + "Invalid signal %s in state %s\n", + osm_get_sm_mgr_signal_str( signal ), + osm_get_sm_mgr_state_str( p_sm_mgr->p_subn->sm_state ) ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_sm_state_mgr_signal_master_is_alive( + IN osm_sm_state_mgr_t * const p_sm_mgr ) +{ + OSM_LOG_ENTER( p_sm_mgr->p_log, osm_sm_state_mgr_signal_master_is_alive ); + p_sm_mgr->retry_number = 0; + OSM_LOG_EXIT( p_sm_mgr->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_sm_state_mgr_process( + IN osm_sm_state_mgr_t * const p_sm_mgr, + IN osm_sm_signal_t signal ) +{ + ib_api_status_t status = IB_SUCCESS; + + CL_ASSERT( p_sm_mgr ); + + OSM_LOG_ENTER( p_sm_mgr->p_log, osm_sm_state_mgr_process ); + + /* + * The state lock prevents many race conditions from screwing + * up the state transition process. + */ + cl_spinlock_acquire( &p_sm_mgr->state_lock ); + + if( osm_log_is_active( p_sm_mgr->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_sm_mgr->p_log, OSM_LOG_DEBUG, + "osm_sm_state_mgr_process: " + "Received signal %s in state %s\n", + osm_get_sm_mgr_signal_str( signal ), + osm_get_sm_mgr_state_str( p_sm_mgr->p_subn->sm_state ) ); + } + + switch ( p_sm_mgr->p_subn->sm_state ) + { + case IB_SMINFO_STATE_INIT: + switch ( signal ) + { + case OSM_SM_SIGNAL_INIT: + /* + * Update the state of the SM to DISCOVERING + */ + __osm_sm_state_mgr_discovering_msg( p_sm_mgr ); + p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_DISCOVERING; + break; + + default: + __osm_sm_state_mgr_signal_error( p_sm_mgr, signal ); + status = IB_INVALID_PARAMETER; + break; + } + break; + + case IB_SMINFO_STATE_DISCOVERING: + switch ( signal ) + { + case OSM_SM_SIGNAL_DISCOVERY_COMPLETED: + /* + * Update the state of the SM to MASTER + */ + __osm_sm_state_mgr_master_msg( p_sm_mgr ); + /* Turn on the moved_to_master_state flag */ + p_sm_mgr->p_subn->moved_to_master_state = TRUE; + /* Turn on the first_time_master_sweep flag */ + if( p_sm_mgr->p_subn->first_time_master_sweep == FALSE ) + p_sm_mgr->p_subn->first_time_master_sweep = TRUE; + + p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_MASTER; + /* + * Make sure to set the subnet master_sm_base_lid + * to the sm_base_lid value + */ + p_sm_mgr->p_subn->master_sm_base_lid = p_sm_mgr->p_subn->sm_base_lid; + break; + case OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED: + /* + * Stop the discovering + */ + osm_state_mgr_process( p_sm_mgr->p_state_mgr, + OSM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED ); + break; + case OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED_DONE: + /* + * Finished all discovery actions - move to STANDBY + * start the polling + */ + __osm_sm_state_mgr_standby_msg( p_sm_mgr ); + p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_STANDBY; + /* + * Since another SM is doing the LFT config - we should not + * ignore the results of it + */ + p_sm_mgr->p_subn->ignore_existing_lfts = FALSE; + + __osm_sm_state_mgr_start_polling( p_sm_mgr ); + break; + case OSM_SM_SIGNAL_HANDOVER: + /* + * Do nothing. We will discover it later on. If we already discovered + * this SM, and got the HANDOVER - this means the remote SM is of + * lower priority. In this case we will stop polling it (since it is + * a lower priority SM in STANDBY state). + */ + break; + default: + __osm_sm_state_mgr_signal_error( p_sm_mgr, signal ); + status = IB_INVALID_PARAMETER; + break; + } + break; + + case IB_SMINFO_STATE_STANDBY: + switch ( signal ) + { + case OSM_SM_SIGNAL_POLLING_TIMEOUT: + case OSM_SM_SIGNAL_DISCOVER: + /* + * case 1: Polling timeout occured - this means that the Master SM + * no longer alive. + * case 2: Got a signal to move to DISCOVERING + * Move to DISCOVERING state, and start sweeping + */ + __osm_sm_state_mgr_discovering_msg( p_sm_mgr ); + p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_DISCOVERING; + p_sm_mgr->p_subn->coming_out_of_standby = TRUE; + osm_state_mgr_process( p_sm_mgr->p_state_mgr, OSM_SIGNAL_EXIT_STBY ); + break; + case OSM_SM_SIGNAL_DISABLE: + /* + * Update the state to NOT_ACTIVE + */ + __osm_sm_state_mgr_notactive_msg( p_sm_mgr ); + p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_NOTACTIVE; + break; + case OSM_SM_SIGNAL_HANDOVER: + /* + * Update state to MASTER, and start sweeping + * OPTIONAL: send ACKNOWLEDGE + */ + __osm_sm_state_mgr_master_msg( p_sm_mgr ); + /* Turn on the moved_to_master_state flag */ + p_sm_mgr->p_subn->moved_to_master_state = TRUE; + /* Turn on the first_time_master_sweep flag */ + if( p_sm_mgr->p_subn->first_time_master_sweep == FALSE ) + p_sm_mgr->p_subn->first_time_master_sweep = TRUE; + /* Turn on the force_immediate_heavy_sweep - we want a + * heavy sweep to occur on the first sweep of this SM. */ + p_sm_mgr->p_subn->force_immediate_heavy_sweep = TRUE; + + p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_MASTER; + /* + * Make sure to set the subnet master_sm_base_lid + * to the sm_base_lid value + */ + p_sm_mgr->p_subn->master_sm_base_lid = p_sm_mgr->p_subn->sm_base_lid; + p_sm_mgr->p_subn->coming_out_of_standby = TRUE; + osm_state_mgr_process( p_sm_mgr->p_state_mgr, OSM_SIGNAL_EXIT_STBY ); + break; + case OSM_SM_SIGNAL_ACKNOWLEDGE: + /* + * Do nothing - already moved to STANDBY + */ + break; + default: + __osm_sm_state_mgr_signal_error( p_sm_mgr, signal ); + status = IB_INVALID_PARAMETER; + break; + } + break; + + case IB_SMINFO_STATE_NOTACTIVE: + switch ( signal ) + { + case OSM_SM_SIGNAL_STANDBY: + /* + * Update the state to STANDBY + * start the polling + */ + __osm_sm_state_mgr_standby_msg( p_sm_mgr ); + p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_STANDBY; + __osm_sm_state_mgr_start_polling( p_sm_mgr ); + break; + default: + __osm_sm_state_mgr_signal_error( p_sm_mgr, signal ); + status = IB_INVALID_PARAMETER; + break; + } + break; + + case IB_SMINFO_STATE_MASTER: + switch ( signal ) + { + case OSM_SM_SIGNAL_POLLING_TIMEOUT: + /* + * we received a polling timeout - this means that we waited for + * a remote master sm to send us a handover, but didn't get it, and + * didn't get a response from that remote sm. + * We want to force a heavy sweep - hopefully this occurred because + * the remote sm died, and we'll find this out and configure the + * subnet after a heavy sweep. + * We also want to clear the p_polling_sm object - since we are + * done polling on that remote sm - we are sweeping again. + */ + case OSM_SM_SIGNAL_HANDOVER: + /* + * If we received a handover in a master state - then we want to + * force a heavy sweep. This means that either we are in a sweep + * currently - in this case - no change, or we are in idle state - + * since we recognized a master SM before - so we want to make a + * heavy sweep and reconfigure the new subnet. + * We also want to clear the p_polling_sm object - since we are + * done polling on that remote sm - we got a handover from it. + */ + osm_log( p_sm_mgr->p_log, OSM_LOG_VERBOSE, + "osm_sm_state_mgr_process: " + "Forcing immediate heavy sweep. " + "Received OSM_SM_SIGNAL_HANDOVER or OSM_SM_SIGNAL_POLLING_TIMEOUT\n" ); + p_sm_mgr->p_polling_sm = NULL; + p_sm_mgr->p_subn->force_immediate_heavy_sweep = TRUE; + osm_state_mgr_process( p_sm_mgr->p_state_mgr, OSM_SIGNAL_SWEEP ); + break; + case OSM_SM_SIGNAL_HANDOVER_SENT: + /* + * Just sent a HANDOVER signal - move to STANDBY + * start the polling + */ + __osm_sm_state_mgr_standby_msg( p_sm_mgr ); + p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_STANDBY; + __osm_sm_state_mgr_start_polling( p_sm_mgr ); + break; + case OSM_SM_SIGNAL_WAIT_FOR_HANDOVER: + /* + * We found a remote master SM, and we are waiting for it + * to handover the mastership to us. Need to start polling + * on that SM, to make sure it is alive, if it isn't - then + * we should move back to discovering, since something must + * have happened to it. + */ + __osm_sm_state_mgr_start_polling( p_sm_mgr ); + break; + case OSM_SM_SIGNAL_DISCOVER: + __osm_sm_state_mgr_discovering_msg( p_sm_mgr ); + p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_DISCOVERING; + break; + default: + __osm_sm_state_mgr_signal_error( p_sm_mgr, signal ); + status = IB_INVALID_PARAMETER; + break; + } + break; + + default: + osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR, + "osm_sm_state_mgr_process: ERR 3208: " + "Invalid state %s\n", + osm_get_sm_mgr_state_str( p_sm_mgr->p_subn->sm_state ) ); + + } + + cl_spinlock_release( &p_sm_mgr->state_lock ); + + OSM_LOG_EXIT( p_sm_mgr->p_log ); + return ( status ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_sm_state_mgr_check_legality( + IN osm_sm_state_mgr_t * const p_sm_mgr, + IN osm_sm_signal_t signal ) +{ + ib_api_status_t status = IB_SUCCESS; + + CL_ASSERT( p_sm_mgr ); + + OSM_LOG_ENTER( p_sm_mgr->p_log, osm_sm_state_mgr_check_legality ); + + /* + * The state lock prevents many race conditions from screwing + * up the state transition process. + */ + cl_spinlock_acquire( &p_sm_mgr->state_lock ); + + if( osm_log_is_active( p_sm_mgr->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_sm_mgr->p_log, OSM_LOG_DEBUG, + "osm_sm_state_mgr_check_legality: " + "Received signal %s in state %s\n", + osm_get_sm_mgr_signal_str( signal ), + osm_get_sm_mgr_state_str( p_sm_mgr->p_subn->sm_state ) ); + } + + switch ( p_sm_mgr->p_subn->sm_state ) + { + case IB_SMINFO_STATE_INIT: + switch ( signal ) + { + case OSM_SM_SIGNAL_INIT: + status = IB_SUCCESS; + break; + default: + __osm_sm_state_mgr_signal_error( p_sm_mgr, signal ); + status = IB_INVALID_PARAMETER; + break; + } + break; + + case IB_SMINFO_STATE_DISCOVERING: + switch ( signal ) + { + case OSM_SM_SIGNAL_DISCOVERY_COMPLETED: + case OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED: + case OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED_DONE: + case OSM_SM_SIGNAL_HANDOVER: + status = IB_SUCCESS; + break; + default: + __osm_sm_state_mgr_signal_error( p_sm_mgr, signal ); + status = IB_INVALID_PARAMETER; + break; + } + break; + + case IB_SMINFO_STATE_STANDBY: + switch ( signal ) + { + case OSM_SM_SIGNAL_POLLING_TIMEOUT: + case OSM_SM_SIGNAL_DISCOVER: + case OSM_SM_SIGNAL_DISABLE: + case OSM_SM_SIGNAL_HANDOVER: + case OSM_SM_SIGNAL_ACKNOWLEDGE: + status = IB_SUCCESS; + break; + default: + __osm_sm_state_mgr_signal_error( p_sm_mgr, signal ); + status = IB_INVALID_PARAMETER; + break; + } + break; + + case IB_SMINFO_STATE_NOTACTIVE: + switch ( signal ) + { + case OSM_SM_SIGNAL_STANDBY: + status = IB_SUCCESS; + break; + default: + __osm_sm_state_mgr_signal_error( p_sm_mgr, signal ); + status = IB_INVALID_PARAMETER; + break; + } + break; + + case IB_SMINFO_STATE_MASTER: + switch ( signal ) + { + case OSM_SM_SIGNAL_HANDOVER: + case OSM_SM_SIGNAL_HANDOVER_SENT: + status = IB_SUCCESS; + break; + default: + __osm_sm_state_mgr_signal_error( p_sm_mgr, signal ); + status = IB_INVALID_PARAMETER; + break; + } + break; + + default: + osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR, + "osm_sm_state_mgr_check_legality: ERR 3209: " + "Invalid state %s\n", + osm_get_sm_mgr_state_str( p_sm_mgr->p_subn->sm_state ) ); + status = IB_INVALID_PARAMETER; + + } + + cl_spinlock_release( &p_sm_mgr->state_lock ); + + OSM_LOG_EXIT( p_sm_mgr->p_log ); + return ( status ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sminfo_rcv.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sminfo_rcv.c new file mode 100644 index 00000000..646ff1ba --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sminfo_rcv.c @@ -0,0 +1,768 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sminfo_rcv.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Implementation of osm_sminfo_rcv_t. + * This object represents the SMInfo Receiver object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.6 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +osm_sminfo_rcv_construct( + IN osm_sminfo_rcv_t* const p_rcv ) +{ + memset( p_rcv, 0, sizeof(*p_rcv) ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_sminfo_rcv_destroy( + IN osm_sminfo_rcv_t* const p_rcv ) +{ + CL_ASSERT( p_rcv ); + + OSM_LOG_ENTER( p_rcv->p_log, osm_sminfo_rcv_destroy ); + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_sminfo_rcv_init( + IN osm_sminfo_rcv_t* const p_rcv, + IN osm_subn_t* const p_subn, + IN osm_stats_t* const p_stats, + IN osm_resp_t* const p_resp, + IN osm_log_t* const p_log, + IN osm_state_mgr_t* const p_state_mgr, + IN osm_sm_state_mgr_t* const p_sm_state_mgr, + IN cl_plock_t* const p_lock ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_sminfo_rcv_init ); + + osm_sminfo_rcv_construct( p_rcv ); + + p_rcv->p_log = p_log; + p_rcv->p_subn = p_subn; + p_rcv->p_lock = p_lock; + p_rcv->p_stats = p_stats; + p_rcv->p_resp = p_resp; + p_rcv->p_state_mgr = p_state_mgr; + p_rcv->p_sm_state_mgr = p_sm_state_mgr; + + OSM_LOG_EXIT( p_rcv->p_log ); + return( status ); +} + +/********************************************************************** + Return TRUE if the remote sm given (by ib_sm_info_t) is higher, + return FALSE otherwise. + By higher - we mean: SM with higher priority or with same priority + and lower GUID. +**********************************************************************/ +static inline boolean_t +__osm_sminfo_rcv_remote_sm_is_higher( + IN const osm_sminfo_rcv_t* p_rcv, + IN const ib_sm_info_t* p_remote_sm ) +{ + + return( osm_sm_is_greater_than( ib_sminfo_get_priority( p_remote_sm ), + p_remote_sm->guid, + p_rcv->p_subn->opt.sm_priority, + p_rcv->p_subn->sm_port_guid) ); + +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_sminfo_rcv_process_get_request( + IN const osm_sminfo_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ) +{ + uint8_t payload[IB_SMP_DATA_SIZE]; + ib_smp_t* p_smp; + ib_sm_info_t* p_smi = (ib_sm_info_t*)payload; + ib_api_status_t status; + ib_sm_info_t* p_remote_smi; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_sminfo_rcv_process_get_request ); + + CL_ASSERT( p_madw ); + + /* + No real need to grab the lock for this function. + */ + memset( payload, 0, sizeof( payload ) ); + + p_smp = osm_madw_get_smp_ptr( p_madw ); + + CL_ASSERT( p_smp->method == IB_MAD_METHOD_GET ); + + p_smi->guid = p_rcv->p_subn->sm_port_guid; + p_smi->act_count = cl_hton32( p_rcv->p_stats->qp0_mads_sent ); + p_smi->pri_state = (uint8_t)(p_rcv->p_subn->sm_state | + p_rcv->p_subn->opt.sm_priority << 4); + /* + p.750 row 11 - Return 0 for the SM key unless we authenticate the + requester as the master SM. + */ + p_remote_smi = ib_smp_get_payload_ptr ( osm_madw_get_smp_ptr (p_madw) ); + if (ib_sminfo_get_state( p_remote_smi ) == IB_SMINFO_STATE_MASTER ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_sminfo_rcv_process_get_request: " + "Responding to master SM with real sm_key\n" ); + p_smi->sm_key = p_rcv->p_subn->opt.sm_key; + } + else + { + /* The requester is not authenticated as master - set sm_key to zero. */ + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_sminfo_rcv_process_get_request: " + "Responding to SM not master with zero sm_key\n" ); + p_smi->sm_key = 0; + } + + status = osm_resp_send( p_rcv->p_resp, p_madw, 0, payload ); + if( status != IB_SUCCESS ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_sminfo_rcv_process_get_request: ERR 2F02: " + "Error sending response (%s)\n", + ib_get_err_str( status ) ); + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + * Check if the p_smp received is legal. + * Current checks: + * MADHeader:AttributeModifiers of ACKNOWLEDGE that was not sent by a + * Standby SM. + * MADHeader:AttributeModifiers of HANDOVER/DISABLE/STANDBY/DISCOVER + * that was not sent by a Master SM. + * FUTURE - TO DO: + * Check that the SM_Key is matching. + **********************************************************************/ +static ib_api_status_t +__osm_sminfo_rcv_check_set_req_legality( + IN const ib_smp_t* const p_smp ) +{ + ib_sm_info_t* p_smi; + + p_smi = ib_smp_get_payload_ptr( p_smp ); + + if (p_smp->attr_mod == IB_SMINFO_ATTR_MOD_ACKNOWLEDGE) + { + if ( ib_sminfo_get_state( p_smi ) == IB_SMINFO_STATE_STANDBY ) + { + return( IB_SUCCESS ); + } + } + else if ( p_smp->attr_mod == IB_SMINFO_ATTR_MOD_HANDOVER || + p_smp->attr_mod == IB_SMINFO_ATTR_MOD_DISABLE || + p_smp->attr_mod == IB_SMINFO_ATTR_MOD_STANDBY || + p_smp->attr_mod == IB_SMINFO_ATTR_MOD_DISCOVER ) + { + if ( ib_sminfo_get_state( p_smi ) == IB_SMINFO_STATE_MASTER ) + { + return( IB_SUCCESS ); + } + } + + return( IB_INVALID_PARAMETER ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_sminfo_rcv_process_set_request( + IN const osm_sminfo_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ) +{ + uint8_t payload[IB_SMP_DATA_SIZE]; + ib_smp_t* p_smp; + ib_sm_info_t* p_smi = (ib_sm_info_t*)payload; + ib_sm_info_t* p_rcv_smi; + ib_api_status_t status; + osm_sm_signal_t sm_signal; + ib_sm_info_t* p_remote_smi; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_sminfo_rcv_process_set_request ); + + CL_ASSERT( p_madw ); + + /* + No real need to grab the lock for this function. + */ + memset( payload, 0, sizeof( payload ) ); + + /* get the lock */ + CL_PLOCK_EXCL_ACQUIRE( p_rcv->p_lock ); + + p_smp = osm_madw_get_smp_ptr( p_madw ); + p_rcv_smi = ib_smp_get_payload_ptr( p_smp ); + + if( p_smp->method != IB_MAD_METHOD_SET ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_sminfo_rcv_process_set_request: ERR 2F03: " + "Unsupported method 0x%X\n", + p_smp->method ); + CL_PLOCK_RELEASE( p_rcv->p_lock ); + goto Exit; + } + + p_smi->guid = p_rcv->p_subn->sm_port_guid; + p_smi->act_count = cl_hton32( p_rcv->p_stats->qp0_mads_sent ); + p_smi->pri_state = (uint8_t)(p_rcv->p_subn->sm_state | + p_rcv->p_subn->opt.sm_priority << 4); + /* + p.750 row 11 - Return 0 for the SM key unless we authenticate the + requester as the master SM. + */ + p_remote_smi = ib_smp_get_payload_ptr ( osm_madw_get_smp_ptr (p_madw) ); + if (ib_sminfo_get_state( p_remote_smi ) == IB_SMINFO_STATE_MASTER ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_sminfo_rcv_process_set_request: " + "Responding to master SM with real sm_key\n" ); + p_smi->sm_key = p_rcv->p_subn->opt.sm_key; + } + else + { + /* The requester is not authenticated as master - set sm_key to zero. */ + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_sminfo_rcv_process_set_request: " + "Responding to SM not master with zero sm_key\n" ); + p_smi->sm_key = 0; + } + + /* Check the legality of the packet */ + status = __osm_sminfo_rcv_check_set_req_legality( p_smp ); + if ( status != IB_SUCCESS ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_sminfo_rcv_process_set_request: ERR 2F04: " + "Check legality failed. AttributeModifier:0x%X RemoteState:%s\n", + p_smp->attr_mod, + osm_get_sm_mgr_state_str(ib_sminfo_get_state( p_rcv_smi ) ) ); + /* send a response with error code */ + status = osm_resp_send( p_rcv->p_resp, p_madw, 7, payload ); + if( status != IB_SUCCESS ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_sminfo_rcv_process_set_request: ERR 2F05: " + "Error sending response (%s)\n", + ib_get_err_str( status ) ); + } + CL_PLOCK_RELEASE( p_rcv->p_lock ); + goto Exit; + } + + /* translate from IB_SMINFO_ATTR to OSM_SM_SIGNAL */ + switch (p_smp->attr_mod) + { + case IB_SMINFO_ATTR_MOD_HANDOVER: + sm_signal = OSM_SM_SIGNAL_HANDOVER; + break; + case IB_SMINFO_ATTR_MOD_ACKNOWLEDGE: + sm_signal = OSM_SM_SIGNAL_ACKNOWLEDGE; + break; + case IB_SMINFO_ATTR_MOD_DISABLE: + sm_signal = OSM_SM_SIGNAL_DISABLE; + break; + case IB_SMINFO_ATTR_MOD_STANDBY: + sm_signal = OSM_SM_SIGNAL_STANDBY; + break; + case IB_SMINFO_ATTR_MOD_DISCOVER: + sm_signal = OSM_SM_SIGNAL_DISCOVER; + break; + default: + /* + This code shouldn't be reached - checked in the + check legality + */ + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_sminfo_rcv_process_set_request: ERR 2F06: " + "THIS CODE SHOULD NOT BE REACHED!!\n"); + CL_PLOCK_RELEASE( p_rcv->p_lock ); + goto Exit; + } + + /* check legality of the needed transition in the SM state machine */ + status = osm_sm_state_mgr_check_legality( p_rcv->p_sm_state_mgr, + sm_signal ); + if ( status != IB_SUCCESS ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_sminfo_rcv_process_set_request: ERR 2F07: " + "Check legality of SM needed transition. AttributeModifier:0x%X RemoteState:%s\n", + p_smp->attr_mod, + osm_get_sm_mgr_state_str(ib_sminfo_get_state( p_rcv_smi ) ) ); + /* send a response with error code */ + status = osm_resp_send( p_rcv->p_resp, p_madw, 7, payload ); + if( status != IB_SUCCESS ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_sminfo_rcv_process_set_request: ERR 2F08: " + "Error sending response (%s)\n", + ib_get_err_str( status ) ); + } + CL_PLOCK_RELEASE( p_rcv->p_lock ); + goto Exit; + } + + /* the SubnSet(SMInfo) command is ok. Send a response. */ + status = osm_resp_send( p_rcv->p_resp, p_madw, 0, payload ); + if( status != IB_SUCCESS ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_sminfo_rcv_process_set_request: ERR 2F09: " + "Error sending response (%s)\n", + ib_get_err_str( status ) ); + } + + /* it is a legal packet - act according to it */ + + /* if the AttributeModifier is STANDBY - need to save on the */ + /* p_sm_state_mgr in the master_guid variable - the guid of the */ + /* current master. */ + if ( p_smp->attr_mod == IB_SMINFO_ATTR_MOD_STANDBY ) + { + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "__osm_sminfo_rcv_process_set_request: " + "Received a STANDBY signal. Updating " + "sm_state_mgr master_guid: 0x%016" PRIx64 "\n", + cl_ntoh64(p_rcv_smi->guid) ); + p_rcv->p_sm_state_mgr->master_guid = p_rcv_smi->guid; + } + + /* call osm_sm_state_mgr_process with the received signal. */ + CL_PLOCK_RELEASE( p_rcv->p_lock ); + status = osm_sm_state_mgr_process( p_rcv->p_sm_state_mgr, + sm_signal ); + + if( status != IB_SUCCESS ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_sminfo_rcv_process_set_request: ERR 2F10: " + "Error in SM state transition (%s)\n", + ib_get_err_str( status ) ); + } + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + * Return a signal with which to call the osm_state_mgr_process. + * This is done since we are locked by p_rcv->p_lock in this function, + * and thus cannot call osm_state_mgr_process (that locks the state_lock). + * If return OSM_SIGNAL_NONE - do not call osm_state_mgr_process. + **********************************************************************/ +static osm_signal_t +__osm_sminfo_rcv_process_get_sm( + IN const osm_sminfo_rcv_t* const p_rcv, + IN const osm_remote_sm_t* const p_sm ) +{ + const ib_sm_info_t* p_smi; + osm_signal_t ret_val = OSM_SIGNAL_NONE; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_sminfo_rcv_process_get_sm ); + + p_smi = &p_sm->smi; + + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "__osm_sminfo_rcv_process_get_sm: " + "Detected SM 0x%016" PRIx64 " in state %u\n", + cl_ntoh64( p_smi->guid ), ib_sminfo_get_state( p_smi ) ); + } + + /* + Check the state of this SM vs. our own. + */ + switch( p_rcv->p_subn->sm_state ) + { + case IB_SMINFO_STATE_NOTACTIVE: + break; + + case IB_SMINFO_STATE_DISCOVERING: + switch( ib_sminfo_get_state( p_smi ) ) + { + case IB_SMINFO_STATE_NOTACTIVE: + break; + case IB_SMINFO_STATE_MASTER: + ret_val = OSM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED; + /* save on the p_sm_state_mgr the guid of the current master. */ + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "__osm_sminfo_rcv_process_get_sm: " + "Found master SM. Updating sm_state_mgr master_guid: 0x%016" PRIx64 "\n", + cl_ntoh64( p_sm->p_port->guid ) ); + p_rcv->p_sm_state_mgr->master_guid = p_sm->p_port->guid; + break; + case IB_SMINFO_STATE_DISCOVERING: + case IB_SMINFO_STATE_STANDBY: + if ( __osm_sminfo_rcv_remote_sm_is_higher(p_rcv, p_smi) == TRUE ) + { + /* the remote is a higher sm - need to stop sweeping */ + ret_val = OSM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED; + /* save on the p_sm_state_mgr the guid of the higher SM we found - */ + /* we will poll it - as long as it lives - we should be in Standby. */ + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "__osm_sminfo_rcv_process_get_sm: " + "Found higher SM. Updating sm_state_mgr master_guid:" + " 0x%016" PRIx64 "\n", + cl_ntoh64(p_sm->p_port->guid) ); + p_rcv->p_sm_state_mgr->master_guid = p_sm->p_port->guid; + } + break; + default: + break; + } + break; + + case IB_SMINFO_STATE_STANDBY: + /* if the guid of the SM that sent us this response is equal to the */ + /* p_sm_mgr->master_guid - then this is a signal that the polling */ + switch( ib_sminfo_get_state( p_smi ) ) + { + case IB_SMINFO_STATE_MASTER: + /* This means the master is alive */ + /* Signal that to the SM state mgr */ + osm_sm_state_mgr_signal_master_is_alive( p_rcv->p_sm_state_mgr ); + break; + case IB_SMINFO_STATE_STANDBY: + /* This should be the response from the sm we are polling. */ + /* If it is - then signal master is alive */ + if (p_rcv->p_sm_state_mgr->master_guid == p_sm->p_port->guid) + { + /* Make sure that it is an SM with higher priority than us. + If we started polling it when it was master, and it moved + to standby - then it might be with a lower priority than + us - and then we don't want to continue polling it. */ + if ( __osm_sminfo_rcv_remote_sm_is_higher(p_rcv, p_smi) == TRUE ) + osm_sm_state_mgr_signal_master_is_alive( p_rcv->p_sm_state_mgr ); + } + break; + default: + /* any other state - do nothing */ + break; + } + break; + + case IB_SMINFO_STATE_MASTER: + switch( ib_sminfo_get_state( p_smi ) ) + { + case IB_SMINFO_STATE_MASTER: + /* If this is a response due to our polling, this means that we are + waiting for a handover from this SM, and it is still alive - + signal that. */ + if ( p_rcv->p_sm_state_mgr->p_polling_sm != NULL ) + { + osm_sm_state_mgr_signal_master_is_alive( p_rcv->p_sm_state_mgr ); + } + else + { + /* This is a response we got while sweeping the subnet. + We will handle a case of handover needed later on, when the sweep + is done and all SMs are recongnized. */ + } + break; + default: + /* any other state - do nothing */ + break; + } + break; + + default: + break; + } + + OSM_LOG_EXIT( p_rcv->p_log ); + return ret_val; +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_sminfo_rcv_process_get_response( + IN const osm_sminfo_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ) +{ + const ib_smp_t* p_smp; + const ib_sm_info_t* p_smi; + cl_qmap_t* p_sm_tbl; + cl_qmap_t* p_port_tbl; + osm_port_t* p_port; + ib_net64_t port_guid; + osm_remote_sm_t* p_sm; + osm_signal_t process_get_sm_ret_val = OSM_SIGNAL_NONE; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_sminfo_rcv_process_get_response ); + + CL_ASSERT( p_madw ); + + p_smp = osm_madw_get_smp_ptr( p_madw ); + + if( p_smp->method != IB_MAD_METHOD_GET_RESP ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_sminfo_rcv_process_get_response: ERR 2F11: " + "Unsupported method 0x%X\n", + p_smp->method ); + goto Exit; + } + + p_smi = ib_smp_get_payload_ptr( p_smp ); + p_sm_tbl = &p_rcv->p_subn->sm_guid_tbl; + p_port_tbl = &p_rcv->p_subn->port_guid_tbl; + port_guid = p_smi->guid; + + osm_dump_sm_info( p_rcv->p_log, p_smi, OSM_LOG_DEBUG ); + + /* + Check that the sm_key of the found SM is the same as ours, + or is zero. If not - OpenSM cannot continue with configuration!. */ + if ( p_smi->sm_key != 0 && + p_smi->sm_key != p_rcv->p_subn->opt.sm_key ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_sminfo_rcv_process_get_response: ERR 2F18: " + "Got SM with sm_key that doesn't match our " + "local key. Exiting\n" ); + osm_log( p_rcv->p_log, OSM_LOG_SYS, + "Found remote SM with non-matching sm_key. Exiting\n" ); + osm_exit_flag = TRUE; + goto Exit; + } + + /* + Determine if we already have another SM object for this SM. + */ + CL_PLOCK_EXCL_ACQUIRE( p_rcv->p_lock ); + + p_port = (osm_port_t*)cl_qmap_get( p_port_tbl, port_guid ); + if( p_port == (osm_port_t*)cl_qmap_end( p_port_tbl ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_sminfo_rcv_process_get_response: ERR 2F12: " + "No port object for this SM\n" ); + goto Exit; + } + + if( osm_port_get_guid( p_port ) != p_smi->guid ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_sminfo_rcv_process_get_response: ERR 2F13: " + "Bogus SM port GUID" + "\n\t\t\t\tExpected 0x%016" PRIx64 + ", Received 0x%016" PRIx64 "\n", + cl_ntoh64( osm_port_get_guid( p_port ) ), + cl_ntoh64( p_smi->guid ) ); + goto Exit; + } + + p_sm = (osm_remote_sm_t*)cl_qmap_get( p_sm_tbl, port_guid ); + if( p_sm == (osm_remote_sm_t*)cl_qmap_end( p_sm_tbl ) ) + { + p_sm = malloc( sizeof(*p_sm) ); + if( p_sm == NULL ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_sminfo_rcv_process_get_response: ERR 2F14: " + "Unable to allocate SM object\n" ); + goto Exit; + } + + osm_remote_sm_init( p_sm, p_port, p_smi ); + + cl_qmap_insert( p_sm_tbl, port_guid, &p_sm->map_item ); + } + else + { + /* + We already know this SM. + Update the SMInfo attribute. + */ + p_sm->smi = *p_smi; + } + + process_get_sm_ret_val = __osm_sminfo_rcv_process_get_sm( p_rcv, p_sm ); + + Exit: + CL_PLOCK_RELEASE( p_rcv->p_lock ); + + /* If process_get_sm_ret_val != OSM_SIGNAL_NONE then we have to signal + * to the state_mgr with that signal. */ + if (process_get_sm_ret_val != OSM_SIGNAL_NONE) + osm_state_mgr_process( p_rcv->p_state_mgr, + process_get_sm_ret_val ); + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_sminfo_rcv_process_set_response( + IN const osm_sminfo_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ) +{ + const ib_smp_t* p_smp; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_sminfo_rcv_process_set_response ); + + CL_ASSERT( p_madw ); + + p_smp = osm_madw_get_smp_ptr( p_madw ); + + if( p_smp->method != IB_MAD_METHOD_GET_RESP ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_sminfo_rcv_process_set_response: ERR 2F16: " + "Unsupported method 0x%X\n", + p_smp->method ); + goto Exit; + } + + /* Check the AttributeModifier */ + if ( p_smp->attr_mod != IB_SMINFO_ATTR_MOD_HANDOVER ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_sminfo_rcv_process_set_response: ERR 2F17: " + "Unsupported attribute modifier 0x%X\n", + p_smp->attr_mod ); + goto Exit; + } + + /* + This is a response on a HANDOVER request - + Nothing to do. + */ + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_sminfo_rcv_process( + IN const osm_sminfo_rcv_t* const p_rcv, + IN osm_madw_t* const p_madw ) +{ + ib_smp_t *p_smp; + osm_smi_context_t *p_smi_context; + + OSM_LOG_ENTER( p_rcv->p_log, osm_sminfo_rcv_process ); + + CL_ASSERT( p_madw ); + + p_smp = osm_madw_get_smp_ptr( p_madw ); + + /* + Determine if this is a request for our own SMInfo + or if this is a response to our request for another + SM's SMInfo. + */ + if( ib_smp_is_response( p_smp ) ) + { + /* Get the context - to see if this is a response to a Get or Set method */ + p_smi_context = osm_madw_get_smi_context_ptr( p_madw ); + if ( p_smi_context->set_method == FALSE ) + { + /* this is a response to a Get method */ + __osm_sminfo_rcv_process_get_response( p_rcv, p_madw ); + } + else + { + /* this is a response to a Set method */ + __osm_sminfo_rcv_process_set_response( p_rcv, p_madw ); + } + } + else + { + /* This is a request */ + if ( p_smp->method == IB_MAD_METHOD_GET ) + { + /* This is a SubnGet request */ + __osm_sminfo_rcv_process_get_request( p_rcv, p_madw ); + } + else + { + /* This is a SubnSet request */ + __osm_sminfo_rcv_process_set_request( p_rcv, p_madw ); + } + } + + OSM_LOG_EXIT( p_rcv->p_log ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sminfo_rcv_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sminfo_rcv_ctrl.c new file mode 100644 index 00000000..8ad3d11f --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sminfo_rcv_ctrl.c @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sminfo_rcv_ctrl.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_sminfo_rcv_ctrl_t. + * This object represents the SMInfo request controller object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +__osm_sminfo_rcv_ctrl_disp_callback( + IN void *context, + IN void *p_data ) +{ + /* ignore return status when invoked via the dispatcher */ + osm_sminfo_rcv_process( ((osm_sminfo_rcv_ctrl_t*)context)->p_rcv, + (osm_madw_t*)p_data ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_sminfo_rcv_ctrl_construct( + IN osm_sminfo_rcv_ctrl_t* const p_ctrl ) +{ + memset( p_ctrl, 0, sizeof(*p_ctrl) ); + p_ctrl->h_disp = CL_DISP_INVALID_HANDLE; +} + +/********************************************************************** + **********************************************************************/ +void +osm_sminfo_rcv_ctrl_destroy( + IN osm_sminfo_rcv_ctrl_t* const p_ctrl ) +{ + CL_ASSERT( p_ctrl ); + cl_disp_unregister( p_ctrl->h_disp ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_sminfo_rcv_ctrl_init( + IN osm_sminfo_rcv_ctrl_t* const p_ctrl, + IN osm_sminfo_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_sminfo_rcv_ctrl_init ); + + osm_sminfo_rcv_ctrl_construct( p_ctrl ); + + p_ctrl->p_log = p_log; + p_ctrl->p_rcv = p_rcv; + p_ctrl->p_disp = p_disp; + + p_ctrl->h_disp = cl_disp_register( + p_disp, + OSM_MSG_MAD_SM_INFO, + __osm_sminfo_rcv_ctrl_disp_callback, + p_ctrl ); + + if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_sminfo_rcv_ctrl_init: ERR 3001: " + "Dispatcher registration failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return( status ); +} + + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_state_mgr.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_state_mgr.c new file mode 100644 index 00000000..ef418705 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_state_mgr.c @@ -0,0 +1,2986 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_state_mgr.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Implementation of osm_state_mgr_t. + * This file implements the State Manager object. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.13 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SUBNET_LIST_FILENAME "/osm-subnet.lst" + +osm_signal_t osm_qos_setup(IN osm_opensm_t * p_osm); + +/********************************************************************** + **********************************************************************/ +void +osm_state_mgr_construct( + IN osm_state_mgr_t * const p_mgr ) +{ + memset( p_mgr, 0, sizeof( *p_mgr ) ); + cl_spinlock_construct( &p_mgr->state_lock ); + cl_spinlock_construct( &p_mgr->idle_lock ); + p_mgr->state = OSM_SM_STATE_INIT; +} + +/********************************************************************** + **********************************************************************/ +void +osm_state_mgr_destroy( + IN osm_state_mgr_t * const p_mgr ) +{ + CL_ASSERT( p_mgr ); + + OSM_LOG_ENTER( p_mgr->p_log, osm_state_mgr_destroy ); + + /* destroy the locks */ + cl_spinlock_destroy( &p_mgr->state_lock ); + cl_spinlock_destroy( &p_mgr->idle_lock ); + + OSM_LOG_EXIT( p_mgr->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_state_mgr_init( + IN osm_state_mgr_t * const p_mgr, + IN osm_subn_t * const p_subn, + IN osm_lid_mgr_t * const p_lid_mgr, + IN osm_ucast_mgr_t * const p_ucast_mgr, + IN osm_mcast_mgr_t * const p_mcast_mgr, + IN osm_link_mgr_t * const p_link_mgr, + IN osm_drop_mgr_t * const p_drop_mgr, + IN osm_req_t * const p_req, + IN osm_stats_t * const p_stats, + IN osm_sm_state_mgr_t * const p_sm_state_mgr, + IN const osm_sm_mad_ctrl_t * const p_mad_ctrl, + IN cl_plock_t * const p_lock, + IN cl_event_t * const p_subnet_up_event, + IN osm_log_t * const p_log ) +{ + cl_status_t status; + + OSM_LOG_ENTER( p_log, osm_state_mgr_init ); + + CL_ASSERT( p_subn ); + CL_ASSERT( p_lid_mgr ); + CL_ASSERT( p_ucast_mgr ); + CL_ASSERT( p_mcast_mgr ); + CL_ASSERT( p_link_mgr ); + CL_ASSERT( p_drop_mgr ); + CL_ASSERT( p_req ); + CL_ASSERT( p_stats ); + CL_ASSERT( p_sm_state_mgr ); + CL_ASSERT( p_mad_ctrl ); + CL_ASSERT( p_lock ); + + osm_state_mgr_construct( p_mgr ); + + p_mgr->p_log = p_log; + p_mgr->p_subn = p_subn; + p_mgr->p_lid_mgr = p_lid_mgr; + p_mgr->p_ucast_mgr = p_ucast_mgr; + p_mgr->p_mcast_mgr = p_mcast_mgr; + p_mgr->p_link_mgr = p_link_mgr; + p_mgr->p_drop_mgr = p_drop_mgr; + p_mgr->p_mad_ctrl = p_mad_ctrl; + p_mgr->p_req = p_req; + p_mgr->p_stats = p_stats; + p_mgr->p_sm_state_mgr = p_sm_state_mgr; + p_mgr->state = OSM_SM_STATE_IDLE; + p_mgr->p_lock = p_lock; + p_mgr->p_subnet_up_event = p_subnet_up_event; + p_mgr->state_step_mode = OSM_STATE_STEP_CONTINUOUS; + p_mgr->next_stage_signal = OSM_SIGNAL_NONE; + + status = cl_spinlock_init( &p_mgr->state_lock ); + if( status != CL_SUCCESS ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "osm_state_mgr_init: ERR 3301: " + "Spinlock init failed (%s)\n", CL_STATUS_MSG( status ) ); + } + + cl_qlist_init( &p_mgr->idle_time_list ); + + status = cl_spinlock_init( &p_mgr->idle_lock ); + if( status != CL_SUCCESS ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "osm_state_mgr_init: ERR 3302: " + "Spinlock init failed (%s)\n", CL_STATUS_MSG( status ) ); + } + + OSM_LOG_EXIT( p_mgr->p_log ); + return ( status ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_state_mgr_up_msg( + IN const osm_state_mgr_t * p_mgr ) +{ + /* + * This message should be written only once - when the + * SM moves to Master state and the subnet is up for + * the first time. The change of state is marked with + * the subnet flag moved_to_master_state + */ + if( p_mgr->p_subn->moved_to_master_state == TRUE ) + { + osm_log( p_mgr->p_log, OSM_LOG_SYS, "SUBNET UP\n" ); /* Format Waived */ + /* clear the signal */ + p_mgr->p_subn->moved_to_master_state = FALSE; + } + else + { + osm_log( p_mgr->p_log, OSM_LOG_INFO, "SUBNET UP\n" ); /* Format Waived */ + } + + if( p_mgr->p_subn->opt.sweep_interval ) + { + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_state_mgr_up_msg: " + "\n\n\n********************************" + "**********************************\n" + "**************************** SUBNET UP " + "***************************\n" + "**************************************" + "****************************\n\n\n" ); + } + else + { + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_state_mgr_up_msg: " + "\n\n\n********************************" + "**********************************\n" + "******************* SUBNET UP " + "(sweep disabled) *******************\n" + "**************************************" + "****************************\n\n\n" ); + } +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_state_mgr_init_errors_msg( + IN const osm_state_mgr_t * p_mgr ) +{ + osm_log( p_mgr->p_log, OSM_LOG_SYS, "Errors during initialization\n" ); /* Format Waived */ + + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_state_mgr_init_errors_msg: " + "\n\n\n********************************" + "**********************************\n" + "****************** ERRORS DURING INITI" + "ALIZATION ******************\n" + "**************************************" + "****************************\n\n\n" ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_state_mgr_light_sweep_done_msg( + IN const osm_state_mgr_t * p_mgr ) +{ + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_state_mgr_light_sweep_done_msg: " + "\n\n\n********************************" + "**********************************\n" + "********************** LIGHT SWEEP " + "COMPLETE **********************\n" + "**************************************" + "****************************\n\n\n" ); + } +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_state_mgr_standby_msg( + IN const osm_state_mgr_t * p_mgr ) +{ + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_state_mgr_standby_msg: " + "\n\n\n********************************" + "**********************************\n" + "******************** ENTERING STANDBY" + " STATE **********************\n" + "**************************************" + "****************************\n\n\n" ); + } +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_state_mgr_sm_port_down_msg( + IN const osm_state_mgr_t * p_mgr ) +{ + osm_log( p_mgr->p_log, OSM_LOG_SYS, "SM port is down\n" ); /* Format Waived */ + + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_state_mgr_sm_port_down_msg: " + "\n\n\n********************************" + "**********************************\n" + "************************** SM PORT DOWN " + "**************************\n" + "**************************************" + "****************************\n\n\n" ); + } +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_state_mgr_lid_assign_msg( + IN const osm_state_mgr_t * p_mgr ) +{ + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_state_mgr_lid_assign_msg: " + "\n\n\n**************************************" + "****************************\n" + "***** LID ASSIGNMENT COMPLETE - STARTING SWITC" + "H TABLE CONFIG *****\n" + "*********************************************" + "*********************\n\n\n" ); + } +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_state_mgr_set_sm_lid_done_msg( + IN const osm_state_mgr_t * p_mgr ) +{ + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_state_mgr_set_sm_lid_done_msg: " + "\n\n\n**************************************" + "****************************\n" + "**** SM LID ASSIGNMENT COMPLETE - STARTING SUBN" + "ET LID CONFIG *****\n" + "*********************************************" + "*********************\n\n\n" ); + } +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_state_mgr_switch_config_msg( + IN const osm_state_mgr_t * p_mgr ) +{ + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_state_mgr_switch_config_msg: " + "\n\n\n**************************************" + "****************************\n" + "***************** SWITCHES CONFIGURED FOR UNICAST " + "****************\n" + "*********************************************" + "*********************\n\n\n" ); + } +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_state_mgr_multicast_config_msg( + IN const osm_state_mgr_t * p_mgr ) +{ + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_state_mgr_multicast_config_msg: " + "\n\n\n**************************************" + "****************************\n" + "**************** SWITCHES CONFIGURED FOR MULTICAST " + "***************\n" + "*********************************************" + "*********************\n\n\n" ); + } +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_state_mgr_links_ports_msg( + IN const osm_state_mgr_t * p_mgr ) +{ + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_state_mgr_links_ports_msg: " + "\n\n\n**************************************" + "****************************\n" + "******* LINKS PORTS CONFIGURED - SET LINKS TO ARMED " + "STATE ********\n" + "*********************************************" + "*********************\n\n\n" ); + } +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_state_mgr_links_armed_msg( + IN const osm_state_mgr_t * p_mgr ) +{ + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_state_mgr_links_armed_msg: " + "\n\n\n**************************************" + "****************************\n" + "************* LINKS ARMED - SET LINKS TO ACTIVE " + "STATE ************\n" + "*********************************************" + "*********************\n\n\n" ); + } +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_state_mgr_sweep_heavy_msg( + IN const osm_state_mgr_t * p_mgr ) +{ + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_state_mgr_sweep_heavy_msg: " + "\n\n\n**************************************" + "****************************\n" + "******************** INITIATING HEAVY SWEEP " + "**********************\n" + "*********************************************" + "*********************\n\n\n" ); + } +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_state_mgr_sweep_heavy_done_msg( + IN const osm_state_mgr_t * p_mgr ) +{ + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_state_mgr_sweep_heavy_done_msg: " + "\n\n\n**************************************" + "****************************\n" + "********************* HEAVY SWEEP COMPLETE " + "***********************\n" + "*********************************************" + "*********************\n\n\n" ); + } +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_state_mgr_sweep_light_msg( + IN const osm_state_mgr_t * p_mgr ) +{ + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_state_mgr_sweep_light_msg: " + "\n\n\n**************************************" + "****************************\n" + "******************** INITIATING LIGHT SWEEP " + "**********************\n" + "*********************************************" + "*********************\n\n\n" ); + } +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_state_mgr_signal_warning( + IN const osm_state_mgr_t * const p_mgr, + IN const osm_signal_t signal ) +{ + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_state_mgr_signal_warning: " + "Invalid signal %s(%lu) in state %s\n", + osm_get_sm_signal_str( signal ), + signal, osm_get_sm_state_str( p_mgr->state ) ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_state_mgr_signal_error( + IN const osm_state_mgr_t * const p_mgr, + IN const osm_signal_t signal ) +{ + /* the Request for IDLE processing can come async to the state so it + * really is just verbose ... */ + if( signal == OSM_SIGNAL_IDLE_TIME_PROCESS_REQUEST ) + __osm_state_mgr_signal_warning( p_mgr, signal ); + else + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_state_mgr_signal_error: ERR 3303: " + "Invalid signal %s(%lu) in state %s\n", + osm_get_sm_signal_str( signal ), + signal, osm_get_sm_state_str( p_mgr->state ) ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_state_mgr_reset_node_count( + IN cl_map_item_t * const p_map_item, + IN void *context ) +{ + osm_node_t *p_node = ( osm_node_t * ) p_map_item; + osm_state_mgr_t *const p_mgr = ( osm_state_mgr_t * ) context; + + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_state_mgr_reset_node_count: " + "Resetting discovery count for node 0x%" PRIx64 "\n", + cl_ntoh64( osm_node_get_node_guid( p_node ) ) ); + } + + osm_node_discovery_count_reset( p_node ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_state_mgr_reset_port_count( + IN cl_map_item_t * const p_map_item, + IN void *context ) +{ + osm_port_t *p_port = ( osm_port_t * ) p_map_item; + osm_state_mgr_t *const p_mgr = ( osm_state_mgr_t * ) context; + + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_state_mgr_reset_port_count: " + "Resetting discovery count for port 0x%" PRIx64 "\n", + cl_ntoh64( osm_port_get_guid( p_port ) ) ); + } + + osm_port_discovery_count_reset( p_port ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_state_mgr_reset_switch_count( + IN cl_map_item_t * const p_map_item, + IN void *context ) +{ + osm_switch_t *p_sw = ( osm_switch_t * ) p_map_item; + osm_state_mgr_t *const p_mgr = ( osm_state_mgr_t * ) context; + + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_state_mgr_reset_switch_count: " + "Resetting discovery count for switch 0x%" PRIx64 "\n", + cl_ntoh64( osm_node_get_node_guid( p_sw->p_node ) ) ); + } + + osm_switch_discovery_count_reset( p_sw ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_state_mgr_get_sw_info( + IN cl_map_item_t * const p_object, + IN void *context ) +{ + osm_node_t *p_node; + osm_dr_path_t *p_dr_path; + osm_madw_context_t mad_context; + osm_switch_t *const p_sw = ( osm_switch_t * ) p_object; + osm_state_mgr_t *const p_mgr = ( osm_state_mgr_t * ) context; + ib_api_status_t status; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_get_sw_info ); + + p_node = osm_switch_get_node_ptr( p_sw ); + p_dr_path = osm_node_get_any_dr_path_ptr( p_node ); + + memset( &context, 0, sizeof( context ) ); + + mad_context.si_context.node_guid = osm_node_get_node_guid( p_node ); + mad_context.si_context.set_method = FALSE; + mad_context.si_context.light_sweep = TRUE; + + status = osm_req_get( p_mgr->p_req, + p_dr_path, + IB_MAD_ATTR_SWITCH_INFO, + 0, OSM_MSG_LIGHT_SWEEP_FAIL, &mad_context ); + + if( status != IB_SUCCESS ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_state_mgr_get_sw_info: ERR 3304: " + "Request SwitchInfo failed\n" ); + } + + OSM_LOG_EXIT( p_mgr->p_log ); +} + +/********************************************************************** + Initiate a remote port info request for the given physical port + **********************************************************************/ +static void +__osm_state_mgr_get_remote_port_info( + IN osm_state_mgr_t * const p_mgr, + IN osm_physp_t * const p_physp ) +{ + osm_dr_path_t *p_dr_path; + osm_dr_path_t rem_node_dr_path; + osm_madw_context_t mad_context; + ib_api_status_t status; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_get_remote_port_info ); + + /* generate a dr path leaving on the physp to the remote node */ + p_dr_path = osm_physp_get_dr_path_ptr( p_physp ); + memcpy( &rem_node_dr_path, p_dr_path, sizeof( osm_dr_path_t ) ); + osm_dr_path_extend( &rem_node_dr_path, osm_physp_get_port_num( p_physp ) ); + + memset( &mad_context, 0, sizeof( mad_context ) ); + + mad_context.pi_context.node_guid = + osm_node_get_node_guid( osm_physp_get_node_ptr( p_physp ) ); + mad_context.pi_context.port_guid = + cl_hton64( osm_physp_get_port_num( p_physp ) ); + mad_context.pi_context.set_method = FALSE; + mad_context.pi_context.light_sweep = TRUE; + mad_context.pi_context.ignore_errors = FALSE; + mad_context.pi_context.update_master_sm_base_lid = FALSE; + mad_context.pi_context.active_transition = FALSE; + + /* note that with some negative logic - if the query failed it means that + * there is no point in going to heavy sweep */ + status = osm_req_get( p_mgr->p_req, + &rem_node_dr_path, + IB_MAD_ATTR_PORT_INFO, + 0, CL_DISP_MSGID_NONE, &mad_context ); + + if( status != IB_SUCCESS ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_state_mgr_get_remote_port_info: ERR 332E: " + "Request for PortInfo failed\n" ); + } + + OSM_LOG_EXIT( p_mgr->p_log ); +} + +/********************************************************************** + Initiates a thorough sweep of the subnet. + Used when there is suspicion that something on the subnet has changed. +**********************************************************************/ +static ib_api_status_t +__osm_state_mgr_sweep_hop_0( + IN osm_state_mgr_t * const p_mgr ) +{ + ib_api_status_t status; + osm_dr_path_t dr_path; + osm_bind_handle_t h_bind; + osm_ni_context_t ni_context; + uint8_t path_array[IB_SUBNET_PATH_HOPS_MAX]; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_sweep_hop_0 ); + + memset( path_array, 0, sizeof( path_array ) ); + + /* + * First, get the bind handle. + */ + h_bind = osm_sm_mad_ctrl_get_bind_handle( p_mgr->p_mad_ctrl ); + if( h_bind != OSM_BIND_INVALID_HANDLE ) + { + __osm_state_mgr_sweep_heavy_msg( p_mgr ); + + /* + * Start the sweep by clearing the port counts, then + * get our own NodeInfo at 0 hops. + */ + CL_PLOCK_ACQUIRE( p_mgr->p_lock ); + + cl_qmap_apply_func( &p_mgr->p_subn->node_guid_tbl, + __osm_state_mgr_reset_node_count, p_mgr ); + + cl_qmap_apply_func( &p_mgr->p_subn->port_guid_tbl, + __osm_state_mgr_reset_port_count, p_mgr ); + + cl_qmap_apply_func( &p_mgr->p_subn->sw_guid_tbl, + __osm_state_mgr_reset_switch_count, p_mgr ); + + /* Set the in_sweep_hop_0 flag in subn to be TRUE. + * This will indicate the sweeping not to continue beyond the + * the current node. + * This is relevant for the case of SM on switch, since in the + * switch info we need to signal somehow not to continue + * the sweeping. */ + p_mgr->p_subn->in_sweep_hop_0 = TRUE; + + CL_PLOCK_RELEASE( p_mgr->p_lock ); + + memset( &ni_context, 0, sizeof( ni_context ) ); + osm_dr_path_init( &dr_path, h_bind, 0, path_array ); + status = osm_req_get( p_mgr->p_req, + &dr_path, + IB_MAD_ATTR_NODE_INFO, + 0, CL_DISP_MSGID_NONE, NULL ); + + if( status != IB_SUCCESS ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_state_mgr_sweep_hop_0: ERR 3305: " + "Request NodeInfo failed\n" ); + } + } + else + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_state_mgr_sweep_hop_0: " + "No bound ports. Deferring sweep...\n" ); + status = IB_INVALID_STATE; + } + + OSM_LOG_EXIT( p_mgr->p_log ); + return ( status ); +} + +/********************************************************************** + Clear out all existing port lid assignments +**********************************************************************/ +static ib_api_status_t +__osm_state_mgr_clean_known_lids( + IN osm_state_mgr_t * const p_mgr ) +{ + ib_api_status_t status = IB_SUCCESS; + cl_ptr_vector_t *p_vec = &( p_mgr->p_subn->port_lid_tbl ); + uint32_t i; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_clean_known_lids ); + + /* we need a lock here! */ + CL_PLOCK_ACQUIRE( p_mgr->p_lock ); + + for( i = 0; i < cl_ptr_vector_get_size( p_vec ); i++ ) + cl_ptr_vector_set( p_vec, i, NULL ); + + CL_PLOCK_RELEASE( p_mgr->p_lock ); + + OSM_LOG_EXIT( p_mgr->p_log ); + return ( status ); +} + +/********************************************************************** + Notifies the transport layer that the local LID has changed, + which give it a chance to update address vectors, etc.. +**********************************************************************/ +static ib_api_status_t +__osm_state_mgr_notify_lid_change( + IN osm_state_mgr_t * const p_mgr ) +{ + ib_api_status_t status; + osm_bind_handle_t h_bind; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_notify_lid_change ); + + /* + * First, get the bind handle. + */ + h_bind = osm_sm_mad_ctrl_get_bind_handle( p_mgr->p_mad_ctrl ); + if( h_bind == OSM_BIND_INVALID_HANDLE ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_state_mgr_notify_lid_change: ERR 3306: " + "No bound ports\n" ); + status = IB_ERROR; + goto Exit; + } + + /* + * Notify the transport layer that we changed the local LID. + */ + status = osm_vendor_local_lid_change( h_bind ); + if( status != IB_SUCCESS ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_state_mgr_notify_lid_change: ERR 3307: " + "Vendor LID update failed (%s)\n", ib_get_err_str( status ) ); + } + + Exit: + OSM_LOG_EXIT( p_mgr->p_log ); + return ( status ); +} + +/********************************************************************** + Returns true if the SM port is down. + The SM's port object must exist in the port_guid table. +**********************************************************************/ +static boolean_t +__osm_state_mgr_is_sm_port_down( + IN osm_state_mgr_t * const p_mgr ) +{ + ib_net64_t port_guid; + osm_port_t *p_port; + osm_physp_t *p_physp; + cl_qmap_t *p_tbl; + uint8_t state; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_is_sm_port_down ); + + port_guid = p_mgr->p_subn->sm_port_guid; + + /* + * If we don't know our own port guid yet, assume the port is down. + */ + if( port_guid == 0 ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_state_mgr_is_sm_port_down: ERR 3308: " + "SM port GUID unknown\n" ); + state = IB_LINK_DOWN; + goto Exit; + } + + p_tbl = &p_mgr->p_subn->port_guid_tbl; + + CL_ASSERT( port_guid ); + + CL_PLOCK_ACQUIRE( p_mgr->p_lock ); + p_port = ( osm_port_t * ) cl_qmap_get( p_tbl, port_guid ); + if( p_port == ( osm_port_t * ) cl_qmap_end( p_tbl ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_state_mgr_is_sm_port_down: ERR 3309: " + "SM port with GUID:%016" PRIx64 " is unknown\n", + cl_ntoh64( port_guid ) ); + state = IB_LINK_DOWN; + CL_PLOCK_RELEASE( p_mgr->p_lock ); + goto Exit; + } + + p_physp = osm_port_get_default_phys_ptr( p_port ); + + CL_ASSERT( p_physp ); + CL_ASSERT( osm_physp_is_valid( p_physp ) ); + + state = osm_physp_get_port_state( p_physp ); + CL_PLOCK_RELEASE( p_mgr->p_lock ); + + Exit: + OSM_LOG_EXIT( p_mgr->p_log ); + return ( state == IB_LINK_DOWN ); +} + +/********************************************************************** + Sweeps the node 1 hop away. + This sets off a "chain reaction" that causes discovery of the subnet. + Used when there is suspicion that something on the subnet has changed. +**********************************************************************/ +static ib_api_status_t +__osm_state_mgr_sweep_hop_1( + IN osm_state_mgr_t * const p_mgr ) +{ + ib_api_status_t status = IB_SUCCESS; + osm_bind_handle_t h_bind; + osm_madw_context_t context; + osm_node_t *p_node; + osm_port_t *p_port; + osm_physp_t *p_physp; + osm_dr_path_t *p_dr_path; + osm_dr_path_t hop_1_path; + ib_net64_t port_guid; + uint8_t port_num; + cl_qmap_t *p_port_tbl; + uint8_t path_array[IB_SUBNET_PATH_HOPS_MAX]; + uint8_t num_ports; + osm_physp_t *p_ext_physp; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_sweep_hop_1 ); + + /* + * First, get our own port and node objects. + */ + p_port_tbl = &p_mgr->p_subn->port_guid_tbl; + port_guid = p_mgr->p_subn->sm_port_guid; + + CL_ASSERT( port_guid ); + + /* Set the in_sweep_hop_0 flag in subn to be FALSE. + * This will indicate the sweeping to continue beyond the + * the current node. + * This is relevant for the case of SM on switch, since in the + * switch info we need to signal that the sweeping should + * continue through the switch. */ + p_mgr->p_subn->in_sweep_hop_0 = FALSE; + + p_port = ( osm_port_t * ) cl_qmap_get( p_port_tbl, port_guid ); + if( p_port == ( osm_port_t * ) cl_qmap_end( p_port_tbl ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_state_mgr_sweep_hop_1: ERR 3310: " + "No SM port object\n" ); + status = IB_ERROR; + goto Exit; + } + + p_node = osm_port_get_parent_node( p_port ); + CL_ASSERT( p_node ); + + port_num = ib_node_info_get_local_port_num( &p_node->node_info ); + + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_state_mgr_sweep_hop_1: " + "Probing hop 1 on local port %u\n", port_num ); + + p_physp = osm_node_get_physp_ptr( p_node, port_num ); + + CL_ASSERT( p_physp ); + CL_ASSERT( osm_physp_is_valid( p_physp ) ); + + p_dr_path = osm_physp_get_dr_path_ptr( p_physp ); + h_bind = osm_dr_path_get_bind_handle( p_dr_path ); + + CL_ASSERT( h_bind != OSM_BIND_INVALID_HANDLE ); + + memset( path_array, 0, sizeof( path_array ) ); + /* the hop_1 operations depend on the type of our node. + * Currently - legal nodes that can host SM are SW and CA */ + switch ( osm_node_get_type( p_node ) ) + { + case IB_NODE_TYPE_CA: + case IB_NODE_TYPE_ROUTER: + context.ni_context.node_guid = osm_node_get_node_guid( p_node ); + context.ni_context.port_num = port_num; + + path_array[1] = port_num; + + osm_dr_path_init( &hop_1_path, h_bind, 1, path_array ); + status = osm_req_get( p_mgr->p_req, + &hop_1_path, + IB_MAD_ATTR_NODE_INFO, + 0, CL_DISP_MSGID_NONE, &context ); + + if( status != IB_SUCCESS ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_state_mgr_sweep_hop_1: ERR 3311: " + "Request NodeInfo failed\n" ); + } + break; + + case IB_NODE_TYPE_SWITCH: + /* Need to go over all the ports of the switch, and send a node_info + * from them. This doesn't include the port 0 of the switch, which + * hosts the SM. + * Note: We'll send another switchInfo on port 0, since if no ports + * are connected, we still want to get some response, and have the + * subnet come up. + */ + num_ports = osm_node_get_num_physp( p_node ); + for( port_num = 0; port_num < num_ports; port_num++ ) + { + /* go through the port only if the port is not DOWN */ + p_ext_physp = osm_node_get_physp_ptr( p_node, port_num ); + /* Make sure the physp object exists */ + if( !p_ext_physp ) + continue; + if( ib_port_info_get_port_state( &( p_ext_physp->port_info ) ) > + IB_LINK_DOWN ) + { + context.ni_context.node_guid = osm_node_get_node_guid( p_node ); + context.ni_context.port_num = port_num; + + path_array[1] = port_num; + + osm_dr_path_init( &hop_1_path, h_bind, 1, path_array ); + status = osm_req_get( p_mgr->p_req, + &hop_1_path, + IB_MAD_ATTR_NODE_INFO, + 0, CL_DISP_MSGID_NONE, &context ); + + if( status != IB_SUCCESS ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_state_mgr_sweep_hop_1: ERR 3312: " + "Request NodeInfo failed\n" ); + } + } + } + break; + + default: + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_state_mgr_sweep_hop_1: ERR 3313: Unknown node type %d\n", + osm_node_get_type( p_node ) ); + } + + Exit: + OSM_LOG_EXIT( p_mgr->p_log ); + return ( status ); +} + +/********************************************************************** + Initiates a lightweight sweep of the subnet. + Used during normal sweeps after the subnet is up. +**********************************************************************/ +static ib_api_status_t +__osm_state_mgr_light_sweep_start( + IN osm_state_mgr_t * const p_mgr ) +{ + ib_api_status_t status = IB_SUCCESS; + osm_bind_handle_t h_bind; + cl_qmap_t *p_sw_tbl; + cl_list_t *p_no_rem_port_list; + cl_list_iterator_t list_iter; + uint8_t path_array[IB_SUBNET_PATH_HOPS_MAX]; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_light_sweep_start ); + + p_sw_tbl = &p_mgr->p_subn->sw_guid_tbl; + + memset( path_array, 0, sizeof( path_array ) ); + + /* + * First, get the bind handle. + */ + h_bind = osm_sm_mad_ctrl_get_bind_handle( p_mgr->p_mad_ctrl ); + if( h_bind != OSM_BIND_INVALID_HANDLE ) + { + __osm_state_mgr_sweep_light_msg( p_mgr ); + CL_PLOCK_ACQUIRE( p_mgr->p_lock ); + cl_qmap_apply_func( p_sw_tbl, __osm_state_mgr_get_sw_info, p_mgr ); + CL_PLOCK_RELEASE( p_mgr->p_lock ); + + /* now scan the list of physical ports that were not down but have no remote port */ + CL_PLOCK_ACQUIRE( p_mgr->p_lock ); + p_no_rem_port_list = &p_mgr->p_subn->light_sweep_physp_list; + list_iter = cl_list_head( p_no_rem_port_list ); + while( list_iter != cl_list_end( p_no_rem_port_list ) ) + { + __osm_state_mgr_get_remote_port_info( p_mgr, + ( osm_physp_t * ) + cl_list_obj( list_iter ) ); + list_iter = cl_list_next( list_iter ); + } + CL_PLOCK_RELEASE( p_mgr->p_lock ); + } + else + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_state_mgr_light_sweep_start: " + "No bound ports. Deferring sweep...\n" ); + status = IB_INVALID_STATE; + } + + OSM_LOG_EXIT( p_mgr->p_log ); + return ( status ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_topology_file_create( + IN osm_state_mgr_t * const p_mgr ) +{ + const osm_node_t *p_node; + char *file_name; + FILE *rc; + char desc[IB_NODE_DESCRIPTION_SIZE + 1]; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_topology_file_create ); + + CL_PLOCK_ACQUIRE( p_mgr->p_lock ); + + file_name = + ( char * )malloc( strlen( p_mgr->p_subn->opt.dump_files_dir ) + + strlen(SUBNET_LIST_FILENAME) + 1 ); + + CL_ASSERT( file_name ); + + strcpy( file_name, p_mgr->p_subn->opt.dump_files_dir ); + strcat( file_name, SUBNET_LIST_FILENAME ); + + if( ( rc = fopen( file_name, "w" ) ) == NULL ) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_topology_file_create: " + "fopen failed for file:%s\n", file_name ); + + CL_PLOCK_RELEASE( p_mgr->p_lock ); + goto Exit; + } + + p_node = ( osm_node_t * ) cl_qmap_head( &p_mgr->p_subn->node_guid_tbl ); + while( p_node != + ( osm_node_t * ) cl_qmap_end( &p_mgr->p_subn->node_guid_tbl ) ) + { + if( p_node->node_info.num_ports ) + { + uint32_t cPort; + osm_node_t *p_nbnode; + osm_physp_t *p_physp; + osm_physp_t *p_default_physp; + osm_physp_t *p_rphysp; + uint8_t link_speed_act; + + for( cPort = 1; cPort < osm_node_get_num_physp( p_node ); cPort++ ) + { + uint8_t port_state; + + p_physp = osm_node_get_physp_ptr( p_node, cPort ); + + if( ( p_physp == NULL ) || ( !osm_physp_is_valid( p_physp ) ) ) + continue; + + p_rphysp = p_physp->p_remote_physp; + + if( ( p_rphysp == NULL ) || ( !osm_physp_is_valid( p_rphysp ) ) ) + continue; + + CL_ASSERT( cPort == p_physp->port_num ); + + if( p_node->node_info.node_type == IB_NODE_TYPE_SWITCH ) + { + p_default_physp = osm_node_get_physp_ptr( p_node, 0 ); + } + else + { + p_default_physp = p_physp; + } + + memcpy(desc, p_node->node_desc.description, + IB_NODE_DESCRIPTION_SIZE); + desc[IB_NODE_DESCRIPTION_SIZE] = '\0'; + + fprintf( rc, "{ %s%s Ports:%02X" + " SystemGUID:%016" PRIx64 + " NodeGUID:%016" PRIx64 + " PortGUID:%016" PRIx64 + " VenID:%06X DevID:%04X Rev:%08X {%s} LID:%04X PN:%02X } ", + ( p_node->node_info.node_type == + IB_NODE_TYPE_SWITCH ) ? "SW" : ( p_node->node_info. + node_type == + IB_NODE_TYPE_CA ) ? + "CA" : ( p_node->node_info.node_type == + IB_NODE_TYPE_ROUTER ) ? "Rt" : "**", + ( p_default_physp->port_info.base_lid == + p_default_physp->port_info. + master_sm_base_lid ) ? "-SM" : "", + p_node->node_info.num_ports, + cl_ntoh64( p_node->node_info.sys_guid ), + cl_ntoh64( p_node->node_info.node_guid ), + cl_ntoh64( p_physp->port_guid ), + cl_ntoh32( ib_node_info_get_vendor_id + ( &p_node->node_info ) ), + cl_ntoh16( p_node->node_info.device_id ), + cl_ntoh32( p_node->node_info.revision ), + desc, + cl_ntoh16( p_default_physp->port_info.base_lid ), + cPort ); + + p_nbnode = p_rphysp->p_node; + + if( p_nbnode->node_info.node_type == IB_NODE_TYPE_SWITCH ) + { + p_default_physp = osm_node_get_physp_ptr( p_nbnode, 0 ); + } + else + { + p_default_physp = p_rphysp; + } + + memcpy(desc, p_nbnode->node_desc.description, + IB_NODE_DESCRIPTION_SIZE); + desc[IB_NODE_DESCRIPTION_SIZE] = '\0'; + + fprintf( rc, "{ %s%s Ports:%02X" + " SystemGUID:%016" PRIx64 + " NodeGUID:%016" PRIx64 + " PortGUID:%016" PRIx64 + " VenID:%08X DevID:%04X Rev:%08X {%s} LID:%04X PN:%02X } ", + ( p_nbnode->node_info.node_type == + IB_NODE_TYPE_SWITCH ) ? "SW" : ( p_nbnode->node_info. + node_type == + IB_NODE_TYPE_CA ) ? + "CA" : ( p_nbnode->node_info.node_type == + IB_NODE_TYPE_ROUTER ) ? "Rt" : "**", + ( p_default_physp->port_info.base_lid == + p_default_physp->port_info. + master_sm_base_lid ) ? "-SM" : "", + p_nbnode->node_info.num_ports, + cl_ntoh64( p_nbnode->node_info.sys_guid ), + cl_ntoh64( p_nbnode->node_info.node_guid ), + cl_ntoh64( p_rphysp->port_guid ), + cl_ntoh32( ib_node_info_get_vendor_id + ( &p_nbnode->node_info ) ), + cl_ntoh32( p_nbnode->node_info.device_id ), + cl_ntoh32( p_nbnode->node_info.revision ), + desc, + cl_ntoh16( p_default_physp->port_info.base_lid ), + p_rphysp->port_num ); + + port_state = ib_port_info_get_port_state( &p_physp->port_info ); + link_speed_act = + ib_port_info_get_link_speed_active( &p_physp->port_info ); + + fprintf( rc, "PHY=%s LOG=%s SPD=%s\n", + ( p_physp->port_info.link_width_active == 1 ) ? "1x" : + ( p_physp->port_info.link_width_active == 2 ) ? "4x" : + ( p_physp->port_info.link_width_active == 8 ) ? "12x" : + "??", + ( ( port_state == IB_LINK_ACTIVE ) ? "ACT" : + ( port_state == IB_LINK_ARMED ) ? "ARM" : + ( port_state == IB_LINK_INIT ) ? "INI" : "DWN" ), + ( link_speed_act == 1 ) ? "2.5" : + ( link_speed_act == 2 ) ? "5" : + ( link_speed_act == 4 ) ? "10" : "??" ); + } + } + p_node = ( osm_node_t * ) cl_qmap_next( &p_node->map_item ); + } + + CL_PLOCK_RELEASE( p_mgr->p_lock ); + + fclose( rc ); + + Exit: + free( file_name ); + OSM_LOG_EXIT( p_mgr->p_log ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_state_mgr_report( + IN osm_state_mgr_t * const p_mgr ) +{ + const cl_qmap_t *p_tbl; + const osm_port_t *p_port; + const osm_node_t *p_node; + const osm_physp_t *p_physp; + const osm_physp_t *p_remote_physp; + const ib_port_info_t *p_pi; + uint8_t port_num; + uint8_t start_port; + uint32_t num_ports; + uint8_t node_type; + + if( !osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) ) + return; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_report ); + + osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE, + "\n===================================================" + "====================================================" + "\nVendor : Ty " + ": # : Sta : LID : LMC : MTU : LWA : LSA : Port GUID " + " : Neighbor Port (Port #)\n" ); + + p_tbl = &p_mgr->p_subn->port_guid_tbl; + + /* + * Hold lock non-exclusively while we perform these read-only operations. + */ + + CL_PLOCK_ACQUIRE( p_mgr->p_lock ); + p_port = ( osm_port_t * ) cl_qmap_head( p_tbl ); + while( p_port != ( osm_port_t * ) cl_qmap_end( p_tbl ) ) + { + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_state_mgr_report: " + "Processing port 0x%016" PRIx64 "\n", + cl_ntoh64( osm_port_get_guid( p_port ) ) ); + } + + p_node = osm_port_get_parent_node( p_port ); + node_type = osm_node_get_type( p_node ); + if( node_type == IB_NODE_TYPE_SWITCH ) + start_port = 0; + else + start_port = 1; + + num_ports = osm_port_get_num_physp( p_port ); + for( port_num = start_port; port_num < num_ports; port_num++ ) + { + p_physp = osm_port_get_phys_ptr( p_port, port_num ); + if( ( p_physp == NULL ) || ( !osm_physp_is_valid( p_physp ) ) ) + continue; + + osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE, "%s : %s : %02X :", + osm_get_manufacturer_str( cl_ntoh64 + ( osm_node_get_node_guid + ( p_node ) ) ), + osm_get_node_type_str_fixed_width( node_type ), + port_num ); + + p_pi = osm_physp_get_port_info_ptr( p_physp ); + + /* + * Port state is not defined for switch port 0 + */ + if( port_num == 0 ) + osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE, " :" ); + else + osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE, " %s :", + osm_get_port_state_str_fixed_width + ( ib_port_info_get_port_state( p_pi ) ) ); + + /* + * LID values are only meaningful in select cases. + */ + if( ib_port_info_get_port_state( p_pi ) != IB_LINK_DOWN + && ( ( node_type == IB_NODE_TYPE_SWITCH && port_num == 0 ) + || node_type != IB_NODE_TYPE_SWITCH ) ) + osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE, " %04X : %01X :", + cl_ntoh16( p_pi->base_lid ), + ib_port_info_get_lmc( p_pi ) ); + else + osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE, " : :" ); + + if( port_num != 0 ) + osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE, " %s : %s : %s ", + osm_get_mtu_str( ib_port_info_get_neighbor_mtu( p_pi ) ), + osm_get_lwa_str( p_pi->link_width_active ), + osm_get_lsa_str( ib_port_info_get_link_speed_active + ( p_pi ) ) ); + else + osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE, " : : " ); + + if( osm_physp_get_port_guid( p_physp ) == + p_mgr->p_subn->sm_port_guid ) + osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE, "* %016" PRIx64 " *", + cl_ntoh64( osm_physp_get_port_guid( p_physp ) ) ); + else + osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE, ": %016" PRIx64 " :", + cl_ntoh64( osm_physp_get_port_guid( p_physp ) ) ); + + if( port_num && + ( ib_port_info_get_port_state( p_pi ) != IB_LINK_DOWN ) ) + { + p_remote_physp = osm_physp_get_remote( p_physp ); + if( p_remote_physp && osm_physp_is_valid( p_remote_physp ) ) + { + osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE, + " %016" PRIx64 " (%02X)", + cl_ntoh64( osm_physp_get_port_guid + ( p_remote_physp ) ), + osm_physp_get_port_num( p_remote_physp ) ); + } + else + osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE, " UNKNOWN" ); + } + + osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE, "\n" ); + } + + osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE, + "------------------------------------------------------" + "------------------------------------------------\n" ); + p_port = ( osm_port_t * ) cl_qmap_next( &p_port->map_item ); + } + + CL_PLOCK_RELEASE( p_mgr->p_lock ); + OSM_LOG_EXIT( p_mgr->p_log ); +} + +/********************************************************************** + **********************************************************************/ +static void +__process_idle_time_queue_done( + IN osm_state_mgr_t * const p_mgr ) +{ + cl_qlist_t *p_list = &p_mgr->idle_time_list; + cl_list_item_t *p_list_item; + osm_idle_item_t *p_process_item; + + OSM_LOG_ENTER( p_mgr->p_log, __process_idle_time_queue_done ); + + cl_spinlock_acquire( &p_mgr->idle_lock ); + p_list_item = cl_qlist_remove_head( p_list ); + + if( p_list_item == cl_qlist_end( p_list ) ) + { + cl_spinlock_release( &p_mgr->idle_lock ); + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__process_idle_time_queue_done: ERR 3314: " + "Idle time queue is empty\n" ); + return; + } + cl_spinlock_release( &p_mgr->idle_lock ); + + p_process_item = ( osm_idle_item_t * ) p_list_item; + + if( p_process_item->pfn_done ) + { + + p_process_item->pfn_done( p_process_item->context1, + p_process_item->context2 ); + } + + free( p_process_item ); + + OSM_LOG_EXIT( p_mgr->p_log ); + return; +} + +/********************************************************************** + **********************************************************************/ +static osm_signal_t +__process_idle_time_queue_start( + IN osm_state_mgr_t * const p_mgr ) +{ + cl_qlist_t *p_list = &p_mgr->idle_time_list; + cl_list_item_t *p_list_item; + osm_idle_item_t *p_process_item; + osm_signal_t signal; + + OSM_LOG_ENTER( p_mgr->p_log, __process_idle_time_queue_start ); + + cl_spinlock_acquire( &p_mgr->idle_lock ); + + p_list_item = cl_qlist_head( p_list ); + if( p_list_item == cl_qlist_end( p_list ) ) + { + cl_spinlock_release( &p_mgr->idle_lock ); + OSM_LOG_EXIT( p_mgr->p_log ); + return OSM_SIGNAL_NONE; + } + + cl_spinlock_release( &p_mgr->idle_lock ); + + p_process_item = ( osm_idle_item_t * ) p_list_item; + + CL_ASSERT( p_process_item->pfn_start ); + + signal = p_process_item->pfn_start( p_process_item->context1, + p_process_item->context2 ); + + CL_ASSERT( signal != OSM_SIGNAL_NONE ); + + OSM_LOG_EXIT( p_mgr->p_log ); + return signal; +} + +/********************************************************************** + * Go over all the remote SMs (as updated in the sm_guid_tbl). + * Find if there is a remote sm that is a master SM. + * If there is a remote master SM - return TRUE, else - return FALSE. + **********************************************************************/ +static osm_remote_sm_t * +__osm_state_mgr_exists_other_master_sm( + IN osm_state_mgr_t * const p_mgr ) +{ + cl_qmap_t *p_sm_tbl; + osm_remote_sm_t *p_sm; + osm_remote_sm_t *p_sm_res = NULL; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_exists_other_master_sm ); + + p_sm_tbl = &p_mgr->p_subn->sm_guid_tbl; + + /* go over all the remote SMs */ + for( p_sm = ( osm_remote_sm_t * ) cl_qmap_head( p_sm_tbl ); + p_sm != ( osm_remote_sm_t * ) cl_qmap_end( p_sm_tbl ); + p_sm = ( osm_remote_sm_t * ) cl_qmap_next( &p_sm->map_item ) ) + { + /* If the sm is in MASTER state - return TRUE */ + if( ib_sminfo_get_state( &p_sm->smi ) == IB_SMINFO_STATE_MASTER ) + { + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_state_mgr_exists_other_master_sm: " + "Found remote master SM with guid:0x%016" PRIx64 "\n", + cl_ntoh64(p_sm->smi.guid) ); + p_sm_res = p_sm; + goto Exit; + } + } + + Exit: + OSM_LOG_EXIT( p_mgr->p_log ); + return ( p_sm_res ); +} + +/********************************************************************** + * Go over all remote SMs (as updated in the sm_guid_tbl). + * Find the one with the highest priority and lowest guid. + * Compare this SM to the local SM. If the local SM is higher - + * return NULL, if the remote SM is higher - return a pointer to it. + **********************************************************************/ +static osm_remote_sm_t * +__osm_state_mgr_get_highest_sm( + IN osm_state_mgr_t * const p_mgr ) +{ + cl_qmap_t *p_sm_tbl; + osm_remote_sm_t *p_sm = NULL; + osm_remote_sm_t *p_highest_sm; + uint8_t highest_sm_priority; + ib_net64_t highest_sm_guid; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_get_highest_sm ); + + p_sm_tbl = &p_mgr->p_subn->sm_guid_tbl; + + /* Start with the local sm as the standard */ + p_highest_sm = NULL; + highest_sm_priority = p_mgr->p_subn->opt.sm_priority; + highest_sm_guid = p_mgr->p_subn->sm_port_guid; + + /* go over all the remote SMs */ + for( p_sm = ( osm_remote_sm_t * ) cl_qmap_head( p_sm_tbl ); + p_sm != ( osm_remote_sm_t * ) cl_qmap_end( p_sm_tbl ); + p_sm = ( osm_remote_sm_t * ) cl_qmap_next( &p_sm->map_item ) ) + { + + /* If the sm is in NOTACTIVE state - continue */ + if( ib_sminfo_get_state( &p_sm->smi ) == IB_SMINFO_STATE_NOTACTIVE ) + continue; + + if( osm_sm_is_greater_than( ib_sminfo_get_priority( &p_sm->smi ), + p_sm->smi.guid, highest_sm_priority, + highest_sm_guid ) ) + { + /* the new p_sm is with higher priority - update the highest_sm */ + /* to this sm */ + p_highest_sm = p_sm; + highest_sm_priority = ib_sminfo_get_priority( &p_sm->smi ); + highest_sm_guid = p_sm->smi.guid; + } + } + + if( p_highest_sm != NULL ) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_state_mgr_get_highest_sm: " + "Found higher SM with guid: %016" PRIx64 "\n", + cl_ntoh64( p_highest_sm->smi.guid ) ); + } + + OSM_LOG_EXIT( p_mgr->p_log ); + return ( p_highest_sm ); +} + +/********************************************************************** + * Send SubnSet(SMInfo) SMP with HANDOVER attribute to the + * remote_sm indicated. + **********************************************************************/ +static void +__osm_state_mgr_send_handover( + IN osm_state_mgr_t * const p_mgr, + IN osm_remote_sm_t * const p_sm ) +{ + uint8_t payload[IB_SMP_DATA_SIZE]; + ib_sm_info_t *p_smi = ( ib_sm_info_t * ) payload; + osm_madw_context_t context; + const osm_port_t *p_port; + ib_api_status_t status; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_send_handover ); + + if( p_mgr->p_subn->opt.testability_mode == + OSM_TEST_MODE_EXIT_BEFORE_SEND_HANDOVER ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_state_mgr_send_handover: ERR 3315: " + "Exit on testability mode OSM_TEST_MODE_EXIT_BEFORE_SEND_HANDOVER\n" ); + osm_exit_flag = TRUE; + sleep( 3 ); + exit( 1 ); + } + + /* + * Send a query of SubnSet(SMInfo) HANDOVER to the remote sm given. + */ + + memset( &context, 0, sizeof( context ) ); + p_port = p_sm->p_port; + if( p_port == NULL ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_state_mgr_send_handover: ERR 3316: " + "No port object on given remote_sm object\n" ); + goto Exit; + } + + /* update the master_guid in the p_sm_state_mgr object according to */ + /* the guid of the port where the new Master SM should reside. */ + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "__osm_state_mgr_send_handover: " + "Handing over mastership. Updating sm_state_mgr master_guid: %016" + PRIx64 "\n", cl_ntoh64( p_port->guid ) ); + p_mgr->p_sm_state_mgr->master_guid = p_port->guid; + + context.smi_context.port_guid = p_port->guid; + context.smi_context.set_method = TRUE; + + p_smi->guid = p_mgr->p_subn->sm_port_guid; + p_smi->act_count = cl_hton32( p_mgr->p_stats->qp0_mads_sent ); + p_smi->pri_state = ( uint8_t ) ( p_mgr->p_subn->sm_state | + p_mgr->p_subn->opt.sm_priority << 4 ); + /* + * Return 0 for the SM key unless we authenticate the requester + * as the master SM. + */ + if( ib_sminfo_get_state( &p_sm->smi ) == IB_SMINFO_STATE_MASTER ) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_state_mgr_send_handover: " + "Responding to master SM with real sm_key\n" ); + p_smi->sm_key = p_mgr->p_subn->opt.sm_key; + } + else + { + /* The requester is not authenticated as master - set sm_key to zero */ + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_state_mgr_send_handover: " + "Responding to SM not master with zero sm_key\n" ); + p_smi->sm_key = 0; + } + + status = osm_req_set( p_mgr->p_req, + osm_physp_get_dr_path_ptr + ( osm_port_get_default_phys_ptr( p_port ) ), payload, + sizeof(payload), + IB_MAD_ATTR_SM_INFO, IB_SMINFO_ATTR_MOD_HANDOVER, + CL_DISP_MSGID_NONE, &context ); + + if( status != IB_SUCCESS ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_state_mgr_send_handover: ERR 3317: " + "Failure requesting SMInfo (%s)\n", ib_get_err_str( status ) ); + } + + Exit: + OSM_LOG_EXIT( p_mgr->p_log ); +} + +/********************************************************************** + * Send Trap 64 on all ports in new_ports_list. + **********************************************************************/ +static void +__osm_state_mgr_report_new_ports( + IN osm_state_mgr_t * const p_mgr ) +{ + osm_port_t *p_port; + ib_gid_t port_gid; + ib_mad_notice_attr_t notice; + ib_api_status_t status; + ib_net64_t port_guid; + uint16_t min_lid_ho; + uint16_t max_lid_ho; + char desc[IB_NODE_DESCRIPTION_SIZE + 1]; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_report_new_ports ); + + CL_PLOCK_ACQUIRE( p_mgr->p_lock ); + p_port = + ( osm_port_t + * ) ( cl_list_remove_head( &p_mgr->p_subn->new_ports_list ) ); + while( p_port != NULL ) + { + port_guid = osm_port_get_guid( p_port ); + /* issue a notice - trap 64 */ + + /* details of the notice */ + notice.generic_type = 0x83; /* is generic subn mgt type */ + ib_notice_set_prod_type_ho( ¬ice, 4 ); /* A Class Manager generator */ + /* endport becomes to be reachable */ + notice.g_or_v.generic.trap_num = CL_HTON16( 64 ); + /* The sm_base_lid is saved in network order already. */ + notice.issuer_lid = p_mgr->p_subn->sm_base_lid; + /* following C14-72.1.1 and table 119 p725 */ + /* we need to provide the GID */ + port_gid.unicast.prefix = p_mgr->p_subn->opt.subnet_prefix; + port_gid.unicast.interface_id = port_guid; + memcpy( &( notice.data_details.ntc_64_67.gid ), + &( port_gid ), sizeof( ib_gid_t ) ); + + /* According to page 653 - the issuer gid in this case of trap + * is the SM gid, since the SM is the initiator of this trap. */ + notice.issuer_gid.unicast.prefix = p_mgr->p_subn->opt.subnet_prefix; + notice.issuer_gid.unicast.interface_id = p_mgr->p_subn->sm_port_guid; + + status = osm_report_notice( p_mgr->p_log, p_mgr->p_subn, ¬ice ); + if( status != IB_SUCCESS ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_state_mgr_report_new_ports: ERR 3318: " + "Error sending trap reports on GUID:0x%016" PRIx64 + " (%s)\n", port_gid.unicast.interface_id, + ib_get_err_str( status ) ); + } + osm_port_get_lid_range_ho( p_port, &min_lid_ho, &max_lid_ho ); + if (p_port->p_node) + { + memcpy(desc, p_port->p_node->node_desc.description, + IB_NODE_DESCRIPTION_SIZE); + desc[IB_NODE_DESCRIPTION_SIZE] = '\0'; + } + osm_log( p_mgr->p_log, OSM_LOG_INFO, + "Discovered new port with GUID:0x%016" PRIx64 + " LID range [0x%X,0x%X] of node:%s\n", + cl_ntoh64( port_gid.unicast.interface_id ), + min_lid_ho, max_lid_ho, + p_port->p_node ? desc : "UNKNOWN" ); + + p_port = + ( osm_port_t + * ) ( cl_list_remove_head( &p_mgr->p_subn->new_ports_list ) ); + } + CL_PLOCK_RELEASE( p_mgr->p_lock ); + + OSM_LOG_EXIT( p_mgr->p_log ); +} + +/********************************************************************** + * Make sure that the lid_port_tbl of the subnet has only the ports + * that are recognized, and in the correct lid place. There could be + * errors if we wanted to assign a certain port with lid X, but that + * request didn't reach the port. In this case port_lid_tbl will have + * the port under lid X, though the port isn't updated with this lid. + * We will run a new heavy sweep (since there were errors in the + * initialization), but here we'll clean the database from incorrect + * information. + **********************************************************************/ +static void +__osm_state_mgr_check_tbl_consistency( + IN osm_state_mgr_t * const p_mgr ) +{ + cl_qmap_t *p_port_guid_tbl; + osm_port_t *p_port; + osm_port_t *p_next_port; + cl_ptr_vector_t *p_port_lid_tbl; + size_t max_lid, ref_size, curr_size, lid; + osm_port_t *p_port_ref, *p_port_stored; + cl_ptr_vector_t ref_port_lid_tbl; + uint16_t min_lid_ho; + uint16_t max_lid_ho; + uint16_t lid_ho; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_check_tbl_consistency ); + + cl_ptr_vector_construct( &ref_port_lid_tbl ); + cl_ptr_vector_init( &ref_port_lid_tbl, + cl_ptr_vector_get_size( &p_mgr->p_subn->port_lid_tbl ), + OSM_SUBNET_VECTOR_GROW_SIZE ); + + p_port_guid_tbl = &p_mgr->p_subn->port_guid_tbl; + + /* Let's go over all the ports according to port_guid_tbl, + * and add the port to a reference port_lid_tbl. */ + p_next_port = ( osm_port_t * ) cl_qmap_head( p_port_guid_tbl ); + while( p_next_port != ( osm_port_t * ) cl_qmap_end( p_port_guid_tbl ) ) + { + p_port = p_next_port; + p_next_port = ( osm_port_t * ) cl_qmap_next( &p_next_port->map_item ); + + osm_port_get_lid_range_ho( p_port, &min_lid_ho, &max_lid_ho ); + for( lid_ho = min_lid_ho; lid_ho <= max_lid_ho; lid_ho++ ) + cl_ptr_vector_set( &ref_port_lid_tbl, lid_ho, p_port ); + } + + p_port_lid_tbl = &p_mgr->p_subn->port_lid_tbl; + + ref_size = cl_ptr_vector_get_size( &ref_port_lid_tbl ); + curr_size = cl_ptr_vector_get_size( p_port_lid_tbl ); + /* They should be the same, but compare it anyway */ + max_lid = ( ref_size > curr_size ) ? ref_size : curr_size; + + for( lid = 1; lid <= max_lid; lid++ ) + { + p_port_ref = NULL; + p_port_stored = NULL; + cl_ptr_vector_at( p_port_lid_tbl, lid, ( void * )&p_port_stored ); + cl_ptr_vector_at( &ref_port_lid_tbl, lid, ( void * )&p_port_ref ); + + if( p_port_stored == p_port_ref ) + /* This is the "good" case - both entries are the same for this lid. + * Nothing to do. */ + continue; + + if( p_port_ref == NULL ) + { + /* There is an object in the subnet database for this lid, + * but no such object exists in the reference port_list_tbl. + * This can occur if we wanted to assign a certain port with some + * lid (different than the one pre-assigned to it), and the port + * didn't get the PortInfo Set request. Due to this, the port + * is updated with its original lid in our database, but with the + * new lid we wanted to give it in our port_lid_tbl. */ + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_state_mgr_check_tbl_consistency: ERR 3322: " + "lid 0x%zX is wrongly assigned to port 0x%016" PRIx64 + " in port_lid_tbl\n", + lid, cl_ntoh64( osm_port_get_guid( p_port_stored ) ) ); + } + else + { + if( p_port_stored == NULL ) + { + /* There is an object in the new database, but no object in our subnet + * database. This is the matching case of the prior check - the port + * still has its original lid. */ + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_state_mgr_check_tbl_consistency: ERR 3323: " + "port 0x%016" PRIx64 " exists in new port_lid_tbl under " + "lid 0x%zX, but missing in subnet port_lid_tbl db\n", + cl_ntoh64( osm_port_get_guid( p_port_ref ) ), lid ); + } + else + { + + /* if we reached here then p_port_stored != p_port_ref. + * We were trying to set a lid to p_port_stored, but it didn't reach it, + * and p_port_ref also didn't get the lid update. */ + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_state_mgr_check_tbl_consistency: ERR 3324: " + "lid 0x%zX has port 0x%016" PRIx64 + " in new port_lid_tbl db, " "and port 0x%016" PRIx64 + " in subnet port_lid_tbl db\n", lid, + cl_ntoh64( osm_port_get_guid( p_port_ref ) ), + cl_ntoh64( osm_port_get_guid( p_port_stored ) ) ); + } + } + /* In any of these cases we want to set NULL in the port_lid_tbl, since this + * entry is invalid. Also, make sure we'll do another heavy sweep. */ + cl_ptr_vector_set( p_port_lid_tbl, lid, NULL ); + p_mgr->p_subn->subnet_initialization_error = TRUE; + } + + cl_ptr_vector_destroy( &ref_port_lid_tbl ); + OSM_LOG_EXIT( p_mgr->p_log ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_state_mgr_process( + IN osm_state_mgr_t * const p_mgr, + IN osm_signal_t signal ) +{ + ib_api_status_t status; + osm_remote_sm_t *p_remote_sm; + osm_signal_t tmp_signal; + + CL_ASSERT( p_mgr ); + + OSM_LOG_ENTER( p_mgr->p_log, osm_state_mgr_process ); + + /* if we are exiting do nothing */ + if( osm_exit_flag ) + signal = OSM_SIGNAL_NONE; + + /* + * The state lock prevents many race conditions from screwing + * up the state transition process. For example, if an function + * puts transactions on the wire, the state lock guarantees this + * loop will see the return code ("DONE PENDING") of the function + * before the "NO OUTSTANDING TRANSACTIONS" signal is asynchronously + * received. + */ + cl_spinlock_acquire( &p_mgr->state_lock ); + + while( signal != OSM_SIGNAL_NONE ) + { + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "osm_state_mgr_process: " + "Received signal %s in state %s\n", + osm_get_sm_signal_str( signal ), + osm_get_sm_state_str( p_mgr->state ) ); + } + + /* + * If we're already sweeping and we get the signal to sweep, + * just ignore it harmlessly. + */ + if( ( p_mgr->state != OSM_SM_STATE_IDLE ) && + ( p_mgr->state != OSM_SM_STATE_STANDBY ) && + ( signal == OSM_SIGNAL_SWEEP ) ) + { + break; + } + + switch ( p_mgr->state ) + { + case OSM_SM_STATE_IDLE: + switch ( signal ) + { + case OSM_SIGNAL_SWEEP: + /* + * If the osm_sm_state_mgr is in INIT state - signal + * it with a INIT signal to move it to DISCOVERY state. + */ + if( p_mgr->p_subn->sm_state == IB_SMINFO_STATE_INIT ) + osm_sm_state_mgr_process( p_mgr->p_sm_state_mgr, + OSM_SM_SIGNAL_INIT ); + + /* + * If we already have switches, then try a light sweep. + * Otherwise, this is probably our first discovery pass + * or we are connected in loopback. In both cases do a + * heavy sweep. + * Note: If we are connected in loopback we want a heavy + * sweep, since we will not be getting any traps if there is + * a lost connection. + */ + /* if we are in DISCOVERING state - this means it is either in + * initializing or wake up from STANDBY - run the heavy sweep */ + if( cl_qmap_count( &p_mgr->p_subn->sw_guid_tbl ) && + p_mgr->p_subn->sm_state != IB_SMINFO_STATE_DISCOVERING && + p_mgr->p_subn->opt.force_heavy_sweep == FALSE && + p_mgr->p_subn->force_immediate_heavy_sweep == FALSE && + p_mgr->p_subn->force_delayed_heavy_sweep == FALSE && + p_mgr->p_subn->subnet_initialization_error == FALSE ) + { + if( __osm_state_mgr_light_sweep_start( p_mgr ) == IB_SUCCESS ) + { + p_mgr->state = OSM_SM_STATE_SWEEP_LIGHT; + } + } + else + { + /* First of all - if force_immediate_heavy_sweep is TRUE then + * need to unset it */ + p_mgr->p_subn->force_immediate_heavy_sweep = FALSE; + /* If force_delayed_heavy_sweep is TRUE then + * need to unset it */ + p_mgr->p_subn->force_delayed_heavy_sweep = FALSE; + /* If subnet_initialization_error is TRUE then + * need to unset it. */ + p_mgr->p_subn->subnet_initialization_error = FALSE; + + /* rescan configuration updates */ + osm_subn_rescan_conf_file(&p_mgr->p_subn->opt); + + status = __osm_state_mgr_sweep_hop_0( p_mgr ); + if( status == IB_SUCCESS ) + { + p_mgr->state = OSM_SM_STATE_SWEEP_HEAVY_SELF; + } + } + signal = OSM_SIGNAL_NONE; + break; + + case OSM_SIGNAL_IDLE_TIME_PROCESS_REQUEST: + p_mgr->state = OSM_SM_STATE_PROCESS_REQUEST; + signal = OSM_SIGNAL_IDLE_TIME_PROCESS; + break; + + default: + __osm_state_mgr_signal_error( p_mgr, signal ); + signal = OSM_SIGNAL_NONE; + break; + } + break; + + case OSM_SM_STATE_PROCESS_REQUEST: + switch ( signal ) + { + case OSM_SIGNAL_IDLE_TIME_PROCESS: + signal = __process_idle_time_queue_start( p_mgr ); + switch ( signal ) + { + case OSM_SIGNAL_NONE: + p_mgr->state = OSM_SM_STATE_IDLE; + break; + + case OSM_SIGNAL_DONE_PENDING: + p_mgr->state = OSM_SM_STATE_PROCESS_REQUEST_WAIT; + signal = OSM_SIGNAL_NONE; + break; + + case OSM_SIGNAL_DONE: + p_mgr->state = OSM_SM_STATE_PROCESS_REQUEST_DONE; + break; + + default: + __osm_state_mgr_signal_error( p_mgr, signal ); + signal = OSM_SIGNAL_NONE; + break; + } + break; + + default: + __osm_state_mgr_signal_error( p_mgr, signal ); + signal = OSM_SIGNAL_NONE; + break; + } + break; + + case OSM_SM_STATE_PROCESS_REQUEST_WAIT: + switch ( signal ) + { + case OSM_SIGNAL_NO_PENDING_TRANSACTIONS: + p_mgr->state = OSM_SM_STATE_PROCESS_REQUEST_DONE; + break; + + default: + __osm_state_mgr_signal_error( p_mgr, signal ); + signal = OSM_SIGNAL_NONE; + break; + } + break; + + case OSM_SM_STATE_PROCESS_REQUEST_DONE: + switch ( signal ) + { + case OSM_SIGNAL_NO_PENDING_TRANSACTIONS: + case OSM_SIGNAL_DONE: + /* CALL the done function */ + __process_idle_time_queue_done( p_mgr ); + + /* + * Set the signal to OSM_SIGNAL_IDLE_TIME_PROCESS + * so that the next element in the queue gets processed + */ + + signal = OSM_SIGNAL_IDLE_TIME_PROCESS; + p_mgr->state = OSM_SM_STATE_PROCESS_REQUEST; + break; + + default: + __osm_state_mgr_signal_error( p_mgr, signal ); + signal = OSM_SIGNAL_NONE; + break; + } + break; + + case OSM_SM_STATE_SWEEP_LIGHT: + switch ( signal ) + { + case OSM_SIGNAL_LIGHT_SWEEP_FAIL: + case OSM_SIGNAL_CHANGE_DETECTED: + /* + * Nothing else to do yet except change state. + */ + p_mgr->state = OSM_SM_STATE_SWEEP_LIGHT_WAIT; + signal = OSM_SIGNAL_NONE; + break; + + case OSM_SIGNAL_NO_PENDING_TRANSACTIONS: + /* + * No change was detected on the subnet. + * We can return to the idle state. + */ + __osm_state_mgr_light_sweep_done_msg( p_mgr ); + p_mgr->state = OSM_SM_STATE_PROCESS_REQUEST; + signal = OSM_SIGNAL_IDLE_TIME_PROCESS; + break; + + default: + __osm_state_mgr_signal_error( p_mgr, signal ); + signal = OSM_SIGNAL_NONE; + break; + } + break; + + case OSM_SM_STATE_SWEEP_LIGHT_WAIT: + switch ( signal ) + { + case OSM_SIGNAL_LIGHT_SWEEP_FAIL: + case OSM_SIGNAL_CHANGE_DETECTED: + /* + * Nothing to do here. One subnet change typcially + * begets another.... But needs to wait for all transactions to + * complete + */ + break; + + case OSM_SIGNAL_NO_PENDING_TRANSACTIONS: + /* + * A change was detected on the subnet. + * Initiate a heavy sweep. + */ + if( __osm_state_mgr_sweep_hop_0( p_mgr ) == IB_SUCCESS ) + { + p_mgr->state = OSM_SM_STATE_SWEEP_HEAVY_SELF; + } + break; + + default: + __osm_state_mgr_signal_error( p_mgr, signal ); + break; + } + signal = OSM_SIGNAL_NONE; + break; + + case OSM_SM_STATE_SWEEP_HEAVY_SELF: + switch ( signal ) + { + case OSM_SIGNAL_CHANGE_DETECTED: + /* + * Nothing to do here. One subnet change typcially + * begets another.... But needs to wait for all transactions + */ + signal = OSM_SIGNAL_NONE; + break; + + case OSM_SIGNAL_NO_PENDING_TRANSACTIONS: + if( __osm_state_mgr_is_sm_port_down( p_mgr ) == TRUE ) + { + __osm_state_mgr_sm_port_down_msg( p_mgr ); + + /* Run the drop manager - we want to clear all records */ + osm_drop_mgr_process( p_mgr->p_drop_mgr ); + + /* Move to DISCOVERING state */ + osm_sm_state_mgr_process( p_mgr->p_sm_state_mgr, + OSM_SM_SIGNAL_DISCOVER ); + + p_mgr->state = OSM_SM_STATE_PROCESS_REQUEST; + signal = OSM_SIGNAL_IDLE_TIME_PROCESS; + } + else + { + if( __osm_state_mgr_sweep_hop_1( p_mgr ) == IB_SUCCESS ) + { + p_mgr->state = OSM_SM_STATE_SWEEP_HEAVY_SUBNET; + } + signal = OSM_SIGNAL_NONE; + } + break; + + default: + __osm_state_mgr_signal_error( p_mgr, signal ); + signal = OSM_SIGNAL_NONE; + break; + } + break; + + /* + * There is no 'OSM_SM_STATE_SWEEP_HEAVY_WAIT' state since we + * know that there are outstanding transactions on the wire already... + */ + case OSM_SM_STATE_SWEEP_HEAVY_SUBNET: + switch ( signal ) + { + case OSM_SIGNAL_CHANGE_DETECTED: + /* + * Nothing to do here. One subnet change typically + * begets another.... + */ + signal = OSM_SIGNAL_NONE; + break; + + case OSM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED: + p_mgr->state = OSM_SM_STATE_MASTER_OR_HIGHER_SM_DETECTED; + break; + + case OSM_SIGNAL_NO_PENDING_TRANSACTIONS: + __osm_state_mgr_sweep_heavy_done_msg( p_mgr ); + + /* If we are MASTER - get the highest remote_sm, and + * see if it is higher than our local sm. If + */ + if( p_mgr->p_subn->sm_state == IB_SMINFO_STATE_MASTER ) + { + p_remote_sm = __osm_state_mgr_get_highest_sm( p_mgr ); + if( p_remote_sm != NULL ) + { + /* need to handover the mastership + * to the remote sm, and move to standby */ + __osm_state_mgr_send_handover( p_mgr, p_remote_sm ); + osm_sm_state_mgr_process( p_mgr->p_sm_state_mgr, + OSM_SM_SIGNAL_HANDOVER_SENT ); + p_mgr->state = OSM_SM_STATE_STANDBY; + signal = OSM_SIGNAL_NONE; + break; + } + else + { + /* We are the highest sm - check to see if there is + * a remote SM that is in master state. */ + p_remote_sm = __osm_state_mgr_exists_other_master_sm( p_mgr ); + if( p_remote_sm != NULL ) + { + /* There is a remote SM that is master. + * need to wait for that SM to relinquish control + * of its portion of the subnet. C14-60. + * Also - need to start polling on that SM. */ + p_mgr->p_sm_state_mgr->p_polling_sm = p_remote_sm; + osm_sm_state_mgr_process( p_mgr->p_sm_state_mgr, + OSM_SM_SIGNAL_WAIT_FOR_HANDOVER ); + p_mgr->state = OSM_SM_STATE_PROCESS_REQUEST; + signal = OSM_SIGNAL_IDLE_TIME_PROCESS; + break; + } + } + } + + /* Need to continue with lid assignment */ + osm_drop_mgr_process( p_mgr->p_drop_mgr ); + + p_mgr->state = OSM_SM_STATE_SET_PKEY; + + /* + * If we are not MASTER already - this means that we are + * in discovery state. call osm_sm_state_mgr with signal + * DISCOVERY_COMPLETED + */ + if( p_mgr->p_subn->sm_state == IB_SMINFO_STATE_DISCOVERING ) + osm_sm_state_mgr_process( p_mgr->p_sm_state_mgr, + OSM_SM_SIGNAL_DISCOVERY_COMPLETED ); + + /* the returned signal might be DONE or DONE_PENDING */ + signal = osm_pkey_mgr_process( p_mgr->p_subn->p_osm ); + + /* the returned signal is always DONE */ + tmp_signal = osm_qos_setup(p_mgr->p_subn->p_osm); + + if (tmp_signal == OSM_SIGNAL_DONE_PENDING) + signal = OSM_SIGNAL_DONE_PENDING; + + /* try to restore SA DB (this should be before lid_mgr + because we may want to disable clients reregistration + when SA DB is restored) */ + osm_sa_db_file_load(p_mgr->p_subn->p_osm); + + break; + + default: + __osm_state_mgr_signal_error( p_mgr, signal ); + signal = OSM_SIGNAL_NONE; + break; + } + break; + + case OSM_SM_STATE_SET_PKEY: + switch ( signal ) + { + case OSM_SIGNAL_DONE: + p_mgr->state = OSM_SM_STATE_SET_PKEY_DONE; + break; + + case OSM_SIGNAL_DONE_PENDING: + /* + * There are outstanding transactions, so we + * must wait for the wire to clear. + */ + p_mgr->state = OSM_SM_STATE_SET_PKEY_WAIT; + signal = OSM_SIGNAL_NONE; + break; + + default: + __osm_state_mgr_signal_error( p_mgr, signal ); + signal = OSM_SIGNAL_NONE; + break; + } + break; + + case OSM_SM_STATE_SET_PKEY_WAIT: + switch ( signal ) + { + case OSM_SIGNAL_NO_PENDING_TRANSACTIONS: + p_mgr->state = OSM_SM_STATE_SET_PKEY_DONE; + break; + + default: + __osm_state_mgr_signal_error( p_mgr, signal ); + signal = OSM_SIGNAL_NONE; + break; + } + break; + + case OSM_SM_STATE_SET_PKEY_DONE: + switch ( signal ) + { + case OSM_SIGNAL_NO_PENDING_TRANSACTIONS: + case OSM_SIGNAL_DONE: + p_mgr->state = OSM_SM_STATE_SET_SM_UCAST_LID; + signal = osm_lid_mgr_process_sm( p_mgr->p_lid_mgr ); + break; + + default: + __osm_state_mgr_signal_error( p_mgr, signal ); + signal = OSM_SIGNAL_NONE; + break; + } + break; + + case OSM_SM_STATE_SET_SM_UCAST_LID: + switch ( signal ) + { + case OSM_SIGNAL_DONE: + p_mgr->state = OSM_SM_STATE_SET_SM_UCAST_LID_DONE; + break; + + case OSM_SIGNAL_DONE_PENDING: + /* + * There are outstanding transactions, so we + * must wait for the wire to clear. + */ + p_mgr->state = OSM_SM_STATE_SET_SM_UCAST_LID_WAIT; + signal = OSM_SIGNAL_NONE; + break; + + default: + __osm_state_mgr_signal_error( p_mgr, signal ); + signal = OSM_SIGNAL_NONE; + break; + } + break; + + case OSM_SM_STATE_SET_SM_UCAST_LID_WAIT: + switch ( signal ) + { + case OSM_SIGNAL_NO_PENDING_TRANSACTIONS: + p_mgr->state = OSM_SM_STATE_SET_SM_UCAST_LID_DONE; + break; + + default: + __osm_state_mgr_signal_error( p_mgr, signal ); + signal = OSM_SIGNAL_NONE; + break; + } + break; + + case OSM_SM_STATE_SET_SM_UCAST_LID_DONE: + switch ( signal ) + { + case OSM_SIGNAL_NO_PENDING_TRANSACTIONS: + case OSM_SIGNAL_DONE: + /* If we run single step we have already done this */ + if( p_mgr->state_step_mode != OSM_STATE_STEP_TAKE_ONE ) + { + __osm_state_mgr_set_sm_lid_done_msg( p_mgr ); + __osm_state_mgr_notify_lid_change( p_mgr ); + } + + /* Break on single step mode - if not continuous */ + if( p_mgr->state_step_mode == OSM_STATE_STEP_BREAK ) + { + p_mgr->next_stage_signal = signal; + signal = OSM_SIGNAL_NONE; + break; + } + + p_mgr->state = OSM_SM_STATE_SET_SUBNET_UCAST_LIDS; + signal = osm_lid_mgr_process_subnet( p_mgr->p_lid_mgr ); + break; + + default: + __osm_state_mgr_signal_error( p_mgr, signal ); + signal = OSM_SIGNAL_NONE; + break; + } + break; + + + case OSM_SM_STATE_SET_SUBNET_UCAST_LIDS: + switch ( signal ) + { + case OSM_SIGNAL_DONE: + /* + * The LID Manager is done processing. + * There are no outstanding transactions, so we + * can move on to configuring the forwarding tables. + */ + p_mgr->state = OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_DONE; + break; + + case OSM_SIGNAL_DONE_PENDING: + /* + * The LID Manager is done processing. + * There are outstanding transactions, so we + * must wait for the wire to clear. + */ + p_mgr->state = OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_WAIT; + signal = OSM_SIGNAL_NONE; + break; + + default: + __osm_state_mgr_signal_error( p_mgr, signal ); + signal = OSM_SIGNAL_NONE; + break; + } + break; + + /* + * In this state, the Unicast Manager has completed processing, + * but there are still transactions on the wire. Therefore, + * wait here until the wire clears. + */ + case OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_WAIT: + switch ( signal ) + { + case OSM_SIGNAL_NO_PENDING_TRANSACTIONS: + /* + * The LID Manager is done processing. + * There are no outstanding transactions, so we + * can move on to configuring the forwarding tables. + */ + p_mgr->state = OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_DONE; + break; + + default: + __osm_state_mgr_signal_error( p_mgr, signal ); + signal = OSM_SIGNAL_NONE; + break; + } + break; + + case OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_DONE: + + switch ( signal ) + { + case OSM_SIGNAL_DONE: + case OSM_SIGNAL_NO_PENDING_TRANSACTIONS: + /* At this point we need to check the consistency of + * the port_lid_tbl under the subnet. There might be + * errors in it if PortInfo Set reqeusts didn't reach + * their destination. */ + __osm_state_mgr_check_tbl_consistency( p_mgr ); + + /* If we run single step we have already done this */ + if( p_mgr->state_step_mode != OSM_STATE_STEP_TAKE_ONE ) + __osm_state_mgr_lid_assign_msg( p_mgr ); + + /* Break on single step mode - just before taking next step */ + if( p_mgr->state_step_mode == OSM_STATE_STEP_BREAK ) + { + p_mgr->next_stage_signal = signal; + signal = OSM_SIGNAL_NONE; + break; + } + + /* + * OK, the wire is clear, so proceed with + * unicast forwarding table configuration. + * First - send trap 64 on newly discovered endports + */ + __osm_state_mgr_report_new_ports( p_mgr ); + + p_mgr->state = OSM_SM_STATE_SET_UCAST_TABLES; + signal = osm_ucast_mgr_process( p_mgr->p_ucast_mgr ); + + /* Break on single step mode */ + if( p_mgr->state_step_mode != OSM_STATE_STEP_CONTINUOUS ) + { + p_mgr->next_stage_signal = signal; + signal = OSM_SIGNAL_NONE; + } + + break; + + default: + __osm_state_mgr_signal_error( p_mgr, signal ); + signal = OSM_SIGNAL_NONE; + break; + } + break; + + case OSM_SM_STATE_SET_UCAST_TABLES: + switch ( signal ) + { + case OSM_SIGNAL_DONE: + p_mgr->state = OSM_SM_STATE_SET_UCAST_TABLES_DONE; + break; + + case OSM_SIGNAL_DONE_PENDING: + /* + * The Unicast Manager is done processing. + * There are outstanding transactions, so we + * must wait for the wire to clear. + */ + p_mgr->state = OSM_SM_STATE_SET_UCAST_TABLES_WAIT; + signal = OSM_SIGNAL_NONE; + break; + + default: + __osm_state_mgr_signal_error( p_mgr, signal ); + signal = OSM_SIGNAL_NONE; + break; + } + break; + + case OSM_SM_STATE_SET_UCAST_TABLES_WAIT: + switch ( signal ) + { + case OSM_SIGNAL_NO_PENDING_TRANSACTIONS: + p_mgr->state = OSM_SM_STATE_SET_UCAST_TABLES_DONE; + break; + + default: + __osm_state_mgr_signal_error( p_mgr, signal ); + signal = OSM_SIGNAL_NONE; + break; + } + break; + + case OSM_SM_STATE_SET_UCAST_TABLES_DONE: + switch ( signal ) + { + case OSM_SIGNAL_NO_PENDING_TRANSACTIONS: + case OSM_SIGNAL_DONE: + /* we are done setting all LFTs so clear the ignore existing. + * From now on, as long as we are still master, we want to + * take into account these lfts. */ + p_mgr->p_subn->ignore_existing_lfts = FALSE; + + /* If we run single step we have already done this */ + if( p_mgr->state_step_mode != OSM_STATE_STEP_TAKE_ONE ) + __osm_state_mgr_switch_config_msg( p_mgr ); + + /* Break on single step mode - just before taking next step */ + if( p_mgr->state_step_mode == OSM_STATE_STEP_BREAK ) + { + p_mgr->next_stage_signal = signal; + signal = OSM_SIGNAL_NONE; + break; + } + + if( !p_mgr->p_subn->opt.disable_multicast ) + { + p_mgr->state = OSM_SM_STATE_SET_MCAST_TABLES; + signal = osm_mcast_mgr_process( p_mgr->p_mcast_mgr ); + } + else + { + p_mgr->state = OSM_SM_STATE_SET_LINK_PORTS; + signal = osm_link_mgr_process( p_mgr->p_link_mgr, + IB_LINK_NO_CHANGE ); + } + break; + + default: + __osm_state_mgr_signal_error( p_mgr, signal ); + signal = OSM_SIGNAL_NONE; + break; + } + break; + + case OSM_SM_STATE_SET_MCAST_TABLES: + switch ( signal ) + { + case OSM_SIGNAL_DONE: + p_mgr->state = OSM_SM_STATE_SET_MCAST_TABLES_DONE; + break; + + case OSM_SIGNAL_DONE_PENDING: + /* + * The Multicast Manager is done processing. + * There are outstanding transactions, so we + * must wait for the wire to clear. + */ + p_mgr->state = OSM_SM_STATE_SET_MCAST_TABLES_WAIT; + signal = OSM_SIGNAL_NONE; + break; + + default: + __osm_state_mgr_signal_error( p_mgr, signal ); + signal = OSM_SIGNAL_NONE; + break; + } + break; + + case OSM_SM_STATE_SET_MCAST_TABLES_WAIT: + switch ( signal ) + { + case OSM_SIGNAL_NO_PENDING_TRANSACTIONS: + p_mgr->state = OSM_SM_STATE_SET_MCAST_TABLES_DONE; + break; + + default: + __osm_state_mgr_signal_error( p_mgr, signal ); + signal = OSM_SIGNAL_NONE; + break; + } + break; + + case OSM_SM_STATE_SET_MCAST_TABLES_DONE: + switch ( signal ) + { + case OSM_SIGNAL_NO_PENDING_TRANSACTIONS: + case OSM_SIGNAL_DONE: + /* If we run single step we have already done this */ + if( p_mgr->state_step_mode != OSM_STATE_STEP_TAKE_ONE ) + __osm_state_mgr_multicast_config_msg( p_mgr ); + + /* Break on single step mode - just before taking next step */ + if( p_mgr->state_step_mode == OSM_STATE_STEP_BREAK ) + { + p_mgr->next_stage_signal = signal; + signal = OSM_SIGNAL_NONE; + break; + } + + p_mgr->state = OSM_SM_STATE_SET_LINK_PORTS; + signal = osm_link_mgr_process( p_mgr->p_link_mgr, + IB_LINK_NO_CHANGE ); + break; + + default: + __osm_state_mgr_signal_error( p_mgr, signal ); + signal = OSM_SIGNAL_NONE; + break; + } + break; + + /* + * The LINK_PORTS state is required since we can not count on + * the port state change MADs to succeed. This is an artifact + * of the spec defining state change from state X to state X + * as an error. The hardware then is not required to process + * other parameters provided by the Set(PortInfo) Packet. + */ + case OSM_SM_STATE_SET_LINK_PORTS: + switch ( signal ) + { + case OSM_SIGNAL_DONE: + p_mgr->state = OSM_SM_STATE_SET_LINK_PORTS_DONE; + break; + + case OSM_SIGNAL_DONE_PENDING: + /* + * The Link Manager is done processing. + * There are outstanding transactions, so we + * must wait for the wire to clear. + */ + p_mgr->state = OSM_SM_STATE_SET_LINK_PORTS_WAIT; + signal = OSM_SIGNAL_NONE; + break; + + default: + __osm_state_mgr_signal_error( p_mgr, signal ); + signal = OSM_SIGNAL_NONE; + break; + } + break; + + case OSM_SM_STATE_SET_LINK_PORTS_WAIT: + switch ( signal ) + { + case OSM_SIGNAL_NO_PENDING_TRANSACTIONS: + p_mgr->state = OSM_SM_STATE_SET_LINK_PORTS_DONE; + break; + + default: + __osm_state_mgr_signal_error( p_mgr, signal ); + signal = OSM_SIGNAL_NONE; + break; + } + break; + + case OSM_SM_STATE_SET_LINK_PORTS_DONE: + switch ( signal ) + { + case OSM_SIGNAL_NO_PENDING_TRANSACTIONS: + case OSM_SIGNAL_DONE: + + __osm_state_mgr_links_ports_msg( p_mgr ); + + p_mgr->state = OSM_SM_STATE_SET_ARMED; + signal = osm_link_mgr_process( p_mgr->p_link_mgr, IB_LINK_ARMED ); + break; + + default: + __osm_state_mgr_signal_error( p_mgr, signal ); + signal = OSM_SIGNAL_NONE; + break; + } + break; + + case OSM_SM_STATE_SET_ARMED: + switch ( signal ) + { + case OSM_SIGNAL_DONE: + p_mgr->state = OSM_SM_STATE_SET_ARMED_DONE; + break; + + case OSM_SIGNAL_DONE_PENDING: + /* + * The Link Manager is done processing. + * There are outstanding transactions, so we + * must wait for the wire to clear. + */ + p_mgr->state = OSM_SM_STATE_SET_ARMED_WAIT; + signal = OSM_SIGNAL_NONE; + break; + + default: + __osm_state_mgr_signal_error( p_mgr, signal ); + signal = OSM_SIGNAL_NONE; + break; + } + break; + + case OSM_SM_STATE_SET_ARMED_WAIT: + switch ( signal ) + { + case OSM_SIGNAL_NO_PENDING_TRANSACTIONS: + p_mgr->state = OSM_SM_STATE_SET_ARMED_DONE; + break; + + default: + __osm_state_mgr_signal_error( p_mgr, signal ); + signal = OSM_SIGNAL_NONE; + break; + } + break; + + case OSM_SM_STATE_SET_ARMED_DONE: + switch ( signal ) + { + case OSM_SIGNAL_NO_PENDING_TRANSACTIONS: + case OSM_SIGNAL_DONE: + + /* If we run single step we have already done this */ + if( p_mgr->state_step_mode != OSM_STATE_STEP_TAKE_ONE ) + __osm_state_mgr_links_armed_msg( p_mgr ); + + /* Break on single step mode - just before taking next step */ + if( p_mgr->state_step_mode == OSM_STATE_STEP_BREAK ) + { + p_mgr->next_stage_signal = signal; + signal = OSM_SIGNAL_NONE; + break; + } + + p_mgr->state = OSM_SM_STATE_SET_ACTIVE; + signal = osm_link_mgr_process( p_mgr->p_link_mgr, + IB_LINK_ACTIVE ); + break; + + default: + __osm_state_mgr_signal_error( p_mgr, signal ); + signal = OSM_SIGNAL_NONE; + break; + } + break; + + case OSM_SM_STATE_SET_ACTIVE: + switch ( signal ) + { + case OSM_SIGNAL_DONE: + /* + * Don't change the signal, just the state. + */ + p_mgr->state = OSM_SM_STATE_SUBNET_UP; + break; + + case OSM_SIGNAL_DONE_PENDING: + /* + * The Link Manager is done processing. + * There are outstanding transactions, so we + * must wait for the wire to clear. + */ + p_mgr->state = OSM_SM_STATE_SET_ACTIVE_WAIT; + signal = OSM_SIGNAL_NONE; + break; + + default: + __osm_state_mgr_signal_error( p_mgr, signal ); + signal = OSM_SIGNAL_NONE; + break; + } + break; + + case OSM_SM_STATE_SET_ACTIVE_WAIT: + switch ( signal ) + { + case OSM_SIGNAL_NO_PENDING_TRANSACTIONS: + /* + * Don't change the signal, just the state. + */ + p_mgr->state = OSM_SM_STATE_SUBNET_UP; + break; + + default: + __osm_state_mgr_signal_error( p_mgr, signal ); + signal = OSM_SIGNAL_NONE; + break; + } + break; + + case OSM_SM_STATE_SUBNET_UP: + switch ( signal ) + { + case OSM_SIGNAL_NO_PENDING_TRANSACTIONS: + case OSM_SIGNAL_DONE: + /* + * The sweep completed! + */ + + /* in any case we zero this flag */ + p_mgr->p_subn->coming_out_of_standby = FALSE; + + /* If there were errors - then the subnet is not really up */ + if( p_mgr->p_subn->subnet_initialization_error == TRUE ) + { + __osm_state_mgr_init_errors_msg( p_mgr ); + } + else + { + /* The subnet is up correctly - set the first_time_master_sweep flag + * (if it is on) to FALSE. */ + if( p_mgr->p_subn->first_time_master_sweep == TRUE ) + { + p_mgr->p_subn->first_time_master_sweep = FALSE; + } + + __osm_topology_file_create( p_mgr ); + __osm_state_mgr_report( p_mgr ); + __osm_state_mgr_up_msg( p_mgr ); + + if( osm_log_is_active(p_mgr->p_log, OSM_LOG_VERBOSE) ) + osm_sa_db_file_dump(p_mgr->p_subn->p_osm); + } + p_mgr->state = OSM_SM_STATE_PROCESS_REQUEST; + signal = OSM_SIGNAL_IDLE_TIME_PROCESS; + + /* + * Finally signal the subnet up event + */ + status = cl_event_signal( p_mgr->p_subnet_up_event ); + if( status != IB_SUCCESS ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "osm_state_mgr_process: ERR 3319: " + "Invalid SM state %u\n", p_mgr->state ); + } + break; + + default: + __osm_state_mgr_signal_error( p_mgr, signal ); + signal = OSM_SIGNAL_NONE; + break; + } + break; + + case OSM_SM_STATE_MASTER_OR_HIGHER_SM_DETECTED: + switch ( signal ) + { + case OSM_SIGNAL_CHANGE_DETECTED: + /* + * Nothing to do here. One subnet change typically + * begets another.... + */ + break; + + case OSM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED: + /* + * If we lost once, we might lose again. Nothing to do. + */ + break; + + case OSM_SIGNAL_NO_PENDING_TRANSACTIONS: + p_mgr->state = OSM_SM_STATE_STANDBY; + /* + * Call the sm_state_mgr with signal + * MASTER_OR_HIGHER_SM_DETECTED_DONE + */ + osm_sm_state_mgr_process( p_mgr->p_sm_state_mgr, + OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED_DONE ); + __osm_state_mgr_standby_msg( p_mgr ); + break; + + default: + __osm_state_mgr_signal_error( p_mgr, signal ); + break; + } + signal = OSM_SIGNAL_NONE; + break; + + case OSM_SM_STATE_STANDBY: + switch ( signal ) + { + case OSM_SIGNAL_EXIT_STBY: + /* + * Need to force re-write of sm_base_lid to all ports + * to do that we want all the ports to be considered + * foriegn + */ + signal = OSM_SIGNAL_SWEEP; + __osm_state_mgr_clean_known_lids( p_mgr ); + p_mgr->state = OSM_SM_STATE_IDLE; + break; + + case OSM_SIGNAL_NO_PENDING_TRANSACTIONS: + /* + * Nothing to do here - need to stay at this state + */ + signal = OSM_SIGNAL_NONE; + break; + + default: + __osm_state_mgr_signal_error( p_mgr, signal ); + signal = OSM_SIGNAL_NONE; + break; + } + /* stay with the same signal - so we can start the sweep */ + break; + + default: + CL_ASSERT( FALSE ); + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "osm_state_mgr_process: ERR 3320: " + "Invalid SM state %u\n", p_mgr->state ); + p_mgr->state = OSM_SM_STATE_IDLE; + signal = OSM_SIGNAL_NONE; + break; + } + + /* if we got a signal to force immediate heavy sweep in the middle of the sweep - + * try another sweep. */ + if( ( p_mgr->p_subn->force_immediate_heavy_sweep ) && + ( p_mgr->state == OSM_SM_STATE_IDLE ) ) + { + signal = OSM_SIGNAL_SWEEP; + } + /* if we got errors during the initialization in the middle of the sweep - + * try another sweep. */ + if( ( p_mgr->p_subn->subnet_initialization_error ) && + ( p_mgr->state == OSM_SM_STATE_IDLE ) ) + { + signal = OSM_SIGNAL_SWEEP; + } + + /* + * for single step mode - some stages need to break only + * after evaluating a single step. + * For those we track the fact we have already performed + * a single loop + */ + if( p_mgr->state_step_mode == OSM_STATE_STEP_TAKE_ONE ) + p_mgr->state_step_mode = OSM_STATE_STEP_BREAK; + } + + cl_spinlock_release( &p_mgr->state_lock ); + + OSM_LOG_EXIT( p_mgr->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_state_mgr_process_idle( + IN osm_state_mgr_t * const p_mgr, + IN osm_pfn_start_t pfn_start, + IN osm_pfn_done_t pfn_done, + void *context1, + void *context2 ) +{ + osm_idle_item_t *p_idle_item; + + OSM_LOG_ENTER( p_mgr->p_log, osm_state_mgr_process_idle ); + + p_idle_item = malloc( sizeof( osm_idle_item_t ) ); + if( p_idle_item == NULL ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "osm_state_mgr_process_idle: ERR 3321: " + "insufficient memory\n" ); + return IB_ERROR; + } + + memset( p_idle_item, 0, sizeof( osm_idle_item_t ) ); + p_idle_item->pfn_start = pfn_start; + p_idle_item->pfn_done = pfn_done; + p_idle_item->context1 = context1; + p_idle_item->context2 = context2; + + cl_spinlock_acquire( &p_mgr->idle_lock ); + cl_qlist_insert_tail( &p_mgr->idle_time_list, &p_idle_item->list_item ); + cl_spinlock_release( &p_mgr->idle_lock ); + + osm_state_mgr_process( p_mgr, OSM_SIGNAL_IDLE_TIME_PROCESS_REQUEST ); + + OSM_LOG_EXIT( p_mgr->p_log ); + + return IB_SUCCESS; +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_state_mgr_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_state_mgr_ctrl.c new file mode 100644 index 00000000..36fd3c66 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_state_mgr_ctrl.c @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_state_mgr_ctrl.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_state_mgr_ctrl_t. + * This object represents the State Manager Controller object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +__osm_state_mgr_ctrl_disp_callback( + IN void *context, + IN void *p_data ) +{ + /* ignore return status when invoked via the dispatcher */ + osm_state_mgr_process( ((osm_state_mgr_ctrl_t*)context)->p_mgr, + (osm_signal_t)(p_data) ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_state_mgr_ctrl_construct( + IN osm_state_mgr_ctrl_t* const p_ctrl ) +{ + memset( p_ctrl, 0, sizeof(*p_ctrl) ); + p_ctrl->h_disp = CL_DISP_INVALID_HANDLE; +} + +/********************************************************************** + **********************************************************************/ +void +osm_state_mgr_ctrl_destroy( + IN osm_state_mgr_ctrl_t* const p_ctrl ) +{ + CL_ASSERT( p_ctrl ); + cl_disp_unregister( p_ctrl->h_disp ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_state_mgr_ctrl_init( + IN osm_state_mgr_ctrl_t* const p_ctrl, + IN osm_state_mgr_t* const p_mgr, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_state_mgr_ctrl_init ); + + osm_state_mgr_ctrl_construct( p_ctrl ); + p_ctrl->p_log = p_log; + + p_ctrl->p_mgr = p_mgr; + p_ctrl->p_disp = p_disp; + + p_ctrl->h_disp = cl_disp_register( + p_disp, + OSM_MSG_NO_SMPS_OUTSTANDING, + __osm_state_mgr_ctrl_disp_callback, + p_ctrl ); + + if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_state_mgr_ctrl_init: ERR 3401: " + "Dispatcher registration failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return( status ); +} + + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_subnet.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_subnet.c new file mode 100644 index 00000000..71c5b3d5 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_subnet.c @@ -0,0 +1,1272 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_subnet.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Implementation of osm_subn_t. + * This object represents an IBA subnet. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.9 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +osm_subn_construct( + IN osm_subn_t* const p_subn ) +{ + memset( p_subn, 0, sizeof(*p_subn) ); + cl_ptr_vector_construct( &p_subn->node_lid_tbl ); + cl_ptr_vector_construct( &p_subn->port_lid_tbl ); + cl_qmap_init( &p_subn->sw_guid_tbl ); + cl_qmap_init( &p_subn->node_guid_tbl ); + cl_qmap_init( &p_subn->port_guid_tbl ); + cl_qmap_init( &p_subn->sm_guid_tbl ); + cl_qlist_init( &p_subn->sa_sr_list ); + cl_qlist_init( &p_subn->sa_infr_list ); + cl_qmap_init( &p_subn->rtr_guid_tbl ); + cl_qmap_init( &p_subn->prtn_pkey_tbl ); + cl_qmap_init( &p_subn->mgrp_mlid_tbl ); + cl_list_construct( &p_subn->new_ports_list ); + cl_list_init( &p_subn->new_ports_list, 10 ); + cl_list_construct( &p_subn->light_sweep_physp_list ); + cl_list_init( &p_subn->light_sweep_physp_list, 5 ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_subn_destroy( + IN osm_subn_t* const p_subn ) +{ + osm_node_t *p_node, *p_next_node; + osm_port_t *p_port, *p_next_port; + osm_switch_t *p_sw, *p_next_sw; + osm_remote_sm_t *p_rsm, *p_next_rsm; + osm_prtn_t *p_prtn, *p_next_prtn; + osm_mgrp_t *p_mgrp, *p_next_mgrp; + osm_infr_t *p_infr, *p_next_infr; + + /* it might be a good idea to de-allocate all known objects */ + p_next_node = (osm_node_t*)cl_qmap_head( &p_subn->node_guid_tbl ); + while( p_next_node != (osm_node_t*)cl_qmap_end( &p_subn->node_guid_tbl ) ) + { + p_node = p_next_node; + p_next_node = (osm_node_t*)cl_qmap_next( &p_node->map_item ); + osm_node_delete( &p_node ); + } + + cl_ptr_vector_destroy( &p_subn->node_lid_tbl ); + + p_next_port = (osm_port_t*)cl_qmap_head( &p_subn->port_guid_tbl ); + while( p_next_port != (osm_port_t*)cl_qmap_end( &p_subn->port_guid_tbl ) ) + { + p_port = p_next_port; + p_next_port = (osm_port_t*)cl_qmap_next( &p_port->map_item ); + osm_port_delete( &p_port ); + } + + p_next_sw = (osm_switch_t*)cl_qmap_head( &p_subn->sw_guid_tbl ); + while( p_next_sw != (osm_switch_t*)cl_qmap_end( &p_subn->sw_guid_tbl ) ) + { + p_sw = p_next_sw; + p_next_sw = (osm_switch_t*)cl_qmap_next( &p_sw->map_item ); + osm_switch_delete( &p_sw ); + } + + p_next_rsm = (osm_remote_sm_t*)cl_qmap_head( &p_subn->sm_guid_tbl ); + while( p_next_rsm != (osm_remote_sm_t*)cl_qmap_end( &p_subn->sm_guid_tbl ) ) + { + p_rsm = p_next_rsm; + p_next_rsm = (osm_remote_sm_t*)cl_qmap_next( &p_rsm->map_item ); + free( p_rsm ); + } + + p_next_prtn = (osm_prtn_t*)cl_qmap_head( &p_subn->prtn_pkey_tbl ); + while( p_next_prtn != (osm_prtn_t*)cl_qmap_end( &p_subn->prtn_pkey_tbl ) ) + { + p_prtn = p_next_prtn; + p_next_prtn = (osm_prtn_t*)cl_qmap_next( &p_prtn->map_item ); + osm_prtn_delete( &p_prtn ); + } + + p_next_mgrp = (osm_mgrp_t*)cl_qmap_head( &p_subn->mgrp_mlid_tbl ); + while( p_next_mgrp != (osm_mgrp_t*)cl_qmap_end( &p_subn->mgrp_mlid_tbl ) ) + { + p_mgrp = p_next_mgrp; + p_next_mgrp = (osm_mgrp_t*)cl_qmap_next( &p_mgrp->map_item ); + osm_mgrp_destroy( p_mgrp ); + } + + p_next_infr = (osm_infr_t*)cl_qlist_head( &p_subn->sa_infr_list ); + while (p_next_infr != (osm_infr_t*)cl_qlist_end( &p_subn->sa_infr_list ) ) + { + p_infr = p_next_infr; + p_next_infr = (osm_infr_t*)cl_qlist_next( &p_infr->list_item ); + osm_infr_destroy( p_infr ); + } + + cl_list_remove_all( &p_subn->new_ports_list ); + cl_list_destroy( &p_subn->new_ports_list ); + + cl_list_remove_all( &p_subn->light_sweep_physp_list ); + cl_list_destroy( &p_subn->light_sweep_physp_list ); + + cl_ptr_vector_destroy( &p_subn->port_lid_tbl ); + cl_map_remove_all(&(p_subn->opt.port_prof_ignore_guids)); + cl_map_destroy(&(p_subn->opt.port_prof_ignore_guids)); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_subn_init( + IN osm_subn_t* const p_subn, + IN osm_opensm_t * const p_osm, + IN const osm_subn_opt_t* const p_opt ) +{ + cl_status_t status; + + p_subn->p_osm = p_osm; + + status = cl_ptr_vector_init( &p_subn->node_lid_tbl, + OSM_SUBNET_VECTOR_MIN_SIZE, + OSM_SUBNET_VECTOR_GROW_SIZE ); + if( status != CL_SUCCESS ) + return( status ); + + status = cl_ptr_vector_init( &p_subn->port_lid_tbl, + OSM_SUBNET_VECTOR_MIN_SIZE, + OSM_SUBNET_VECTOR_GROW_SIZE ); + if( status != CL_SUCCESS ) + return( status ); + + status = cl_ptr_vector_set_capacity( &p_subn->node_lid_tbl, + OSM_SUBNET_VECTOR_CAPACITY ); + if( status != CL_SUCCESS ) + return( status ); + + status = cl_ptr_vector_set_capacity( &p_subn->port_lid_tbl, + OSM_SUBNET_VECTOR_CAPACITY ); + if( status != CL_SUCCESS ) + return( status ); + + /* + LID zero is not valid. NULL out this entry for the + convenience of other code. + */ + cl_ptr_vector_set( &p_subn->node_lid_tbl, 0, NULL ); + cl_ptr_vector_set( &p_subn->port_lid_tbl, 0, NULL ); + + p_subn->opt = *p_opt; + p_subn->max_unicast_lid_ho = IB_LID_UCAST_END_HO; + p_subn->max_multicast_lid_ho = IB_LID_MCAST_END_HO; + p_subn->min_ca_mtu = IB_MAX_MTU; + p_subn->min_ca_rate = IB_MAX_RATE; + + /* note that insert and remove are part of the port_profile thing */ + cl_map_init(&(p_subn->opt.port_prof_ignore_guids), 10); + + /* ignore_existing_lfts follows reassign_lfts on first sweep */ + p_subn->ignore_existing_lfts = p_subn->opt.reassign_lfts; + + /* we assume master by default - so we only need to set it true if STANDBY */ + p_subn->coming_out_of_standby = FALSE; + + return( IB_SUCCESS ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_get_gid_by_mad_addr( + IN osm_log_t* p_log, + IN const osm_subn_t *p_subn, + IN const osm_mad_addr_t *p_mad_addr, + OUT ib_gid_t *p_gid) +{ + const cl_ptr_vector_t* p_tbl; + const osm_port_t* p_port = NULL; + const osm_physp_t* p_physp = NULL; + + if ( p_gid == NULL ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_get_gid_by_mad_addr: ERR 7505: " + "Provided output GID is NULL\n"); + return(IB_INVALID_PARAMETER); + } + + /* Find the port gid of the request in the subnet */ + p_tbl = &p_subn->port_lid_tbl; + + CL_ASSERT( cl_ptr_vector_get_size(p_tbl) < 0x10000 ); + + if ((uint16_t)cl_ptr_vector_get_size(p_tbl) > + cl_ntoh16(p_mad_addr->dest_lid)) + { + p_port = cl_ptr_vector_get( p_tbl, cl_ntoh16(p_mad_addr->dest_lid) ); + if ( p_port == NULL ) + { + osm_log( p_log, OSM_LOG_DEBUG, + "osm_get_gid_by_mad_addr: " + "Did not find any port with LID: 0x%X\n", + cl_ntoh16(p_mad_addr->dest_lid) + ); + return(IB_INVALID_PARAMETER); + } + p_physp = osm_port_get_phys_ptr( p_port, p_port->default_port_num); + p_gid->unicast.interface_id = p_physp->port_guid; + p_gid->unicast.prefix = p_subn->opt.subnet_prefix; + } + else + { + /* The dest_lid is not in the subnet table - this is an error */ + osm_log( p_log, OSM_LOG_ERROR, + "osm_get_gid_by_mad_addr: ERR 7501: " + "LID is out of range: 0x%X\n", + cl_ntoh16(p_mad_addr->dest_lid) + ); + return(IB_INVALID_PARAMETER); + } + + return( IB_SUCCESS ); +} + +/********************************************************************** + **********************************************************************/ +osm_physp_t* +osm_get_physp_by_mad_addr( + IN osm_log_t* p_log, + IN const osm_subn_t *p_subn, + IN osm_mad_addr_t *p_mad_addr ) +{ + const cl_ptr_vector_t* p_port_lid_tbl; + osm_port_t* p_port = NULL; + osm_physp_t* p_physp = NULL; + + /* Find the port gid of the request in the subnet */ + p_port_lid_tbl = &p_subn->port_lid_tbl; + + CL_ASSERT( cl_ptr_vector_get_size(p_port_lid_tbl) < 0x10000 ); + + if ((uint16_t)cl_ptr_vector_get_size(p_port_lid_tbl) > + cl_ntoh16(p_mad_addr->dest_lid)) + { + p_port = cl_ptr_vector_get( p_port_lid_tbl, cl_ntoh16(p_mad_addr->dest_lid) ); + if (p_port == NULL) + { + /* The port is not in the port_lid table - this is an error */ + osm_log( p_log, OSM_LOG_ERROR, + "osm_get_physp_by_mad_addr: ERR 7502: " + "Cannot locate port object by lid: 0x%X\n", + cl_ntoh16(p_mad_addr->dest_lid) + ); + + goto Exit; + } + p_physp = osm_port_get_phys_ptr( p_port, p_port->default_port_num); + } + else + { + /* The dest_lid is not in the subnet table - this is an error */ + osm_log( p_log, OSM_LOG_ERROR, + "osm_get_physp_by_mad_addr: ERR 7503: " + "Lid is out of range: 0x%X\n", + cl_ntoh16(p_mad_addr->dest_lid) + ); + } + + Exit: + return p_physp; +} + +/********************************************************************** + **********************************************************************/ +osm_port_t* +osm_get_port_by_mad_addr( + IN osm_log_t* p_log, + IN const osm_subn_t *p_subn, + IN osm_mad_addr_t *p_mad_addr ) +{ + const cl_ptr_vector_t* p_port_lid_tbl; + osm_port_t* p_port = NULL; + + /* Find the port gid of the request in the subnet */ + p_port_lid_tbl = &p_subn->port_lid_tbl; + + CL_ASSERT( cl_ptr_vector_get_size(p_port_lid_tbl) < 0x10000 ); + + if ((uint16_t)cl_ptr_vector_get_size(p_port_lid_tbl) > + cl_ntoh16(p_mad_addr->dest_lid)) + { + p_port = + cl_ptr_vector_get( p_port_lid_tbl, cl_ntoh16(p_mad_addr->dest_lid) ); + } + else + { + /* The dest_lid is not in the subnet table - this is an error */ + osm_log( p_log, OSM_LOG_ERROR, + "osm_get_port_by_mad_addr: ERR 7504: " + "Lid is out of range: 0x%X\n", + cl_ntoh16(p_mad_addr->dest_lid) + ); + } + + return p_port; +} + +/********************************************************************** + **********************************************************************/ +osm_switch_t * +osm_get_switch_by_guid( + IN const osm_subn_t *p_subn, + IN uint64_t guid) +{ + osm_switch_t *p_switch; + + p_switch = (osm_switch_t*)cl_qmap_get( &(p_subn->sw_guid_tbl), guid ); + if( p_switch == (osm_switch_t*)cl_qmap_end( &(p_subn->sw_guid_tbl)) ) + p_switch = NULL; + return p_switch; +} + +/********************************************************************** + **********************************************************************/ +osm_node_t * +osm_get_node_by_guid( + IN osm_subn_t const *p_subn, + IN uint64_t guid) +{ + osm_node_t *p_node; + + p_node = (osm_node_t*)cl_qmap_get( &(p_subn->node_guid_tbl), guid ); + if( p_node == (osm_node_t*)cl_qmap_end( &(p_subn->node_guid_tbl)) ) + p_node = NULL; + return p_node; +} + +/********************************************************************** + **********************************************************************/ +osm_port_t * +osm_get_port_by_guid( + IN osm_subn_t const *p_subn, + IN uint64_t guid) +{ + osm_port_t *p_port; + + p_port = (osm_port_t*)cl_qmap_get( &(p_subn->port_guid_tbl), guid ); + if( p_port == (osm_port_t*)cl_qmap_end( &(p_subn->port_guid_tbl)) ) + p_port = NULL; + return p_port; +} + +/********************************************************************** + **********************************************************************/ +static void +subn_set_default_qos_options( + IN osm_qos_options_t *opt) +{ + opt->max_vls = 15; + opt->high_limit = 0; + opt->vlarb_high = "0:4,1:0,2:0,3:0,4:0,5:0,6:0,7:0,8:0,9:0,10:0,11:0,12:0,13:0,14:0"; + opt->vlarb_low = "0:0,1:4,2:4,3:4,4:4,5:4,6:4,7:4,8:4,9:4,10:4,11:4,12:4,13:4,14:4"; + opt->sl2vl = "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,7"; +} + +/********************************************************************** + **********************************************************************/ +void +osm_subn_set_default_opt( + IN osm_subn_opt_t* const p_opt ) +{ + memset(p_opt, 0, sizeof(osm_subn_opt_t)); + p_opt->guid = 0; + p_opt->m_key = OSM_DEFAULT_M_KEY; + p_opt->sm_key = OSM_DEFAULT_SM_KEY; + p_opt->subnet_prefix = IB_DEFAULT_SUBNET_PREFIX; + p_opt->m_key_lease_period = 0; + p_opt->sweep_interval = OSM_DEFAULT_SWEEP_INTERVAL_SECS; + p_opt->max_wire_smps = OSM_DEFAULT_SMP_MAX_ON_WIRE; + p_opt->console = FALSE; + p_opt->transaction_timeout = OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC; + /* by default we will consider waiting for 50x transaction timeout normal */ + p_opt->max_msg_fifo_timeout = 50*OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC; + p_opt->sm_priority = OSM_DEFAULT_SM_PRIORITY; + p_opt->lmc = OSM_DEFAULT_LMC; + p_opt->lmc_esp0 = FALSE; + p_opt->max_op_vls = OSM_DEFAULT_MAX_OP_VLS; + p_opt->force_link_speed = 0; + p_opt->reassign_lids = FALSE; + p_opt->reassign_lfts = TRUE; + p_opt->ignore_other_sm = FALSE; + p_opt->single_thread = FALSE; + p_opt->no_multicast_option = FALSE; + p_opt->disable_multicast = FALSE; + p_opt->force_log_flush = FALSE; + p_opt->subnet_timeout = OSM_DEFAULT_SUBNET_TIMEOUT; + p_opt->packet_life_time = OSM_DEFAULT_SWITCH_PACKET_LIFE; + p_opt->vl_stall_count = OSM_DEFAULT_VL_STALL_COUNT; + p_opt->leaf_vl_stall_count = OSM_DEFAULT_LEAF_VL_STALL_COUNT; + p_opt->head_of_queue_lifetime = OSM_DEFAULT_HEAD_OF_QUEUE_LIFE; + p_opt->leaf_head_of_queue_lifetime = OSM_DEFAULT_LEAF_HEAD_OF_QUEUE_LIFE; + p_opt->local_phy_errors_threshold = OSM_DEFAULT_ERROR_THRESHOLD; + p_opt->overrun_errors_threshold = OSM_DEFAULT_ERROR_THRESHOLD; + p_opt->sminfo_polling_timeout = OSM_SM_DEFAULT_POLLING_TIMEOUT_MILLISECS; + p_opt->polling_retry_number = OSM_SM_DEFAULT_POLLING_RETRY_NUMBER; + p_opt->force_heavy_sweep = FALSE; + p_opt->log_flags = 0; + p_opt->honor_guid2lid_file = FALSE; + + p_opt->dump_files_dir = getenv("OSM_TMP_DIR"); + if (!p_opt->dump_files_dir || !(*p_opt->dump_files_dir)) + p_opt->dump_files_dir = OSM_DEFAULT_TMP_DIR; + + p_opt->log_file = OSM_DEFAULT_LOG_FILE; + p_opt->log_max_size = 0; + p_opt->partition_config_file = OSM_DEFAULT_PARTITION_CONFIG_FILE; + p_opt->no_partition_enforcement = FALSE; + p_opt->no_qos = TRUE; + p_opt->accum_log_file = TRUE; + p_opt->port_profile_switch_nodes = FALSE; + p_opt->pfn_ui_pre_lid_assign = NULL; + p_opt->ui_pre_lid_assign_ctx = NULL; + p_opt->pfn_ui_mcast_fdb_assign = NULL; + p_opt->ui_mcast_fdb_assign_ctx = NULL; + p_opt->sweep_on_trap = TRUE; + p_opt->testability_mode = OSM_TEST_MODE_NONE; + p_opt->routing_engine_name = NULL; + p_opt->lid_matrix_dump_file = NULL; + p_opt->ucast_dump_file = NULL; + p_opt->updn_guid_file = NULL; + p_opt->sa_db_file = NULL; + p_opt->exit_on_fatal = TRUE; + p_opt->enable_quirks = FALSE; + p_opt->no_clients_rereg = FALSE; + subn_set_default_qos_options(&p_opt->qos_options); + subn_set_default_qos_options(&p_opt->qos_ca_options); + subn_set_default_qos_options(&p_opt->qos_sw0_options); + subn_set_default_qos_options(&p_opt->qos_swe_options); + subn_set_default_qos_options(&p_opt->qos_rtr_options); +} + +/********************************************************************** + **********************************************************************/ +static inline void +__osm_subn_opts_unpack_net64( + IN char *p_req_key, + IN char *p_key, + IN char *p_val_str, + IN uint64_t *p_val) +{ + uint64_t val; + if (!strcmp(p_req_key, p_key)) + { +#if __WORDSIZE == 64 + val = strtoul(p_val_str, NULL, 0); +#else + val = strtoull(p_val_str, NULL, 0); +#endif + if (cl_hton64(val) != *p_val) + { + char buff[128]; + sprintf(buff, " Using Cached Option:%s = 0x%016" PRIx64 "\n", + p_key, val); + printf(buff); + cl_log_event("OpenSM", LOG_INFO, buff, NULL, 0); + *p_val = cl_ntoh64(val); + } + } +} + +/********************************************************************** + **********************************************************************/ +static inline void +__osm_subn_opts_unpack_uint32( + IN char *p_req_key, + IN char *p_key, + IN char *p_val_str, + IN uint32_t *p_val) +{ + uint32_t val; + if (!strcmp(p_req_key, p_key)) + { + val = strtoul(p_val_str, NULL, 0); + if (val != *p_val) + { + char buff[128]; + sprintf(buff, " Using Cached Option:%s = %u\n", + p_key, val); + printf(buff); + cl_log_event("OpenSM", LOG_INFO, buff, NULL, 0); + *p_val = val; + } + } +} + +/********************************************************************** + **********************************************************************/ +static inline void +__osm_subn_opts_unpack_net16( + IN char *p_req_key, + IN char *p_key, + IN char *p_val_str, + IN uint16_t *p_val) +{ + if (!strcmp(p_req_key, p_key)) + { + uint32_t val; + val = strtoul(p_val_str, NULL, 0); + CL_ASSERT( val < 0x10000 ); + if (cl_hton32(val) != *p_val) + { + char buff[128]; + sprintf(buff, " Using Cached Option:%s = 0x%04x\n", + p_key, val); + printf(buff); + cl_log_event("OpenSM", LOG_INFO, buff, NULL, 0); + *p_val = cl_hton16((uint16_t)val); + } + } +} + +/********************************************************************** + **********************************************************************/ +static inline void +__osm_subn_opts_unpack_uint8( + IN char *p_req_key, + IN char *p_key, + IN char *p_val_str, + IN uint8_t *p_val) +{ + if (!strcmp(p_req_key, p_key)) + { + uint32_t val; + val = strtoul(p_val_str, NULL, 0); + CL_ASSERT( val < 0x100 ); + if (val != *p_val) + { + char buff[128]; + sprintf(buff, " Using Cached Option:%s = %u\n", + p_key, val); + printf(buff); + cl_log_event("OpenSM", LOG_INFO, buff, NULL, 0); + *p_val = (uint8_t)val; + } + } +} + +/********************************************************************** + **********************************************************************/ +static inline void +__osm_subn_opts_unpack_boolean( + IN char *p_req_key, + IN char *p_key, + IN char *p_val_str, + IN boolean_t *p_val) +{ + if (!strcmp(p_req_key, p_key) && p_val_str) + { + boolean_t val; + if (strcmp("TRUE", p_val_str)) + val = FALSE; + else + val = TRUE; + + if (val != *p_val) { + char buff[128]; + sprintf(buff, " Using Cached Option:%s = %s\n", + p_key, p_val_str); + printf(buff); + cl_log_event("OpenSM", LOG_INFO, buff, NULL, 0); + *p_val = val; + } + } +} + +/********************************************************************** + **********************************************************************/ +static inline void +__osm_subn_opts_unpack_charp( + IN char *p_req_key, + IN char *p_key, + IN char *p_val_str, + IN char **p_val) +{ + if (!strcmp(p_req_key, p_key) && p_val_str) + { + if ((*p_val == NULL) || strcmp(p_val_str, *p_val)) + { + char buff[128]; + sprintf(buff, " Using Cached Option:%s = %s\n", + p_key, p_val_str); + printf(buff); + cl_log_event("OpenSM", LOG_INFO, buff, NULL, 0); + + /* + Ignore the possible memory leak here; + the pointer may be to a static default. + */ + *p_val = (char *)malloc( strlen(p_val_str) +1 ); + strcpy( *p_val, p_val_str); + } + } +} + +/********************************************************************** + **********************************************************************/ +static void +subn_parse_qos_options( + IN const char *prefix, + IN char *p_key, + IN char *p_val_str, + IN osm_qos_options_t *opt) +{ + char name[256]; + + snprintf(name, sizeof(name), "%s_max_vls", prefix); + __osm_subn_opts_unpack_uint32(name, p_key, p_val_str, &opt->max_vls); + snprintf(name, sizeof(name), "%s_high_limit", prefix); + __osm_subn_opts_unpack_uint32(name, p_key, p_val_str, &opt->high_limit); + snprintf(name, sizeof(name), "%s_vlarb_high", prefix); + __osm_subn_opts_unpack_charp(name, p_key, p_val_str, &opt->vlarb_high); + snprintf(name, sizeof(name), "%s_vlarb_low", prefix); + __osm_subn_opts_unpack_charp(name, p_key, p_val_str, &opt->vlarb_low); + snprintf(name, sizeof(name), "%s_sl2vl", prefix); + __osm_subn_opts_unpack_charp(name, p_key, p_val_str, &opt->sl2vl); +} + +static int +subn_dump_qos_options( + FILE *file, + const char *set_name, + const char *prefix, + osm_qos_options_t *opt) +{ + return fprintf(file, "# %s\n" + "%s_max_vls %u\n" + "%s_high_limit %u\n" + "%s_vlarb_high %s\n" + "%s_vlarb_low %s\n" + "%s_sl2vl %s\n", + set_name, + prefix, opt->max_vls, + prefix, opt->high_limit, + prefix, opt->vlarb_high, + prefix, opt->vlarb_low, + prefix, opt->sl2vl); +} + +/********************************************************************** + **********************************************************************/ +void +osm_subn_rescan_conf_file( + IN osm_subn_opt_t* const p_opts ) +{ + char *p_cache_dir = getenv("OSM_CACHE_DIR"); + char file_name[256]; + FILE *opts_file; + char line[1024]; + char *p_key, *p_val ,*p_last; + + /* try to open the options file from the cache dir */ + if (!p_cache_dir || !(*p_cache_dir)) + p_cache_dir = OSM_DEFAULT_CACHE_DIR; + + strcpy(file_name, p_cache_dir); + strcat(file_name, "opensm.opts"); + + opts_file = fopen(file_name, "r"); + if (!opts_file) + return; + + while (fgets(line, 1023, opts_file) != NULL) + { + /* get the first token */ + p_key = strtok_r(line, " \t\n", &p_last); + if (p_key) + { + p_val = strtok_r(NULL, " \t\n", &p_last); + + subn_parse_qos_options("qos", + p_key, p_val, &p_opts->qos_options); + + subn_parse_qos_options("qos_ca", + p_key, p_val, &p_opts->qos_ca_options); + + subn_parse_qos_options("qos_sw0", + p_key, p_val, &p_opts->qos_sw0_options); + + subn_parse_qos_options("qos_swe", + p_key, p_val, &p_opts->qos_swe_options); + + subn_parse_qos_options("qos_rtr", + p_key, p_val, &p_opts->qos_rtr_options); + + } + } + fclose(opts_file); +} + +/********************************************************************** + **********************************************************************/ +void +osm_subn_parse_conf_file( + IN osm_subn_opt_t* const p_opts ) +{ + char *p_cache_dir = getenv("OSM_CACHE_DIR"); + char file_name[256]; + FILE *opts_file; + char line[1024]; + char *p_key, *p_val ,*p_last; + + /* try to open the options file from the cache dir */ + if (!p_cache_dir || !(*p_cache_dir)) + p_cache_dir = OSM_DEFAULT_CACHE_DIR; + + strcpy(file_name, p_cache_dir); + strcat(file_name, "opensm.opts"); + + opts_file = fopen(file_name, "r"); + if (!opts_file) return; + + while (fgets(line, 1023, opts_file) != NULL) + { + /* get the first token */ + p_key = strtok_r(line, " \t\n", &p_last); + if (p_key) + { + p_val = strtok_r(NULL, " \t\n", &p_last); + + __osm_subn_opts_unpack_net64( + "guid", p_key, p_val, &p_opts->guid); + + __osm_subn_opts_unpack_net64( + "m_key", p_key, p_val, &p_opts->m_key); + + __osm_subn_opts_unpack_net64( + "sm_key", p_key, p_val, &p_opts->sm_key); + + __osm_subn_opts_unpack_net64( + "subnet_prefix", + p_key, p_val, &p_opts->subnet_prefix); + + __osm_subn_opts_unpack_net16( + "m_key_lease_period", + p_key, p_val, &p_opts->m_key_lease_period); + + __osm_subn_opts_unpack_uint32( + "sweep_interval", + p_key, p_val, &p_opts->sweep_interval); + + __osm_subn_opts_unpack_uint32( + "max_wire_smps", + p_key, p_val, &p_opts->max_wire_smps); + + __osm_subn_opts_unpack_uint32( + "transaction_timeout", + p_key, p_val, &p_opts->transaction_timeout); + + __osm_subn_opts_unpack_uint32( + "max_msg_fifo_timeout", + p_key, p_val, &p_opts->max_msg_fifo_timeout); + + __osm_subn_opts_unpack_uint8( + "sm_priority", + p_key, p_val, &p_opts->sm_priority); + + __osm_subn_opts_unpack_uint8( + "lmc", + p_key, p_val, &p_opts->lmc); + + __osm_subn_opts_unpack_boolean( + "lmc_esp0", + p_key, p_val, &p_opts->lmc_esp0); + + __osm_subn_opts_unpack_uint8( + "max_op_vls", + p_key, p_val, &p_opts->max_op_vls); + + __osm_subn_opts_unpack_uint8( + "force_link_speed", + p_key, p_val, &p_opts->force_link_speed); + + __osm_subn_opts_unpack_boolean( + "reassign_lids", + p_key, p_val, &p_opts->reassign_lids); + + __osm_subn_opts_unpack_boolean( + "reassign_lfts", + p_key, p_val, &p_opts->reassign_lfts); + + __osm_subn_opts_unpack_boolean( + "ignore_other_sm", + p_key, p_val, &p_opts->ignore_other_sm); + + __osm_subn_opts_unpack_boolean( + "single_thread", + p_key, p_val, &p_opts->single_thread); + + __osm_subn_opts_unpack_boolean( + "no_multicast_option", + p_key, p_val, &p_opts->no_multicast_option); + + __osm_subn_opts_unpack_boolean( + "disable_multicast", + p_key, p_val, &p_opts->disable_multicast); + + __osm_subn_opts_unpack_boolean( + "force_log_flush", + p_key, p_val, &p_opts->force_log_flush); + + __osm_subn_opts_unpack_uint8( + "subnet_timeout", + p_key, p_val, &p_opts->subnet_timeout); + + __osm_subn_opts_unpack_uint8( + "packet_life_time", + p_key, p_val, &p_opts->packet_life_time); + + __osm_subn_opts_unpack_uint8( + "vl_stall_count", + p_key, p_val, &p_opts->vl_stall_count); + + __osm_subn_opts_unpack_uint8( + "leaf_vl_stall_count", + p_key, p_val, &p_opts->leaf_vl_stall_count); + + __osm_subn_opts_unpack_uint8( + "head_of_queue_lifetime", + p_key, p_val, &p_opts->head_of_queue_lifetime); + + __osm_subn_opts_unpack_uint8( + "leaf_head_of_queue_lifetime", + p_key, p_val, &p_opts->leaf_head_of_queue_lifetime); + + __osm_subn_opts_unpack_uint8( + "local_phy_errors_threshold", + p_key, p_val, &p_opts->local_phy_errors_threshold); + + __osm_subn_opts_unpack_uint8( + "overrun_errors_threshold", + p_key, p_val, &p_opts->overrun_errors_threshold); + + __osm_subn_opts_unpack_uint32( + "sminfo_polling_timeout", + p_key, p_val, &p_opts->sminfo_polling_timeout); + + __osm_subn_opts_unpack_uint32( + "polling_retry_number", + p_key, p_val, &p_opts->polling_retry_number); + + __osm_subn_opts_unpack_boolean( + "force_heavy_sweep", + p_key, p_val, &p_opts->force_heavy_sweep); + + __osm_subn_opts_unpack_uint8( + "log_flags", + p_key, p_val, &p_opts->log_flags); + + __osm_subn_opts_unpack_boolean( + "port_profile_switch_nodes", + p_key, p_val, &p_opts->port_profile_switch_nodes); + + __osm_subn_opts_unpack_boolean( + "sweep_on_trap", + p_key, p_val, &p_opts->sweep_on_trap); + + __osm_subn_opts_unpack_charp( + "routing_engine", + p_key, p_val, &p_opts->routing_engine_name); + + __osm_subn_opts_unpack_charp( + "log_file", p_key, p_val, &p_opts->log_file); + + __osm_subn_opts_unpack_uint32( + "log_max_size", + p_key, p_val, (uint32_t *)&p_opts->log_max_size); + + __osm_subn_opts_unpack_charp( + "partition_config_file", + p_key, p_val, &p_opts->partition_config_file); + + __osm_subn_opts_unpack_boolean( + "no_partition_enforcement", + p_key, p_val, &p_opts->no_partition_enforcement); + + __osm_subn_opts_unpack_boolean( + "no_qos", + p_key, p_val, &p_opts->no_qos); + + __osm_subn_opts_unpack_boolean( + "accum_log_file", + p_key, p_val, &p_opts->accum_log_file); + + __osm_subn_opts_unpack_charp( + "dump_files_dir", + p_key, p_val, &p_opts->dump_files_dir); + + __osm_subn_opts_unpack_charp( + "lid_matrix_dump_file", + p_key, p_val, &p_opts->lid_matrix_dump_file); + + __osm_subn_opts_unpack_charp( + "ucast_dump_file", + p_key, p_val, &p_opts->ucast_dump_file); + + __osm_subn_opts_unpack_charp( + "updn_guid_file", + p_key, p_val, &p_opts->updn_guid_file); + + __osm_subn_opts_unpack_charp( + "sa_db_file", + p_key, p_val, &p_opts->sa_db_file); + + __osm_subn_opts_unpack_boolean( + "exit_on_fatal", + p_key, p_val, &p_opts->exit_on_fatal); + + __osm_subn_opts_unpack_boolean( + "honor_guid2lid_file", + p_key, p_val, &p_opts->honor_guid2lid_file); + + subn_parse_qos_options("qos", + p_key, p_val, &p_opts->qos_options); + + subn_parse_qos_options("qos_ca", + p_key, p_val, &p_opts->qos_ca_options); + + subn_parse_qos_options("qos_sw0", + p_key, p_val, &p_opts->qos_sw0_options); + + subn_parse_qos_options("qos_swe", + p_key, p_val, &p_opts->qos_swe_options); + + subn_parse_qos_options("qos_rtr", + p_key, p_val, &p_opts->qos_rtr_options); + + __osm_subn_opts_unpack_boolean( + "enable_quirks", + p_key, p_val, &p_opts->enable_quirks); + + } + } + fclose(opts_file); +} + +/********************************************************************** + **********************************************************************/ +void +osm_subn_write_conf_file( + IN osm_subn_opt_t* const p_opts ) +{ + char *p_cache_dir = getenv("OSM_CACHE_DIR"); + char file_name[256]; + FILE *opts_file; + + /* try to open the options file from the cache dir */ + if (!p_cache_dir || !(*p_cache_dir)) + p_cache_dir = OSM_DEFAULT_CACHE_DIR; + + strcpy(file_name, p_cache_dir); + strcat(file_name, "opensm.opts"); + + opts_file = fopen(file_name, "w"); + if (!opts_file) return; + + fprintf( + opts_file, + "#\n# DEVICE ATTRIBUTES OPTIONS\n#\n" + "# The port GUID on which the OpenSM is running\n" + "guid 0x%016" PRIx64 "\n\n" + "# M_Key value sent to all ports qualifying all Set(PortInfo)\n" + "m_key 0x%016" PRIx64 "\n\n" + "# The lease period used for the M_Key on this subnet in [msec]\n" + "m_key_lease_period %u\n\n" + "# SM_Key value of the SM to qualify rcv SA queries as 'trusted'\n" + "sm_key 0x%016" PRIx64 "\n\n" + "# Subnet prefix used on this subnet\n" + "subnet_prefix 0x%016" PRIx64 "\n\n" + "# The LMC value used on this subnet\n" + "lmc %u\n\n" + "# lmc_esp0 determines whether LMC value used on subnet is used for\n" + "#enhanced switch port 0. If TRUE, LMC value for subnet is used for\n" + "#ESP0. Otherwise, LMC value for ESP0s is 0.\n" + "lmc_esp0 %s\n\n" + "# The code of maximal time a packet can live in a switch\n" + "# The actual time is 4.096usec * 2^\n" + "# The value 0x14 disables this mechanism\n" + "packet_life_time 0x%02x\n\n" + "# The number of sequential packets dropped that cause the port\n" + "# to enter the VLStalled state. The result of setting this value to\n" + "# zero is undefined.\n" + "vl_stall_count 0x%02x\n\n" + "# The number of sequential packets dropped that cause the port\n" + "# to enter the VLStalled state. This value is for switch ports\n" + "# driving a CA or router port. The result of setting this value\n" + "# to zero is undefined.\n" + "leaf_vl_stall_count 0x%02x\n\n" + "# The code of maximal time a packet can wait at the head of\n" + "# transmission queue. \n" + "# The actual time is 4.096usec * 2^\n" + "# The value 0x14 disables this mechanism\n" + "head_of_queue_lifetime 0x%02x\n\n" + "# The maximal time a packet can wait at the head of queue on \n" + "# switch port connected to a CA or router port\n" + "leaf_head_of_queue_lifetime 0x%02x\n\n" + "# Limit the maximal operational VLs\n" + "max_op_vls %u\n\n" + "# Force switch links which are more than SDR capable to \n" + "# operate at SDR speed\n\n" + "force_link_speed %u\n\n" + "# The subnet_timeout code that will be set for all the ports\n" + "# The actual timeout is 4.096usec * 2^\n" + "subnet_timeout %u\n\n" + "# Threshold of local phy errors for sending Trap 129\n" + "local_phy_errors_threshold 0x%02x\n\n" + "# Threshold of credits over-run errors for sending Trap 129\n" + "overrun_errors_threshold 0x%02x\n\n", + cl_ntoh64(p_opts->guid), + cl_ntoh64(p_opts->m_key), + cl_ntoh16(p_opts->m_key_lease_period), + cl_ntoh64(p_opts->sm_key), + cl_ntoh64(p_opts->subnet_prefix), + p_opts->lmc, + p_opts->lmc_esp0 ? "TRUE" : "FALSE", + p_opts->packet_life_time, + p_opts->vl_stall_count, + p_opts->leaf_vl_stall_count, + p_opts->head_of_queue_lifetime, + p_opts->leaf_head_of_queue_lifetime, + p_opts->max_op_vls, + p_opts->force_link_speed, + p_opts->subnet_timeout, + p_opts->local_phy_errors_threshold, + p_opts->overrun_errors_threshold + ); + + fprintf( + opts_file, + "#\n# PARTITIONING OPTIONS\n#\n" + "# Partition configuration file to be used\n" + "partition_config_file %s\n\n" + "# Disable partition enforcement by switches\n" + "no_partition_enforcement %s\n\n", + p_opts->partition_config_file, + p_opts->no_partition_enforcement ? "TRUE" : "FALSE"); + + fprintf( + opts_file, + "#\n# SWEEP OPTIONS\n#\n" + "# The number of seconds between subnet sweeps (0 disables it)\n" + "sweep_interval %u\n\n" + "# If TRUE cause all lids to be reassigned\n" + "reassign_lids %s\n\n" + "# If TRUE ignore existing LFT entries on first sweep (default).\n" + "# Otherwise only non minimal hop cases are modified.\n" + "# NOTE: A standby SM clears its first sweep flag - since the\n" + "# master SM already sweeps...\n" + "reassign_lfts %s\n\n" + "# If TRUE forces every sweep to be a heavy sweep\n" + "force_heavy_sweep %s\n\n" + "# If TRUE every trap will cause a heavy sweep.\n" + "# NOTE: successive identical traps (>10) are suppressed\n" + "sweep_on_trap %s\n\n", + p_opts->sweep_interval, + p_opts->reassign_lids ? "TRUE" : "FALSE", + p_opts->reassign_lfts ? "TRUE" : "FALSE", + p_opts->force_heavy_sweep ? "TRUE" : "FALSE", + p_opts->sweep_on_trap ? "TRUE" : "FALSE" + ); + + fprintf( + opts_file, + "#\n# ROUTING OPTIONS\n#\n" + "# If TRUE count switches as link subscriptions\n" + "port_profile_switch_nodes %s\n\n", + p_opts->port_profile_switch_nodes ? "TRUE" : "FALSE"); + + if (p_opts->routing_engine_name) + fprintf( opts_file, + "# Routing engine\n" + "routing_engine %s\n\n", + p_opts->routing_engine_name); + if (p_opts->lid_matrix_dump_file) + fprintf( opts_file, + "# Lid matrix dump file name\n" + "lid_matrix_dump_file %s\n\n", + p_opts->lid_matrix_dump_file); + if (p_opts->ucast_dump_file) + fprintf( opts_file, + "# Ucast dump file name\n" + "ucast_dump_file %s\n\n", + p_opts->ucast_dump_file); + if (p_opts->updn_guid_file) + fprintf( opts_file, + "# The file holding the Up/Down root node guids\n" + "# One guid in each line\n" + "updn_guid_file %s\n\n", + p_opts->updn_guid_file); + if (p_opts->sa_db_file) + fprintf( opts_file, + "# SA database file name\n" + "sa_db_file %s\n\n", + p_opts->sa_db_file); + + fprintf( + opts_file, + "#\n# HANDOVER - MULTIPLE SMs OPTIONS\n#\n" + "# SM priority used for deciding who is the master\n" + "sm_priority %u\n\n" + "# If TRUE other SMs on the subnet should be ignored\n" + "ignore_other_sm %s\n\n" + "# Timeout in [msec] between two polls of active master SM\n" + "sminfo_polling_timeout %u\n\n" + "# Number of failing polls of remote SM that declares it dead\n" + "polling_retry_number %u\n\n" + "# If TRUE honor the guid2lid file when coming out of standby\n" + "# state, if such file exists and is valid\n" + "honor_guid2lid_file %s\n\n", + p_opts->sm_priority, + p_opts->ignore_other_sm ? "TRUE" : "FALSE", + p_opts->sminfo_polling_timeout, + p_opts->polling_retry_number, + p_opts->honor_guid2lid_file ? "TRUE" : "FALSE" + ); + + fprintf( + opts_file, + "#\n# TIMING AND THREADING OPTIONS\n#\n" + "# Number of MADs sent in parallel\n" + "max_wire_smps %u\n\n" + "# The time taken to a transaction to finish in [msec]\n" + "transaction_timeout %u\n\n" + "# Maximal time in [msec] a message can stay in the incoming message queue.\n" + "# If there is more than one message in the queue and the last message\n" + "# stayed in the queue more than this value any SA request will be \n" + "# immediately returned with a BUSY status.\n" + "max_msg_fifo_timeout %u\n\n" + "# Use a single thread for handling SA queries\n" + "single_thread %s\n\n", + p_opts->max_wire_smps, + p_opts->transaction_timeout, + p_opts->max_msg_fifo_timeout, + p_opts->single_thread ? "TRUE" : "FALSE" + ); + + fprintf( + opts_file, + "#\n# DEBUG FEATURES\n#\n" + "# The log flags used\n" + "log_flags 0x%02x\n\n" + "# Force flush of the log file after each log message\n" + "force_log_flush %s\n\n" + "# Log file to be used\n" + "log_file %s\n\n" + "# Limit the size of the log file. If overrun, log is restarted\n" + "log_max_size %lu\n\n" + "# If TRUE will accumulate the log over multiple OpenSM sessions\n" + "accum_log_file %s\n\n" + "# The directory to hold the file OpenSM dumps\n" + "dump_files_dir %s\n\n" + "# If TRUE enables new high risk options and hardware specific quirks\n" + "enable_quirks %s\n\n" + "# If TRUE OpenSM should disable multicast support\n" + "no_multicast_option %s\n\n" + "# No multicast routing is performed if TRUE\n" + "disable_multicast %s\n\n" + "# If TRUE opensm will exit on fatal initialization issues\n" + "exit_on_fatal %s\n\n", + p_opts->log_flags, + p_opts->force_log_flush ? "TRUE" : "FALSE", + p_opts->log_file, + p_opts->log_max_size, + p_opts->accum_log_file ? "TRUE" : "FALSE", + p_opts->dump_files_dir, + p_opts->enable_quirks ? "TRUE" : "FALSE", + p_opts->no_multicast_option ? "TRUE" : "FALSE", + p_opts->disable_multicast ? "TRUE" : "FALSE", + p_opts->exit_on_fatal ? "TRUE" : "FALSE" + ); + + fprintf( + opts_file, + "#\n# QoS OPTIONS\n#\n" + "# Disable QoS setup\n" + "no_qos %s\n\n", + p_opts->no_qos ? "TRUE" : "FALSE"); + + subn_dump_qos_options(opts_file, + "QoS default options", "qos", &p_opts->qos_options); + fprintf(opts_file, "\n"); + subn_dump_qos_options(opts_file, + "QoS CA options", "qos_ca", &p_opts->qos_ca_options); + fprintf(opts_file, "\n"); + subn_dump_qos_options(opts_file, + "QoS Switch Port 0 options", "qos_sw0", &p_opts->qos_sw0_options); + fprintf(opts_file, "\n"); + subn_dump_qos_options(opts_file, + "QoS Switch external ports options", "qos_swe", &p_opts->qos_swe_options); + fprintf(opts_file, "\n"); + subn_dump_qos_options(opts_file, + "QoS Router ports options", "qos_rtr", &p_opts->qos_rtr_options); + + /* optional string attributes ... */ + + fclose(opts_file); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sw_info_rcv.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sw_info_rcv.c new file mode 100644 index 00000000..5edbf0bf --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sw_info_rcv.c @@ -0,0 +1,681 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sw_info_rcv.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Implementation of osm_si_rcv_t. + * This object represents the SwitchInfo Receiver object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.6 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + The plock must be held before calling this function. +**********************************************************************/ +static void +__osm_si_rcv_get_port_info( + IN const osm_si_rcv_t* const p_rcv, + IN osm_switch_t* const p_sw, + IN const osm_madw_t* const p_madw ) +{ + osm_madw_context_t context; + uint8_t port_num; + osm_physp_t *p_physp; + osm_node_t *p_node; + uint8_t num_ports; + osm_dr_path_t dr_path; + const ib_smp_t* p_smp; + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_si_rcv_get_port_info ); + + CL_ASSERT( p_sw ); + + p_node = osm_switch_get_node_ptr( p_sw ); + p_smp = osm_madw_get_smp_ptr( p_madw ); + + CL_ASSERT( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH ); + + /* + Request PortInfo attribute for each port on the switch. + Don't trust the port's own DR Path, since it may no longer + be a legitimate path through the subnet. + Build a path from the mad instead, since we know that path works. + The port's DR Path info gets updated when the PortInfo + attribute is received. + */ + p_physp = osm_node_get_any_physp_ptr( p_node ); + + CL_ASSERT( osm_physp_is_valid( p_physp ) ); + + context.pi_context.node_guid = osm_node_get_node_guid( p_node ); + context.pi_context.port_guid = osm_physp_get_port_guid( p_physp ); + context.pi_context.set_method = FALSE; + context.pi_context.update_master_sm_base_lid = FALSE; + context.pi_context.ignore_errors = FALSE; + context.pi_context.light_sweep = FALSE; + context.pi_context.active_transition = FALSE; + + num_ports = osm_node_get_num_physp( p_node ); + osm_dr_path_init( &dr_path, + osm_madw_get_bind_handle( p_madw ), + p_smp->hop_count, p_smp->initial_path ); + + for( port_num = 0; port_num < num_ports; port_num++) + { + status = osm_req_get( + p_rcv->p_req, + &dr_path, + IB_MAD_ATTR_PORT_INFO, + cl_hton32( port_num ), + CL_DISP_MSGID_NONE, + &context ); + if( status != IB_SUCCESS ) + { + /* continue the loop despite the error */ + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_si_rcv_get_port_info: ERR 3602: " + "Failure initiating PortInfo request (%s)\n", + ib_get_err_str(status)); + } + } + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + The plock must be held before calling this function. +**********************************************************************/ +static void +__osm_si_rcv_get_fwd_tbl( + IN const osm_si_rcv_t* const p_rcv, + IN osm_switch_t* const p_sw ) +{ + osm_madw_context_t context; + osm_dr_path_t *p_dr_path; + osm_physp_t *p_physp; + osm_node_t *p_node; + uint32_t block_id_ho; + uint32_t max_block_id_ho; + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_si_rcv_get_fwd_tbl ); + + CL_ASSERT( p_sw ); + + p_node = osm_switch_get_node_ptr( p_sw ); + + CL_ASSERT( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH ); + + p_physp = osm_node_get_any_physp_ptr( p_node ); + + CL_ASSERT( osm_physp_is_valid( p_physp ) ); + + context.lft_context.node_guid = osm_node_get_node_guid( p_node ); + context.lft_context.set_method = FALSE; + + max_block_id_ho = osm_switch_get_max_block_id_in_use( p_sw ); + + p_dr_path = osm_physp_get_dr_path_ptr( p_physp ); + + for( block_id_ho = 0; block_id_ho <= max_block_id_ho; block_id_ho++) + { + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_si_rcv_get_fwd_tbl: " + "Retrieving FT block %u\n", block_id_ho ); + } + + status = osm_req_get( + p_rcv->p_req, + p_dr_path, + IB_MAD_ATTR_LIN_FWD_TBL, + cl_hton32( block_id_ho ), + CL_DISP_MSGID_NONE, + &context ); + if( status != IB_SUCCESS ) + { + /* continue the loop despite the error */ + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_si_rcv_get_fwd_tbl: ERR 3603: " + "Failure initiating PortInfo request (%s)\n", + ib_get_err_str(status)); + } + } + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +#if 0 +/********************************************************************** + The plock must be held before calling this function. +**********************************************************************/ +static void +__osm_si_rcv_get_mcast_fwd_tbl( + IN const osm_si_rcv_t* const p_rcv, + IN osm_switch_t* const p_sw ) +{ + osm_madw_context_t context; + osm_dr_path_t *p_dr_path; + osm_physp_t *p_physp; + osm_node_t *p_node; + osm_mcast_tbl_t* p_tbl; + uint32_t block_id_ho; + uint32_t max_block_id_ho; + uint32_t position; + uint32_t max_position; + uint32_t attr_mod_ho; + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_si_rcv_get_mcast_fwd_tbl ); + + CL_ASSERT( p_sw ); + + p_node = osm_switch_get_node_ptr( p_sw ); + + CL_ASSERT( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH ); + + if( osm_switch_get_mcast_fwd_tbl_size( p_sw ) == 0 ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_si_rcv_get_mcast_fwd_tbl: " + "Multicast not supported by switch 0x%016" PRIx64 "\n", + cl_ntoh64( osm_node_get_node_guid( p_node ) ) ); + goto Exit; + } + + p_physp = osm_node_get_any_physp_ptr( p_node ); + p_tbl = osm_switch_get_mcast_tbl_ptr( p_sw ); + + CL_ASSERT( osm_physp_is_valid( p_physp ) ); + + context.mft_context.node_guid = osm_node_get_node_guid( p_node ); + context.mft_context.set_method = FALSE; + + max_block_id_ho = osm_mcast_tbl_get_max_block( p_tbl ); + + if( max_block_id_ho > IB_MCAST_MAX_BLOCK_ID ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_si_rcv_get_mcast_fwd_tbl: ERR 3609: " + "Out-of-range mcast block size = %u on switch 0x%016" PRIx64 + "\n", max_block_id_ho, + cl_ntoh64( osm_node_get_node_guid( p_node ) ) ); + goto Exit; + } + + max_position = osm_mcast_tbl_get_max_position( p_tbl ); + + CL_ASSERT( max_position <= IB_MCAST_POSITION_MAX ); + + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_si_rcv_get_mcast_fwd_tbl: " + "Max MFT block = %u, Max position = %u\n", max_block_id_ho, + max_position ); + + p_dr_path = osm_physp_get_dr_path_ptr( p_physp ); + + for( block_id_ho = 0; block_id_ho <= max_block_id_ho; block_id_ho++) + { + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_si_rcv_get_mcast_fwd_tbl: " + "Retrieving MFT block %u\n", block_id_ho ); + } + + for( position = 0; position <= max_position; position++ ) + { + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_si_rcv_get_mcast_fwd_tbl: " + "Retrieving MFT position %u\n", position ); + } + + attr_mod_ho = block_id_ho | position << IB_MCAST_POSITION_SHIFT; + status = osm_req_get( + p_rcv->p_req, + p_dr_path, + IB_MAD_ATTR_MCAST_FWD_TBL, + cl_hton32( attr_mod_ho ), + CL_DISP_MSGID_NONE, + &context ); + if( status != IB_SUCCESS ) + { + /* continue the loop despite the error */ + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_si_rcv_get_mcast_fwd_tbl: ERR 3607: " + "Failure initiating PortInfo request (%s)\n", + ib_get_err_str(status)); + } + } + } + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} +#endif + +/********************************************************************** + Lock must be held on entry to this function. +**********************************************************************/ +static void +__osm_si_rcv_process_new( + IN const osm_si_rcv_t* const p_rcv, + IN osm_node_t* const p_node, + IN const osm_madw_t* const p_madw ) +{ + osm_switch_t *p_sw; + osm_switch_t *p_check; + ib_switch_info_t *p_si; + ib_smp_t *p_smp; + cl_qmap_t *p_sw_guid_tbl; + + CL_ASSERT( p_rcv ); + + OSM_LOG_ENTER( p_rcv->p_log, __osm_si_rcv_process_new ); + + CL_ASSERT( p_madw ); + + p_sw_guid_tbl = &p_rcv->p_subn->sw_guid_tbl; + + p_smp = osm_madw_get_smp_ptr( p_madw ); + p_si = (ib_switch_info_t*)ib_smp_get_payload_ptr( p_smp ); + + osm_dump_switch_info( p_rcv->p_log, p_si, OSM_LOG_DEBUG ); + + /* + Allocate a new switch object for this switch, + and place it in the switch table. + */ + p_sw = osm_switch_new( p_node, p_madw ); + if( p_sw == NULL ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_si_rcv_process_new: ERR 3608: " + "Unable to allocate new switch object\n" ); + goto Exit; + } + + /* set subnet max mlid to the minimum MulticastFDBCap of all switches */ + if ( p_sw->mcast_tbl.max_mlid_ho < p_rcv->p_subn->max_multicast_lid_ho ) + { + p_rcv->p_subn->max_multicast_lid_ho = p_sw->mcast_tbl.max_mlid_ho; + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "__osm_si_rcv_process_new: " + "Subnet max multicast lid is 0x%X\n", + p_rcv->p_subn->max_multicast_lid_ho ); + } + + /* set subnet max unicast lid to the minimum LinearFDBCap of all switches */ + if ( p_sw->fwd_tbl.p_lin_tbl->size < p_rcv->p_subn->max_unicast_lid_ho ) + { + p_rcv->p_subn->max_unicast_lid_ho = p_sw->fwd_tbl.p_lin_tbl->size; + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "__osm_si_rcv_process_new: " + "Subnet max unicast lid is 0x%X\n", + p_rcv->p_subn->max_unicast_lid_ho ); + } + + p_check = (osm_switch_t*)cl_qmap_insert( p_sw_guid_tbl, + osm_node_get_node_guid( p_node ), + &p_sw->map_item ); + + if( p_check != p_sw ) + { + /* + This shouldn't happen since we hold the lock! + */ + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_si_rcv_process_new: ERR 3605: " + "Unable to add new switch object to database\n" ); + osm_switch_delete( &p_sw ); + goto Exit; + } + + p_node->sw = p_sw; + + /* + Update the switch info according to the + info we just received. + */ + osm_switch_set_switch_info( p_sw, p_si ); + osm_switch_discovery_count_inc( p_sw ); + + /* + Get the PortInfo attribute for every port. + */ + __osm_si_rcv_get_port_info( p_rcv, p_sw, p_madw ); + __osm_si_rcv_get_fwd_tbl( p_rcv, p_sw ); + + /* + Don't bother retrieving the current multicast tables + from the switches. The current version of SM does + not support silent take-over of an existing multicast + configuration. + + Gathering the multicast tables can also generate large amounts + of extra subnet-init traffic. + + The code to retrieve the tables was fully debugged. + */ +#if 0 + if( !p_rcv->p_subn->opt.disable_multicast ) + __osm_si_rcv_get_mcast_fwd_tbl( p_rcv, p_sw ); +#endif + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + Lock must be held on entry to this function. + Return 1 if the caller is expected to send a change_detected event. + this can not be done internally as the event needs the lock... +**********************************************************************/ +static boolean_t +__osm_si_rcv_process_existing( + IN const osm_si_rcv_t* const p_rcv, + IN osm_node_t* const p_node, + IN const osm_madw_t* const p_madw ) +{ + osm_switch_t *p_sw = p_node->sw; + ib_switch_info_t *p_si; + osm_si_context_t *p_si_context; + ib_smp_t *p_smp; + boolean_t is_change_detected = FALSE; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_si_rcv_process_existing ); + + CL_ASSERT( p_madw ); + + p_smp = osm_madw_get_smp_ptr( p_madw ); + p_si = (ib_switch_info_t*)ib_smp_get_payload_ptr( p_smp ); + p_si_context = osm_madw_get_si_context_ptr( p_madw ); + + if( p_si_context->set_method ) + { + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_si_rcv_process_existing: " + "Received logical SetResp()\n" ); + } + + osm_switch_set_switch_info( p_sw, p_si ); + } + else + { + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_si_rcv_process_existing: " + "Received logical GetResp()\n" ); + } + + osm_switch_set_switch_info( p_sw, p_si ); + + /* + Check the port state change bit. If true, then this switch + has seen a port state transition, so continue probing. + */ + if( p_si_context->light_sweep == TRUE ) + { + /* This is a light sweep */ + /* If the mad was returned with an error - + signal a change to the state manager. */ + if ( ib_smp_get_status( p_smp ) != 0 ) + { + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "__osm_si_rcv_process_existing: " + "GetResp() received with error in light sweep. " + "Commencing heavy sweep\n" ); + is_change_detected = TRUE; + } + else + { + /* + If something changed, then just signal the state + manager. Don't attempt to probe further during + a light sweep. + */ + if( ib_switch_info_get_state_change( p_si ) ) + { + osm_dump_switch_info( p_rcv->p_log, p_si, OSM_LOG_DEBUG ); + is_change_detected = TRUE; + } + } + } + else + { + /* + This is a heavy sweep. Get information regardless + of the state change bit. + */ + osm_switch_discovery_count_inc( p_sw ); + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "__osm_si_rcv_process_existing: " + "discovery_count is:%u\n", + osm_switch_discovery_count_get( p_sw ) ); + + /* If this is the first discovery - then get the port_info */ + if ( osm_switch_discovery_count_get( p_sw ) == 1 ) + __osm_si_rcv_get_port_info( p_rcv, p_sw, p_madw ); + else + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_si_rcv_process_existing: " + "Not discovering again through switch:0x%" + PRIx64 "\n", + osm_node_get_node_guid( p_sw->p_node) ); + } + } + } + + OSM_LOG_EXIT( p_rcv->p_log ); + return is_change_detected; +} + +/********************************************************************** + **********************************************************************/ +void +osm_si_rcv_construct( + IN osm_si_rcv_t* const p_rcv ) +{ + memset( p_rcv, 0, sizeof(*p_rcv) ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_si_rcv_destroy( + IN osm_si_rcv_t* const p_rcv ) +{ + CL_ASSERT( p_rcv ); + + OSM_LOG_ENTER( p_rcv->p_log, osm_si_rcv_destroy ); + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_si_rcv_init( + IN osm_si_rcv_t* const p_rcv, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN osm_req_t* const p_req, + IN osm_state_mgr_t* const p_state_mgr, + IN cl_plock_t* const p_lock ) +{ + ib_api_status_t status = IB_SUCCESS; + OSM_LOG_ENTER( p_log, osm_si_rcv_init ); + + osm_si_rcv_construct( p_rcv ); + + p_rcv->p_log = p_log; + p_rcv->p_subn = p_subn; + p_rcv->p_lock = p_lock; + p_rcv->p_req = p_req; + p_rcv->p_state_mgr = p_state_mgr; + + OSM_LOG_EXIT( p_rcv->p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_si_rcv_process( + IN const osm_si_rcv_t* const p_rcv, + IN osm_madw_t* const p_madw ) +{ + cl_qmap_t *p_node_guid_tbl; + ib_switch_info_t *p_si; + ib_smp_t *p_smp; + osm_node_t *p_node; + ib_net64_t node_guid; + osm_si_context_t *p_context; + + CL_ASSERT( p_rcv ); + + OSM_LOG_ENTER( p_rcv->p_log, osm_si_rcv_process ); + + CL_ASSERT( p_madw ); + + p_node_guid_tbl = &p_rcv->p_subn->node_guid_tbl; + p_smp = osm_madw_get_smp_ptr( p_madw ); + p_si = (ib_switch_info_t*)ib_smp_get_payload_ptr( p_smp ); + + /* + Acquire the switch object and add the switch info. + */ + + p_context = osm_madw_get_si_context_ptr( p_madw ); + + node_guid = p_context->node_guid; + + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "osm_si_rcv_process: " + "Switch GUID 0x%016" PRIx64 + ", TID 0x%" PRIx64 "\n", + cl_ntoh64( node_guid ), + cl_ntoh64( p_smp->trans_id ) ); + } + + CL_PLOCK_EXCL_ACQUIRE( p_rcv->p_lock ); + + p_node = (osm_node_t*)cl_qmap_get( p_node_guid_tbl, node_guid ); + if( p_node == (osm_node_t*)cl_qmap_end( p_node_guid_tbl ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_si_rcv_process: ERR 3606: " + "SwitchInfo received for nonexistent node " + "with GUID 0x%" PRIx64 "\n", + cl_ntoh64( node_guid ) ); + } + else + { + + /* + Hack for bad value in Mellanox switch + */ + if( cl_ntoh16( p_si->lin_top ) > IB_LID_UCAST_END_HO ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_si_rcv_process: ERR 3610: " + "\n\t\t\t\tBad LinearFDBTop value = 0x%X " + "on switch 0x%" PRIx64 + "\n\t\t\t\tForcing correction to 0x%X\n", + cl_ntoh16( p_si->lin_top ), + cl_ntoh64( osm_node_get_node_guid( p_node ) ), + 0 ); + + p_si->lin_top = 0; + } + + /* + Acquire the switch object for this switch. + */ + if( !p_node->sw ) + { + __osm_si_rcv_process_new( p_rcv, p_node, p_madw ); + /* + A new switch was found during the sweep so we need + to ignore the current LFT settings. + */ + p_rcv->p_subn->ignore_existing_lfts = TRUE; + } + else + { + /* we might get back a request for signaling change was detected */ + if (__osm_si_rcv_process_existing( p_rcv, p_node, p_madw )) + { + CL_PLOCK_RELEASE( p_rcv->p_lock ); + osm_state_mgr_process( p_rcv->p_state_mgr, + OSM_SIGNAL_CHANGE_DETECTED ); + goto Exit; + } + } + } + + CL_PLOCK_RELEASE( p_rcv->p_lock ); + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sw_info_rcv_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sw_info_rcv_ctrl.c new file mode 100644 index 00000000..6c8c478c --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sw_info_rcv_ctrl.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sw_info_rcv_ctrl.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Implementation of osm_si_rcv_ctrl_t. + * This object represents the SwitchInfo request controller object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +__osm_si_rcv_ctrl_disp_callback( + IN void *context, + IN void *p_data ) +{ + /* ignore return status when invoked via the dispatcher */ + osm_si_rcv_process( ((osm_si_rcv_ctrl_t*)context)->p_rcv, + (osm_madw_t*)p_data ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_si_rcv_ctrl_construct( + IN osm_si_rcv_ctrl_t* const p_ctrl ) +{ + memset( p_ctrl, 0, sizeof(*p_ctrl) ); + p_ctrl->h_disp = CL_DISP_INVALID_HANDLE; +} + +/********************************************************************** + **********************************************************************/ +void +osm_si_rcv_ctrl_destroy( + IN osm_si_rcv_ctrl_t* const p_ctrl ) +{ + CL_ASSERT( p_ctrl ); + cl_disp_unregister( p_ctrl->h_disp ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_si_rcv_ctrl_init( + IN osm_si_rcv_ctrl_t* const p_ctrl, + IN osm_si_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_si_rcv_ctrl_init ); + + osm_si_rcv_ctrl_construct( p_ctrl ); + p_ctrl->p_log = p_log; + + p_ctrl->p_rcv = p_rcv; + p_ctrl->p_disp = p_disp; + + p_ctrl->h_disp = cl_disp_register( + p_disp, + OSM_MSG_MAD_SWITCH_INFO, + __osm_si_rcv_ctrl_disp_callback, + p_ctrl ); + + if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_si_rcv_ctrl_init: ERR 3701: " + "Dispatcher registration failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return( status ); +} + + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sweep_fail_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sweep_fail_ctrl.c new file mode 100644 index 00000000..19335621 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sweep_fail_ctrl.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_sweep_fail_ctrl.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_sweep_fail_ctrl_t. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.5 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +__osm_sweep_fail_ctrl_disp_callback( + IN void *context, + IN void *p_data ) +{ + osm_sweep_fail_ctrl_t* const p_ctrl = (osm_sweep_fail_ctrl_t*)context; + + OSM_LOG_ENTER( p_ctrl->p_log, __osm_sweep_fail_ctrl_disp_callback ); + + UNUSED_PARAM( p_data ); + /* + Notify the state manager that we had a light sweep failure. + */ + osm_state_mgr_process( p_ctrl->p_state_mgr, + OSM_SIGNAL_LIGHT_SWEEP_FAIL ); + + OSM_LOG_EXIT( p_ctrl->p_log ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_sweep_fail_ctrl_construct( + IN osm_sweep_fail_ctrl_t* const p_ctrl ) +{ + memset( p_ctrl, 0, sizeof(*p_ctrl) ); + p_ctrl->h_disp = CL_DISP_INVALID_HANDLE; +} + +/********************************************************************** + **********************************************************************/ +void +osm_sweep_fail_ctrl_destroy( + IN osm_sweep_fail_ctrl_t* const p_ctrl ) +{ + CL_ASSERT( p_ctrl ); + cl_disp_unregister( p_ctrl->h_disp ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_sweep_fail_ctrl_init( + IN osm_sweep_fail_ctrl_t* const p_ctrl, + IN osm_log_t* const p_log, + IN osm_state_mgr_t* const p_state_mgr, + IN cl_dispatcher_t* const p_disp ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_sweep_fail_ctrl_init ); + + osm_sweep_fail_ctrl_construct( p_ctrl ); + p_ctrl->p_log = p_log; + p_ctrl->p_disp = p_disp; + p_ctrl->p_state_mgr = p_state_mgr; + + p_ctrl->h_disp = cl_disp_register( + p_disp, + OSM_MSG_LIGHT_SWEEP_FAIL, + __osm_sweep_fail_ctrl_disp_callback, + p_ctrl ); + + if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_sweep_fail_ctrl_init: ERR 3501: " + "Dispatcher registration failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return( status ); +} + + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_switch.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_switch.c new file mode 100644 index 00000000..f59fcf67 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_switch.c @@ -0,0 +1,550 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_switch.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Implementation of osm_switch_t. + * This object represents an Infiniband switch. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.13 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +osm_switch_construct( + IN osm_switch_t* const p_sw ) +{ + CL_ASSERT( p_sw ); + memset( p_sw, 0, sizeof(*p_sw) ); + osm_lid_matrix_construct( &p_sw->lmx ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_switch_init( + IN osm_switch_t* const p_sw, + IN osm_node_t* const p_node, + IN const osm_madw_t* const p_madw ) +{ + ib_api_status_t status = IB_SUCCESS; + ib_switch_info_t *p_si; + ib_smp_t *p_smp; + uint8_t num_ports; + uint32_t port_num; + + CL_ASSERT( p_sw ); + CL_ASSERT( p_madw ); + CL_ASSERT( p_node ); + + osm_switch_construct( p_sw ); + + p_smp = osm_madw_get_smp_ptr( p_madw ); + p_si = (ib_switch_info_t*)ib_smp_get_payload_ptr( p_smp ); + num_ports = osm_node_get_num_physp( p_node ); + + CL_ASSERT( p_smp->attr_id == IB_MAD_ATTR_SWITCH_INFO ); + + p_sw->p_node = p_node; + p_sw->switch_info = *p_si; + + status = osm_lid_matrix_init( &p_sw->lmx, num_ports ); + if( status != IB_SUCCESS ) + goto Exit; + + status = osm_fwd_tbl_init( &p_sw->fwd_tbl, p_si ); + if( status != IB_SUCCESS ) + goto Exit; + + p_sw->p_prof = malloc( sizeof(*p_sw->p_prof) * num_ports ); + if( p_sw->p_prof == NULL ) + { + status = IB_INSUFFICIENT_MEMORY; + goto Exit; + } + + memset( p_sw->p_prof, 0, sizeof(*p_sw->p_prof) * num_ports ); + + status = osm_mcast_tbl_init( &p_sw->mcast_tbl, + osm_node_get_num_physp( p_node ), cl_ntoh16( p_si->mcast_cap ) ); + if( status != IB_SUCCESS ) + goto Exit; + + for( port_num = 0; port_num < num_ports; port_num++ ) + osm_port_prof_construct( &p_sw->p_prof[port_num] ); + + Exit: + return( status ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_switch_destroy( + IN osm_switch_t* const p_sw ) +{ + /* free memory to avoid leaks */ + osm_mcast_tbl_destroy( &p_sw->mcast_tbl ); + free( p_sw->p_prof ); + osm_fwd_tbl_destroy( &p_sw->fwd_tbl ); + osm_lid_matrix_destroy( &p_sw->lmx ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_switch_delete( + IN OUT osm_switch_t** const pp_sw ) +{ + osm_switch_destroy( *pp_sw ); + free( *pp_sw ); + *pp_sw = NULL; +} + +/********************************************************************** + **********************************************************************/ +osm_switch_t* +osm_switch_new( + IN osm_node_t* const p_node, + IN const osm_madw_t* const p_madw ) +{ + ib_api_status_t status; + osm_switch_t *p_sw; + + p_sw = (osm_switch_t*)malloc( sizeof(*p_sw) ); + if( p_sw ) + { + memset( p_sw, 0, sizeof(*p_sw) ); + status = osm_switch_init( p_sw, p_node, p_madw ); + if( status != IB_SUCCESS ) + osm_switch_delete( &p_sw ); + } + + return( p_sw ); +} + +/********************************************************************** + **********************************************************************/ +boolean_t +osm_switch_get_fwd_tbl_block( + IN const osm_switch_t* const p_sw, + IN const uint32_t block_id, + OUT uint8_t* const p_block ) +{ + uint16_t base_lid_ho; + uint16_t max_lid_ho; + uint16_t lid_ho; + uint16_t block_top_lid_ho; + uint32_t lids_per_block; + osm_fwd_tbl_t *p_tbl; + boolean_t return_flag = FALSE; + + CL_ASSERT( p_sw ); + CL_ASSERT( p_block ); + + p_tbl = osm_switch_get_fwd_tbl_ptr( p_sw ); + max_lid_ho = osm_switch_get_max_lid_ho( p_sw ); + lids_per_block = osm_fwd_tbl_get_lids_per_block( &p_sw->fwd_tbl ); + base_lid_ho = (uint16_t)(block_id * lids_per_block); + + if( base_lid_ho <= max_lid_ho ) + { + /* Initialize LIDs in block to invalid port number. */ + memset( p_block, 0xff, IB_SMP_DATA_SIZE ); + /* + Determine the range of LIDs we can return with this block. + */ + block_top_lid_ho = (uint16_t)(base_lid_ho + lids_per_block - 1); + if( block_top_lid_ho > max_lid_ho ) + block_top_lid_ho = max_lid_ho; + + /* + Configure the forwarding table with the routing + information for the specified block of LIDs. + */ + for( lid_ho = base_lid_ho; lid_ho <= block_top_lid_ho; lid_ho++ ) + { + p_block[lid_ho - base_lid_ho] = osm_fwd_tbl_get( p_tbl, lid_ho ); + } + + return_flag = TRUE; + } + + return( return_flag ); +} + +/********************************************************************** + **********************************************************************/ +uint8_t +osm_switch_recommend_path( + IN const osm_switch_t* const p_sw, + IN const uint16_t lid_ho, + IN const boolean_t ignore_existing, + IN OUT uint64_t *remote_sys_guids, + IN OUT uint16_t *p_num_used_sys, + IN OUT uint64_t *remote_node_guids, + IN OUT uint16_t *p_num_used_nodes + ) +{ + /* + We support an enhanced LMC aware routing mode: + In the case of LMC > 0, we can track the remote side + system and node for all of the lids of the target + and try and avoid routing again through the same + system / node. + + If the procedure is provided with the tracking arrays + and counters we can conduct this algorithm. + */ + boolean_t routing_for_lmc = remote_sys_guids && remote_node_guids && + p_num_used_sys && p_num_used_nodes; + boolean_t sys_used, node_used; + uint16_t i; + uint8_t hops; + uint8_t least_hops; + uint8_t port_num; + uint8_t num_ports; + uint32_t least_paths = 0xFFFFFFFF; + /* + The follwing will track the least paths if the + route should go through a new system/node + */ + uint32_t least_paths_other_sys = 0xFFFFFFFF; + uint32_t least_paths_other_nodes = 0xFFFFFFFF; + uint32_t check_count; + uint8_t best_port = 0; + /* + These vars track the best port if it connects to + not used system/node. + */ + uint8_t best_port_other_sys = 0; + uint8_t best_port_other_node = 0; + boolean_t port_found = FALSE; + osm_physp_t *p_physp; + osm_physp_t *p_rem_physp; + osm_node_t *p_rem_node; + + CL_ASSERT( lid_ho > 0 ); + + num_ports = osm_switch_get_num_ports( p_sw ); + + least_hops = osm_switch_get_least_hops( p_sw, lid_ho ); + if ( least_hops == OSM_NO_PATH ) + return (OSM_NO_PATH); + + /* + First, inquire with the forwarding table for an existing + route. If one is found, honor it unless: + 1. the ignore existing flag is set. + 2. the physical port is not a valid one or not healthy + 3. the physical port has a remote port (the link is up) + 4. the port has min-hops to the target (avoid loops) + */ + if( !ignore_existing ) + { + port_num = osm_fwd_tbl_get( &p_sw->fwd_tbl, lid_ho ); + + if (port_num != OSM_NO_PATH) + { + p_physp = osm_node_get_physp_ptr(p_sw->p_node, port_num); + /* + Don't be too trusting of the current forwarding table! + Verify that the port number is legal and that the + LID is reachable through this port. + */ + if( (port_num < num_ports ) && + osm_physp_is_valid(p_physp) && + osm_physp_is_healthy(p_physp) && + osm_physp_get_remote(p_physp) ) + { + hops = osm_switch_get_hop_count( p_sw, lid_ho, port_num ); + /* + If we aren't using pre-defined user routes function, then + we need to make sure that the current path is the minimum one. + In case of having such a user function - this check will not + be done, and the old routing will be used. + Note: This means that it is the user's job to clean all data + in the forwarding tables that he wants to be overridden by the + minimum hop function. + */ + if ( hops == least_hops ) + { + return( port_num ); + } + } + } + } + + /* + This algorithm selects a port based on a static load balanced + selection across equal hop-count ports. + There is lots of room for improved sophistication here, + possibly guided by user configuration info. + */ + + /* + OpenSM routing is "local" - not considering a full lid to lid + path. As such we can not guarantee a path will not loop if we + do not always follow least hops. + So we must abort if not least hops. + */ + + /* port number starts with zero and num_ports is 1 + num phys ports */ + for ( port_num = 0; port_num < num_ports; port_num++ ) + { + if ( osm_switch_get_hop_count( p_sw, lid_ho, port_num ) == least_hops) + { + /* let us make sure it is not down or unhealthy */ + p_physp = osm_node_get_physp_ptr(p_sw->p_node, port_num); + if (osm_physp_is_valid(p_physp) && + osm_physp_is_healthy(p_physp) && + /* + we require all - non sma ports to be linked + to be routed through + */ + (!port_num || osm_physp_get_remote(p_physp))) + { + + /* + We located a least-hop port, possibly one of many. + For this port, check the running total count of + the number of paths through this port. Select + the port routing the least number of paths. + */ + check_count = osm_port_prof_path_count_get( + &p_sw->p_prof[port_num] ); + + /* + Advanced LMC routing requires tracking of the + best port by the node connected to the other side of + it. + */ + if (routing_for_lmc && port_num) + { +#if 0 + printf("LID:0x%X SYS:%d NODE:%d\n", lid_ho, *p_num_used_sys, *p_num_used_nodes); +#endif + + /* Get the Remote Node */ + p_rem_physp = osm_physp_get_remote(p_physp); + p_rem_node = osm_physp_get_node_ptr(p_rem_physp); + + /* Is the sys guid already used ? */ + sys_used = FALSE; + for (i = 0; !sys_used && (i < *p_num_used_sys); i++) + if (!memcmp(&p_rem_node->node_info.sys_guid, + &remote_sys_guids[i], + sizeof(uint64_t))) + sys_used = TRUE; + + /* If not update the least hops for this case */ + if (!sys_used) + { + if (check_count < least_paths_other_sys) + { + least_paths_other_sys = check_count; + best_port_other_sys = port_num; + } + } + else + { /* same sys found - try node */ + + /* Else is the node guid already used ? */ + node_used = FALSE; + for (i = 0; !node_used && (i < *p_num_used_nodes); i++) + if (!memcmp(&p_rem_node->node_info.node_guid, + &remote_node_guids[i], + sizeof(uint64_t))) + node_used = TRUE; + + + /* If not update the least hops for this case */ + if (!node_used) + { + if (check_count < least_paths_other_nodes) + { + least_paths_other_nodes = check_count; + best_port_other_node = port_num; + } + } + + } /* same sys found */ + } /* routing for LMC mode */ + + /* + the count is min but also lower then the max subscribed + */ + if( check_count < least_paths ) + { + port_found = TRUE; + best_port = port_num; + least_paths = check_count; + } + } + } + } + + if ( port_found == FALSE ) + return (OSM_NO_PATH); + + /* + if we are in enhanced routing mode and the best port is not + the local port 0 + */ + if (routing_for_lmc && best_port) + { + /* Select the least hop port of the non used sys first */ + if (best_port_other_sys) + best_port = best_port_other_sys; + else if (best_port_other_node) + best_port = best_port_other_node; + + /* track the remote node and system of the port used. */ + p_physp = osm_node_get_physp_ptr(p_sw->p_node, best_port); + p_rem_physp = osm_physp_get_remote(p_physp); + p_rem_node = osm_physp_get_node_ptr(p_rem_physp); + memcpy(&remote_node_guids[*p_num_used_nodes], + &(p_rem_node->node_info.node_guid), + sizeof(uint64_t)); + (*p_num_used_nodes)++; + memcpy(&remote_sys_guids[*p_num_used_sys], + &(p_rem_node->node_info.sys_guid), + sizeof(uint64_t)); + (*p_num_used_sys)++; + } + + return( best_port ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_switch_prepare_path_rebuild( + IN osm_switch_t* const p_sw ) +{ + uint8_t port_num; + uint8_t num_ports; + + num_ports = osm_switch_get_num_ports( p_sw ); + osm_lid_matrix_clear( &p_sw->lmx ); + for( port_num = 0; port_num < num_ports; port_num++ ) + osm_port_prof_construct( &p_sw->p_prof[port_num] ); +} + +/********************************************************************** + **********************************************************************/ +uint8_t +osm_switch_recommend_mcast_path( + IN osm_switch_t* const p_sw, + IN uint16_t const lid_ho, + IN uint16_t const mlid_ho, + IN boolean_t const ignore_existing ) +{ + uint8_t hops; + uint8_t port_num; + uint8_t num_ports; + uint8_t least_hops; + + CL_ASSERT( lid_ho > 0 ); + CL_ASSERT( mlid_ho >= IB_LID_MCAST_START_HO ); + + num_ports = osm_switch_get_num_ports( p_sw ); + + /* + If the user wants us to ignore existing multicast routes, + then simply return the shortest hop count path to the + target port. + + Otherwise, return the first port that has a path to the target, + picking from the ports that are already in the multicast group. + */ + if( !ignore_existing ) + { + for( port_num = 1; port_num < num_ports; port_num++ ) + { + if( osm_mcast_tbl_is_port( &p_sw->mcast_tbl, mlid_ho, port_num ) ) + { + /* + Don't be too trusting of the current forwarding table! + Verify that the LID is reachable through this port. + */ + hops = osm_switch_get_hop_count( p_sw, lid_ho, port_num ); + if( hops != OSM_NO_PATH ) + { + return( port_num ); + } + } + } + } + + /* + Either no existing mcast paths reach this port or we are + ignoring existing paths. + + Determine the best multicast path to the target. Note that this + algorithm is slightly different from the one used for unicast route + recommendation. In this case (multicast), we must NOT + perform any sort of load balancing. We MUST take the FIRST + port found that has <= the lowest hop count path. This prevents + more than one multicast path to the same remote switch which + prevents a multicast loop. Multicast loops are bad since the same + multicast packet will go around and around, inevitably creating + a black hole that will destroy the Earth in a firey conflagration. + */ + least_hops = osm_switch_get_least_hops( p_sw, lid_ho ); + for( port_num = 0; port_num < num_ports; port_num++ ) + { + if( osm_switch_get_hop_count( p_sw, lid_ho, port_num ) == least_hops ) + break; + } + + CL_ASSERT( port_num < num_ports ); + return( port_num ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_trap_rcv.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_trap_rcv.c new file mode 100644 index 00000000..dbd511ce --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_trap_rcv.c @@ -0,0 +1,771 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_trap_rcv.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Implementation of osm_trap_rcv_t. + * This object represents the Trap Receiver object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.12 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + * + * TRAP HANDLING: + * + * Assuming traps can be caused by bad hardware we should provide + * a mechanism for filtering their propagation into the actual logic + * of OpenSM such that it is not overloaded by them. + * + * We will provide a trap filtering mechanism with "Aging" capability. + * This mechanism will track incoming traps, clasify them by their + * source and content and provide back their age. + * + * A timer running in the background will toggle a timer counter + * that should be referenced by the aging algorithm. + * To provide an efficient handling of aging. We also track all traps + * in a sorted list by their aging. + * + * The generic Aging Tracker mechanism is implemented in the + * cl_aging_tracker object. + * + **********************************************************************/ + +typedef struct _osm_trap_aging_tracker_context +{ + osm_log_t* p_log; + osm_physp_t* p_physp; +} osm_trap_aging_tracker_context_t; + +/********************************************************************** + **********************************************************************/ +osm_physp_t * +__get_physp_by_lid_and_num( + IN osm_trap_rcv_t* const p_rcv, + IN uint16_t lid, + IN uint8_t num) +{ + cl_ptr_vector_t *p_vec = &(p_rcv->p_subn->port_lid_tbl); + osm_port_t *p_port; + + if (lid > cl_ptr_vector_get_size(p_vec)) + return NULL; + + p_port = (osm_port_t *)cl_ptr_vector_get(p_vec, lid); + if (! p_port) + return NULL; + + if (osm_port_get_num_physp(p_port) < num) + return NULL; + + return( osm_port_get_phys_ptr(p_port, num) ); +} + +/********************************************************************** + **********************************************************************/ +uint64_t +osm_trap_rcv_aging_tracker_callback( + IN uint64_t key, + IN uint32_t num_regs, + IN void* context ) +{ + osm_trap_rcv_t* p_rcv = (osm_trap_rcv_t*)context; + uint16_t lid; + uint8_t port_num; + osm_physp_t* p_physp; + + OSM_LOG_ENTER( p_rcv->p_log, osm_trap_rcv_aging_tracker_callback ); + + if (osm_exit_flag) + /* We got an exit flag - do nothing */ + return 0; + + lid = cl_ntoh16((uint16_t)(( key & 0x0000FFFF00000000ULL) >> 32)); + port_num = (uint8_t)(( key & 0x00FF000000000000ULL) >> 48); + + p_physp = __get_physp_by_lid_and_num( p_rcv, lid, port_num ); + if (!p_physp) + { + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "osm_trap_rcv_aging_tracker_callback: " + "Cannot find port num:0x%X with lid:%u\n", + port_num, lid ); + } + else + { + /* make sure the physp is still valid */ + if ( osm_physp_is_valid(p_physp) ) + { + /* If the health port was false - set it to true */ + if (!osm_physp_is_healthy(p_physp) ) + { + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "osm_trap_rcv_aging_tracker_callback: " + "Clearing health bit of port num:%u with lid:%u\n", + port_num, lid ); + + /* Clear its health bit */ + osm_physp_set_health(p_physp, TRUE); + } + } + } + + OSM_LOG_EXIT (p_rcv->p_log ); + + /* We want to remove the event from the tracker - so + need to return zero. */ + return 0; +} + +/********************************************************************** + **********************************************************************/ +void +osm_trap_rcv_construct( + IN osm_trap_rcv_t* const p_rcv ) +{ + memset( p_rcv, 0, sizeof(*p_rcv) ); + cl_event_wheel_construct( &p_rcv->trap_aging_tracker ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_trap_rcv_destroy( + IN osm_trap_rcv_t* const p_rcv ) +{ + CL_ASSERT( p_rcv ); + + OSM_LOG_ENTER( p_rcv->p_log, osm_trap_rcv_destroy ); + + cl_event_wheel_destroy( &p_rcv->trap_aging_tracker ); + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_trap_rcv_init( + IN osm_trap_rcv_t* const p_rcv, + IN osm_subn_t* const p_subn, + IN osm_stats_t* const p_stats, + IN osm_resp_t* const p_resp, + IN osm_log_t* const p_log, + IN osm_state_mgr_t* const p_state_mgr, + IN cl_plock_t* const p_lock ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_trap_rcv_init ); + + osm_trap_rcv_construct( p_rcv ); + + p_rcv->p_log = p_log; + p_rcv->p_subn = p_subn; + p_rcv->p_lock = p_lock; + p_rcv->p_stats = p_stats; + p_rcv->p_resp = p_resp; + p_rcv->p_state_mgr = p_state_mgr; + + cl_event_wheel_init( &p_rcv->trap_aging_tracker, p_log ); + + OSM_LOG_EXIT( p_rcv->p_log ); + return( status ); +} + +/********************************************************************** + * CRC calculation for notice identification + **********************************************************************/ + +#define CRC32_POLYNOMIAL 0xEDB88320L + +/* calculate the crc for a given buffer */ +static uint32_t +__osm_trap_calc_crc32(void *buffer, uint32_t count) +{ + uint32_t temp1, temp2; + uint32_t crc = -1L; + unsigned char *p = (unsigned char *)buffer; + /* pre - calculated table for faster crc calculation */ + static uint32_t crc_table[256]; + static boolean_t first = TRUE; + int i, j; + + /* if we need to initialize the lookup table */ + if (first) + { + /* calc the CRC table */ + for (i = 0; i <= 255; i++) + { + crc = i; + for (j = 8; j > 0; j--) + if (crc & 1) + crc = (crc >> 1) ^ CRC32_POLYNOMIAL; + else + crc >>= 1; + crc_table[i] = crc; + } + first = FALSE; + } + + crc = -1L; + /* do the calculation */ + while (count-- != 0) + { + temp1 = (crc >> 8) & 0x00FFFFFFL; + temp2 = crc_table[((int)crc ^ *p++) & 0xFF]; + crc = temp1 ^ temp2; + } + return crc; +} + +/******************************************************************** + ********************************************************************/ + +/* The key is created in the following manner: + port_num lid crc + \______/ \___/ \___/ + 16b 16b 32b +*/ +static void +__osm_trap_get_key( + IN uint16_t lid, + IN uint8_t port_num, + IN ib_mad_notice_attr_t* p_ntci, + OUT uint64_t *trap_key) +{ + uint32_t crc = 0; + + CL_ASSERT(trap_key); + + crc = __osm_trap_calc_crc32(p_ntci, sizeof(ib_mad_notice_attr_t)); + *trap_key = ((uint64_t)port_num << 48) | ((uint64_t)lid << 32) | crc; +} + +/********************************************************************** + **********************************************************************/ +static int +__print_num_received( + IN uint32_t num_received ) +{ + uint32_t i; + + /* Series is 10, 20, 50, 100, 200, 500, ... */ + i = num_received; + while (i >= 10) { + if (i % 10) + break; + i = i / 10; + } + if (i == 1 || i == 2 || i == 5) + return 1; + else + return 0; +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_trap_rcv_process_request( + IN osm_trap_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ) +{ + uint8_t payload[sizeof(ib_mad_notice_attr_t)]; + ib_smp_t* p_smp; + ib_mad_notice_attr_t* p_ntci = (ib_mad_notice_attr_t*)payload; + ib_api_status_t status; + osm_madw_t tmp_madw; /* we need a copy to last after repress */ + uint64_t trap_key; + uint32_t num_received; + osm_physp_t* p_physp; + cl_ptr_vector_t* p_tbl; + osm_port_t* p_port; + ib_net16_t source_lid = 0; + boolean_t is_gsi = TRUE; + uint8_t port_num = 0; + boolean_t physp_change_trap = FALSE; + uint64_t event_wheel_timeout = OSM_DEFAULT_TRAP_SUPRESSION_TIMEOUT; + boolean_t run_heavy_sweep = FALSE; + + OSM_LOG_ENTER( p_rcv->p_log, __osm_trap_rcv_process_request ); + + CL_ASSERT( p_madw ); + + if (osm_exit_flag) + { + /* + We got an exit flag - do nothing + Otherwise we start a sweep on the trap 144 caused by cleaning up + SM Cap bit... + */ + goto Exit; + } + + /* update the is_gsi flag according to the mgmt_class field */ + if (p_madw->p_mad->mgmt_class == IB_MCLASS_SUBN_LID || + p_madw->p_mad->mgmt_class == IB_MCLASS_SUBN_DIR ) + is_gsi = FALSE; + + /* + No real need to grab the lock for this function. + */ + memset( payload, 0, sizeof( payload ) ); + memset( &tmp_madw, 0, sizeof( tmp_madw )); + + p_smp = osm_madw_get_smp_ptr( p_madw ); + + if( p_smp->method != IB_MAD_METHOD_TRAP ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_trap_rcv_process_request: ERR 3801: " + "Unsupported method 0x%X\n", + p_smp->method ); + goto Exit; + } + + /* + * The NOTICE Attribute is part of the SMP CLASS attributes + * As such the actual attribute data resides inside the SMP + * payload. + */ + + memcpy(payload, &(p_smp->data), IB_SMP_DATA_SIZE); + memcpy(&tmp_madw, p_madw, sizeof( tmp_madw )); + + if (is_gsi == FALSE) + { + /* We are in smi flow */ + /* + * When we received a TRAP with dlid = 0 - it means it + * came from our own node. So we need to fix it. + */ + + if (p_madw->mad_addr.addr_type.smi.source_lid == 0) + { + /* Check if the sm_base_lid is 0. If yes - this means that + the local lid wasn't configured yet. Don't send a response + to the trap. */ + if (p_rcv->p_subn->sm_base_lid == 0) + { + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_trap_rcv_process_request: " + "Received SLID=0 Trap with local LID=0. Ignoring MAD\n"); + goto Exit; + } + osm_log( p_rcv->p_log, OSM_LOG_DEBUG, + "__osm_trap_rcv_process_request: " + "Received SLID=0 Trap. Using local LID:0x%04X instead\n", + cl_ntoh16(p_rcv->p_subn->sm_base_lid) + ); + tmp_madw.mad_addr.addr_type.smi.source_lid = p_rcv->p_subn->sm_base_lid; + } + + source_lid = tmp_madw.mad_addr.addr_type.smi.source_lid; + + /* Print some info about the incoming Trap */ + if (ib_notice_is_generic(p_ntci)) + { + if ((p_ntci->g_or_v.generic.trap_num == CL_HTON16(129)) || + (p_ntci->g_or_v.generic.trap_num == CL_HTON16(130)) || + (p_ntci->g_or_v.generic.trap_num == CL_HTON16(131))) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_trap_rcv_process_request: " + "Received Generic Notice type:0x%02X num:%u Producer:%u " + "from LID:0x%04X Port %d TID:0x%016" PRIx64 "\n", + ib_notice_get_type(p_ntci), + cl_ntoh16(p_ntci->g_or_v.generic.trap_num), + cl_ntoh32(ib_notice_get_prod_type(p_ntci)), + cl_hton16(source_lid), + p_ntci->data_details.ntc_129_131.port_num, + cl_ntoh64(p_smp->trans_id) + ); + } + else + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_trap_rcv_process_request: " + "Received Generic Notice type:0x%02X num:%u Producer:%u " + "from LID:0x%04X TID:0x%016" PRIx64 "\n", + ib_notice_get_type(p_ntci), + cl_ntoh16(p_ntci->g_or_v.generic.trap_num), + cl_ntoh32(ib_notice_get_prod_type(p_ntci)), + cl_hton16(source_lid), + cl_ntoh64(p_smp->trans_id) + ); + } + } + else + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_trap_rcv_process_request: " + "Received Vendor Notice type:0x%02X vend:0x%06X dev:%u " + "from LID:0x%04X TID:0x%016" PRIx64 "\n", + ib_notice_get_type(p_ntci), + cl_ntoh32(ib_notice_get_vend_id(p_ntci)), + cl_ntoh16(p_ntci->g_or_v.vend.dev_id), + cl_ntoh16(source_lid), + cl_ntoh64(p_smp->trans_id) + ); + } + } + + osm_dump_notice( p_rcv->p_log, p_ntci, OSM_LOG_VERBOSE ); + + status = osm_resp_send( p_rcv->p_resp, &tmp_madw, 0, payload ); + if( status != IB_SUCCESS ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_trap_rcv_process_request: ERR 3802: " + "Error sending response (%s)\n", + ib_get_err_str( status ) ); + goto Exit; + } + + /* + * We would like to filter out recurring Traps so we track them by + * their source lid and content. If the same trap was already + * received within the aging time window more than 10 times, + * we simply ignore it. This is done only if we are in smi mode + */ + + if (is_gsi == FALSE) + { + if (ib_notice_is_generic(p_ntci) && + ((p_ntci->g_or_v.generic.trap_num == CL_HTON16(129)) || + (p_ntci->g_or_v.generic.trap_num == CL_HTON16(130)) || + (p_ntci->g_or_v.generic.trap_num == CL_HTON16(131))) ) + { + /* If this is a trap 129, 130, or 131 - then this is a trap + signaling a change on a physical port. Mark the flag physp_change_trap as TRUE. */ + physp_change_trap = TRUE; + /* The source_lid should be based on the source_lid from the trap */ + source_lid = p_ntci->data_details.ntc_129_131.lid; + } + + /* If physp_change_trap is TRUE - the key will include the port number. + If not - the port_number in the key will be zero. */ + if ( physp_change_trap == TRUE ) + { + port_num = p_ntci->data_details.ntc_129_131.port_num; + __osm_trap_get_key(source_lid, port_num, p_ntci, &trap_key); + } + else + __osm_trap_get_key(source_lid, 0, p_ntci, &trap_key); + + /* try to find it in the aging tracker */ + num_received = cl_event_wheel_num_regs(&p_rcv->trap_aging_tracker, + trap_key); + + /* Now we know how many times it provided this trap */ + if (num_received > 10) + { + if (__print_num_received(num_received)) + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_trap_rcv_process_request: ERR 3804: " + "Received trap %u times consecutively\n", + num_received); + /* + * If the trap provides info about a bad port + * we mark it as unhealthy. + */ + if (physp_change_trap == TRUE) + { + /* get the port */ + p_physp = __get_physp_by_lid_and_num( + p_rcv, + cl_ntoh16(p_ntci->data_details.ntc_129_131.lid), + port_num + ); + + if (! p_physp) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_trap_rcv_process_request: ERR 3805: " + "Failed to find physical port by lid:0x%02X num:%u\n", + cl_ntoh16(p_ntci->data_details.ntc_129_131.lid), + p_ntci->data_details.ntc_129_131.port_num + ); + } + else + { + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "__osm_trap_rcv_process_request: " + "Marking unhealthy physical port by lid:0x%02X num:%u\n", + cl_ntoh16(p_ntci->data_details.ntc_129_131.lid), + p_ntci->data_details.ntc_129_131.port_num + ); + /* check if the current state of the p_physp is healthy. If + it is - then this is a first change of state. Run a heavy sweep. + if it is not - no need to mark it again - just restart the timer. */ + if ( osm_physp_is_healthy(p_physp) ) + { + osm_physp_set_health(p_physp, FALSE); + /* Make sure we sweep again - force a heavy sweep. */ + /* The sweep should be done only after the re-registration, or + else we'll be losing track of the timer. */ + run_heavy_sweep = TRUE; + } + /* If we are marking the port as unhealthy - we want to + keep this for a longer period of time than the + OSM_DEFAULT_TRAP_SUPRESSION_TIMEOUT. Use the + OSM_DEFAULT_UNHEALTHY_TIMEOUT */ + event_wheel_timeout = OSM_DEFAULT_UNHEALTHY_TIMEOUT; + } + } + } + + /* restart the aging anyway */ + /* If physp_change_trap is TRUE - then use a callback to unset the + healthy bit. If not - no need to use a callback. */ + if (physp_change_trap == TRUE ) + cl_event_wheel_reg(&p_rcv->trap_aging_tracker, + trap_key, + cl_get_time_stamp() + event_wheel_timeout, + osm_trap_rcv_aging_tracker_callback, /* no callback */ + p_rcv /* no context */ + ); + else + cl_event_wheel_reg(&p_rcv->trap_aging_tracker, + trap_key, + cl_get_time_stamp() + event_wheel_timeout, + NULL, /* no callback */ + NULL /* no context */ + ); + + /* If was already registered do nothing more */ + if ( num_received > 10 && run_heavy_sweep == FALSE ) + { + if (__print_num_received(num_received)) + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "__osm_trap_rcv_process_request: " + "Continuously received this trap %u times. Ignoring it\n", + num_received); + goto Exit; + } + } + + /* do a sweep if we received a trap */ + if (p_rcv->p_subn->opt.sweep_on_trap) + { + /* if this is trap number 128 or run_heavy_sweep is TRUE - update the + force_single_heavy_sweep flag of the subnet. + Sweep also on traps 144/145 - these traps signal a change on a certain + port capability/system image guid. + TODO: In the future we can change this to just getting PortInfo on + this port instead of sweeping the entire subnet. */ + if (ib_notice_is_generic(p_ntci) && + ( (cl_ntoh16(p_ntci->g_or_v.generic.trap_num) == 128) || + (cl_ntoh16(p_ntci->g_or_v.generic.trap_num) == 144) || + (cl_ntoh16(p_ntci->g_or_v.generic.trap_num) == 145) || + run_heavy_sweep )) + { + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "__osm_trap_rcv_process_request: " + "Forcing immediate heavy sweep. " + "Received trap:%u\n", + cl_ntoh16(p_ntci->g_or_v.generic.trap_num) ); + + p_rcv->p_subn->force_immediate_heavy_sweep = TRUE; + } + osm_state_mgr_process( p_rcv->p_state_mgr, OSM_SIGNAL_SWEEP ); + } + + /* If we reached here due to trap 129/130/131 - do not need to do + the notice report. Just goto exit. We know this is the case + if physp_change_trap is TRUE. */ + if ( physp_change_trap == TRUE ) + goto Exit; + + /* Add a call to osm_report_notice */ + /* We are going to report the notice - so need to fix the IssuerGID + accordingly. See IBA 1.1 P.653 or IBA 1.2 P.739 for details. */ + if (is_gsi) + { + if (tmp_madw.mad_addr.addr_type.gsi.global_route) + { + memcpy(&(p_ntci->issuer_gid), + &(tmp_madw.mad_addr.addr_type.gsi.grh_info.src_gid), + sizeof(ib_gid_t)); + } + else + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_trap_rcv_process_request: ERR 3806: " + "Received gsi trap with global_route FALSE. " + "Cannot update issuer_gid!\n" ); + goto Exit; + } + } + else + { + /* Need to use the IssuerLID */ + p_tbl = &p_rcv->p_subn->port_lid_tbl; + + CL_ASSERT( cl_ptr_vector_get_size(p_tbl) < 0x10000 ); + + if ((uint16_t)cl_ptr_vector_get_size(p_tbl) <= cl_ntoh16(source_lid) ) + { + /* the source lid is out of range */ + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "__osm_trap_rcv_process_request: " + "source lid is out of range:0x%X\n", + cl_ntoh16(source_lid) ); + + goto Exit; + } + p_port = cl_ptr_vector_get( p_tbl, cl_ntoh16(source_lid) ); + if ( p_port == 0) + { + /* We have the lid - but no corresponding port */ + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "__osm_trap_rcv_process_request: " + "Cannot find port according to lid:0x%X\n", + cl_ntoh16(source_lid) ); + + goto Exit; + } + + p_ntci->issuer_gid.unicast.prefix = p_rcv->p_subn->opt.subnet_prefix; + p_ntci->issuer_gid.unicast.interface_id = p_port->guid; + } + + /* we need a lock here as the InformInfo DB must be stable */ + CL_PLOCK_ACQUIRE( p_rcv->p_lock ); + status = osm_report_notice(p_rcv->p_log, p_rcv->p_subn, p_ntci); + CL_PLOCK_RELEASE( p_rcv->p_lock ); + if( status != IB_SUCCESS ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_trap_rcv_process_request: ERR 3803: " + "Error sending trap reports (%s)\n", + ib_get_err_str( status ) ); + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_rcv->p_log ); +} + +#if 0 +/********************************************************************** + CURRENTLY WE ARE NOT CREATING TRAPS - SO THIS CALL IS AN ERROR +**********************************************************************/ +static void +__osm_trap_rcv_process_sm( + IN const osm_trap_rcv_t* const p_rcv, + IN const osm_remote_sm_t* const p_sm ) +{ + /* const ib_sm_info_t* p_smi; */ + OSM_LOG_ENTER( p_rcv->p_log, __osm_trap_rcv_process_sm ); + + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_trap_rcv_process_sm: ERR 3807: " + "This function is not supported yet\n"); + + OSM_LOG_EXIT( p_rcv->p_log ); +} +#endif + +/********************************************************************** + CURRENTLY WE ARE NOT CREATING TRAPS - SO THIS CALL IN AN ERROR +**********************************************************************/ +static void +__osm_trap_rcv_process_response( + IN const osm_trap_rcv_t* const p_rcv, + IN const osm_madw_t* const p_madw ) +{ + + OSM_LOG_ENTER( p_rcv->p_log, __osm_trap_rcv_process_response ); + + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "__osm_trap_rcv_process_response: ERR 3808: " + "This function is not supported yet\n"); + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_trap_rcv_process( + IN osm_trap_rcv_t* const p_rcv, + IN osm_madw_t* const p_madw ) +{ + ib_smp_t *p_smp; + + OSM_LOG_ENTER( p_rcv->p_log, osm_trap_rcv_process ); + + CL_ASSERT( p_madw ); + + p_smp = osm_madw_get_smp_ptr( p_madw ); + + /* + Determine if this is a request for our own Trap + or if this is a response to our request for another + SM's Trap. + */ + if( ib_smp_is_response( p_smp ) ) + { + __osm_trap_rcv_process_response( p_rcv, p_madw ); + } + else + { + __osm_trap_rcv_process_request( p_rcv, p_madw ); + } + + OSM_LOG_EXIT( p_rcv->p_log ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_trap_rcv_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_trap_rcv_ctrl.c new file mode 100644 index 00000000..2a331334 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_trap_rcv_ctrl.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_trap_rcv_ctrl.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_trap_rcv_ctrl_t. + * This object represents the Trap request controller object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.3 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +__osm_trap_rcv_ctrl_disp_callback( + IN void *context, + IN void *p_data ) +{ + /* ignore return status when invoked via the dispatcher */ + osm_trap_rcv_process( ((osm_trap_rcv_ctrl_t*)context)->p_rcv, + (osm_madw_t*)p_data ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_trap_rcv_ctrl_construct( + IN osm_trap_rcv_ctrl_t* const p_ctrl ) +{ + memset( p_ctrl, 0, sizeof(*p_ctrl) ); + p_ctrl->h_disp = CL_DISP_INVALID_HANDLE; +} + +/********************************************************************** + **********************************************************************/ +void +osm_trap_rcv_ctrl_destroy( + IN osm_trap_rcv_ctrl_t* const p_ctrl ) +{ + CL_ASSERT( p_ctrl ); + cl_disp_unregister( p_ctrl->h_disp ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_trap_rcv_ctrl_init( + IN osm_trap_rcv_ctrl_t* const p_ctrl, + IN osm_trap_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_trap_rcv_ctrl_init ); + + osm_trap_rcv_ctrl_construct( p_ctrl ); + + p_ctrl->p_log = p_log; + p_ctrl->p_rcv = p_rcv; + p_ctrl->p_disp = p_disp; + + p_ctrl->h_disp = cl_disp_register( + p_disp, + OSM_MSG_MAD_NOTICE, + __osm_trap_rcv_ctrl_disp_callback, + p_ctrl ); + + if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_trap_rcv_ctrl_init: ERR 3901: " + "Dispatcher registration failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return( status ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_ucast_file.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_ucast_file.c new file mode 100644 index 00000000..424fed24 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_ucast_file.c @@ -0,0 +1,413 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ + + +/* + * Abstract: + * Implementation of OpenSM unicast routing module which loads + * routes from the dump file + * + * Environment: + * Linux User Mode + * + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +static uint16_t remap_lid(osm_opensm_t *p_osm, uint16_t lid, ib_net64_t guid) +{ + osm_port_t *p_port; + uint16_t min_lid, max_lid; + uint8_t lmc; + + p_port = (osm_port_t *)cl_qmap_get(&p_osm->subn.port_guid_tbl, guid); + if (!p_port || + p_port == (osm_port_t *)cl_qmap_end(&p_osm->subn.port_guid_tbl)) { + osm_log(&p_osm->log, OSM_LOG_VERBOSE, + "remap_lid: cannot find port guid 0x%016" PRIx64 + " , will use the same lid\n", cl_ntoh64(guid)); + return lid; + } + + osm_port_get_lid_range_ho(p_port, &min_lid, &max_lid); + if (min_lid <= lid && lid <= max_lid) + return lid; + + lmc = osm_port_get_lmc(p_port); + return min_lid + (lid & ((1 << lmc) - 1)); +} + +static void add_path(osm_opensm_t * p_osm, + osm_switch_t * p_sw, uint16_t lid, uint8_t port_num, + ib_net64_t port_guid) +{ + uint16_t new_lid; + uint8_t old_port; + + new_lid = port_guid ? remap_lid(p_osm, lid, port_guid) : lid; + old_port = osm_fwd_tbl_get(osm_switch_get_fwd_tbl_ptr(p_sw), new_lid); + if (old_port != OSM_NO_PATH && old_port != port_num) { + osm_log(&p_osm->log, OSM_LOG_VERBOSE, + "add_path: LID collision is detected on switch " + "0x016%" PRIx64 ", will overwrite LID 0x%x entry\n", + cl_ntoh64(osm_node_get_node_guid + (osm_switch_get_node_ptr(p_sw))), new_lid); + } + + p_osm->sm.ucast_mgr.lft_buf[new_lid] = port_num; + if (!(p_osm->subn.opt.port_profile_switch_nodes && port_guid && + osm_get_switch_by_guid(&p_osm->subn, port_guid))) + osm_switch_count_path(p_sw, port_num); + + osm_log(&p_osm->log, OSM_LOG_DEBUG, + "add_path: route 0x%04x(was 0x%04x) %u 0x%016" PRIx64 + " is added to switch 0x%016" PRIx64 "\n", + new_lid, lid, port_num, cl_ntoh64(port_guid), + cl_ntoh64(osm_node_get_node_guid + (osm_switch_get_node_ptr(p_sw)))); +} + +static void add_lid_hops(osm_opensm_t *p_osm, osm_switch_t *p_sw, + uint16_t lid, ib_net64_t guid, + uint8_t hops[], unsigned len) +{ + uint16_t new_lid; + uint8_t i; + + new_lid = guid ? remap_lid(p_osm, lid, guid) : lid; + if (len > osm_switch_get_num_ports(p_sw)) + len = osm_switch_get_num_ports(p_sw); + + for (i = 0 ; i < len ; i++) + osm_switch_set_hops(p_sw, lid, i, hops[i]); +} + +static int do_ucast_file_load(void *context) +{ + char line[1024]; + char *file_name; + FILE *file; + ib_net64_t sw_guid, port_guid; + osm_opensm_t *p_osm = context; + osm_switch_t *p_sw; + uint16_t lid; + uint8_t port_num; + unsigned lineno; + + file_name = p_osm->subn.opt.ucast_dump_file; + if (!file_name) { + osm_log(&p_osm->log, OSM_LOG_ERROR|OSM_LOG_SYS, + "do_ucast_file_load: ERR 6301: " + "ucast dump file name is not defined; " + "using default routing algorithm\n"); + return -1; + } + + file = fopen(file_name, "r"); + if (!file) { + osm_log(&p_osm->log, OSM_LOG_ERROR|OSM_LOG_SYS, + "do_ucast_file_load: ERR 6302: " + "cannot open ucast dump file \'%s\'; " + "using default routing algorithm\n", file_name); + return -1; + } + + lineno = 0; + p_sw = NULL; + + while (fgets(line, sizeof(line) - 1, file) != NULL) { + char *p, *q; + lineno++; + + p = line; + while (isspace(*p)) + p++; + + if (*p == '#') + continue; + + if (!strncmp(p, "Multicast mlids", 15)) { + osm_log(&p_osm->log, OSM_LOG_ERROR|OSM_LOG_SYS, + "do_ucast_file_load: ERR 6303: " + "Multicast dump file detected; " + "skipping parsing. Using default " + "routing algorithm\n"); + } else if (!strncmp(p, "Unicast lids", 12)) { + if (p_sw) + osm_ucast_mgr_set_fwd_table(&p_osm->sm.ucast_mgr, p_sw); + q = strstr(p, " guid 0x"); + if (!q) { + osm_log(&p_osm->log, OSM_LOG_ERROR, + "PARSE ERROR: %s:%u: " + "cannot parse switch definition\n", + file_name, lineno); + return -1; + } + p = q + 8; + sw_guid = strtoull(p, &q, 16); + if (q == p || !isspace(*q)) { + osm_log(&p_osm->log, OSM_LOG_ERROR, + "PARSE ERROR: %s:%u: " + "cannot parse switch guid: \'%s\'\n", + file_name, lineno, p); + return -1; + } + sw_guid = cl_hton64(sw_guid); + + p_sw = osm_get_switch_by_guid(&p_osm->subn, sw_guid); + if (!p_sw) { + osm_log(&p_osm->log, OSM_LOG_VERBOSE, + "do_ucast_file_load: " + "cannot find switch %016" PRIx64 "\n", + cl_ntoh64(sw_guid)); + continue; + } + memset(p_osm->sm.ucast_mgr.lft_buf, 0xff, IB_LID_UCAST_END_HO + 1); + } else if (p_sw && !strncmp(p, "0x", 2)) { + p += 2; + lid = (uint16_t)strtoul(p, &q, 16); + if (q == p || !isspace(*q)) { + osm_log(&p_osm->log, OSM_LOG_ERROR, + "PARSE ERROR: %s:%u: " + "cannot parse lid: \'%s\'\n", + file_name, lineno, p); + return -1; + } + p = q; + while (isspace(*p)) + p++; + port_num = (uint8_t)strtoul(p, &q, 10); + if (q == p || !isspace(*q)) { + osm_log(&p_osm->log, OSM_LOG_ERROR, + "PARSE ERROR: %s:%u: " + "cannot parse port: \'%s\'\n", + file_name, lineno, p); + return -1; + } + p = q; + /* additionally try to exract guid */ + q = strstr(p, " portguid 0x"); + if (!q) { + osm_log(&p_osm->log, OSM_LOG_VERBOSE, + "PARSE WARNING: %s:%u: " + "cannot find port guid " + "(maybe broken dump): \'%s\'\n", + file_name, lineno, p); + port_guid = 0; + } + else { + p = q + 12; + port_guid = strtoull(p, &q, 16); + if (q == p || (!isspace(*q) && *q != ':')) { + osm_log(&p_osm->log, OSM_LOG_VERBOSE, + "PARSE WARNING: %s:%u: " + "cannot parse port guid " + "(maybe broken dump): \'%s\'\n", + file_name, lineno, p); + port_guid = 0; + } + } + port_guid = cl_hton64(port_guid); + add_path(p_osm, p_sw, lid, port_num, port_guid); + } + } + + if (p_sw) + osm_ucast_mgr_set_fwd_table(&p_osm->sm.ucast_mgr, p_sw); + + fclose(file); + return 0; +} + +static int do_lid_matrix_file_load(void *context) +{ + char line[1024]; + uint8_t hops[256]; + char *file_name; + FILE *file; + ib_net64_t guid; + osm_opensm_t *p_osm = context; + osm_switch_t *p_sw; + unsigned lineno; + uint16_t lid; + + file_name = p_osm->subn.opt.lid_matrix_dump_file; + if (!file_name) { + osm_log(&p_osm->log, OSM_LOG_ERROR|OSM_LOG_SYS, + "do_lid_matrix_file_load: ERR 6304: " + "lid matrix file name is not defined; " + "using default lid matrix generation algorithm\n"); + return -1; + } + + file = fopen(file_name, "r"); + if (!file) { + osm_log(&p_osm->log, OSM_LOG_ERROR|OSM_LOG_SYS, + "do_lid_matrix_file_load: ERR 6305: " + "cannot open lid matrix file \'%s\'; " + "using default lid matrix generation algorithm\n", + file_name); + return -1; + } + + lineno = 0; + p_sw = NULL; + + while (fgets(line, sizeof(line) - 1, file) != NULL) { + char *p, *q; + lineno++; + + p = line; + while (isspace(*p)) + p++; + + if (*p == '#') + continue; + + if (!strncmp(p, "Switch", 6)) { + q = strstr(p, " guid 0x"); + if (!q) { + osm_log(&p_osm->log, OSM_LOG_ERROR, + "PARSE ERROR: %s:%u: " + "cannot parse switch definition\n", + file_name, lineno); + return -1; + } + p = q + 8; + guid = strtoull(p, &q, 16); + if (q == p || !isspace(*q)) { + osm_log(&p_osm->log, OSM_LOG_ERROR, + "PARSE ERROR: %s:%u: " + "cannot parse switch guid: \'%s\'\n", + file_name, lineno, p); + return -1; + } + guid = cl_hton64(guid); + + p_sw = osm_get_switch_by_guid(&p_osm->subn, guid); + if (!p_sw) { + osm_log(&p_osm->log, OSM_LOG_VERBOSE, + "do_lid_matrix_file_load: " + "cannot find switch %016" PRIx64 "\n", + cl_ntoh64(guid)); + continue; + } + } else if (p_sw && !strncmp(p, "0x", 2)) { + unsigned long num; + unsigned len = 0; + + memset(hops, 0xff, sizeof(hops)); + + p += 2; + num = strtoul(p, &q, 16); + if (num > 0xffff || q == p || + (*q != ':' && !isspace(*q))) { + osm_log(&p_osm->log, OSM_LOG_ERROR, + "PARSE ERROR: %s:%u: " + "cannot parse lid: \'%s\'\n", + file_name, lineno, p); + return -1; + } + /* Just checked the range, so casting is safe */ + lid = (uint16_t)num; + p = q; + while (isspace(*p) || *p == ':') + p++; + while (len < 256 && *p && *p != '#') { + num = strtoul(p, &q, 16); + if (num > 0xff || q == p) { + osm_log(&p_osm->log, OSM_LOG_ERROR, + "PARSE ERROR: %s:%u: " + "cannot parse hops number: \'%s\'\n", + file_name, lineno, p); + return -1; + } + /* Just checked the range, so casting is safe */ + hops[len++] = (uint8_t)num; + p = q; + while (isspace(*p)) + p++; + } + /* additionally try to extract guid */ + q = strstr(p, " portguid 0x"); + if (!q) { + osm_log(&p_osm->log, OSM_LOG_VERBOSE, + "PARSE WARNING: %s:%u: " + "cannot find port guid " + "(maybe broken dump): \'%s\'\n", + file_name, lineno, p); + guid = 0; + } + else { + p = q + 12; + guid = strtoull(p, &q, 16); + if (q == p || !isspace(*q)) { + osm_log(&p_osm->log, OSM_LOG_VERBOSE, + "PARSE WARNING: %s:%u: " + "cannot parse port guid " + "(maybe broken dump): \'%s\'\n", + file_name, lineno, p); + guid = 0; + } + } + guid = cl_hton64(guid); + add_lid_hops(p_osm, p_sw, lid, guid, hops, len); + } + } + + fclose(file); + return 0; +} + +int osm_ucast_file_setup(osm_opensm_t * p_osm) +{ + p_osm->routing_engine.context = (void *)p_osm; + p_osm->routing_engine.build_lid_matrices = do_lid_matrix_file_load; + p_osm->routing_engine.ucast_build_fwd_tables = do_ucast_file_load; + return 0; +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_ucast_ftree.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_ucast_ftree.c new file mode 100644 index 00000000..6a8eae2d --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_ucast_ftree.c @@ -0,0 +1,3141 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ + + +/* + * Abstract: + * Implementation of OpenSM FatTree routing + * + * Environment: + * Linux User Mode + * + */ + +#if HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * FatTree rank is bounded between 2 and 8: + * - Tree of rank 1 has only trivial routing pathes, + * so no need to use FatTree routing. + * - Why maximum rank is 8: + * Each node (switch) is assigned a unique tuple. + * Switches are stored in two cl_qmaps - one is + * ordered by guid, and the other by a key that is + * generated from tuple. Since cl_qmap supports only + * a 64-bit key, the maximal tuple lenght is 8 bytes. + * which means that maximal tree rank is 8. + * Note that the above also implies that each switch + * can have at max 255 up/down ports. + */ + +#define FAT_TREE_MIN_RANK 2 +#define FAT_TREE_MAX_RANK 8 + +typedef enum { + FTREE_DIRECTION_DOWN = -1, + FTREE_DIRECTION_SAME, + FTREE_DIRECTION_UP +} ftree_direction_t; + + +/*************************************************** + ** + ** Forward references + ** + ***************************************************/ + +struct ftree_sw_t_; +struct ftree_hca_t_; +struct ftree_port_t_; +struct ftree_port_group_t_; +struct ftree_fabric_t_; + +/*************************************************** + ** + ** ftree_tuple_t definition + ** + ***************************************************/ + +#define FTREE_TUPLE_BUFF_LEN 1024 +#define FTREE_TUPLE_LEN 8 + +typedef uint8_t ftree_tuple_t[FTREE_TUPLE_LEN]; +typedef uint64_t ftree_tuple_key_t; + +/*************************************************** + ** + ** ftree_sw_table_element_t definition + ** + ***************************************************/ + +typedef struct { + cl_map_item_t map_item; + struct ftree_sw_t_ * p_sw; +} ftree_sw_tbl_element_t; + +/*************************************************** + ** + ** ftree_fwd_tbl_t definition + ** + ***************************************************/ + +typedef uint8_t * ftree_fwd_tbl_t; +#define FTREE_FWD_TBL_LEN (IB_LID_UCAST_END_HO + 1) + +/*************************************************** + ** + ** ftree_port_t definition + ** + ***************************************************/ + +typedef struct ftree_port_t_ +{ + cl_map_item_t map_item; + uint8_t port_num; /* port number on the current node */ + uint8_t remote_port_num; /* port number on the remote node */ + uint32_t counter_up; /* number of allocated routs upwards */ + uint32_t counter_down; /* number of allocated routs downwards */ +} ftree_port_t; + +/*************************************************** + ** + ** ftree_port_group_t definition + ** + ***************************************************/ + +typedef struct ftree_port_group_t_ +{ + cl_map_item_t map_item; + ib_net16_t base_lid; /* base lid of the current node */ + ib_net16_t remote_base_lid; /* base lid of the remote node */ + ib_net64_t port_guid; /* port guid of this port */ + ib_net64_t remote_port_guid; /* port guid of the remote port */ + ib_net64_t remote_node_guid; /* node guid of the remote node */ + uint8_t remote_node_type; /* IB_NODE_TYPE_{CA,SWITCH,ROUTER,...} */ + union remote_hca_or_sw_ + { + struct ftree_hca_t_ * remote_hca; + struct ftree_sw_t_ * remote_sw; + } remote_hca_or_sw; /* pointer to remote hca/switch */ + cl_ptr_vector_t ports; /* vector of ports to the same lid */ +} ftree_port_group_t; + +/*************************************************** + ** + ** ftree_sw_t definition + ** + ***************************************************/ + +typedef struct ftree_sw_t_ +{ + cl_map_item_t map_item; + osm_switch_t * p_osm_sw; + uint8_t rank; + ftree_tuple_t tuple; + ib_net16_t base_lid; + ftree_port_group_t ** down_port_groups; + uint8_t down_port_groups_num; + ftree_port_group_t ** up_port_groups; + uint8_t up_port_groups_num; + ftree_fwd_tbl_t lft_buf; +} ftree_sw_t; + +/*************************************************** + ** + ** ftree_hca_t definition + ** + ***************************************************/ + +typedef struct ftree_hca_t_ { + cl_map_item_t map_item; + osm_node_t * p_osm_node; + ftree_port_group_t ** up_port_groups; + uint16_t up_port_groups_num; +} ftree_hca_t; + +/*************************************************** + ** + ** ftree_fabric_t definition + ** + ***************************************************/ + +typedef struct ftree_fabric_t_ +{ + osm_opensm_t * p_osm; + cl_qmap_t hca_tbl; + cl_qmap_t sw_tbl; + cl_qmap_t sw_by_tuple_tbl; + uint8_t tree_rank; + ftree_sw_t ** leaf_switches; + uint32_t leaf_switches_num; + uint16_t max_hcas_per_leaf; + cl_pool_t sw_fwd_tbl_pool; + uint16_t lft_max_lid_ho; + boolean_t fabric_built; +} ftree_fabric_t; + +/*************************************************** + ** + ** comparators + ** + ***************************************************/ + +static int OSM_CDECL +__osm_ftree_compare_switches_by_index( + IN const void * p1, + IN const void * p2) +{ + ftree_sw_t ** pp_sw1 = (ftree_sw_t **)p1; + ftree_sw_t ** pp_sw2 = (ftree_sw_t **)p2; + + uint16_t i; + for (i = 0; i < FTREE_TUPLE_LEN; i++) + { + if ((*pp_sw1)->tuple[i] > (*pp_sw2)->tuple[i]) + return 1; + if ((*pp_sw1)->tuple[i] < (*pp_sw2)->tuple[i]) + return -1; + } + return 0; +} + +/***************************************************/ + +static int OSM_CDECL +__osm_ftree_compare_port_groups_by_remote_switch_index( + IN const void * p1, + IN const void * p2) +{ + ftree_port_group_t ** pp_g1 = (ftree_port_group_t **)p1; + ftree_port_group_t ** pp_g2 = (ftree_port_group_t **)p2; + + return __osm_ftree_compare_switches_by_index( + &((*pp_g1)->remote_hca_or_sw.remote_sw), + &((*pp_g2)->remote_hca_or_sw.remote_sw) ); +} + +/***************************************************/ + +boolean_t +__osm_ftree_sw_less_by_index( + IN ftree_sw_t * p_sw1, + IN ftree_sw_t * p_sw2) +{ + if (__osm_ftree_compare_switches_by_index((void *)&p_sw1, + (void *)&p_sw2) < 0) + return TRUE; + return FALSE; +} + +/***************************************************/ + +boolean_t +__osm_ftree_sw_greater_by_index( + IN ftree_sw_t * p_sw1, + IN ftree_sw_t * p_sw2) +{ + if (__osm_ftree_compare_switches_by_index((void *)&p_sw1, + (void *)&p_sw2) > 0) + return TRUE; + return FALSE; +} + +/*************************************************** + ** + ** ftree_tuple_t functions + ** + ***************************************************/ + +static void +__osm_ftree_tuple_init( + IN ftree_tuple_t tuple) +{ + memset(tuple, 0xFF, FTREE_TUPLE_LEN); +} + +/***************************************************/ + +static inline boolean_t +__osm_ftree_tuple_assigned( + IN ftree_tuple_t tuple) +{ + return (tuple[0] != 0xFF); +} + +/***************************************************/ + +#define FTREE_TUPLE_BUFFERS_NUM 6 + +static char * +__osm_ftree_tuple_to_str( + IN ftree_tuple_t tuple) +{ + static char buffer[FTREE_TUPLE_BUFFERS_NUM][FTREE_TUPLE_BUFF_LEN]; + static uint8_t ind = 0; + char * ret_buffer; + uint32_t i; + + if (!__osm_ftree_tuple_assigned(tuple)) + return "INDEX.NOT.ASSIGNED"; + + buffer[ind][0] = '\0'; + + for(i = 0; (i < FTREE_TUPLE_LEN) && (tuple[i] != 0xFF); i++) + { + if ((strlen(buffer[ind]) + 10) > FTREE_TUPLE_BUFF_LEN) + return "INDEX.TOO.LONG"; + if (i != 0) + strcat(buffer[ind],"."); + sprintf(&buffer[ind][strlen(buffer[ind])], "%u", tuple[i]); + } + + ret_buffer = buffer[ind]; + ind = (ind + 1) % FTREE_TUPLE_BUFFERS_NUM; + return ret_buffer; +} /* __osm_ftree_tuple_to_str() */ + +/***************************************************/ + +static inline ftree_tuple_key_t +__osm_ftree_tuple_to_key( + IN ftree_tuple_t tuple) +{ + ftree_tuple_key_t key; + memcpy(&key, tuple, FTREE_TUPLE_LEN); + return key; +} + +/***************************************************/ + +static inline void +__osm_ftree_tuple_from_key( + IN ftree_tuple_t tuple, + IN ftree_tuple_key_t key) +{ + memcpy(tuple, &key, FTREE_TUPLE_LEN); +} + +/*************************************************** + ** + ** ftree_sw_tbl_element_t functions + ** + ***************************************************/ + +static ftree_sw_tbl_element_t * +__osm_ftree_sw_tbl_element_create( + IN ftree_sw_t * p_sw) +{ + ftree_sw_tbl_element_t * p_element = + (ftree_sw_tbl_element_t *) malloc(sizeof(ftree_sw_tbl_element_t)); + if (!p_element) + return NULL; + memset(p_element, 0,sizeof(ftree_sw_tbl_element_t)); + + if (p_element) + p_element->p_sw = p_sw; + return p_element; +} + +/***************************************************/ + +static void +__osm_ftree_sw_tbl_element_destroy( + IN ftree_sw_tbl_element_t * p_element) +{ + if (!p_element) + return; + free(p_element); +} + +/*************************************************** + ** + ** ftree_port_t functions + ** + ***************************************************/ + +static ftree_port_t * +__osm_ftree_port_create( + IN uint8_t port_num, + IN uint8_t remote_port_num) +{ + ftree_port_t * p_port = (ftree_port_t *)malloc(sizeof(ftree_port_t)); + if (!p_port) + return NULL; + memset(p_port,0,sizeof(ftree_port_t)); + + p_port->port_num = port_num; + p_port->remote_port_num = remote_port_num; + + return p_port; +} + +/***************************************************/ + +static void +__osm_ftree_port_destroy( + IN ftree_port_t * p_port) +{ + if(p_port) + free(p_port); +} + +/*************************************************** + ** + ** ftree_port_group_t functions + ** + ***************************************************/ + +static ftree_port_group_t * +__osm_ftree_port_group_create( + IN ib_net16_t base_lid, + IN ib_net16_t remote_base_lid, + IN ib_net64_t * p_port_guid, + IN ib_net64_t * p_remote_port_guid, + IN ib_net64_t * p_remote_node_guid, + IN uint8_t remote_node_type, + IN void * p_remote_hca_or_sw) +{ + ftree_port_group_t * p_group = + (ftree_port_group_t *)malloc(sizeof(ftree_port_group_t)); + if (p_group == NULL) + return NULL; + memset(p_group, 0, sizeof(ftree_port_group_t)); + + p_group->base_lid = base_lid; + p_group->remote_base_lid = remote_base_lid; + memcpy(&p_group->port_guid, p_port_guid, sizeof(ib_net64_t)); + memcpy(&p_group->remote_port_guid, p_remote_port_guid, sizeof(ib_net64_t)); + memcpy(&p_group->remote_node_guid, p_remote_node_guid, sizeof(ib_net64_t)); + + p_group->remote_node_type = remote_node_type; + switch (remote_node_type) + { + case IB_NODE_TYPE_CA: + p_group->remote_hca_or_sw.remote_hca = (ftree_hca_t *)p_remote_hca_or_sw; + break; + case IB_NODE_TYPE_SWITCH: + p_group->remote_hca_or_sw.remote_sw = (ftree_sw_t *)p_remote_hca_or_sw; + break; + default: + /* we shouldn't get here - port is created only in hca or switch */ + CL_ASSERT(0); + } + + cl_ptr_vector_init(&p_group->ports, + 0, /* min size */ + 8); /* grow size */ + return p_group; +} /* __osm_ftree_port_group_create() */ + +/***************************************************/ + +static void +__osm_ftree_port_group_destroy( + IN ftree_port_group_t * p_group) +{ + uint32_t i; + uint32_t size; + ftree_port_t * p_port; + + if (!p_group) + return; + + /* remove all the elements of p_group->ports vector */ + size = cl_ptr_vector_get_size(&p_group->ports); + for (i = 0; i < size; i++) + { + cl_ptr_vector_at(&p_group->ports, i, (void **)&p_port); + __osm_ftree_port_destroy(p_port); + } + cl_ptr_vector_destroy(&p_group->ports); + free(p_group); +} /* __osm_ftree_port_group_destroy() */ + +/***************************************************/ + +static void +__osm_ftree_port_group_dump( + IN ftree_fabric_t *p_ftree, + IN ftree_port_group_t * p_group, + IN ftree_direction_t direction) +{ + ftree_port_t * p_port; + uint32_t size; + uint32_t i; + char buff[10*1024]; + + if (!p_group) + return; + + if (!osm_log_is_active(&p_ftree->p_osm->log, OSM_LOG_DEBUG)) + return; + + size = cl_ptr_vector_get_size(&p_group->ports); + buff[0] = '\0'; + + for (i = 0; i < size; i++) + { + cl_ptr_vector_at(&p_group->ports, i, (void **)&p_port); + CL_ASSERT(p_port); + + if (i != 0) + strcat(buff,", "); + sprintf(buff + strlen(buff), "%u", p_port->port_num); + } + + osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG, + "__osm_ftree_port_group_dump:" + " Port Group of size %u, port(s): %s, direction: %s\n" + " Local <--> Remote GUID (LID):" + "0x%016" PRIx64 " (0x%x) <--> 0x%016" PRIx64 " (0x%x)\n", + size, + buff, + (direction == FTREE_DIRECTION_DOWN)? "DOWN" : "UP", + cl_ntoh64(p_group->port_guid), + cl_ntoh16(p_group->base_lid), + cl_ntoh64(p_group->remote_port_guid), + cl_ntoh16(p_group->remote_base_lid)); + +} /* __osm_ftree_port_group_dump() */ + +/***************************************************/ + +static void +__osm_ftree_port_group_add_port( + IN ftree_port_group_t * p_group, + IN uint8_t port_num, + IN uint8_t remote_port_num) +{ + uint16_t i; + ftree_port_t * p_port; + + for (i = 0; i < cl_ptr_vector_get_size(&p_group->ports); i++) + { + cl_ptr_vector_at(&p_group->ports, i, (void **)&p_port); + if (p_port->port_num == port_num) + return; + } + + p_port = __osm_ftree_port_create(port_num,remote_port_num); + cl_ptr_vector_insert(&p_group->ports, p_port, NULL); +} + +/*************************************************** + ** + ** ftree_sw_t functions + ** + ***************************************************/ + +static ftree_sw_t * +__osm_ftree_sw_create( + IN ftree_fabric_t * p_ftree, + IN osm_switch_t * p_osm_sw) +{ + ftree_sw_t * p_sw; + uint8_t ports_num; + + /* make sure that the switch has ports */ + if (osm_switch_get_num_ports(p_osm_sw) == 1) + return NULL; + + p_sw = (ftree_sw_t *)malloc(sizeof(ftree_sw_t)); + if (p_sw == NULL) + return NULL; + memset(p_sw, 0, sizeof(ftree_sw_t)); + + p_sw->p_osm_sw = p_osm_sw; + p_sw->rank = 0xFF; + __osm_ftree_tuple_init(p_sw->tuple); + + p_sw->base_lid = osm_node_get_base_lid(osm_switch_get_node_ptr(p_sw->p_osm_sw),0); + + ports_num = osm_node_get_num_physp(osm_switch_get_node_ptr(p_sw->p_osm_sw)); + p_sw->down_port_groups = + (ftree_port_group_t **) malloc(ports_num * sizeof(ftree_port_group_t *)); + p_sw->up_port_groups = + (ftree_port_group_t **) malloc(ports_num * sizeof(ftree_port_group_t *)); + if (!p_sw->down_port_groups || !p_sw->up_port_groups) + return NULL; + p_sw->down_port_groups_num = 0; + p_sw->up_port_groups_num = 0; + + /* initialize lft buffer */ + p_sw->lft_buf = (ftree_fwd_tbl_t)cl_pool_get(&p_ftree->sw_fwd_tbl_pool); + memset(p_sw->lft_buf, OSM_NO_PATH, FTREE_FWD_TBL_LEN); + + return p_sw; +} /* __osm_ftree_sw_create() */ + +/***************************************************/ + +static void +__osm_ftree_sw_destroy( + IN ftree_fabric_t * p_ftree, + IN ftree_sw_t * p_sw) +{ + uint8_t i; + + if (!p_sw) + return; + + for (i = 0; i < p_sw->down_port_groups_num; i++) + __osm_ftree_port_group_destroy(p_sw->down_port_groups[i]); + for (i = 0; i < p_sw->up_port_groups_num; i++) + __osm_ftree_port_group_destroy(p_sw->up_port_groups[i]); + if (p_sw->down_port_groups) + free(p_sw->down_port_groups); + if (p_sw->up_port_groups) + free(p_sw->up_port_groups); + + /* return switch fwd_tbl to pool */ + if (p_sw->lft_buf) + cl_pool_put(&p_ftree->sw_fwd_tbl_pool, (void *)p_sw->lft_buf); + + free(p_sw); +} /* __osm_ftree_sw_destroy() */ + +/***************************************************/ + +static void +__osm_ftree_sw_dump( + IN ftree_fabric_t * p_ftree, + IN ftree_sw_t * p_sw) +{ + uint32_t i; + + if (!p_sw) + return; + + if (!osm_log_is_active(&p_ftree->p_osm->log, OSM_LOG_DEBUG)) + return; + + osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG, + "__osm_ftree_sw_dump: " + "Switch index: %s, GUID: 0x%016" PRIx64 ", Ports: %u DOWN, %u UP\n", + __osm_ftree_tuple_to_str(p_sw->tuple), + cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(p_sw->p_osm_sw))), + p_sw->down_port_groups_num, + p_sw->up_port_groups_num); + + for( i = 0; i < p_sw->down_port_groups_num; i++ ) + __osm_ftree_port_group_dump(p_ftree, + p_sw->down_port_groups[i], + FTREE_DIRECTION_DOWN); + for( i = 0; i < p_sw->up_port_groups_num; i++ ) + __osm_ftree_port_group_dump(p_ftree, + p_sw->up_port_groups[i], + FTREE_DIRECTION_UP); + +} /* __osm_ftree_sw_dump() */ + +/***************************************************/ + +static boolean_t +__osm_ftree_sw_ranked( + IN ftree_sw_t * p_sw) +{ + return (p_sw->rank != 0xFF); +} + +/***************************************************/ + +static ftree_port_group_t * +__osm_ftree_sw_get_port_group_by_remote_lid( + IN ftree_sw_t * p_sw, + IN ib_net16_t remote_base_lid, + IN ftree_direction_t direction) +{ + uint32_t i; + uint32_t size; + ftree_port_group_t ** port_groups; + + if (direction == FTREE_DIRECTION_UP) + { + port_groups = p_sw->up_port_groups; + size = p_sw->up_port_groups_num; + } + else + { + port_groups = p_sw->down_port_groups; + size = p_sw->down_port_groups_num; + } + + for (i = 0; i < size; i++) + if (remote_base_lid == port_groups[i]->remote_base_lid) + return port_groups[i]; + + return NULL; +} /* __osm_ftree_sw_get_port_group_by_remote_lid() */ + +/***************************************************/ + +static void +__osm_ftree_sw_add_port( + IN ftree_sw_t * p_sw, + IN uint8_t port_num, + IN uint8_t remote_port_num, + IN ib_net16_t base_lid, + IN ib_net16_t remote_base_lid, + IN ib_net64_t port_guid, + IN ib_net64_t remote_port_guid, + IN ib_net64_t remote_node_guid, + IN uint8_t remote_node_type, + IN void * p_remote_hca_or_sw, + IN ftree_direction_t direction) +{ + ftree_port_group_t * p_group = + __osm_ftree_sw_get_port_group_by_remote_lid(p_sw,remote_base_lid,direction); + + if (!p_group) + { + p_group = __osm_ftree_port_group_create( + base_lid, + remote_base_lid, + &port_guid, + &remote_port_guid, + &remote_node_guid, + remote_node_type, + p_remote_hca_or_sw); + CL_ASSERT(p_group); + + if (direction == FTREE_DIRECTION_UP) + p_sw->up_port_groups[p_sw->up_port_groups_num++] = p_group; + else + p_sw->down_port_groups[p_sw->down_port_groups_num++] = p_group; + } + __osm_ftree_port_group_add_port(p_group,port_num,remote_port_num); + +} /* __osm_ftree_sw_add_port() */ + +/***************************************************/ + +static inline void +__osm_ftree_sw_set_fwd_table_block( + IN ftree_sw_t * p_sw, + IN uint16_t lid_ho, + IN uint8_t port_num) +{ + p_sw->lft_buf[lid_ho] = port_num; +} + +/***************************************************/ + +static inline uint8_t +__osm_ftree_sw_get_fwd_table_block( + IN ftree_sw_t * p_sw, + IN uint16_t lid_ho) +{ + return p_sw->lft_buf[lid_ho]; +} + +/***************************************************/ + +static inline cl_status_t +__osm_ftree_sw_set_hops( + IN ftree_sw_t * p_sw, + IN uint16_t max_lid_ho, + IN uint16_t lid_ho, + IN uint8_t port_num, + IN uint8_t hops) +{ + /* make sure the lid matrix has enough room */ + osm_switch_set_min_lid_size(p_sw->p_osm_sw, max_lid_ho); + + /* set local min hop table(LID) */ + return osm_switch_set_hops(p_sw->p_osm_sw, + lid_ho, + port_num, + hops); +} + +/*************************************************** + ** + ** ftree_hca_t functions + ** + ***************************************************/ + +static ftree_hca_t * +__osm_ftree_hca_create( + IN osm_node_t * p_osm_node) +{ + ftree_hca_t * p_hca = (ftree_hca_t *)malloc(sizeof(ftree_hca_t)); + if (p_hca == NULL) + return NULL; + memset(p_hca,0,sizeof(ftree_hca_t)); + + p_hca->p_osm_node = p_osm_node; + p_hca->up_port_groups = (ftree_port_group_t **) + malloc(osm_node_get_num_physp(p_hca->p_osm_node) * sizeof (ftree_port_group_t *)); + if (!p_hca->up_port_groups) + return NULL; + p_hca->up_port_groups_num = 0; + return p_hca; +} + +/***************************************************/ + +static void +__osm_ftree_hca_destroy( + IN ftree_hca_t * p_hca) +{ + uint32_t i; + + if (!p_hca) + return; + + for (i = 0; i < p_hca->up_port_groups_num; i++) + __osm_ftree_port_group_destroy(p_hca->up_port_groups[i]); + + if (p_hca->up_port_groups) + free(p_hca->up_port_groups); + + free(p_hca); +} + +/***************************************************/ + +static void +__osm_ftree_hca_dump( + IN ftree_fabric_t * p_ftree, + IN ftree_hca_t * p_hca) +{ + uint32_t i; + + if (!p_hca) + return; + + if (!osm_log_is_active(&p_ftree->p_osm->log,OSM_LOG_DEBUG)) + return; + + osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG, + "__osm_ftree_hca_dump: " + "HCA GUID: 0x%016" PRIx64 ", Ports: %u UP\n", + cl_ntoh64(osm_node_get_node_guid(p_hca->p_osm_node)), + p_hca->up_port_groups_num); + + for( i = 0; i < p_hca->up_port_groups_num; i++ ) + __osm_ftree_port_group_dump(p_ftree, + p_hca->up_port_groups[i], + FTREE_DIRECTION_UP); +} + +/***************************************************/ + +static ftree_port_group_t * +__osm_ftree_hca_get_port_group_by_remote_lid( + IN ftree_hca_t * p_hca, + IN ib_net16_t remote_base_lid) +{ + uint32_t i; + for (i = 0; i < p_hca->up_port_groups_num; i++) + if (remote_base_lid == p_hca->up_port_groups[i]->remote_base_lid) + return p_hca->up_port_groups[i]; + + return NULL; +} + +/***************************************************/ + +static void +__osm_ftree_hca_add_port( + IN ftree_hca_t * p_hca, + IN uint8_t port_num, + IN uint8_t remote_port_num, + IN ib_net16_t base_lid, + IN ib_net16_t remote_base_lid, + IN ib_net64_t port_guid, + IN ib_net64_t remote_port_guid, + IN ib_net64_t remote_node_guid, + IN uint8_t remote_node_type, + IN void * p_remote_hca_or_sw) +{ + ftree_port_group_t * p_group; + + /* this function is supposed to be called only for adding ports + in hca's that lead to switches */ + CL_ASSERT(remote_node_type == IB_NODE_TYPE_SWITCH); + + p_group = __osm_ftree_hca_get_port_group_by_remote_lid(p_hca,remote_base_lid); + + if (!p_group) + { + p_group = __osm_ftree_port_group_create( + base_lid, + remote_base_lid, + &port_guid, + &remote_port_guid, + &remote_node_guid, + remote_node_type, + p_remote_hca_or_sw); + p_hca->up_port_groups[p_hca->up_port_groups_num++] = p_group; + } + __osm_ftree_port_group_add_port(p_group, port_num, remote_port_num); + +} /* __osm_ftree_hca_add_port() */ + +/*************************************************** + ** + ** ftree_fabric_t functions + ** + ***************************************************/ + +static ftree_fabric_t * +__osm_ftree_fabric_create() +{ + cl_status_t status; + ftree_fabric_t * p_ftree = (ftree_fabric_t *)malloc(sizeof(ftree_fabric_t)); + if (p_ftree == NULL) + return NULL; + + memset(p_ftree,0,sizeof(ftree_fabric_t)); + + cl_qmap_init(&p_ftree->hca_tbl); + cl_qmap_init(&p_ftree->sw_tbl); + cl_qmap_init(&p_ftree->sw_by_tuple_tbl); + + status = cl_pool_init( &p_ftree->sw_fwd_tbl_pool, + 8, /* min pool size */ + 0, /* max pool size - unlimited */ + 8, /* grow size */ + FTREE_FWD_TBL_LEN, /* object_size */ + NULL, /* object initializer */ + NULL, /* object destructor */ + NULL ); /* context */ + if (status != CL_SUCCESS) + return NULL; + + p_ftree->tree_rank = 1; + return p_ftree; +} + +/***************************************************/ + +static void +__osm_ftree_fabric_clear(ftree_fabric_t * p_ftree) +{ + ftree_hca_t * p_hca; + ftree_hca_t * p_next_hca; + ftree_sw_t * p_sw; + ftree_sw_t * p_next_sw; + ftree_sw_tbl_element_t * p_element; + ftree_sw_tbl_element_t * p_next_element; + + if (!p_ftree) + return; + + /* remove all the elements of hca_tbl */ + + p_next_hca = (ftree_hca_t *)cl_qmap_head(&p_ftree->hca_tbl); + while( p_next_hca != (ftree_hca_t *)cl_qmap_end( &p_ftree->hca_tbl ) ) + { + p_hca = p_next_hca; + p_next_hca = (ftree_hca_t *)cl_qmap_next(&p_hca->map_item ); + __osm_ftree_hca_destroy(p_hca); + } + cl_qmap_remove_all(&p_ftree->hca_tbl); + + /* remove all the elements of sw_tbl */ + + p_next_sw = (ftree_sw_t *)cl_qmap_head(&p_ftree->sw_tbl); + while( p_next_sw != (ftree_sw_t *)cl_qmap_end( &p_ftree->sw_tbl ) ) + { + p_sw = p_next_sw; + p_next_sw = (ftree_sw_t *)cl_qmap_next(&p_sw->map_item ); + __osm_ftree_sw_destroy(p_ftree,p_sw); + } + cl_qmap_remove_all(&p_ftree->sw_tbl); + + /* remove all the elements of sw_by_tuple_tbl */ + + p_next_element = + (ftree_sw_tbl_element_t *)cl_qmap_head(&p_ftree->sw_by_tuple_tbl); + while( p_next_element != + (ftree_sw_tbl_element_t *)cl_qmap_end( &p_ftree->sw_by_tuple_tbl ) ) + { + p_element = p_next_element; + p_next_element = + (ftree_sw_tbl_element_t *)cl_qmap_next(&p_element->map_item); + __osm_ftree_sw_tbl_element_destroy(p_element); + } + cl_qmap_remove_all(&p_ftree->sw_by_tuple_tbl); + + /* free the leaf switches array */ + if ((p_ftree->leaf_switches_num > 0) && (p_ftree->leaf_switches)) + free(p_ftree->leaf_switches); + + p_ftree->leaf_switches_num = 0; + p_ftree->leaf_switches = NULL; + p_ftree->fabric_built = FALSE; + +} /* __osm_ftree_fabric_destroy() */ + +/***************************************************/ + +static void +__osm_ftree_fabric_destroy(ftree_fabric_t * p_ftree) +{ + if (!p_ftree) + return; + __osm_ftree_fabric_clear(p_ftree); + cl_pool_destroy(&p_ftree->sw_fwd_tbl_pool); + free(p_ftree); +} + +/***************************************************/ + +static void +__osm_ftree_fabric_set_rank(ftree_fabric_t * p_ftree, uint8_t rank) +{ + if (rank > p_ftree->tree_rank) + p_ftree->tree_rank = rank; +} + +/***************************************************/ + +static uint8_t +__osm_ftree_fabric_get_rank(ftree_fabric_t * p_ftree) +{ + return p_ftree->tree_rank; +} + +/***************************************************/ + +static void +__osm_ftree_fabric_add_hca(ftree_fabric_t * p_ftree, osm_node_t * p_osm_node) +{ + ftree_hca_t * p_hca = __osm_ftree_hca_create(p_osm_node); + + CL_ASSERT(osm_node_get_type(p_osm_node) == IB_NODE_TYPE_CA); + + cl_qmap_insert(&p_ftree->hca_tbl, + p_osm_node->node_info.node_guid, + &p_hca->map_item); +} + +/***************************************************/ + +static void +__osm_ftree_fabric_add_sw(ftree_fabric_t * p_ftree, osm_switch_t * p_osm_sw) +{ + ftree_sw_t * p_sw = __osm_ftree_sw_create(p_ftree,p_osm_sw); + + CL_ASSERT(osm_node_get_type(p_osm_sw->p_node) == IB_NODE_TYPE_SWITCH); + + cl_qmap_insert(&p_ftree->sw_tbl, + p_osm_sw->p_node->node_info.node_guid, + &p_sw->map_item); + + /* track the max lid (in host order) that exists in the fabric */ + if (cl_ntoh16(p_sw->base_lid) > p_ftree->lft_max_lid_ho) + p_ftree->lft_max_lid_ho = cl_ntoh16(p_sw->base_lid); +} + +/***************************************************/ + +static void +__osm_ftree_fabric_add_sw_by_tuple( + IN ftree_fabric_t * p_ftree, + IN ftree_sw_t * p_sw) +{ + CL_ASSERT(__osm_ftree_tuple_assigned(p_sw->tuple)); + + cl_qmap_insert(&p_ftree->sw_by_tuple_tbl, + __osm_ftree_tuple_to_key(p_sw->tuple), + &__osm_ftree_sw_tbl_element_create(p_sw)->map_item); +} + +/***************************************************/ + +static ftree_sw_t * +__osm_ftree_fabric_get_sw_by_tuple( + IN ftree_fabric_t * p_ftree, + IN ftree_tuple_t tuple) +{ + ftree_sw_tbl_element_t * p_element; + + CL_ASSERT(__osm_ftree_tuple_assigned(tuple)); + + __osm_ftree_tuple_to_key(tuple); + + p_element = (ftree_sw_tbl_element_t * )cl_qmap_get(&p_ftree->sw_by_tuple_tbl, + __osm_ftree_tuple_to_key(tuple)); + if (p_element == (ftree_sw_tbl_element_t * )cl_qmap_end(&p_ftree->sw_by_tuple_tbl)) + return NULL; + + return p_element->p_sw; +} + +/***************************************************/ + +static void +__osm_ftree_fabric_dump(ftree_fabric_t * p_ftree) +{ + uint32_t i; + ftree_hca_t * p_hca; + ftree_sw_t * p_sw; + + if (!osm_log_is_active(&p_ftree->p_osm->log,OSM_LOG_DEBUG)) + return; + + osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG,"__osm_ftree_fabric_dump: \n" + " |-------------------------------|\n" + " |- Full fabric topology dump -|\n" + " |-------------------------------|\n\n"); + + osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG, + "__osm_ftree_fabric_dump: -- HCAs:\n"); + + for ( p_hca = (ftree_hca_t *)cl_qmap_head(&p_ftree->hca_tbl); + p_hca != (ftree_hca_t *)cl_qmap_end(&p_ftree->hca_tbl); + p_hca = (ftree_hca_t *)cl_qmap_next(&p_hca->map_item) ) + { + __osm_ftree_hca_dump(p_ftree, p_hca); + } + + for (i = 0; i < __osm_ftree_fabric_get_rank(p_ftree); i++) + { + osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG, + "__osm_ftree_fabric_dump: -- Rank %u switches\n", i); + for ( p_sw = (ftree_sw_t *)cl_qmap_head(&p_ftree->sw_tbl); + p_sw != (ftree_sw_t *)cl_qmap_end(&p_ftree->sw_tbl); + p_sw = (ftree_sw_t *)cl_qmap_next(&p_sw->map_item) ) + { + if (p_sw->rank == i) + __osm_ftree_sw_dump(p_ftree, p_sw); + } + } + + osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG,"__osm_ftree_fabric_dump: \n" + " |---------------------------------------|\n" + " |- Full fabric topology dump completed -|\n" + " |---------------------------------------|\n\n"); +} /* __osm_ftree_fabric_dump() */ + +/***************************************************/ + +static void +__osm_ftree_fabric_dump_general_info( + IN ftree_fabric_t * p_ftree) +{ + uint32_t i,j; + ftree_sw_t * p_sw; + char * addition_str; + + osm_log(&p_ftree->p_osm->log, OSM_LOG_INFO, + "__osm_ftree_fabric_dump_general_info: " + "General fabric topology info\n"); + osm_log(&p_ftree->p_osm->log, OSM_LOG_INFO,"__osm_ftree_fabric_dump_general_info: " + "============================\n"); + + osm_log(&p_ftree->p_osm->log, OSM_LOG_INFO, + "__osm_ftree_fabric_dump_general_info: " + " - FatTree rank (switches only): %u\n", + p_ftree->tree_rank); + osm_log(&p_ftree->p_osm->log, OSM_LOG_INFO, + "__osm_ftree_fabric_dump_general_info: " + " - Fabric has %u HCAs, %u switches\n", + cl_qmap_count(&p_ftree->hca_tbl), + cl_qmap_count(&p_ftree->sw_tbl)); + + for (i = 0; i < __osm_ftree_fabric_get_rank(p_ftree); i++) + { + j = 0; + for ( p_sw = (ftree_sw_t *)cl_qmap_head(&p_ftree->sw_tbl); + p_sw != (ftree_sw_t *)cl_qmap_end(&p_ftree->sw_tbl); + p_sw = (ftree_sw_t *)cl_qmap_next(&p_sw->map_item) ) + { + if (p_sw->rank == i) + j++; + } + if (i == 0) + addition_str = " (root) "; + else + if (i == (__osm_ftree_fabric_get_rank(p_ftree) - 1)) + addition_str = " (leaf) "; + else + addition_str = " "; + osm_log(&p_ftree->p_osm->log, OSM_LOG_INFO, + "__osm_ftree_fabric_dump_general_info: " + " - Fabric has %u rank %u%s switches\n", + j, i, addition_str); + } + + if (osm_log_is_active(&p_ftree->p_osm->log, OSM_LOG_VERBOSE)) + { + osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, + "__osm_ftree_fabric_dump_general_info: " + " - Root switches:\n"); + for ( p_sw = (ftree_sw_t *)cl_qmap_head(&p_ftree->sw_tbl); + p_sw != (ftree_sw_t *)cl_qmap_end(&p_ftree->sw_tbl); + p_sw = (ftree_sw_t *)cl_qmap_next(&p_sw->map_item) ) + { + if (p_sw->rank == 0) + osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, + "__osm_ftree_fabric_dump_general_info: " + " GUID: 0x%016" PRIx64 ", LID: 0x%x, Index %s\n", + cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(p_sw->p_osm_sw))), + cl_ntoh16(p_sw->base_lid), + __osm_ftree_tuple_to_str(p_sw->tuple)); + } + + osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, + "__osm_ftree_fabric_dump_general_info: " + " - Leaf switches (sorted by index):\n"); + for (i = 0; i < p_ftree->leaf_switches_num; i++) + { + osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, + "__osm_ftree_fabric_dump_general_info: " + " GUID: 0x%016" PRIx64 ", LID: 0x%x, Index %s\n", + cl_ntoh64(osm_node_get_node_guid( + osm_switch_get_node_ptr( + p_ftree->leaf_switches[i]->p_osm_sw))), + cl_ntoh16(p_ftree->leaf_switches[i]->base_lid), + __osm_ftree_tuple_to_str(p_ftree->leaf_switches[i]->tuple)); + } + } +} /* __osm_ftree_fabric_dump_general_info() */ + +/***************************************************/ + +static void +__osm_ftree_fabric_dump_hca_ordering( + IN ftree_fabric_t * p_ftree) +{ + ftree_hca_t * p_hca; + ftree_sw_t * p_sw; + ftree_port_group_t * p_group; + uint32_t i; + uint32_t j; + + char desc[IB_NODE_DESCRIPTION_SIZE + 1]; + char path[1024]; + FILE * p_hca_ordering_file; + char * filename = "osm-ftree-ca-order.dump"; + + snprintf(path, sizeof(path), "%s/%s", + p_ftree->p_osm->subn.opt.dump_files_dir, filename); + p_hca_ordering_file = fopen(path, "w"); + if (!p_hca_ordering_file) + { + osm_log(&p_ftree->p_osm->log, OSM_LOG_ERROR, + "__osm_ftree_fabric_dump_hca_ordering: ERR AB01: " + "cannot open file \'%s\': %s\n", + filename, strerror(errno)); + OSM_LOG_EXIT(&p_ftree->p_osm->log); + return; + } + + /* for each leaf switch (in indexing order) */ + for(i = 0; i < p_ftree->leaf_switches_num; i++) + { + p_sw = p_ftree->leaf_switches[i]; + /* for each real HCA connected to this switch */ + for (j = 0; j < p_sw->down_port_groups_num; j++) + { + p_group = p_sw->down_port_groups[j]; + p_hca = p_group->remote_hca_or_sw.remote_hca; + memcpy(desc,p_hca->p_osm_node->node_desc.description,IB_NODE_DESCRIPTION_SIZE); + desc[IB_NODE_DESCRIPTION_SIZE] = '\0'; + + fprintf(p_hca_ordering_file,"0x%x\t%s\n", + cl_ntoh16(p_group->remote_base_lid), desc); + } + + /* now print dummy HCAs */ + for (j = p_sw->down_port_groups_num; j < p_ftree->max_hcas_per_leaf; j++) + { + fprintf(p_hca_ordering_file,"0xFFFF\tDUMMY\n"); + } + + } + /* done going through all the leaf switches */ + + fclose(p_hca_ordering_file); +} /* __osm_ftree_fabric_dump_hca_ordering() */ + +/***************************************************/ + +static void +__osm_ftree_fabric_assign_tuple( + IN ftree_fabric_t * p_ftree, + IN ftree_sw_t * p_sw, + IN ftree_tuple_t new_tuple) +{ + memcpy(p_sw->tuple, new_tuple, FTREE_TUPLE_LEN); + __osm_ftree_fabric_add_sw_by_tuple(p_ftree,p_sw); +} + +/***************************************************/ + +static void +__osm_ftree_fabric_assign_first_tuple( + IN ftree_fabric_t * p_ftree, + IN ftree_sw_t * p_sw) +{ + uint8_t i; + ftree_tuple_t new_tuple; + + __osm_ftree_tuple_init(new_tuple); + new_tuple[0] = p_sw->rank; + for (i = 1; i <= p_sw->rank; i++) + new_tuple[i] = 0; + + __osm_ftree_fabric_assign_tuple(p_ftree,p_sw,new_tuple); +} + +/***************************************************/ + +static void +__osm_ftree_fabric_get_new_tuple( + IN ftree_fabric_t * p_ftree, + OUT ftree_tuple_t new_tuple, + IN ftree_tuple_t from_tuple, + IN ftree_direction_t direction) +{ + ftree_sw_t * p_sw; + ftree_tuple_t temp_tuple; + uint8_t var_index; + uint8_t i; + + __osm_ftree_tuple_init(new_tuple); + memcpy(temp_tuple, from_tuple, FTREE_TUPLE_LEN); + + if (direction == FTREE_DIRECTION_DOWN) + { + temp_tuple[0] ++; + var_index = from_tuple[0] + 1; + } + else + { + temp_tuple[0] --; + var_index = from_tuple[0]; + } + + for (i = 0; i < 0xFF; i++) + { + temp_tuple[var_index] = i; + p_sw = __osm_ftree_fabric_get_sw_by_tuple(p_ftree,temp_tuple); + if (p_sw == NULL) /* found free tuple */ + break; + } + + if (i == 0xFF) + { + /* new tuple not found - there are more than 255 ports in one direction */ + return; + } + memcpy(new_tuple, temp_tuple, FTREE_TUPLE_LEN); + +} /* __osm_ftree_fabric_get_new_tuple() */ + +/***************************************************/ + +static void +__osm_ftree_fabric_calculate_rank( + IN ftree_fabric_t * p_ftree) +{ + ftree_sw_t * p_sw; + ftree_sw_t * p_next_sw; + uint16_t max_rank = 0; + + /* go over all the switches and find maximal switch rank */ + + p_next_sw = (ftree_sw_t *)cl_qmap_head(&p_ftree->sw_tbl); + while( p_next_sw != (ftree_sw_t *)cl_qmap_end(&p_ftree->sw_tbl) ) + { + p_sw = p_next_sw; + if(p_sw->rank > max_rank) + max_rank = p_sw->rank; + p_next_sw = (ftree_sw_t *)cl_qmap_next(&p_sw->map_item ); + } + + /* set FatTree rank */ + __osm_ftree_fabric_set_rank(p_ftree, max_rank + 1); +} + +/***************************************************/ + +static void +__osm_ftree_fabric_make_indexing( + IN ftree_fabric_t * p_ftree) +{ + ftree_sw_t * p_remote_sw; + ftree_sw_t * p_sw; + ftree_sw_t * p_next_sw; + ftree_tuple_t new_tuple; + uint32_t i; + cl_list_t bfs_list; + ftree_sw_tbl_element_t * p_sw_tbl_element; + + OSM_LOG_ENTER(&p_ftree->p_osm->log, __osm_ftree_fabric_make_indexing); + + osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,"__osm_ftree_fabric_make_indexing: " + "Starting FatTree indexing\n"); + + /* create array of leaf switches */ + p_ftree->leaf_switches = (ftree_sw_t **) + malloc(cl_qmap_count(&p_ftree->sw_tbl) * sizeof(ftree_sw_t *)); + + /* Looking for a leaf switch - the one that has rank equal to (tree_rank - 1). + This switch will be used as a starting point for indexing algorithm. */ + + p_next_sw = (ftree_sw_t *)cl_qmap_head(&p_ftree->sw_tbl); + while( p_next_sw != (ftree_sw_t *)cl_qmap_end( &p_ftree->sw_tbl ) ) + { + p_sw = p_next_sw; + if(p_sw->rank == (__osm_ftree_fabric_get_rank(p_ftree) - 1)) + break; + p_next_sw = (ftree_sw_t *)cl_qmap_next(&p_sw->map_item ); + } + + CL_ASSERT(p_next_sw != (ftree_sw_t *)cl_qmap_end(&p_ftree->sw_tbl)); + + /* Assign the first tuple to the switch that is used as BFS starting point. + The tuple will be as follows: [rank].0.0.0... + This fuction also adds the switch it into the switch_by_tuple table. */ + __osm_ftree_fabric_assign_first_tuple(p_ftree,p_sw); + + osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, + "__osm_ftree_fabric_make_indexing: Indexing starting point:\n" + " - Switch rank : %u\n" + " - Switch index : %s\n" + " - Node LID : 0x%x\n" + " - Node GUID : 0x%016" PRIx64 "\n", + p_sw->rank, + __osm_ftree_tuple_to_str(p_sw->tuple), + cl_ntoh16(p_sw->base_lid), + cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(p_sw->p_osm_sw)))); + + /* + * Now run BFS and assign indexes to all switches + * Pseudo code of the algorithm is as follows: + * + * * Add first switch to BFS queue + * * While (BFS queue not empty) + * - Pop the switch from the head of the queue + * - Scan all the downward and upward ports + * - For each port + * + Get the remote switch + * + Assign index to the remote switch + * + Add remote switch to the BFS queue + */ + + cl_list_init(&bfs_list, cl_qmap_count(&p_ftree->sw_tbl)); + cl_list_insert_tail(&bfs_list, &__osm_ftree_sw_tbl_element_create(p_sw)->map_item); + + while (!cl_is_list_empty(&bfs_list)) + { + p_sw_tbl_element = (ftree_sw_tbl_element_t *)cl_list_remove_head(&bfs_list); + p_sw = p_sw_tbl_element->p_sw; + __osm_ftree_sw_tbl_element_destroy(p_sw_tbl_element); + + /* Discover all the nodes from ports that are pointing down */ + + if (p_sw->rank == (__osm_ftree_fabric_get_rank(p_ftree) - 1)) + { + /* add switch to leaf switches array */ + p_ftree->leaf_switches[p_ftree->leaf_switches_num++] = p_sw; + /* update the max_hcas_per_leaf value */ + if (p_sw->down_port_groups_num > p_ftree->max_hcas_per_leaf) + p_ftree->max_hcas_per_leaf = p_sw->down_port_groups_num; + } + else + { + /* This is not the leaf switch, which means that all the + ports that point down are taking us to another switches. + No need to assign indexing to HCAs */ + for( i = 0; i < p_sw->down_port_groups_num; i++ ) + { + p_remote_sw = p_sw->down_port_groups[i]->remote_hca_or_sw.remote_sw; + if (__osm_ftree_tuple_assigned(p_remote_sw->tuple)) + { + /* this switch has been already indexed */ + continue; + } + /* allocate new tuple */ + __osm_ftree_fabric_get_new_tuple(p_ftree, + new_tuple, + p_sw->tuple, + FTREE_DIRECTION_DOWN); + /* Assign the new tuple to the remote switch. + This fuction also adds the switch into the switch_by_tuple table. */ + __osm_ftree_fabric_assign_tuple(p_ftree, + p_remote_sw, + new_tuple); + + /* add the newly discovered switch to the BFS queue */ + cl_list_insert_tail(&bfs_list, + &__osm_ftree_sw_tbl_element_create(p_remote_sw)->map_item); + } + /* Done assigning indexes to all the remote switches + that are pointed by the downgoing ports. + Now sort port groups according to remote index. */ + qsort(p_sw->down_port_groups, /* array */ + p_sw->down_port_groups_num, /* number of elements */ + sizeof(ftree_port_group_t *), /* size of each element */ + __osm_ftree_compare_port_groups_by_remote_switch_index); /* comparator */ + } + + /* Done indexing switches from ports that go down. + Now do the same with ports that are pointing up. */ + + if (p_sw->rank != 0) + { + /* This is not the root switch, which means that all the ports + that are pointing up are taking us to another switches. */ + for( i = 0; i < p_sw->up_port_groups_num; i++ ) + { + p_remote_sw = p_sw->up_port_groups[i]->remote_hca_or_sw.remote_sw; + if (__osm_ftree_tuple_assigned(p_remote_sw->tuple)) + continue; + /* allocate new tuple */ + __osm_ftree_fabric_get_new_tuple(p_ftree, + new_tuple, + p_sw->tuple, + FTREE_DIRECTION_UP); + /* Assign the new tuple to the remote switch. + This fuction also adds the switch to the + switch_by_tuple table. */ + __osm_ftree_fabric_assign_tuple(p_ftree, + p_remote_sw, + new_tuple); + /* add the newly discovered switch to the BFS queue */ + cl_list_insert_tail(&bfs_list, + &__osm_ftree_sw_tbl_element_create(p_remote_sw)->map_item); + } + /* Done assigning indexes to all the remote switches + that are pointed by the upgoing ports. + Now sort port groups according to remote index. */ + qsort(p_sw->up_port_groups, /* array */ + p_sw->up_port_groups_num, /* number of elements */ + sizeof(ftree_port_group_t *), /* size of each element */ + __osm_ftree_compare_port_groups_by_remote_switch_index); /* comparator */ + } + /* Done assigning indexes to all the switches that are directly connected + to the current switch - go to the next switch in the BFS queue */ + } + + /* sort array of leaf switches by index */ + qsort(p_ftree->leaf_switches, /* array */ + p_ftree->leaf_switches_num, /* number of elements */ + sizeof(ftree_sw_t *), /* size of each element */ + __osm_ftree_compare_switches_by_index); /* comparator */ + + OSM_LOG_EXIT(&p_ftree->p_osm->log); +} /* __osm_ftree_fabric_make_indexing() */ + +/***************************************************/ + +static boolean_t +__osm_ftree_fabric_validate_topology( + IN ftree_fabric_t * p_ftree) +{ + ftree_port_group_t * p_group; + ftree_port_group_t * p_ref_group; + ftree_sw_t * p_sw; + ftree_sw_t * p_next_sw; + ftree_sw_t ** reference_sw_arr; + uint16_t tree_rank = __osm_ftree_fabric_get_rank(p_ftree); + boolean_t res = TRUE; + uint8_t i; + + OSM_LOG_ENTER(&p_ftree->p_osm->log, __osm_ftree_fabric_validate_topology); + + osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, + "__osm_ftree_fabric_validate_topology: " + "Validating fabric topology\n"); + + reference_sw_arr = (ftree_sw_t **)malloc(tree_rank * sizeof(ftree_sw_t *)); + if ( reference_sw_arr == NULL ) + { + osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS, + "Fat-tree routing: Memory allocation failed\n"); + return FALSE; + } + memset(reference_sw_arr, 0, tree_rank * sizeof(ftree_sw_t *)); + + p_next_sw = (ftree_sw_t *)cl_qmap_head(&p_ftree->sw_tbl); + while( res && + p_next_sw != (ftree_sw_t *)cl_qmap_end( &p_ftree->sw_tbl ) ) + { + p_sw = p_next_sw; + p_next_sw = (ftree_sw_t *)cl_qmap_next(&p_sw->map_item ); + + if (!reference_sw_arr[p_sw->rank]) + { + /* This is the first switch in the current level that + we're checking - use it as a reference */ + reference_sw_arr[p_sw->rank] = p_sw; + } + else + { + /* compare this switch properties to the reference switch */ + + if ( reference_sw_arr[p_sw->rank]->up_port_groups_num != p_sw->up_port_groups_num ) + { + osm_log(&p_ftree->p_osm->log, OSM_LOG_ERROR, + "__osm_ftree_fabric_validate_topology: " + "ERR AB09: Different number of upward port groups on switches:\n" + " GUID 0x%016" PRIx64 ", LID 0x%x, Index %s - %u groups\n" + " GUID 0x%016" PRIx64 ", LID 0x%x, Index %s - %u groups\n", + cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(reference_sw_arr[p_sw->rank]->p_osm_sw))), + cl_ntoh16(reference_sw_arr[p_sw->rank]->base_lid), + __osm_ftree_tuple_to_str(reference_sw_arr[p_sw->rank]->tuple), + reference_sw_arr[p_sw->rank]->up_port_groups_num, + cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(p_sw->p_osm_sw))), + cl_ntoh16(p_sw->base_lid), + __osm_ftree_tuple_to_str(p_sw->tuple), + p_sw->up_port_groups_num); + res = FALSE; + break; + } + + if ( p_sw->rank != (__osm_ftree_fabric_get_rank(p_ftree) - 1) && + reference_sw_arr[p_sw->rank]->down_port_groups_num != p_sw->down_port_groups_num ) + { + /* we're allowing some hca's to be missing */ + osm_log(&p_ftree->p_osm->log, OSM_LOG_ERROR, + "__osm_ftree_fabric_validate_topology: " + "ERR AB0A: Different number of downward port groups on switches:\n" + " GUID 0x%016" PRIx64 ", LID 0x%x, Index %s - %u port groups\n" + " GUID 0x%016" PRIx64 ", LID 0x%x, Index %s - %u port groups\n", + cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(reference_sw_arr[p_sw->rank]->p_osm_sw))), + cl_ntoh16(reference_sw_arr[p_sw->rank]->base_lid), + __osm_ftree_tuple_to_str(reference_sw_arr[p_sw->rank]->tuple), + reference_sw_arr[p_sw->rank]->down_port_groups_num, + cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(p_sw->p_osm_sw))), + cl_ntoh16(p_sw->base_lid), + __osm_ftree_tuple_to_str(p_sw->tuple), + p_sw->down_port_groups_num); + res = FALSE; + break; + } + + if ( reference_sw_arr[p_sw->rank]->up_port_groups_num != 0 ) + { + p_ref_group = reference_sw_arr[p_sw->rank]->up_port_groups[0]; + for (i = 0; i < p_sw->up_port_groups_num; i++) + { + p_group = p_sw->up_port_groups[i]; + if (cl_ptr_vector_get_size(&p_ref_group->ports) != cl_ptr_vector_get_size(&p_group->ports)) + { + osm_log(&p_ftree->p_osm->log, OSM_LOG_ERROR, + "__osm_ftree_fabric_validate_topology: " + "ERR AB0B: Different number of ports in an upward port group on switches:\n" + " GUID 0x%016" PRIx64 ", LID 0x%x, Index %s - %u ports\n" + " GUID 0x%016" PRIx64 ", LID 0x%x, Index %s - %u ports\n", + cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(reference_sw_arr[p_sw->rank]->p_osm_sw))), + cl_ntoh16(reference_sw_arr[p_sw->rank]->base_lid), + __osm_ftree_tuple_to_str(reference_sw_arr[p_sw->rank]->tuple), + cl_ptr_vector_get_size(&p_ref_group->ports), + cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(p_sw->p_osm_sw))), + cl_ntoh16(p_sw->base_lid), + __osm_ftree_tuple_to_str(p_sw->tuple), + cl_ptr_vector_get_size(&p_group->ports)); + res = FALSE; + break; + } + } + } + if ( reference_sw_arr[p_sw->rank]->down_port_groups_num != 0 && + p_sw->rank != (tree_rank - 1) ) + { + /* we're allowing some hca's to be missing */ + p_ref_group = reference_sw_arr[p_sw->rank]->down_port_groups[0]; + for (i = 0; i < p_sw->down_port_groups_num; i++) + { + p_group = p_sw->down_port_groups[0]; + if (cl_ptr_vector_get_size(&p_ref_group->ports) != cl_ptr_vector_get_size(&p_group->ports)) + { + osm_log(&p_ftree->p_osm->log, OSM_LOG_ERROR, + "__osm_ftree_fabric_validate_topology: " + "ERR AB0C: Different number of ports in an downward port group on switches:\n" + " GUID 0x%016" PRIx64 ", LID 0x%x, Index %s - %u ports\n" + " GUID 0x%016" PRIx64 ", LID 0x%x, Index %s - %u ports\n", + cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(reference_sw_arr[p_sw->rank]->p_osm_sw))), + cl_ntoh16(reference_sw_arr[p_sw->rank]->base_lid), + __osm_ftree_tuple_to_str(reference_sw_arr[p_sw->rank]->tuple), + cl_ptr_vector_get_size(&p_ref_group->ports), + cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(p_sw->p_osm_sw))), + cl_ntoh16(p_sw->base_lid), + __osm_ftree_tuple_to_str(p_sw->tuple), + cl_ptr_vector_get_size(&p_group->ports)); + res = FALSE; + break; + } + } + } + } /* end of else */ + } /* end of while */ + + if (res == TRUE) + osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, + "__osm_ftree_fabric_validate_topology: " + "Fabric topology has been identified as FatTree\n"); + else + osm_log(&p_ftree->p_osm->log, OSM_LOG_ERROR, + "__osm_ftree_fabric_validate_topology: " + "ERR AB0D: Fabric topology hasn't been identified as FatTree\n"); + + free(reference_sw_arr); + OSM_LOG_EXIT(&p_ftree->p_osm->log); + return res; +} /* __osm_ftree_fabric_validate_topology() */ + +/*************************************************** + ***************************************************/ + +static void +__osm_ftree_set_sw_fwd_table( + IN cl_map_item_t* const p_map_item, + IN void *context) +{ + ftree_sw_t * p_sw = (ftree_sw_t * const) p_map_item; + ftree_fabric_t * p_ftree = (ftree_fabric_t *)context; + + /* calculate lft length rounded up to a multiple of 64 (block length) */ + uint16_t lft_len = 64 * ((p_ftree->lft_max_lid_ho + 1 + 63) / 64); + + p_sw->p_osm_sw->max_lid_ho = p_ftree->lft_max_lid_ho; + + memcpy(p_ftree->p_osm->sm.ucast_mgr.lft_buf, + p_sw->lft_buf, + lft_len); + osm_ucast_mgr_set_fwd_table(&p_ftree->p_osm->sm.ucast_mgr, p_sw->p_osm_sw); +} + +/*************************************************** + ***************************************************/ + +/* + * Function: assign-up-going-port-by-descending-down + * Given : a switch and a LID + * Pseudo code: + * foreach down-going-port-group (in indexing order) + * skip this group if the LFT(LID) port is part of this group + * find the least loaded port of the group (scan in indexing order) + * r-port is the remote port connected to it + * assign the remote switch node LFT(LID) to r-port + * increase r-port usage counter + * assign-up-going-port-by-descending-down to r-port node (recursion) + */ + +static void +__osm_ftree_fabric_route_upgoing_by_going_down( + IN ftree_fabric_t * p_ftree, + IN ftree_sw_t * p_sw, + IN ftree_sw_t * p_prev_sw, + IN ib_net16_t target_lid, + IN uint8_t target_rank, + IN boolean_t is_real_lid, + IN boolean_t is_main_path, + IN uint8_t highest_rank_in_route) +{ + ftree_sw_t * p_remote_sw; + uint16_t ports_num; + ftree_port_group_t * p_group; + ftree_port_t * p_port; + ftree_port_t * p_min_port; + uint16_t i; + uint16_t j; + + /* we shouldn't enter here if both real_lid and main_path are false */ + CL_ASSERT(is_real_lid || is_main_path); + + /* can't be here for leaf switch, */ + CL_ASSERT(p_sw->rank != (__osm_ftree_fabric_get_rank(p_ftree) - 1)); + + /* if there is no down-going ports */ + if (p_sw->down_port_groups_num == 0) + return; + + /* foreach down-going port group (in indexing order) */ + for (i = 0; i < p_sw->down_port_groups_num; i++) + { + p_group = p_sw->down_port_groups[i]; + + if ( p_prev_sw && (p_group->remote_base_lid == p_prev_sw->base_lid) ) + { + /* This port group has a port that was used when we entered this switch, + which means that the current group points to the switch where we were + at the previous step of the algorithm (before going up). + Skipping this group. */ + continue; + } + + /* find the least loaded port of the group (in indexing order) */ + p_min_port = NULL; + ports_num = (uint16_t)cl_ptr_vector_get_size(&p_group->ports); + /* ToDo: no need to select a least loaded port for non-main path. + Think about optimization. */ + for (j = 0; j < ports_num; j++) + { + cl_ptr_vector_at(&p_group->ports, j, (void **)&p_port); + if (!p_min_port) + { + /* first port that we're checking - set as port with the lowest load */ + p_min_port = p_port; + } + else if (p_port->counter_up < p_min_port->counter_up) + { + /* this port is less loaded - use it as min */ + p_min_port = p_port; + } + } + /* At this point we have selected a port in this group with the + lowest load of upgoing routes. + Set on the remote switch how to get to the target_lid - + set LFT(target_lid) on the remote switch to the remote port */ + p_remote_sw = p_group->remote_hca_or_sw.remote_sw; + + /* Four possible cases: + * + * 1. is_real_lid == TRUE && is_main_path == TRUE: + * - going DOWN(TRUE,TRUE) through ALL the groups + * + promoting port counter + * + setting path in remote switch fwd tbl + * + setting hops in remote switch on all the ports of each group + * + * 2. is_real_lid == TRUE && is_main_path == FALSE: + * - going DOWN(TRUE,FALSE) through ALL the groups but only if + * the remote (upper) switch hasn't been already configured + * for this target LID + * + NOT promoting port counter + * + setting path in remote switch fwd tbl if it hasn't been set yet + * + setting hops in remote switch on all the ports of each group + * if it hasn't been set yet + * + * 3. is_real_lid == FALSE && is_main_path == TRUE: + * - going DOWN(FALSE,TRUE) through ALL the groups + * + promoting port counter + * + NOT setting path in remote switch fwd tbl + * + NOT setting hops in remote switch + * + * 4. is_real_lid == FALSE && is_main_path == FALSE: + * - illegal state - we shouldn't get here + */ + + /* second case: skip the port group if the remote (upper) + switch has been already configured for this target LID */ + if ( is_real_lid && !is_main_path && + __osm_ftree_sw_get_fwd_table_block(p_remote_sw, + cl_ntoh16(target_lid)) != OSM_NO_PATH ) + continue; + + /* setting fwd tbl port only if this is real LID */ + if (is_real_lid) + { + __osm_ftree_sw_set_fwd_table_block(p_remote_sw, + cl_ntoh16(target_lid), + p_min_port->remote_port_num); + osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG, + "__osm_ftree_fabric_route_upgoing_by_going_down: " + "Switch %s: set path to HCA LID 0x%x through port %u\n", + __osm_ftree_tuple_to_str(p_remote_sw->tuple), + cl_ntoh16(target_lid), + p_min_port->remote_port_num); + + /* On the remote switch that is pointed by the p_group, + set hops for ALL the ports in the remote group. */ + + for (j = 0; j < ports_num; j++) + { + cl_ptr_vector_at(&p_group->ports, j, (void **)&p_port); + + __osm_ftree_sw_set_hops(p_remote_sw, + p_ftree->lft_max_lid_ho, + cl_ntoh16(target_lid), + p_port->remote_port_num, + ( (target_rank - highest_rank_in_route) + + (p_remote_sw->rank - highest_rank_in_route) )); + } + + + } + + /* The number of upgoing routes is tracked in the + p_port->counter_up counter of the port that belongs to + the upper side of the link (on switch with lower rank). + Counter is promoted only if we're routing LID on the main + path (whether it's a real LID or a dummy one). */ + if (is_main_path) + p_min_port->counter_up++; + + /* Recursion step: + Assign upgoing ports by stepping down, starting on REMOTE switch. + Recursion stop condition - if the REMOTE switch is a leaf switch. */ + if (p_remote_sw->rank != (__osm_ftree_fabric_get_rank(p_ftree) - 1)) + { + __osm_ftree_fabric_route_upgoing_by_going_down( + p_ftree, + p_remote_sw, /* remote switch - used as a route-upgoing alg. start point */ + NULL, /* prev. position - NULL to mark that we went down and not up */ + target_lid, /* LID that we're routing to */ + target_rank, /* rank of the LID that we're routing to */ + is_real_lid, /* whether the target LID is real or dummy */ + is_main_path, /* whether this is path to HCA that should by tracked by counters */ + highest_rank_in_route); /* highest visited point in the tree before going down */ + } + } + /* done scanning all the down-going port groups */ + +} /* __osm_ftree_fabric_route_upgoing_by_going_down() */ + +/***************************************************/ + +/* + * Function: assign-down-going-port-by-descending-up + * Given : a switch and a LID + * Pseudo code: + * find the least loaded port of all the upgoing groups (scan in indexing order) + * assign the LFT(LID) of remote switch to that port + * track that port usage + * assign-up-going-port-by-descending-down on CURRENT switch + * assign-down-going-port-by-descending-up on REMOTE switch (recursion) + */ + +static void +__osm_ftree_fabric_route_downgoing_by_going_up( + IN ftree_fabric_t * p_ftree, + IN ftree_sw_t * p_sw, + IN ftree_sw_t * p_prev_sw, + IN ib_net16_t target_lid, + IN uint8_t target_rank, + IN boolean_t is_real_lid, + IN boolean_t is_main_path) +{ + ftree_sw_t * p_remote_sw; + uint16_t ports_num; + ftree_port_group_t * p_group; + ftree_port_t * p_port; + ftree_port_group_t * p_min_group; + ftree_port_t * p_min_port; + uint16_t i; + uint16_t j; + + /* we shouldn't enter here if both real_lid and main_path are false */ + CL_ASSERT(is_real_lid || is_main_path); + + /* If this switch isn't a leaf switch: + Assign upgoing ports by stepping down, starting on THIS switch. */ + if (p_sw->rank != (__osm_ftree_fabric_get_rank(p_ftree) - 1)) + { + __osm_ftree_fabric_route_upgoing_by_going_down( + p_ftree, + p_sw, /* local switch - used as a route-upgoing alg. start point */ + p_prev_sw, /* switch that we went up from (NULL means that we went down) */ + target_lid, /* LID that we're routing to */ + target_rank, /* rank of the LID that we're routing to */ + is_real_lid, /* whether this target LID is real or dummy */ + is_main_path, /* whether this path to HCA should by tracked by counters */ + p_sw->rank); /* the highest visited point in the tree before going down */ + } + + /* recursion stop condition - if it's a root switch, */ + if (p_sw->rank == 0) + return; + + /* Find the least loaded port of all the upgoing port groups + (in indexing order of the remote switches). */ + p_min_group = NULL; + p_min_port = NULL; + for (i = 0; i < p_sw->up_port_groups_num; i++) + { + p_group = p_sw->up_port_groups[i]; + + ports_num = (uint16_t)cl_ptr_vector_get_size(&p_group->ports); + for (j = 0; j < ports_num; j++) + { + cl_ptr_vector_at(&p_group->ports, j, (void **)&p_port); + if (!p_min_group) + { + /* first port that we're checking - use + it as a port with the lowest load */ + p_min_group = p_group; + p_min_port = p_port; + } + else + { + if ( p_port->counter_down < p_min_port->counter_down ) + { + /* this port is less loaded - use it as min */ + p_min_group = p_group; + p_min_port = p_port; + } + } + } + } + + /* At this point we have selected a group and port with the + lowest load of downgoing routes. + Set on the remote switch how to get to the target_lid - + set LFT(target_lid) on the remote switch to the remote port */ + p_remote_sw = p_min_group->remote_hca_or_sw.remote_sw; + + /* Four possible cases: + * + * 1. is_real_lid == TRUE && is_main_path == TRUE: + * - going UP(TRUE,TRUE) on selected min_group and min_port + * + promoting port counter + * + setting path in remote switch fwd tbl + * + setting hops in remote switch on all the ports of selected group + * - going UP(TRUE,FALSE) on rest of the groups, each time on port 0 + * + NOT promoting port counter + * + setting path in remote switch fwd tbl if it hasn't been set yet + * + setting hops in remote switch on all the ports of each group + * if it hasn't been set yet + * + * 2. is_real_lid == TRUE && is_main_path == FALSE: + * - going UP(TRUE,FALSE) on ALL the groups, each time on port 0, + * but only if the remote (upper) switch hasn't been already + * configured for this target LID + * + NOT promoting port counter + * + setting path in remote switch fwd tbl if it hasn't been set yet + * + setting hops in remote switch on all the ports of each group + * if it hasn't been set yet + * + * 3. is_real_lid == FALSE && is_main_path == TRUE: + * - going UP(FALSE,TRUE) ONLY on selected min_group and min_port + * + promoting port counter + * + NOT setting path in remote switch fwd tbl + * + NOT setting hops in remote switch + * + * 4. is_real_lid == FALSE && is_main_path == FALSE: + * - illegal state - we shouldn't get here + */ + + /* covering first half of case 1, and case 3 */ + if (is_main_path) + { + if (p_sw->rank == (__osm_ftree_fabric_get_rank(p_ftree) - 1)) + { + osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG, + "__osm_ftree_fabric_route_downgoing_by_going_up: " + " - Routing MAIN path for %s HCA LID 0x%x: %s --> %s\n", + (is_real_lid)? "real" : "DUMMY", + cl_ntoh16(target_lid), + __osm_ftree_tuple_to_str(p_sw->tuple), + __osm_ftree_tuple_to_str(p_remote_sw->tuple)); + } + /* The number of downgoing routes is tracked in the + p_port->counter_down counter of the port that belongs to + the lower side of the link (on switch with higher rank) */ + p_min_port->counter_down++; + if (is_real_lid) + { + __osm_ftree_sw_set_fwd_table_block(p_remote_sw, + cl_ntoh16(target_lid), + p_min_port->remote_port_num); + osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG, + "__osm_ftree_fabric_route_downgoing_by_going_up: " + "Switch %s: set path to HCA LID 0x%x through port %u\n", + __osm_ftree_tuple_to_str(p_remote_sw->tuple), + cl_ntoh16(target_lid),p_min_port->remote_port_num); + + /* On the remote switch that is pointed by the min_group, + set hops for ALL the ports in the remote group. */ + + ports_num = (uint16_t)cl_ptr_vector_get_size(&p_min_group->ports); + for (j = 0; j < ports_num; j++) + { + cl_ptr_vector_at(&p_min_group->ports, j, (void **)&p_port); + __osm_ftree_sw_set_hops(p_remote_sw, + p_ftree->lft_max_lid_ho, + cl_ntoh16(target_lid), + p_port->remote_port_num, + target_rank - p_remote_sw->rank); + } + } + + /* Recursion step: + Assign downgoing ports by stepping up, starting on REMOTE switch. */ + __osm_ftree_fabric_route_downgoing_by_going_up( + p_ftree, + p_remote_sw, /* remote switch - used as a route-downgoing alg. next step point */ + p_sw, /* this switch - prev. position switch for the function */ + target_lid, /* LID that we're routing to */ + target_rank, /* rank of the LID that we're routing to */ + is_real_lid, /* whether this target LID is real or dummy */ + is_main_path); /* whether this is path to HCA that should by tracked by counters */ + } + + /* we're done for the third case */ + if (!is_real_lid) + return; + + /* What's left to do at this point: + * + * 1. is_real_lid == TRUE && is_main_path == TRUE: + * - going UP(TRUE,FALSE) on rest of the groups, each time on port 0, + * but only if the remote (upper) switch hasn't been already + * configured for this target LID + * + NOT promoting port counter + * + setting path in remote switch fwd tbl if it hasn't been set yet + * + setting hops in remote switch on all the ports of each group + * if it hasn't been set yet + * + * 2. is_real_lid == TRUE && is_main_path == FALSE: + * - going UP(TRUE,FALSE) on ALL the groups, each time on port 0, + * but only if the remote (upper) switch hasn't been already + * configured for this target LID + * + NOT promoting port counter + * + setting path in remote switch fwd tbl if it hasn't been set yet + * + setting hops in remote switch on all the ports of each group + * if it hasn't been set yet + * + * These two rules can be rephrased this way: + * - foreach UP port group + * + if remote switch has been set with the target LID + * - skip this port group + * + else + * - select port 0 + * - do NOT promote port counter + * - set path in remote switch fwd tbl + * - set hops in remote switch on all the ports of this group + * - go UP(TRUE,FALSE) to the remote switch + */ + + for (i = 0; i < p_sw->up_port_groups_num; i++) + { + p_group = p_sw->up_port_groups[i]; + p_remote_sw = p_group->remote_hca_or_sw.remote_sw; + + /* skip if target lid has been already set on remote switch fwd tbl */ + if (__osm_ftree_sw_get_fwd_table_block( + p_remote_sw,cl_ntoh16(target_lid)) != OSM_NO_PATH) + continue; + + if (p_sw->rank == (__osm_ftree_fabric_get_rank(p_ftree) - 1)) + { + osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG, + "__osm_ftree_fabric_route_downgoing_by_going_up: " + " - Routing SECONDARY path for LID 0x%x: %s --> %s\n", + cl_ntoh16(target_lid), + __osm_ftree_tuple_to_str(p_sw->tuple), + __osm_ftree_tuple_to_str(p_remote_sw->tuple)); + } + + cl_ptr_vector_at(&p_group->ports, 0, (void **)&p_port); + __osm_ftree_sw_set_fwd_table_block(p_remote_sw, + cl_ntoh16(target_lid), + p_port->remote_port_num); + + /* On the remote switch that is pointed by the p_group, + set hops for ALL the ports in the remote group. */ + + ports_num = (uint16_t)cl_ptr_vector_get_size(&p_group->ports); + for (j = 0; j < ports_num; j++) + { + cl_ptr_vector_at(&p_group->ports, j, (void **)&p_port); + + __osm_ftree_sw_set_hops(p_remote_sw, + p_ftree->lft_max_lid_ho, + cl_ntoh16(target_lid), + p_port->remote_port_num, + target_rank - p_remote_sw->rank); + } + + /* Recursion step: + Assign downgoing ports by stepping up, starting on REMOTE switch. */ + __osm_ftree_fabric_route_downgoing_by_going_up( + p_ftree, + p_remote_sw, /* remote switch - used as a route-downgoing alg. next step point */ + p_sw, /* this switch - prev. position switch for the function */ + target_lid, /* LID that we're routing to */ + target_rank, /* rank of the LID that we're routing to */ + TRUE, /* whether the target LID is real or dummy */ + FALSE); /* whether this is path to HCA that should by tracked by counters */ + } + +} /* ftree_fabric_route_downgoing_by_going_up() */ + +/***************************************************/ + +/* + * Pseudo code: + * foreach leaf switch (in indexing order) + * for each compute node (in indexing order) + * obtain the LID of the compute node + * set local LFT(LID) of the port connecting to compute node + * call assign-down-going-port-by-descending-up(TRUE,TRUE) on CURRENT switch + * for each MISSING compute node + * call assign-down-going-port-by-descending-up(FALSE,TRUE) on CURRENT switch + */ + +static void +__osm_ftree_fabric_route_to_hcas( + IN ftree_fabric_t * p_ftree) +{ + ftree_sw_t * p_sw; + ftree_port_group_t * p_group; + ftree_port_t * p_port; + uint32_t i; + uint32_t j; + ib_net16_t remote_lid; + + OSM_LOG_ENTER(&p_ftree->p_osm->log, __osm_ftree_fabric_route_to_hcas); + + /* for each leaf switch (in indexing order) */ + for(i = 0; i < p_ftree->leaf_switches_num; i++) + { + p_sw = p_ftree->leaf_switches[i]; + + /* for each HCA connected to this switch */ + for (j = 0; j < p_sw->down_port_groups_num; j++) + { + /* obtain the LID of HCA port */ + p_group = p_sw->down_port_groups[j]; + remote_lid = p_group->remote_base_lid; + + /* set local LFT(LID) to the port that is connected to HCA */ + cl_ptr_vector_at(&p_group->ports, 0, (void **)&p_port); + __osm_ftree_sw_set_fwd_table_block(p_sw, + cl_ntoh16(remote_lid), + p_port->port_num); + osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG, + "__osm_ftree_fabric_route_to_hcas: " + "Switch %s: set path to HCA LID 0x%x through port %u\n", + __osm_ftree_tuple_to_str(p_sw->tuple), + cl_ntoh16(remote_lid), + p_port->port_num); + + /* set local min hop table(LID) to route to the CA */ + __osm_ftree_sw_set_hops(p_sw, + p_ftree->lft_max_lid_ho, + cl_ntoh16(remote_lid), + p_port->port_num, + 1); + + /* assign downgoing ports by stepping up */ + __osm_ftree_fabric_route_downgoing_by_going_up( + p_ftree, + p_sw, /* local switch - used as a route-downgoing alg. start point */ + NULL, /* prev. position switch */ + remote_lid, /* LID that we're routing to */ + __osm_ftree_fabric_get_rank(p_ftree), /* rank of the LID that we're routing to */ + TRUE, /* whether this HCA LID is real or dummy */ + TRUE); /* whether this path to HCA should by tracked by counters */ + } + + /* We're done with the real HCAs. Now route the dummy HCAs that are missing. + When routing to dummy HCAs we don't fill lid matrices. */ + + if (p_ftree->max_hcas_per_leaf > p_sw->down_port_groups_num) + { + osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG,"__osm_ftree_fabric_route_to_hcas: " + "Routing %u dummy HCAs\n", + p_ftree->max_hcas_per_leaf - p_sw->down_port_groups_num); + for ( j = 0; + ((int)j) < (p_ftree->max_hcas_per_leaf - p_sw->down_port_groups_num); + j++) + { + /* assign downgoing ports by stepping up */ + __osm_ftree_fabric_route_downgoing_by_going_up( + p_ftree, + p_sw, /* local switch - used as a route-downgoing alg. start point */ + NULL, /* prev. position switch */ + 0, /* LID that we're routing to - ignored for dummy HCA */ + 0, /* rank of the LID that we're routing to - ignored for dummy HCA */ + FALSE, /* whether this HCA LID is real or dummy */ + TRUE); /* whether this path to HCA should by tracked by counters */ + } + } + } + /* done going through all the leaf switches */ + OSM_LOG_EXIT(&p_ftree->p_osm->log); +} /* __osm_ftree_fabric_route_to_hcas() */ + +/***************************************************/ + +/* + * Pseudo code: + * foreach switch in fabric + * obtain its LID + * set local LFT(LID) to port 0 + * call assign-down-going-port-by-descending-up(TRUE,FALSE) on CURRENT switch + * + * Routing to switch is similar to routing a REAL hca lid on SECONDARY path: + * - we should set fwd tables + * - we should NOT update port counters + */ + +static void +__osm_ftree_fabric_route_to_switches( + IN ftree_fabric_t * p_ftree) +{ + ftree_sw_t * p_sw; + ftree_sw_t * p_next_sw; + + OSM_LOG_ENTER(&p_ftree->p_osm->log, __osm_ftree_fabric_route_to_switches); + + p_next_sw = (ftree_sw_t *)cl_qmap_head(&p_ftree->sw_tbl); + while( p_next_sw != (ftree_sw_t *)cl_qmap_end(&p_ftree->sw_tbl) ) + { + p_sw = p_next_sw; + p_next_sw = (ftree_sw_t *)cl_qmap_next(&p_sw->map_item ); + + /* set local LFT(LID) to 0 (route to itself) */ + __osm_ftree_sw_set_fwd_table_block(p_sw, + cl_ntoh16(p_sw->base_lid), + 0); + + osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG, + "__osm_ftree_fabric_route_to_switches: " + "Switch %s (LID 0x%x): routing switch-to-switch pathes\n", + __osm_ftree_tuple_to_str(p_sw->tuple), + cl_ntoh16(p_sw->base_lid)); + + /* set min hop table of the switch to itself */ + __osm_ftree_sw_set_hops(p_sw, + p_ftree->lft_max_lid_ho, + cl_ntoh16(p_sw->base_lid), + 0, /* port_num */ + 0);/* hops */ + + __osm_ftree_fabric_route_downgoing_by_going_up( + p_ftree, + p_sw, /* local switch - used as a route-downgoing alg. start point */ + NULL, /* prev. position switch */ + p_sw->base_lid, /* LID that we're routing to */ + p_sw->rank, /* rank of the LID that we're routing to */ + TRUE, /* whether the target LID is a real or dummy */ + FALSE); /* whether this path should by tracked by counters */ + } + + OSM_LOG_EXIT(&p_ftree->p_osm->log); +} /* __osm_ftree_fabric_route_to_switches() */ + +/*************************************************** + ***************************************************/ + +static int +__osm_ftree_fabric_populate_switches( + IN ftree_fabric_t * p_ftree) +{ + osm_switch_t * p_osm_sw; + osm_switch_t * p_next_osm_sw; + + OSM_LOG_ENTER(&p_ftree->p_osm->log, __osm_ftree_fabric_populate_switches); + + p_next_osm_sw = (osm_switch_t *)cl_qmap_head(&p_ftree->p_osm->subn.sw_guid_tbl); + while( p_next_osm_sw != (osm_switch_t *)cl_qmap_end(&p_ftree->p_osm->subn.sw_guid_tbl) ) + { + p_osm_sw = p_next_osm_sw; + p_next_osm_sw = (osm_switch_t *)cl_qmap_next(&p_osm_sw->map_item ); + __osm_ftree_fabric_add_sw(p_ftree,p_osm_sw); + } + OSM_LOG_EXIT(&p_ftree->p_osm->log); + return 0; +} /* __osm_ftree_fabric_populate_switches() */ + +/*************************************************** + ***************************************************/ + +static int +__osm_ftree_fabric_populate_hcas( + IN ftree_fabric_t * p_ftree) +{ + osm_node_t * p_osm_node; + osm_node_t * p_next_osm_node; + + OSM_LOG_ENTER(&p_ftree->p_osm->log, __osm_ftree_fabric_populate_hcas); + + p_next_osm_node = (osm_node_t *)cl_qmap_head(&p_ftree->p_osm->subn.node_guid_tbl); + while( p_next_osm_node != (osm_node_t *)cl_qmap_end(&p_ftree->p_osm->subn.node_guid_tbl) ) + { + p_osm_node = p_next_osm_node; + p_next_osm_node = (osm_node_t *)cl_qmap_next(&p_osm_node->map_item); + switch (osm_node_get_type(p_osm_node)) + { + case IB_NODE_TYPE_CA: + __osm_ftree_fabric_add_hca(p_ftree,p_osm_node); + break; + case IB_NODE_TYPE_ROUTER: + break; + case IB_NODE_TYPE_SWITCH: + /* all the switches added separately */ + break; + default: + osm_log(&p_ftree->p_osm->log, OSM_LOG_ERROR, + "__osm_ftree_fabric_populate_hcas: ERR AB0E: " + "Node GUID 0x%016" PRIx64 " - Unknown node type: %s\n", + cl_ntoh64(osm_node_get_node_guid(p_osm_node)), + ib_get_node_type_str(osm_node_get_type(p_osm_node))); + OSM_LOG_EXIT(&p_ftree->p_osm->log); + return -1; + } + } + + OSM_LOG_EXIT(&p_ftree->p_osm->log); + return 0; +} /* __osm_ftree_fabric_populate_hcas() */ + +/*************************************************** + ***************************************************/ + +static void +__osm_ftree_rank_from_switch( + IN ftree_fabric_t * p_ftree, + IN ftree_sw_t * p_starting_sw) +{ + ftree_sw_t * p_sw; + ftree_sw_t * p_remote_sw; + osm_node_t * p_node; + osm_node_t * p_remote_node; + osm_physp_t * p_osm_port; + uint8_t i; + cl_list_t bfs_list; + ftree_sw_tbl_element_t * p_sw_tbl_element = NULL; + + p_starting_sw->rank = 0; + + /* Run BFS scan of the tree, starting from this switch */ + + cl_list_init(&bfs_list, cl_qmap_count(&p_ftree->sw_tbl)); + cl_list_insert_tail(&bfs_list, &__osm_ftree_sw_tbl_element_create(p_starting_sw)->map_item); + + while (!cl_is_list_empty(&bfs_list)) + { + p_sw_tbl_element = (ftree_sw_tbl_element_t *)cl_list_remove_head(&bfs_list); + p_sw = p_sw_tbl_element->p_sw; + __osm_ftree_sw_tbl_element_destroy(p_sw_tbl_element); + + p_node = osm_switch_get_node_ptr(p_sw->p_osm_sw); + + /* note: skipping port 0 on switches */ + for (i = 1; i < osm_node_get_num_physp(p_node); i++) + { + p_osm_port = osm_node_get_physp_ptr(p_node,i); + if (!osm_physp_is_valid(p_osm_port)) + continue; + if (!osm_link_is_healthy(p_osm_port)) + continue; + + p_remote_node = osm_node_get_remote_node(p_node,i,NULL); + if (!p_remote_node) + continue; + if (osm_node_get_type(p_remote_node) != IB_NODE_TYPE_SWITCH) + continue; + + p_remote_sw = (ftree_sw_t *)cl_qmap_get(&p_ftree->sw_tbl, + osm_node_get_node_guid(p_remote_node)); + if (p_remote_sw == (ftree_sw_t *)cl_qmap_end(&p_ftree->sw_tbl)) + { + /* remote node is not a switch */ + continue; + } + if (__osm_ftree_sw_ranked(p_remote_sw) && p_remote_sw->rank <= (p_sw->rank + 1)) + continue; + + /* rank the remote switch and add it to the BFS list */ + p_remote_sw->rank = p_sw->rank + 1; + cl_list_insert_tail(&bfs_list, + &__osm_ftree_sw_tbl_element_create(p_remote_sw)->map_item); + } + } +} /* __osm_ftree_rank_from_switch() */ + + +/*************************************************** + ***************************************************/ + +static int +__osm_ftree_rank_switches_from_hca( + IN ftree_fabric_t * p_ftree, + IN ftree_hca_t * p_hca) +{ + ftree_sw_t * p_sw; + osm_node_t * p_osm_node = p_hca->p_osm_node; + osm_node_t * p_remote_osm_node; + osm_physp_t * p_osm_port; + static uint8_t i = 0; + int res = 0; + + OSM_LOG_ENTER(&p_ftree->p_osm->log, __osm_ftree_rank_switches_from_hca); + + for (i = 0; i < osm_node_get_num_physp(p_osm_node); i++) + { + p_osm_port = osm_node_get_physp_ptr(p_osm_node,i); + if (!osm_physp_is_valid(p_osm_port)) + continue; + if (!osm_link_is_healthy(p_osm_port)) + continue; + + p_remote_osm_node = osm_node_get_remote_node(p_osm_node,i,NULL); + + switch (osm_node_get_type(p_remote_osm_node)) + { + case IB_NODE_TYPE_CA: + /* HCA connected directly to another HCA - not FatTree */ + osm_log(&p_ftree->p_osm->log, OSM_LOG_ERROR, + "__osm_ftree_rank_switches_from_hca: ERR AB0F: " + "HCA conected directly to another HCA: " + "0x%016" PRIx64 " <---> 0x%016" PRIx64 "\n", + cl_ntoh64(osm_node_get_node_guid(p_hca->p_osm_node)), + cl_ntoh64(osm_node_get_node_guid(p_remote_osm_node))); + res = -1; + goto Exit; + + case IB_NODE_TYPE_ROUTER: + /* leaving this port - proceeding to the next one */ + continue; + + case IB_NODE_TYPE_SWITCH: + /* continue with this port */ + break; + + default: + osm_log(&p_ftree->p_osm->log, OSM_LOG_ERROR, + "__osm_ftree_rank_switches_from_hca: ERR AB10: " + "Node GUID 0x%016" PRIx64 " - Unknown node type: %s\n", + cl_ntoh64(osm_node_get_node_guid(p_remote_osm_node)), + ib_get_node_type_str(osm_node_get_type(p_remote_osm_node))); + res = -1; + goto Exit; + } + + /* remote node is switch */ + + p_sw = (ftree_sw_t *)cl_qmap_get(&p_ftree->sw_tbl, + p_osm_port->p_remote_physp->p_node->node_info.node_guid); + + CL_ASSERT(p_sw != (ftree_sw_t *)cl_qmap_end(&p_ftree->sw_tbl)); + + if (__osm_ftree_sw_ranked(p_sw) && p_sw->rank == 0) + continue; + + osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG, + "__osm_ftree_rank_switches_from_hca: " + "Marking rank of switch that is directly connected to HCA:\n" + " - HCA guid : 0x%016" PRIx64 "\n" + " - Switch guid: 0x%016" PRIx64 "\n" + " - Switch LID : 0x%x\n", + cl_ntoh64(osm_node_get_node_guid(p_hca->p_osm_node)), + cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(p_sw->p_osm_sw))), + cl_ntoh16(p_sw->base_lid)); + __osm_ftree_rank_from_switch(p_ftree, p_sw); + } + + Exit: + OSM_LOG_EXIT(&p_ftree->p_osm->log); + return res; +} /* __osm_ftree_rank_switches_from_hca() */ + +/***************************************************/ + +static void +__osm_ftree_sw_reverse_rank( + IN cl_map_item_t* const p_map_item, + IN void *context) +{ + ftree_fabric_t * p_ftree = (ftree_fabric_t *)context; + ftree_sw_t * p_sw = (ftree_sw_t * const) p_map_item; + p_sw->rank = __osm_ftree_fabric_get_rank(p_ftree) - p_sw->rank - 1; +} + +/*************************************************** + ***************************************************/ + +static int +__osm_ftree_fabric_construct_hca_ports( + IN ftree_fabric_t * p_ftree, + IN ftree_hca_t * p_hca) +{ + ftree_sw_t * p_remote_sw; + osm_node_t * p_node = p_hca->p_osm_node; + osm_node_t * p_remote_node; + uint8_t remote_node_type; + ib_net64_t remote_node_guid; + osm_physp_t * p_remote_osm_port; + uint8_t i; + uint8_t remote_port_num; + int res = 0; + + for (i = 0; i < osm_node_get_num_physp(p_node); i++) + { + osm_physp_t * p_osm_port = osm_node_get_physp_ptr(p_node,i); + + if (!osm_physp_is_valid(p_osm_port)) + continue; + if (!osm_link_is_healthy(p_osm_port)) + continue; + + p_remote_osm_port = osm_physp_get_remote(p_osm_port); + p_remote_node = osm_node_get_remote_node(p_node,i,&remote_port_num); + + if (!p_remote_osm_port) + continue; + + remote_node_type = osm_node_get_type(p_remote_node); + remote_node_guid = osm_node_get_node_guid(p_remote_node); + + switch (remote_node_type) + { + case IB_NODE_TYPE_ROUTER: + /* leaving this port - proceeding to the next one */ + continue; + + case IB_NODE_TYPE_CA: + /* HCA connected directly to another HCA - not FatTree */ + osm_log(&p_ftree->p_osm->log, OSM_LOG_ERROR, + "__osm_ftree_fabric_construct_hca_ports: ERR AB11: " + "HCA conected directly to another HCA: " + "0x%016" PRIx64 " <---> 0x%016" PRIx64 "\n", + cl_ntoh64(osm_node_get_node_guid(p_node)), + cl_ntoh64(remote_node_guid)); + res = -1; + goto Exit; + + case IB_NODE_TYPE_SWITCH: + /* continue with this port */ + break; + + default: + osm_log(&p_ftree->p_osm->log, OSM_LOG_ERROR, + "__osm_ftree_fabric_construct_hca_ports: ERR AB12: " + "Node GUID 0x%016" PRIx64 " - Unknown node type: %s\n", + cl_ntoh64(remote_node_guid), + ib_get_node_type_str(remote_node_type)); + res = -1; + goto Exit; + } + + /* remote node is switch */ + + p_remote_sw = (ftree_sw_t *)cl_qmap_get(&p_ftree->sw_tbl,remote_node_guid); + CL_ASSERT( p_remote_sw != (ftree_sw_t *)cl_qmap_end(&p_ftree->sw_tbl) ); + CL_ASSERT( (p_remote_sw->rank + 1) == __osm_ftree_fabric_get_rank(p_ftree) ); + + __osm_ftree_hca_add_port( + p_hca, /* local ftree_hca object */ + i, /* local port number */ + remote_port_num, /* remote port number */ + osm_node_get_base_lid(p_node, i), /* local lid */ + osm_node_get_base_lid(p_remote_node, 0), /* remote lid */ + osm_physp_get_port_guid(p_osm_port), /* local port guid */ + osm_physp_get_port_guid(p_remote_osm_port),/* remote port guid */ + remote_node_guid, /* remote node guid */ + remote_node_type, /* remote node type */ + (void *) p_remote_sw); /* remote ftree_hca/sw object */ + } + + Exit: + return res; +} /* __osm_ftree_fabric_construct_hca_ports() */ + +/*************************************************** + ***************************************************/ + +static int +__osm_ftree_fabric_construct_sw_ports( + IN ftree_fabric_t * p_ftree, + IN ftree_sw_t * p_sw) +{ + ftree_hca_t * p_remote_hca; + ftree_sw_t * p_remote_sw; + osm_node_t * p_node = osm_switch_get_node_ptr(p_sw->p_osm_sw); + osm_node_t * p_remote_node; + ib_net16_t remote_base_lid; + uint8_t remote_node_type; + ib_net64_t remote_node_guid; + osm_physp_t * p_remote_osm_port; + ftree_direction_t direction; + void * p_remote_hca_or_sw; + uint8_t i; + uint8_t remote_port_num; + int res = 0; + + CL_ASSERT(osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH); + + for (i = 0; i < osm_node_get_num_physp(p_node); i++) + { + osm_physp_t * p_osm_port = osm_node_get_physp_ptr(p_node,i); + + if (!osm_physp_is_valid(p_osm_port)) + continue; + if (!osm_link_is_healthy(p_osm_port)) + continue; + + p_remote_osm_port = osm_physp_get_remote(p_osm_port); + p_remote_node = osm_node_get_remote_node(p_node,i,&remote_port_num); + + if (!p_remote_osm_port) + continue; + + remote_node_type = osm_node_get_type(p_remote_node); + remote_node_guid = osm_node_get_node_guid(p_remote_node); + + switch (remote_node_type) + { + case IB_NODE_TYPE_ROUTER: + /* leaving this port - proceeding to the next one */ + continue; + + case IB_NODE_TYPE_CA: + /* switch connected to hca */ + + CL_ASSERT((p_sw->rank + 1) == __osm_ftree_fabric_get_rank(p_ftree)); + + p_remote_hca = (ftree_hca_t *)cl_qmap_get(&p_ftree->hca_tbl,remote_node_guid); + CL_ASSERT(p_remote_hca != (ftree_hca_t *)cl_qmap_end(&p_ftree->hca_tbl)); + + p_remote_hca_or_sw = (void *)p_remote_hca; + direction = FTREE_DIRECTION_DOWN; + + remote_base_lid = osm_physp_get_base_lid(p_remote_osm_port); + break; + + case IB_NODE_TYPE_SWITCH: + /* switch connected to another switch */ + + p_remote_sw = (ftree_sw_t *)cl_qmap_get(&p_ftree->sw_tbl,remote_node_guid); + CL_ASSERT(p_remote_sw != (ftree_sw_t *)cl_qmap_end(&p_ftree->sw_tbl)); + p_remote_hca_or_sw = (void *)p_remote_sw; + + if (abs(p_sw->rank - p_remote_sw->rank) != 1) + { + osm_log(&p_ftree->p_osm->log, OSM_LOG_ERROR, + "__osm_ftree_fabric_construct_sw_ports: ERR AB16: " + "Illegal link between switches with ranks %u and %u:\n" + " GUID 0x%016" PRIx64 ", LID 0x%x, rank %u\n" + " GUID 0x%016" PRIx64 ", LID 0x%x, rank %u\n", + p_sw->rank, + p_remote_sw->rank, + cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(p_sw->p_osm_sw))), + cl_ntoh16(p_sw->base_lid), + p_sw->rank, + cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(p_remote_sw->p_osm_sw))), + cl_ntoh16(p_remote_sw->base_lid), + p_remote_sw->rank); + res = -1; + goto Exit; + } + + if (p_sw->rank > p_remote_sw->rank) + direction = FTREE_DIRECTION_UP; + else + direction = FTREE_DIRECTION_DOWN; + + /* switch LID is only in port 0 port_info structure */ + remote_base_lid = osm_node_get_base_lid(p_remote_node, 0); + + break; + + default: + osm_log(&p_ftree->p_osm->log, OSM_LOG_ERROR, + "__osm_ftree_fabric_construct_sw_ports: ERR AB13: " + "Node GUID 0x%016" PRIx64 " - Unknown node type: %s\n", + cl_ntoh64(remote_node_guid), + ib_get_node_type_str(remote_node_type)); + res = -1; + goto Exit; + } + __osm_ftree_sw_add_port( + p_sw, /* local ftree_sw object */ + i, /* local port number */ + remote_port_num, /* remote port number */ + p_sw->base_lid, /* local lid */ + remote_base_lid, /* remote lid */ + osm_physp_get_port_guid(p_osm_port), /* local port guid */ + osm_physp_get_port_guid(p_remote_osm_port), /* remote port guid */ + remote_node_guid, /* remote node guid */ + remote_node_type, /* remote node type */ + p_remote_hca_or_sw, /* remote ftree_hca/sw object */ + direction); /* port direction (up or down) */ + + /* Track the max lid (in host order) that exists in the fabric */ + if (cl_ntoh16(remote_base_lid) > p_ftree->lft_max_lid_ho) + p_ftree->lft_max_lid_ho = cl_ntoh16(remote_base_lid); + } + + Exit: + return res; +} /* __osm_ftree_fabric_construct_sw_ports() */ + +/*************************************************** + ***************************************************/ + +/* ToDo: improve ranking algorithm complexity + by propogating BFS from more nodes */ +static int +__osm_ftree_fabric_perform_ranking( + IN ftree_fabric_t * p_ftree) +{ + ftree_hca_t * p_hca; + ftree_hca_t * p_next_hca; + int res = 0; + + OSM_LOG_ENTER(&p_ftree->p_osm->log, __osm_ftree_fabric_perform_ranking); + + /* Mark REVERSED rank of all the switches in the subnet. + Start from switches that are connected to hca's, and + scan all the switches in the subnet. */ + p_next_hca = (ftree_hca_t *)cl_qmap_head(&p_ftree->hca_tbl); + while( p_next_hca != (ftree_hca_t *)cl_qmap_end( &p_ftree->hca_tbl ) ) + { + p_hca = p_next_hca; + p_next_hca = (ftree_hca_t *)cl_qmap_next(&p_hca->map_item ); + if (__osm_ftree_rank_switches_from_hca(p_ftree,p_hca) != 0) + { + res = -1; + osm_log(&p_ftree->p_osm->log, OSM_LOG_ERROR, + "__osm_ftree_fabric_perform_ranking: ERR AB14: " + "Subnet ranking failed - subnet is not FatTree"); + goto Exit; + } + } + + /* calculate and set FatTree rank */ + __osm_ftree_fabric_calculate_rank(p_ftree); + osm_log(&p_ftree->p_osm->log, OSM_LOG_INFO, + "__osm_ftree_fabric_perform_ranking: " + "FatTree rank is %u\n", __osm_ftree_fabric_get_rank(p_ftree)); + + /* fix ranking of the switches by reversing the ranking direction */ + cl_qmap_apply_func(&p_ftree->sw_tbl, __osm_ftree_sw_reverse_rank, (void *)p_ftree); + + if ( __osm_ftree_fabric_get_rank(p_ftree) > FAT_TREE_MAX_RANK || + __osm_ftree_fabric_get_rank(p_ftree) < FAT_TREE_MIN_RANK ) + { + osm_log(&p_ftree->p_osm->log, OSM_LOG_ERROR, + "__osm_ftree_fabric_perform_ranking: ERR AB15: " + "Tree rank is %u (should be between %u and %u)\n", + __osm_ftree_fabric_get_rank(p_ftree), + FAT_TREE_MIN_RANK, + FAT_TREE_MAX_RANK); + res = -1; + goto Exit; + } + + Exit: + OSM_LOG_EXIT(&p_ftree->p_osm->log); + return res; +} /* __osm_ftree_fabric_perform_ranking() */ + +/*************************************************** + ***************************************************/ + +static int +__osm_ftree_fabric_populate_ports( + IN ftree_fabric_t * p_ftree) +{ + ftree_hca_t * p_hca; + ftree_hca_t * p_next_hca; + ftree_sw_t * p_sw; + ftree_sw_t * p_next_sw; + int res = 0; + + OSM_LOG_ENTER(&p_ftree->p_osm->log, __osm_ftree_fabric_populate_ports); + + p_next_hca = (ftree_hca_t *)cl_qmap_head(&p_ftree->hca_tbl); + while( p_next_hca != (ftree_hca_t *)cl_qmap_end( &p_ftree->hca_tbl ) ) + { + p_hca = p_next_hca; + p_next_hca = (ftree_hca_t *)cl_qmap_next(&p_hca->map_item ); + if (__osm_ftree_fabric_construct_hca_ports(p_ftree,p_hca) != 0) + { + res = -1; + goto Exit; + } + } + + p_next_sw = (ftree_sw_t *)cl_qmap_head(&p_ftree->sw_tbl); + while( p_next_sw != (ftree_sw_t *)cl_qmap_end( &p_ftree->sw_tbl ) ) + { + p_sw = p_next_sw; + p_next_sw = (ftree_sw_t *)cl_qmap_next(&p_sw->map_item ); + if (__osm_ftree_fabric_construct_sw_ports(p_ftree,p_sw) != 0) + { + res = -1; + goto Exit; + } + } + Exit: + OSM_LOG_EXIT(&p_ftree->p_osm->log); + return res; +} /* __osm_ftree_fabric_populate_ports() */ + +/*************************************************** + ***************************************************/ + +static int +__osm_ftree_construct_fabric( + IN void * context) +{ + ftree_fabric_t * p_ftree = context; + int status = 0; + + OSM_LOG_ENTER(&p_ftree->p_osm->log, __osm_ftree_construct_fabric); + + if (p_ftree->p_osm->subn.opt.lmc > 0) + { + osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS, + "LMC > 0 is not supported by fat-tree routing.\n" + "Falling back to default routing.\n"); + status = -1; + goto Exit; + } + + if ( cl_qmap_count(&p_ftree->p_osm->subn.sw_guid_tbl) < 2 ) + { + osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS, + "Fabric has %u switches - topology is not fat-tree.\n" + "Falling back to default routing.\n", + cl_qmap_count(&p_ftree->p_osm->subn.sw_guid_tbl)); + status = -1; + goto Exit; + } + + if ( (cl_qmap_count(&p_ftree->p_osm->subn.node_guid_tbl) - + cl_qmap_count(&p_ftree->p_osm->subn.sw_guid_tbl)) < 2) + { + osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS, + "Fabric has %u nodes (%u switches) - topology is not fat-tree.\n" + "Falling back to default routing.\n", + cl_qmap_count(&p_ftree->p_osm->subn.node_guid_tbl), + cl_qmap_count(&p_ftree->p_osm->subn.sw_guid_tbl)); + status = -1; + goto Exit; + } + + osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,"__osm_ftree_construct_fabric: \n" + " |----------------------------------------|\n" + " |- Starting FatTree fabric construction -|\n" + " |----------------------------------------|\n\n"); + + osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, + "__osm_ftree_construct_fabric: " + "Populating FatTree switch table\n"); + /* ToDo: now that the pointer from node to switch exists, + no need to fill the switch table in a separate loop */ + if (__osm_ftree_fabric_populate_switches(p_ftree) != 0) + { + osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS, + "Fabric topology is not fat-tree - " + "falling back to default routing\n"); + status = -1; + goto Exit; + } + + osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, + "__osm_ftree_construct_fabric: " + "Populating FatTree HCA table\n"); + if (__osm_ftree_fabric_populate_hcas(p_ftree) != 0) + { + osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS, + "Fabric topology is not fat-tree - " + "falling back to default routing\n"); + status = -1; + goto Exit; + } + + if (cl_qmap_count(&p_ftree->hca_tbl) < 2) + { + osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS, + "Fabric has %u HCAa - topology is not fat-tree.\n" + "Falling back to default routing.\n", + cl_qmap_count(&p_ftree->hca_tbl)); + status = -1; + goto Exit; + } + + osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, + "__osm_ftree_construct_fabric: Ranking FatTree\n"); + + if (__osm_ftree_fabric_perform_ranking(p_ftree) != 0) + { + if (__osm_ftree_fabric_get_rank(p_ftree) > FAT_TREE_MAX_RANK) + osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS, + "Fabric rank is %u (>%u) - " + "fat-tree routing falls back to default routing\n", + __osm_ftree_fabric_get_rank(p_ftree), FAT_TREE_MAX_RANK); + else if (__osm_ftree_fabric_get_rank(p_ftree) < FAT_TREE_MIN_RANK) + osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS, + "Fabric rank is %u (<%u) - " + "fat-tree routing falls back to default routing\n", + __osm_ftree_fabric_get_rank(p_ftree), FAT_TREE_MIN_RANK); + status = -1; + goto Exit; + } + + /* For each hca and switch, construct array of ports. + This is done after the whole FatTree data structure is ready, because + we want the ports to have pointers to ftree_{sw,hca}_t objects.*/ + osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, + "__osm_ftree_construct_fabric: " + "Populating HCA & switch ports\n"); + if (__osm_ftree_fabric_populate_ports(p_ftree) != 0) + { + osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS, + "Fabric topology is not a fat-tree - " + "routing falls back to default routing\n"); + status = -1; + goto Exit; + } + + /* Assign index to all the switches and hca's in the fabric. + This function also sorts all the port arrays of the switches + by the remote switch index, creates a leaf switch array + sorted by the switch index, and tracks the maximal number of + hcas per leaf switch. */ + __osm_ftree_fabric_make_indexing(p_ftree); + + /* print general info about fabric topology */ + __osm_ftree_fabric_dump_general_info(p_ftree); + + /* dump full tree topology */ + if (osm_log_is_active(&p_ftree->p_osm->log, OSM_LOG_DEBUG)) + __osm_ftree_fabric_dump(p_ftree); + + if (! __osm_ftree_fabric_validate_topology(p_ftree)) + { + osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS, + "Fabric topology is not a fat-tree - " + "routing falls back to default routing\n"); + status = -1; + goto Exit; + } + + osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, + "__osm_ftree_construct_fabric: " + "Max LID in switch LFTs (in host order): 0x%x\n", + p_ftree->lft_max_lid_ho); + + Exit: + if (status != 0) + { + osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, + "__osm_ftree_construct_fabric: " + "Clearing FatTree Fabric data structures\n"); + __osm_ftree_fabric_clear(p_ftree); + } + else + p_ftree->fabric_built = TRUE; + + osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, + "__osm_ftree_construct_fabric: \n" + " |--------------------------------------------------|\n" + " |- Done constructing FatTree fabric (status = %d) -|\n" + " |--------------------------------------------------|\n\n", + status); + + OSM_LOG_EXIT(&p_ftree->p_osm->log); + return status; +} /* __osm_ftree_construct_fabric() */ + +/*************************************************** + ***************************************************/ + +static int +__osm_ftree_do_routing( + IN void * context) +{ + ftree_fabric_t * p_ftree = context; + + OSM_LOG_ENTER(&p_ftree->p_osm->log, __osm_ftree_do_routing); + + if (!p_ftree->fabric_built) + goto Exit; + + osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,"__osm_ftree_do_routing: " + "Starting FatTree routing\n"); + + osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,"__osm_ftree_do_routing: " + "Filling switch forwarding tables for routes to HCAs\n"); + __osm_ftree_fabric_route_to_hcas(p_ftree); + + osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,"__osm_ftree_do_routing: " + "Filling switch forwarding tables for switch-to-switch pathes\n"); + __osm_ftree_fabric_route_to_switches(p_ftree); + + /* for each switch, set its fwd table */ + cl_qmap_apply_func(&p_ftree->sw_tbl, __osm_ftree_set_sw_fwd_table, (void *)p_ftree); + + /* write out hca ordering file */ + __osm_ftree_fabric_dump_hca_ordering(p_ftree); + + osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,"__osm_ftree_do_routing: " + "FatTree routing is done\n"); + + Exit: + OSM_LOG_EXIT(&p_ftree->p_osm->log); + return 0; +} + +/*************************************************** + ***************************************************/ + +static void +__osm_ftree_delete( + IN void * context) +{ + if (!context) + return; + __osm_ftree_fabric_destroy((ftree_fabric_t *)context); +} + +/*************************************************** + ***************************************************/ + +int osm_ucast_ftree_setup(osm_opensm_t * p_osm) +{ + ftree_fabric_t * p_ftree = __osm_ftree_fabric_create(); + if (!p_ftree) + return -1; + + p_ftree->p_osm = p_osm; + + p_osm->routing_engine.context = (void *)p_ftree; + p_osm->routing_engine.build_lid_matrices = __osm_ftree_construct_fabric; + p_osm->routing_engine.ucast_build_fwd_tables = __osm_ftree_do_routing; + p_osm->routing_engine.delete = __osm_ftree_delete; + return 0; +} + +/*************************************************** + ***************************************************/ + + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_ucast_mgr.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_ucast_mgr.c new file mode 100644 index 00000000..a1433a99 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_ucast_mgr.c @@ -0,0 +1,1277 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_ucast_mgr.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Implementation of osm_ucast_mgr_t. + * This file implements the Unicast Manager object. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.14 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LINE_LENGTH 256 + +/********************************************************************** + **********************************************************************/ +/* + * This flag is used for stopping the relaxation algorithm if no + * change detected during the fabric scan + */ +static boolean_t __some_hop_count_set; + +/********************************************************************** + **********************************************************************/ +void +osm_ucast_mgr_construct( + IN osm_ucast_mgr_t* const p_mgr ) +{ + memset( p_mgr, 0, sizeof(*p_mgr) ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_ucast_mgr_destroy( + IN osm_ucast_mgr_t* const p_mgr ) +{ + CL_ASSERT( p_mgr ); + + OSM_LOG_ENTER( p_mgr->p_log, osm_ucast_mgr_destroy ); + + if (p_mgr->lft_buf) + free(p_mgr->lft_buf); + + OSM_LOG_EXIT( p_mgr->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_ucast_mgr_init( + IN osm_ucast_mgr_t* const p_mgr, + IN osm_req_t* const p_req, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_ucast_mgr_init ); + + CL_ASSERT( p_req ); + CL_ASSERT( p_subn ); + CL_ASSERT( p_lock ); + + osm_ucast_mgr_construct( p_mgr ); + + p_mgr->p_log = p_log; + p_mgr->p_subn = p_subn; + p_mgr->p_lock = p_lock; + p_mgr->p_req = p_req; + + p_mgr->lft_buf = malloc(IB_LID_UCAST_END_HO + 1); + if (!p_mgr->lft_buf) + return IB_INSUFFICIENT_MEMORY; + + OSM_LOG_EXIT( p_mgr->p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +struct ucast_mgr_dump_context { + osm_ucast_mgr_t *p_mgr; + FILE *file; +}; + +static void +ucast_mgr_dump(osm_ucast_mgr_t *p_mgr, FILE *file, + void (*func)(cl_map_item_t *, void *)) +{ + struct ucast_mgr_dump_context dump_context; + + dump_context.p_mgr = p_mgr; + dump_context.file = file; + + cl_qmap_apply_func(&p_mgr->p_subn->sw_guid_tbl, func, &dump_context); +} + +void +ucast_mgr_dump_to_file(osm_ucast_mgr_t *p_mgr, const char *file_name, + void (*func)(cl_map_item_t *, void *)) +{ + char path[1024]; + FILE *file; + + snprintf(path, sizeof(path), "%s/%s", + p_mgr->p_subn->opt.dump_files_dir, file_name); + + file = fopen(path, "w"); + if (!file) { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "ucast_mgr_dump_to_file: ERR 3A12: " + "Failed to open fdb file (%s)\n", path ); + return; + } + + ucast_mgr_dump(p_mgr, file, func); + + fclose(file); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_ucast_mgr_dump_path_distribution( + IN cl_map_item_t *p_map_item, + IN void *cxt) +{ + osm_node_t *p_node; + osm_node_t *p_remote_node; + uint8_t i; + uint8_t num_ports; + uint32_t num_paths; + ib_net64_t remote_guid_ho; + osm_switch_t* p_sw = (osm_switch_t *)p_map_item; + osm_ucast_mgr_t* p_mgr = ((struct ucast_mgr_dump_context *)cxt)->p_mgr; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_ucast_mgr_dump_path_distribution ); + + p_node = osm_switch_get_node_ptr( p_sw ); + num_ports = osm_switch_get_num_ports( p_sw ); + + osm_log_printf( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_ucast_mgr_dump_path_distribution: " + "Switch 0x%" PRIx64 "\n" + "Port : Path Count Through Port", + cl_ntoh64( osm_node_get_node_guid( p_node ) ) ); + + for( i = 0; i < num_ports; i++ ) + { + num_paths = osm_switch_path_count_get( p_sw , i ); + osm_log_printf( p_mgr->p_log, OSM_LOG_DEBUG,"\n %03u : %u", i, num_paths ); + if( i == 0 ) + { + osm_log_printf( p_mgr->p_log, OSM_LOG_DEBUG, " (switch management port)" ); + continue; + } + + p_remote_node = osm_node_get_remote_node( p_node, i, NULL ); + if( p_remote_node == NULL ) + continue; + + remote_guid_ho = cl_ntoh64( osm_node_get_node_guid( p_remote_node ) ); + + switch( osm_node_get_remote_type( p_node, i ) ) + { + case IB_NODE_TYPE_SWITCH: + osm_log_printf( p_mgr->p_log, OSM_LOG_DEBUG, " (link to switch" ); + break; + case IB_NODE_TYPE_ROUTER: + osm_log_printf( p_mgr->p_log, OSM_LOG_DEBUG, " (link to router" ); + break; + case IB_NODE_TYPE_CA: + osm_log_printf( p_mgr->p_log, OSM_LOG_DEBUG, " (link to CA" ); + break; + default: + osm_log_printf( p_mgr->p_log, OSM_LOG_DEBUG, " (link to unknown node type" ); + break; + } + + osm_log_printf( p_mgr->p_log, OSM_LOG_DEBUG, " 0x%" PRIx64 ")", + remote_guid_ho ); + } + + osm_log_printf( p_mgr->p_log, OSM_LOG_DEBUG, "\n" ); + + OSM_LOG_EXIT( p_mgr->p_log ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_ucast_mgr_dump_ucast_routes( + IN cl_map_item_t *p_map_item, + IN void *cxt ) +{ + const osm_node_t* p_node; + uint8_t port_num; + uint8_t num_hops; + uint8_t best_hops; + uint8_t best_port; + uint16_t max_lid_ho; + uint16_t lid_ho; + osm_switch_t* p_sw = (osm_switch_t *)p_map_item; + osm_ucast_mgr_t* p_mgr = ((struct ucast_mgr_dump_context *)cxt)->p_mgr; + FILE *file = ((struct ucast_mgr_dump_context *)cxt)->file; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_ucast_mgr_dump_ucast_routes ); + + p_node = osm_switch_get_node_ptr( p_sw ); + + max_lid_ho = osm_switch_get_max_lid_ho( p_sw ); + + fprintf( file, "__osm_ucast_mgr_dump_ucast_routes: " + "Switch 0x%016" PRIx64 "\n" + "LID : Port : Hops : Optimal\n", + cl_ntoh64( osm_node_get_node_guid( p_node ) ) ); + for( lid_ho = 1; lid_ho <= max_lid_ho; lid_ho++ ) + { + fprintf(file, "0x%04X : ", lid_ho); + + port_num = osm_switch_get_port_by_lid( p_sw, lid_ho ); + if( port_num == OSM_NO_PATH ) + { + /* + This may occur if there are 'holes' in the existing + LID assignments. Running SM with --reassign_lids + will reassign and compress the LID range. The + subnet should work fine either way. + */ + fprintf( file, "UNREACHABLE\n" ); + continue; + } + /* + Switches can lie about which port routes a given + lid due to a recent reconfiguration of the subnet. + Therefore, ensure that the hop count is better than + OSM_NO_PATH. + */ + num_hops = osm_switch_get_hop_count( p_sw, lid_ho, port_num ); + if( num_hops == OSM_NO_PATH ) + { + fprintf( file, "UNREACHABLE\n" ); + continue; + } + + best_hops = osm_switch_get_least_hops( p_sw, lid_ho ); + fprintf( file, "%03u : %02u : ", port_num, num_hops ); + + if( best_hops == num_hops ) + fprintf( file, "yes" ); + else + { + best_port = osm_switch_recommend_path( + p_sw, lid_ho, TRUE, + NULL, NULL, NULL, NULL ); /* No LMC Optimization */ + fprintf( file, "No %u hop path possible via port %u!", + best_hops, best_port ); + } + + fprintf( file, "\n" ); + } + + OSM_LOG_EXIT( p_mgr->p_log ); +} + +/********************************************************************** + **********************************************************************/ +static void +ucast_mgr_dump_lid_matrix(cl_map_item_t *p_map_item, void *cxt) +{ + osm_switch_t* p_sw = (osm_switch_t *)p_map_item; + osm_ucast_mgr_t* p_mgr = ((struct ucast_mgr_dump_context *)cxt)->p_mgr; + FILE *file = ((struct ucast_mgr_dump_context *)cxt)->file; + osm_node_t *p_node = osm_switch_get_node_ptr(p_sw); + unsigned max_lid = osm_switch_get_max_lid_ho(p_sw); + unsigned max_port = osm_switch_get_num_ports(p_sw); + uint16_t lid; + uint8_t port; + + fprintf(file, "Switch: guid 0x%016" PRIx64 "\n", + cl_ntoh64(osm_node_get_node_guid(p_node))); + for (lid = 1; lid <= max_lid; lid++) { + osm_port_t *p_port; + + fprintf(file, "0x%04x:", lid); + for (port = 0 ; port < max_port ; port++) + fprintf(file, " %02x", + osm_switch_get_hop_count(p_sw, lid, port)); + p_port = cl_ptr_vector_get(&p_mgr->p_subn->port_lid_tbl, lid); + if (p_port) + fprintf(file, " # portguid 0x%" PRIx64, + cl_ntoh64(osm_port_get_guid(p_port))); + fprintf(file, "\n"); + } +} + +/********************************************************************** + **********************************************************************/ +void +ucast_mgr_dump_lfts(cl_map_item_t *p_map_item, void *cxt) +{ + osm_switch_t* p_sw = (osm_switch_t *)p_map_item; + osm_ucast_mgr_t* p_mgr = ((struct ucast_mgr_dump_context *)cxt)->p_mgr; + FILE *file = ((struct ucast_mgr_dump_context *)cxt)->file; + osm_node_t *p_node = osm_switch_get_node_ptr(p_sw); + unsigned max_lid = osm_switch_get_max_lid_ho(p_sw); + unsigned max_port = osm_switch_get_num_ports(p_sw); + uint16_t lid; + uint8_t port; + char desc[IB_NODE_DESCRIPTION_SIZE + 1]; + + memcpy(desc, p_node->node_desc.description, IB_NODE_DESCRIPTION_SIZE); + desc[IB_NODE_DESCRIPTION_SIZE] = '\0'; + fprintf(file, "Unicast lids [0x0-0x%x] of switch Lid %u guid 0x%016" + PRIx64 " (\'%s\'):\n", + max_lid, osm_node_get_base_lid(p_node, 0), + cl_ntoh64(osm_node_get_node_guid(p_node)), desc); + for (lid = 0; lid <= max_lid; lid++) { + osm_port_t *p_port; + port = osm_switch_get_port_by_lid(p_sw, lid); + + if (port >= max_port) + continue; + + fprintf(file, "0x%04x %03u # ", lid, port); + + p_port = cl_ptr_vector_get(&p_mgr->p_subn->port_lid_tbl, lid); + if (p_port) { + p_node = osm_port_get_parent_node(p_port); + memcpy(desc, p_node->node_desc.description, + IB_NODE_DESCRIPTION_SIZE); + desc[IB_NODE_DESCRIPTION_SIZE] = '\0'; + fprintf(file, "%s portguid 0x016%" PRIx64 ": \'%s\'", + ib_get_node_type_str(osm_node_get_type(p_node)), + cl_ntoh64(osm_port_get_guid(p_port)), desc); + } + else + fprintf(file, "unknown node and type"); + fprintf(file, "\n"); + } + fprintf(file, "%u lids dumped\n", max_lid); +} + +/********************************************************************** + **********************************************************************/ +static void __osm_ucast_mgr_dump_tables(osm_ucast_mgr_t *p_mgr) +{ + ucast_mgr_dump_to_file(p_mgr, "opensm-lid-matrix.dump", + ucast_mgr_dump_lid_matrix); + ucast_mgr_dump_to_file(p_mgr, "opensm-lfts.dump", ucast_mgr_dump_lfts); + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) ) + ucast_mgr_dump(p_mgr, NULL, __osm_ucast_mgr_dump_path_distribution); + ucast_mgr_dump_to_file(p_mgr, "osm.fdbs", __osm_ucast_mgr_dump_ucast_routes); +} + +/********************************************************************** + Starting a rebuild, so notify the switch so it can clear tables, etc... +**********************************************************************/ +static void +__osm_ucast_mgr_clean_switch( + IN cl_map_item_t* const p_map_item, + IN void* context ) +{ + osm_switch_prepare_path_rebuild((osm_switch_t *)p_map_item); +} + +/********************************************************************** + Add each switch's own LID(s) to its LID matrix. +**********************************************************************/ +static void +__osm_ucast_mgr_process_hop_0( + IN cl_map_item_t* const p_map_item, + IN void* context ) +{ + osm_switch_t* const p_sw = (osm_switch_t*)p_map_item; + osm_ucast_mgr_t* const p_mgr = (osm_ucast_mgr_t*)context; + osm_node_t *p_node; + uint16_t lid_ho, base_lid_ho, max_lid_ho; + cl_status_t status; + uint8_t lmc; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_ucast_mgr_process_hop_0 ); + + p_node = p_sw->p_node; + + CL_ASSERT( p_node ); + CL_ASSERT( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH ); + + base_lid_ho = cl_ntoh16( osm_node_get_base_lid( p_node, 0 ) ); + if (osm_switch_sp0_is_lmc_capable( p_sw, p_mgr->p_subn )) + lmc = osm_node_get_lmc( p_node, 0 ); + else + lmc = 0; + max_lid_ho = (uint16_t)( base_lid_ho + (1 << lmc) - 1 ); + + for (lid_ho = base_lid_ho; lid_ho <= max_lid_ho; lid_ho++) + { + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_ucast_mgr_process_hop_0: " + "Processing switch GUID 0x%" PRIx64 ", LID 0x%X\n", + cl_ntoh64( osm_node_get_node_guid( p_node ) ), + lid_ho ); + } + + status = osm_switch_set_hops( p_sw, lid_ho, 0, 0 ); + if( status != CL_SUCCESS ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_ucast_mgr_process_hop_0: ERR 3A02: " + "Setting hop count failed (%s) for " + "switch GUID 0x%" PRIx64 ", LID 0x%X\n", + CL_STATUS_MSG( status ), + cl_ntoh64( osm_node_get_node_guid( p_node ) ), + lid_ho ); + } + } + + OSM_LOG_EXIT( p_mgr->p_log ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_ucast_mgr_process_neighbor( + IN osm_ucast_mgr_t* const p_mgr, + IN osm_switch_t* const p_sw, + IN osm_switch_t* const p_remote_sw, + IN const uint8_t port_num, + IN const uint8_t remote_port_num ) +{ + uint16_t lid_ho; + uint16_t max_lid_ho; + osm_node_t* p_node; + const osm_node_t* p_remote_node; + uint8_t hops; + cl_status_t status; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_ucast_mgr_process_neighbor ); + + CL_ASSERT( p_sw ); + CL_ASSERT( p_remote_sw ); + CL_ASSERT( port_num ); + CL_ASSERT( remote_port_num ); + + p_node = osm_switch_get_node_ptr( p_sw ); + p_remote_node = osm_switch_get_node_ptr( p_remote_sw ); + + CL_ASSERT( p_node ); + CL_ASSERT( p_remote_node ); + + CL_ASSERT( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH ); + CL_ASSERT( osm_node_get_type( p_remote_node ) == IB_NODE_TYPE_SWITCH ); + + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_ucast_mgr_process_neighbor: " + "Node 0x%" PRIx64 ", remote node 0x%" PRIx64 "\n" + "\t\t\t\tport 0x%X, remote port 0x%X\n", + cl_ntoh64( osm_node_get_node_guid( p_node ) ), + cl_ntoh64( osm_node_get_node_guid( p_remote_node ) ), + port_num, remote_port_num ); + } + + /* + Iterate through all the LIDs in the neighbor switch. + */ + max_lid_ho = osm_switch_get_max_lid_ho( p_remote_sw ); + + /* + Make sure the local lid matrix has enough room to hold + all the LID info coming from the remote LID matrix. + */ + osm_switch_set_min_lid_size( p_sw, max_lid_ho ); + + hops = OSM_NO_PATH; + for( lid_ho = 1; lid_ho <= max_lid_ho; lid_ho++ ) + { + /* + Find the lowest hop count value to this LID. + */ + hops = osm_switch_get_least_hops( p_remote_sw, lid_ho ); + + if( hops != OSM_NO_PATH ) + { + /* + Increment hop count of the neighbor by 1, since it + takes 1 hop to get to the neighbor. + */ + hops++; + + CL_ASSERT( hops <= osm_switch_get_hop_count( p_sw, lid_ho, + port_num ) ); + if( osm_switch_get_hop_count( p_sw, lid_ho, + port_num ) > hops ) + { + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_ucast_mgr_process_neighbor: " + "New best path is %u hops for LID 0x%X\n", + hops, lid_ho ); + } + + /* mark the fact we have got to change anything */ + __some_hop_count_set = TRUE; + + status = osm_switch_set_hops( p_sw, lid_ho, + port_num, hops ); + if( status != CL_SUCCESS ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_ucast_mgr_process_neighbor: ERR 3A03: " + "Setting hop count failed (%s)\n", + CL_STATUS_MSG( status ) ); + } + } + } + } + + OSM_LOG_EXIT( p_mgr->p_log ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_ucast_mgr_process_leaf( + IN osm_ucast_mgr_t* const p_mgr, + IN osm_switch_t* const p_sw, + IN osm_node_t* const p_node, + IN const uint8_t port_num, + IN osm_node_t* const p_remote_node, + IN const uint8_t remote_port_num ) +{ + uint16_t i; + uint16_t base_lid_ho; + uint16_t max_lid_ho; + uint8_t lmc; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_ucast_mgr_process_leaf ); + + CL_ASSERT( p_node ); + CL_ASSERT( p_remote_node ); + CL_ASSERT( port_num ); + CL_ASSERT( remote_port_num ); + + switch( osm_node_get_type( p_remote_node ) ) + { + case IB_NODE_TYPE_CA: + case IB_NODE_TYPE_ROUTER: + base_lid_ho = cl_ntoh16( osm_node_get_base_lid( + p_remote_node, remote_port_num ) ); + lmc = osm_node_get_lmc( p_remote_node, remote_port_num ); + break; +#if 0 + case IB_NODE_TYPE_SWITCH: + base_lid_ho = cl_ntoh16( osm_node_get_base_lid( + p_remote_node, 0 ) ); + lmc = 0; + break; +#endif + + default: + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_ucast_mgr_process_leaf: ERR 3A01: " + "Bad node type %u, GUID 0x%" PRIx64 "\n", + osm_node_get_type( p_remote_node ), + cl_ntoh64( osm_node_get_node_guid( p_node ) )); + goto Exit; + } + + max_lid_ho = (uint16_t)(base_lid_ho + (1 << lmc) - 1 ); + + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_ucast_mgr_process_leaf: " + "Discovered LIDs [0x%X,0x%X]\n" + "\t\t\t\tport number 0x%X, node 0x%" PRIx64 "\n", + base_lid_ho, max_lid_ho, + port_num, cl_ntoh64( osm_node_get_node_guid( p_node ) )); + } + + for( i = base_lid_ho; i <= max_lid_ho; i++ ) + osm_switch_set_hops( p_sw, i, port_num, 1 ); + + Exit: + OSM_LOG_EXIT( p_mgr->p_log ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_ucast_mgr_process_leaves( + IN cl_map_item_t* const p_map_item, + IN void* context ) +{ + osm_switch_t* const p_sw = (osm_switch_t*)p_map_item; + osm_ucast_mgr_t* const p_mgr = (osm_ucast_mgr_t*)context; + osm_node_t *p_node; + osm_node_t *p_remote_node; + uint32_t port_num; + uint8_t remote_port_num; + uint32_t num_ports; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_ucast_mgr_process_leaves ); + + p_node = p_sw->p_node; + + CL_ASSERT( p_node ); + CL_ASSERT( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH ); + + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_ucast_mgr_process_leaves: " + "Processing switch 0x%" PRIx64 "\n", + cl_ntoh64( osm_node_get_node_guid( p_node ) )); + } + + /* + Add the LIDs of all leaves of this switch to the LID matrix. + Don't bother processing loopback paths from one port of + this switch to the another port. + Don't process neighbor switches yet. + Start with port 1 to skip the switch's management port. + */ + num_ports = osm_node_get_num_physp( p_node ); + + for( port_num = 1; port_num < num_ports; port_num++ ) + { + p_remote_node = osm_node_get_remote_node( p_node, + (uint8_t)port_num, &remote_port_num ); + + if( p_remote_node && (p_remote_node != p_node ) + && (osm_node_get_type( p_remote_node ) != IB_NODE_TYPE_SWITCH ) ) + { + __osm_ucast_mgr_process_leaf( + p_mgr, + p_sw, + p_node, + (uint8_t)port_num, + p_remote_node, + remote_port_num ); + } + } + + OSM_LOG_EXIT( p_mgr->p_log ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_ucast_mgr_process_port( + IN osm_ucast_mgr_t* const p_mgr, + IN osm_switch_t* const p_sw, + IN const osm_port_t* const p_port ) +{ + uint16_t min_lid_ho; + uint16_t max_lid_ho; + uint16_t lid_ho; + uint8_t port; + boolean_t is_ignored_by_port_prof; + ib_net64_t node_guid; + /* + The following are temporary structures that will aid + in providing better routing in LMC > 0 situations + */ + uint16_t lids_per_port = 1 << p_mgr->p_subn->opt.lmc; + uint64_t *remote_sys_guids = NULL; + uint64_t *remote_node_guids = NULL; + uint16_t num_used_sys = 0; + uint16_t num_used_nodes = 0; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_ucast_mgr_process_port ); + + remote_sys_guids = malloc( sizeof(uint64_t) * lids_per_port ); + if( remote_sys_guids == NULL ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_ucast_mgr_process_port: ERR 3A09: " + "Cannot allocate array. Insufficient memory\n"); + goto Exit; + } + + memset( remote_sys_guids, 0, sizeof(uint64_t) * lids_per_port ); + + remote_node_guids = malloc( sizeof(uint64_t) * lids_per_port ); + if( remote_node_guids == NULL ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_ucast_mgr_process_port: ERR 3A0A: " + "Cannot allocate array. Insufficient memory\n"); + goto Exit; + } + + memset( remote_node_guids, 0, sizeof(uint64_t) * lids_per_port ); + + osm_port_get_lid_range_ho( p_port, &min_lid_ho, &max_lid_ho ); + + /* If the lids are zero - then there was some problem with the initialization. + Don't handle this port. */ + if ( min_lid_ho == 0 || max_lid_ho == 0 ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_ucast_mgr_process_port: ERR 3A04: " + "Port 0x%" PRIx64 " has LID 0. An initialization " + "error occurred. Ignoring port\n", + cl_ntoh64( osm_port_get_guid( p_port ) ) ); + goto Exit; + } + + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_ucast_mgr_process_port: " + "Processing port 0x%" PRIx64 + ", LIDs [0x%X,0x%X]\n", + cl_ntoh64( osm_port_get_guid( p_port ) ), + min_lid_ho, max_lid_ho ); + } + + /* + TO DO - This should be runtime error, not a CL_ASSERT() + */ + CL_ASSERT( max_lid_ho < osm_switch_get_fwd_tbl_size( p_sw ) ); + + node_guid = osm_node_get_node_guid(osm_switch_get_node_ptr( p_sw ) ); + + /* + The lid matrix contains the number of hops to each + lid from each port. From this information we determine + how best to distribute the LID range across the ports + that can reach those LIDs. + */ + for( lid_ho = min_lid_ho; lid_ho <= max_lid_ho; lid_ho++ ) + { + /* Use the enhanced algorithm only for LMC > 0 */ + if (lids_per_port > 1) + port = osm_switch_recommend_path( p_sw, lid_ho, + p_mgr->p_subn->ignore_existing_lfts, + remote_sys_guids, &num_used_sys, + remote_node_guids, &num_used_nodes ); + else + port = osm_switch_recommend_path( p_sw, lid_ho, + p_mgr->p_subn->ignore_existing_lfts, + NULL, NULL, NULL, NULL ); + + /* + There might be no path to the target + */ + if (port == OSM_NO_PATH) + { + /* do not try to overwrite the ppro of non existing port ... */ + is_ignored_by_port_prof = TRUE; + + /* Up/Down routing can cause unreachable routes between some + switches so we do not report that as an error in that case */ + if (!p_mgr->p_subn->p_osm->routing_engine.build_lid_matrices) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "__osm_ucast_mgr_process_port: ERR 3A08: " + "No path to get to LID 0x%X from switch 0x%" PRIx64 "\n", + lid_ho, cl_ntoh64( node_guid ) ); + /* trigger a new sweep - try again ... */ + p_mgr->p_subn->subnet_initialization_error = TRUE; + } + else + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_ucast_mgr_process_port: " + "No path to get to LID 0x%X from switch 0x%" PRIx64 "\n", + lid_ho, cl_ntoh64( node_guid ) ); + } + else + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_ucast_mgr_process_port: " + "Routing LID 0x%X to port 0x%X" + "\n\t\t\t\tFor switch 0x%" PRIx64 "\n", + lid_ho, port, cl_ntoh64( node_guid ) ); + + /* + we would like to optionally ignore this port in equalization + like in the case of the Mellanox Anafa Internal PCI TCA port + */ + is_ignored_by_port_prof = + osm_port_prof_is_ignored_port(p_mgr->p_subn, cl_ntoh64(node_guid), port); + + /* + We also would ignore this route if the target lid is of a switch + and the port_profile_switch_node is not TRUE + */ + if (! p_mgr->p_subn->opt.port_profile_switch_nodes) + { + is_ignored_by_port_prof |= + (osm_node_get_type(osm_port_get_parent_node(p_port)) == + IB_NODE_TYPE_SWITCH); + } + } + + /* + We have selected the port for this LID. + Write it to the forwarding tables. + */ + p_mgr->lft_buf[lid_ho] = port; + if (!is_ignored_by_port_prof) + osm_switch_count_path(p_sw, port); + } + + Exit: + if (remote_sys_guids) + free(remote_sys_guids); + if (remote_node_guids) + free(remote_node_guids); + OSM_LOG_EXIT( p_mgr->p_log ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_ucast_mgr_set_fwd_table( + IN osm_ucast_mgr_t* const p_mgr, + IN osm_switch_t* const p_sw ) +{ + osm_node_t *p_node; + osm_dr_path_t *p_path; + osm_madw_context_t context; + ib_api_status_t status; + ib_switch_info_t si; + uint32_t block_id_ho = 0; + uint8_t block[IB_SMP_DATA_SIZE]; + boolean_t set_swinfo_require = FALSE; + uint16_t lin_top; + uint8_t life_state; + + CL_ASSERT( p_mgr ); + + OSM_LOG_ENTER( p_mgr->p_log, osm_ucast_mgr_set_fwd_table ); + + CL_ASSERT( p_sw ); + + p_node = osm_switch_get_node_ptr( p_sw ); + + CL_ASSERT( p_node ); + + p_path = osm_node_get_any_dr_path_ptr( p_node ); + + CL_ASSERT( p_path ); + + /* + Set the top of the unicast forwarding table. + */ + si = *osm_switch_get_si_ptr( p_sw ); + lin_top = cl_hton16( osm_switch_get_max_lid_ho( p_sw ) ); + if (lin_top != si.lin_top) + { + set_swinfo_require = TRUE; + si.lin_top = lin_top; + } + + /* check to see if the change state bit is on. If it is - then we + need to clear it. */ + if ( ib_switch_info_get_state_change( &si ) ) + life_state = ( (p_mgr->p_subn->opt.packet_life_time <<3 ) + | ( si.life_state & IB_SWITCH_PSC ) ) & 0xfc; + else + life_state = (p_mgr->p_subn->opt.packet_life_time <<3 ) & 0xf8; + + if ( (life_state != si.life_state) || ib_switch_info_get_state_change( &si ) ) + { + set_swinfo_require = TRUE; + si.life_state = life_state; + } + + if ( set_swinfo_require ) + { + if ( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "osm_ucast_mgr_set_fwd_table: " + "Setting switch FT top to LID 0x%X\n", + osm_switch_get_max_lid_ho( p_sw ) ); + } + + context.si_context.light_sweep = FALSE; + context.si_context.node_guid = osm_node_get_node_guid( p_node ); + context.si_context.set_method = TRUE; + + status = osm_req_set( p_mgr->p_req, + p_path, + (uint8_t*)&si, + sizeof(si), + IB_MAD_ATTR_SWITCH_INFO, + 0, + CL_DISP_MSGID_NONE, + &context ); + + if( status != IB_SUCCESS ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "osm_ucast_mgr_set_fwd_table: ERR 3A06: " + "Sending SwitchInfo attribute failed (%s)\n", + ib_get_err_str( status ) ); + } + else + p_mgr->any_change = TRUE; + } + + /* + Send linear forwarding table blocks to the switch + as long as the switch indicates it has blocks needing + configuration. + */ + + context.lft_context.node_guid = osm_node_get_node_guid( p_node ); + context.lft_context.set_method = TRUE; + + for (block_id_ho = 0; + osm_switch_get_fwd_tbl_block( p_sw, block_id_ho, block ) ; + block_id_ho++ ) + { + if (!memcmp(block, p_mgr->lft_buf + block_id_ho * 64, 64)) + continue; + + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "osm_ucast_mgr_set_fwd_table: " + "Writing FT block %u\n", block_id_ho ); + } + + status = osm_req_set( p_mgr->p_req, + p_path, + p_mgr->lft_buf + block_id_ho * 64, + sizeof(block), + IB_MAD_ATTR_LIN_FWD_TBL, + cl_hton32( block_id_ho ), + CL_DISP_MSGID_NONE, + &context ); + + if( status != IB_SUCCESS ) + { + osm_log( p_mgr->p_log, OSM_LOG_ERROR, + "osm_ucast_mgr_set_fwd_table: ERR 3A05: " + "Sending linear fwd. tbl. block failed (%s)\n", + ib_get_err_str( status ) ); + } + else + { + p_mgr->any_change = TRUE; + /* + HACK: for now we will assume we succeeded to send + and set the local DB based on it. This should allow + us to immediatly dump out our routing. + */ + osm_switch_set_ft_block( + p_sw, p_mgr->lft_buf + block_id_ho * 64, block_id_ho ); + } + } + + OSM_LOG_EXIT( p_mgr->p_log ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_ucast_mgr_process_tbl( + IN cl_map_item_t* const p_map_item, + IN void* context ) +{ + osm_switch_t* const p_sw = (osm_switch_t*)p_map_item; + osm_ucast_mgr_t* const p_mgr = (osm_ucast_mgr_t*)context; + osm_node_t *p_node; + const osm_port_t *p_port; + const cl_qmap_t* p_port_tbl; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_ucast_mgr_process_tbl ); + + p_node = p_sw->p_node; + + CL_ASSERT( p_node ); + CL_ASSERT( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH ); + + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_ucast_mgr_process_tbl: " + "Processing switch 0x%" PRIx64 "\n", + cl_ntoh64( osm_node_get_node_guid( p_node ) )); + } + + /* Initialize LIDs in buffer to invalid port number. */ + memset(p_mgr->lft_buf, 0xff, IB_LID_UCAST_END_HO + 1); + + p_port_tbl = &p_mgr->p_subn->port_guid_tbl; + + /* + Iterate through every port setting LID routes for each + port based on base LID and LMC value. + */ + + for( p_port = (osm_port_t*)cl_qmap_head( p_port_tbl ); + p_port != (osm_port_t*)cl_qmap_end( p_port_tbl ); + p_port = (osm_port_t*)cl_qmap_next( &p_port->map_item ) ) + { + __osm_ucast_mgr_process_port( p_mgr, p_sw, p_port ); + } + + osm_ucast_mgr_set_fwd_table( p_mgr, p_sw ); + + OSM_LOG_EXIT( p_mgr->p_log ); +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_ucast_mgr_process_neighbors( + IN cl_map_item_t* const p_map_item, + IN void* context ) +{ + osm_switch_t* const p_sw = (osm_switch_t*)p_map_item; + osm_ucast_mgr_t* const p_mgr = (osm_ucast_mgr_t*)context; + osm_node_t *p_node; + osm_node_t *p_remote_node; + uint32_t port_num; + uint8_t remote_port_num; + uint32_t num_ports; + osm_physp_t* p_physp; + + OSM_LOG_ENTER( p_mgr->p_log, __osm_ucast_mgr_process_neighbors ); + + p_node = p_sw->p_node; + + CL_ASSERT( p_node ); + CL_ASSERT( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH ); + + if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "__osm_ucast_mgr_process_neighbors: " + "Processing switch with GUID 0x%" PRIx64 "\n", + cl_ntoh64( osm_node_get_node_guid( p_node ) ) ); + } + + num_ports = osm_node_get_num_physp( p_node ); + + /* + Start with port 1 to skip the switch's management port. + */ + for( port_num = 1; port_num < num_ports; port_num++ ) + { + p_remote_node = osm_node_get_remote_node( p_node, + (uint8_t)port_num, &remote_port_num ); + + if( p_remote_node && (p_remote_node != p_node ) + && p_remote_node->sw ) + { + /* make sure the link is healthy. If it is not - don't + propagate through it. */ + p_physp = osm_node_get_physp_ptr( p_node, port_num ); + if (!osm_link_is_healthy( p_physp ) ) + continue; + + __osm_ucast_mgr_process_neighbor(p_mgr, p_sw, p_remote_node->sw, + (uint8_t)port_num, remote_port_num ); + + } + } + + OSM_LOG_EXIT( p_mgr->p_log ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_ucast_mgr_build_lid_matrices( + IN osm_ucast_mgr_t* const p_mgr ) +{ + uint32_t i; + uint32_t iteration_max; + cl_qmap_t *p_sw_guid_tbl; + + p_sw_guid_tbl = &p_mgr->p_subn->sw_guid_tbl; + + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "osm_ucast_mgr_build_lid_matrices: " + "Starting switches Min Hop Table Assignment\n" ); + + /* + Set the switch matrices for each switch's own port 0 LID(s) + then set the lid matrices for the each switch's leaf nodes. + */ + cl_qmap_apply_func( p_sw_guid_tbl, + __osm_ucast_mgr_process_hop_0, p_mgr ); + + cl_qmap_apply_func( p_sw_guid_tbl, + __osm_ucast_mgr_process_leaves, p_mgr ); + + /* + Get the switch matrices for each switch's neighbors. + This process requires a number of iterations equal to + the number of switches in the subnet minus 1. + + In each iteration, a switch learns the lid/port/hop + information (as contained by a switch's lid matrix) from + its immediate neighbors. After each iteration, a switch + (and it's neighbors) know more routing information than + it did on the previous iteration. + Thus, by repeatedly absorbing the routing information of + neighbor switches, every switch eventually learns how to + route all LIDs on the subnet. + + Note that there may not be any switches in the subnet if + we are in simple p2p configuration. + */ + iteration_max = cl_qmap_count( p_sw_guid_tbl ); + + /* + If there are switches in the subnet, iterate until the lid + matrix has been constructed. Otherwise, just immediately + indicate we're done if no switches exist. + */ + if( iteration_max ) + { + iteration_max--; + + /* + we need to find out when the propagation of + hop counts has relaxed. So this global variable + is preset to 0 on each iteration and if + if non of the switches was set will exit the + while loop + */ + __some_hop_count_set = TRUE; + for( i = 0; (i < iteration_max) && __some_hop_count_set; i++ ) + { + __some_hop_count_set = FALSE; + cl_qmap_apply_func( p_sw_guid_tbl, + __osm_ucast_mgr_process_neighbors, p_mgr ); + } + osm_log( p_mgr->p_log, OSM_LOG_DEBUG, + "osm_ucast_mgr_build_lid_matrices: " + "Min-hop propagated in %d steps\n", i ); + } +} + +/********************************************************************** + **********************************************************************/ +osm_signal_t +osm_ucast_mgr_process( + IN osm_ucast_mgr_t* const p_mgr ) +{ + struct osm_routing_engine *p_routing_eng; + osm_signal_t signal = OSM_SIGNAL_DONE; + cl_qmap_t *p_sw_guid_tbl; + boolean_t default_routing = TRUE; + + OSM_LOG_ENTER( p_mgr->p_log, osm_ucast_mgr_process ); + + p_sw_guid_tbl = &p_mgr->p_subn->sw_guid_tbl; + p_routing_eng = &p_mgr->p_subn->p_osm->routing_engine; + + CL_PLOCK_EXCL_ACQUIRE( p_mgr->p_lock ); + + /* + If there are no switches in the subnet, we are done. + */ + if (cl_qmap_count( p_sw_guid_tbl ) == 0) + goto Exit; + + p_mgr->any_change = FALSE; + cl_qmap_apply_func(p_sw_guid_tbl, __osm_ucast_mgr_clean_switch, NULL); + + if (!p_routing_eng->build_lid_matrices || + p_routing_eng->build_lid_matrices(p_routing_eng->context) != 0) + osm_ucast_mgr_build_lid_matrices(p_mgr); + + osm_log( p_mgr->p_log, OSM_LOG_INFO, + "osm_ucast_mgr_process: " + "Min Hop Tables configured on all switches\n" ); + + /* + Now that the lid matrices have been built, we can + build and download the switch forwarding tables. + */ + + if ( p_routing_eng->ucast_build_fwd_tables && + (p_routing_eng->ucast_build_fwd_tables(p_routing_eng->context) == 0) ) + default_routing = FALSE; + else + cl_qmap_apply_func( p_sw_guid_tbl, __osm_ucast_mgr_process_tbl, p_mgr ); + + /* dump fdb into file: */ + if ( osm_log_is_active( p_mgr->p_log, OSM_LOG_ROUTING ) ) + { + if ( !default_routing && p_routing_eng->ucast_dump_tables != 0 ) + p_routing_eng->ucast_dump_tables(p_routing_eng->context); + else + __osm_ucast_mgr_dump_tables( p_mgr ); + } + + if (p_mgr->any_change) + { + signal = OSM_SIGNAL_DONE_PENDING; + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "osm_ucast_mgr_process: " + "LFT Tables configured on all switches\n"); + } + else + { + signal = OSM_SIGNAL_DONE; + osm_log( p_mgr->p_log, OSM_LOG_VERBOSE, + "osm_ucast_mgr_process: " + "No need to set any LFT Tables on any switches\n"); + } + + Exit: + CL_PLOCK_RELEASE( p_mgr->p_lock ); + OSM_LOG_EXIT( p_mgr->p_log ); + return( signal ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_ucast_updn.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_ucast_updn.c new file mode 100644 index 00000000..c0cbb5c7 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_ucast_updn.c @@ -0,0 +1,1281 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_ucast_updn.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Implementation of Up Down Algorithm using ranking & Min Hop + * Calculation functions + * + * Environment: + * Linux User Mode + * + * $Revision: 1.0 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include + +/* //////////////////////////// */ +/* Local types */ +/* //////////////////////////// */ + +/* direction */ +typedef enum _updn_switch_dir +{ + UP = 0, + DOWN +} updn_switch_dir_t; + +/* This enum respresent available states in the UPDN algorithm */ +typedef enum _updn_state +{ + UPDN_INIT = 0, + UPDN_RANK, + UPDN_MIN_HOP_CALC, +} updn_state_t; + +/* Rank value of this node */ +typedef struct _updn_rank +{ + cl_map_item_t map_item; + uint8_t rank; +} updn_rank_t; + +/* Histogram element - the number of occurences of the same hop value */ +typedef struct _updn_hist +{ + cl_map_item_t map_item; + uint32_t bar_value; +} updn_hist_t; + +typedef struct _updn_next_step +{ + updn_switch_dir_t state; + osm_switch_t *p_sw; +} updn_next_step_t; + +/* guids list */ +typedef struct _updn_input +{ + uint32_t num_guids; + uint64_t * guid_list; +} updn_input_t; + +/* updn structure */ +typedef struct _updn +{ + updn_state_t state; + boolean_t auto_detect_root_nodes; + cl_qmap_t guid_rank_tbl; + updn_input_t updn_ucast_reg_inputs; + cl_list_t * p_root_nodes; + osm_opensm_t *p_osm; +} updn_t; + +/* ///////////////////////////////// */ +/* Statics */ +/* ///////////////////////////////// */ +static int __osm_updn_find_root_nodes_by_min_hop(OUT updn_t *p_updn); + +/********************************************************************** + **********************************************************************/ +/* This function returns direction based on rank and guid info of current & + remote ports */ +static updn_switch_dir_t +__updn_get_dir( + IN updn_t *p_updn, + IN uint8_t cur_rank, + IN uint8_t rem_rank, + IN uint64_t cur_guid, + IN uint64_t rem_guid ) +{ + uint32_t i = 0, max_num_guids = p_updn->updn_ucast_reg_inputs.num_guids; + uint64_t *p_guid = p_updn->updn_ucast_reg_inputs.guid_list; + boolean_t cur_is_root = FALSE, rem_is_root = FALSE; + + /* HACK: comes to solve root nodes connection, in a classic subnet root nodes do not connect + directly, but in case they are we assign to root node an UP direction to allow UPDN discover + the subnet correctly (and not from the point of view of the last root node). + */ + for ( i = 0; i < max_num_guids; i++ ) + { + if (cur_guid == p_guid[i]) + cur_is_root = TRUE; + if (rem_guid == p_guid[i]) + rem_is_root = TRUE; + } + if (cur_is_root && rem_is_root) + return UP; + + if (cur_rank < rem_rank) + return DOWN; + else if (cur_rank > rem_rank) + return UP; + else + { + /* Equal rank, decide by guid number, bigger == UP direction */ + if (cur_guid > rem_guid) + return UP; + else + return DOWN; + } +} + +/********************************************************************** + **********************************************************************/ +/* This function creates a new element of updn_next_step_t type then return its + pointer , Null if malloc has failed */ +static updn_next_step_t* +__updn_create_updn_next_step_t( + IN updn_switch_dir_t state, + IN osm_switch_t* const p_sw ) +{ + updn_next_step_t *p_next_step; + + p_next_step = (updn_next_step_t*) malloc(sizeof(*p_next_step)); + if (p_next_step) + { + memset(p_next_step, 0, sizeof(*p_next_step)); + p_next_step->state = state; + p_next_step->p_sw = p_sw; + } + + return p_next_step; +} + +/********************************************************************** + **********************************************************************/ +/* This function updates an element in the qmap list by guid index and rank value */ +/* Return 0 if no need to futher update 1 if brought a new value */ +static int +__updn_update_rank( + IN cl_qmap_t *p_guid_rank_tbl, + IN ib_net64_t guid, + IN uint8_t rank ) +{ + updn_rank_t *p_updn_rank; + + p_updn_rank = (updn_rank_t*) cl_qmap_get(p_guid_rank_tbl, guid); + if (p_updn_rank == (updn_rank_t*) cl_qmap_end(p_guid_rank_tbl)) + { + p_updn_rank = (updn_rank_t*) malloc(sizeof(updn_rank_t)); + + CL_ASSERT (p_updn_rank); + + p_updn_rank->rank = rank; + + cl_qmap_insert(p_guid_rank_tbl, guid, &p_updn_rank->map_item); + return 1; + } + else + { + if (p_updn_rank->rank > rank) + { + p_updn_rank->rank = rank; + return 1; + } + } + return 0; +} + +/********************************************************************** + * This function does the bfs of min hop table calculation by guid index + * as a starting point. + **********************************************************************/ +static int +__updn_bfs_by_node( + IN updn_t *p_updn, + IN osm_subn_t *p_subn, + IN osm_port_t *p_port, + IN cl_qmap_t *p_guid_rank_tbl ) +{ + /* Init local vars */ + osm_switch_t *p_self_node = NULL; + uint8_t pn, pn_rem; + osm_physp_t *p_physp, *p_remote_physp; + cl_list_t *p_currList, *p_nextList; + uint16_t root_lid, max_sw_lid; + updn_next_step_t *p_updn_switch, *p_tmp; + updn_switch_dir_t next_dir, current_dir; + osm_log_t *p_log = &p_updn->p_osm->log; + + OSM_LOG_ENTER( p_log, __updn_bfs_by_node ); + + /* Init the list pointers */ + p_nextList = (cl_list_t*)malloc(sizeof(cl_list_t)); + cl_list_construct( p_nextList ); + cl_list_init( p_nextList, 10 ); + p_currList = p_nextList; + + p_physp = osm_port_get_default_phys_ptr(p_port); + /* Check valid pointer */ + if (!p_physp || !osm_physp_is_valid(p_physp )) + { + OSM_LOG_EXIT( p_log ); + return 1; + } + /* The Root BFS - lid */ + root_lid = cl_ntoh16(osm_physp_get_base_lid( p_physp )); + /* printf ("-V- BFS through lid : 0x%x\n", root_lid); */ + osm_log( p_log, OSM_LOG_DEBUG, + "__updn_bfs_by_node:" + "Starting lid : 0x%x \n", root_lid ); + + if (p_port->p_node->sw) + { + p_self_node = p_port->p_node->sw; + /* Update its Min Hop Table */ + osm_log( p_log, OSM_LOG_DEBUG, + "__updn_bfs_by_node:" + "Update Min Hop Table of GUID 0x%" PRIx64 "\n", + cl_ntoh64(p_port->guid) ); + osm_switch_set_hops(p_self_node, root_lid, 0, 0); + } + else + { + /* This is a CA or router - need to take its remote port */ + p_remote_physp = p_physp->p_remote_physp; + /* + make sure that the following occur: + 1. The port isn't NULL + 2. The port is a valid port + */ + if ( p_remote_physp && osm_physp_is_valid ( p_remote_physp )) + { + /* Check if the remote port is a switch, if it is update root_lid, + Min Hop Table */ + if (!p_remote_physp->p_node->sw) + { + osm_log( p_log, OSM_LOG_ERROR, + "__updn_bfs_by_node: ERR AA07: " + "This is a non switched subnet OR non valid connection, cannot perform UPDN algorithm\n" ); + OSM_LOG_EXIT( p_log ); + return 1; + } + else + { + p_self_node = p_remote_physp->p_node->sw; + max_sw_lid = osm_switch_get_max_lid_ho(p_self_node); + if ((1 <= root_lid) && (root_lid <= max_sw_lid)) + /* Update its Min Hop Table */ + { + /* NOTE : Check if there is a function which prints the Min Hop Table */ + osm_log( p_log, OSM_LOG_DEBUG, + "__updn_bfs_by_node:" + "Update Min Hop Table of GUID 0x%" PRIx64 "\n", + cl_ntoh64(p_remote_physp->port_guid) ); + osm_switch_set_hops(p_self_node, root_lid, + p_remote_physp->port_num, 1); + + } + else + { + osm_log( p_log, OSM_LOG_ERROR, + "__updn_bfs_by_node: ERR AA09: " + " Invalid lid value 0x%x for switch 0x%" PRIx64 "\n", + root_lid, + cl_ntoh64(p_self_node->p_node->node_info.port_guid) ); + OSM_LOG_EXIT( p_log ); + return 1; + } + } + } + } + + CL_ASSERT(p_self_node); + + osm_log( p_log, OSM_LOG_DEBUG, + "__updn_bfs_by_node:" + "Starting from switch - port GUID 0x%" PRIx64 "\n", + cl_ntoh64(p_self_node->p_node->node_info.port_guid) ); + + /* Update list with the updn_next_step_t new element */ + /* NOTE : When inserting an item which is a pointer to a struct, does remove + action also free its memory */ + if (!(p_tmp=__updn_create_updn_next_step_t(UP, p_self_node))) + { + osm_log( p_log, OSM_LOG_ERROR, + "__updn_bfs_by_node: ERR AA08: " + "Could not create updn_next_step_t\n" ); + return 1; + } + + cl_list_insert_tail(p_currList, p_tmp); + + /* BFS the list till no next element */ + osm_log( p_log, OSM_LOG_VERBOSE, + "__updn_bfs_by_node:" + "BFS the subnet [\n" ); + + while (!cl_is_list_empty(p_currList)) + { + osm_log( p_log, OSM_LOG_DEBUG, + "__updn_bfs_by_node:" + "Starting a new iteration with %zu elements in current list\n", + cl_list_count(p_currList) ); + /* Init the switch directed list */ + p_nextList = (cl_list_t*)malloc(sizeof(cl_list_t)); + cl_list_construct( p_nextList ); + cl_list_init( p_nextList, 10 ); + /* Go over all current list items till it's empty */ + /* printf ("-V- In inner while\n"); */ + p_updn_switch = (updn_next_step_t*)cl_list_remove_head( p_currList ); + /* While there is a pointer to updn struct we continue to BFS */ + while (p_updn_switch) + { + current_dir = p_updn_switch->state; + osm_log( p_log, OSM_LOG_DEBUG, + "__updn_bfs_by_node:" + "Visiting port GUID 0x%" PRIx64 "\n", + cl_ntoh64(p_updn_switch->p_sw->p_node->node_info.port_guid) ); + /* Go over all ports of the switch and find unvisited remote nodes */ + for ( pn = 0; pn < osm_switch_get_num_ports(p_updn_switch->p_sw); pn++ ) + { + /* printf("-V- Inner for in port num 0x%X\n", pn); */ + osm_node_t *p_remote_node; + cl_list_iterator_t updn_switch_iterator; + boolean_t HasVisited = FALSE; + ib_net64_t remote_guid,current_guid; + updn_rank_t *p_rem_rank, *p_cur_rank; + uint8_t current_min_hop, remote_min_hop, set_hop_return_value; + osm_switch_t *p_remote_sw; + + current_guid = osm_node_get_node_guid(p_updn_switch->p_sw->p_node); + p_remote_node = osm_node_get_remote_node( p_updn_switch->p_sw->p_node + , pn, &pn_rem ); + /* If no remote node OR remote node is not a SWITCH + continue to next pn */ + if( !p_remote_node || + (osm_node_get_type(p_remote_node) != IB_NODE_TYPE_SWITCH) ) + continue; + /* Fetch remote guid only after validation of remote node */ + remote_guid = osm_node_get_node_guid(p_remote_node); + /* printf ("-V- Current guid : 0x%" PRIx64 " Remote guid : 0x%" PRIx64 "\n", */ + /* cl_ntoh64(current_guid), cl_ntoh64(remote_guid)); */ + p_remote_sw = p_remote_node->sw; + p_rem_rank = (updn_rank_t*)cl_qmap_get(p_guid_rank_tbl, remote_guid); + p_cur_rank = (updn_rank_t*)cl_qmap_get(p_guid_rank_tbl, current_guid); + /* Decide which direction to mark it (UP/DOWN) */ + next_dir = __updn_get_dir (p_updn, p_cur_rank->rank, p_rem_rank->rank, + current_guid, remote_guid); + + osm_log( p_log, OSM_LOG_DEBUG, + "__updn_bfs_by_node:" + "move from 0x%016" PRIx64 " rank: %u " + "to 0x%016" PRIx64" rank: %u\n", + cl_ntoh64(current_guid), p_cur_rank->rank, + cl_ntoh64(remote_guid), p_rem_rank->rank ); + /* Check if this is a legal step : the only illegal step is going + from DOWN to UP */ + if ((current_dir == DOWN) && (next_dir == UP)) + { + osm_log( p_log, OSM_LOG_DEBUG, + "__updn_bfs_by_node:" + "Avoiding move from 0x%016" PRIx64 " to 0x%016" PRIx64"\n", + cl_ntoh64(current_guid), cl_ntoh64(remote_guid) ); + /* Illegal step */ + continue; + } + /* Set MinHop value for the current lid */ + current_min_hop = osm_switch_get_least_hops(p_updn_switch->p_sw,root_lid); + /* Check hop count if better insert into NextState list && update + the remote node Min Hop Table */ + remote_min_hop = osm_switch_get_hop_count(p_remote_sw, root_lid, pn_rem); + if (current_min_hop + 1 < remote_min_hop) + { + osm_log( p_log, OSM_LOG_DEBUG, + "__updn_bfs_by_node (less):" + "Setting Min Hop Table of switch: 0x%" PRIx64 + "\n\t\tCurrent hop count is: %d, next hop count: %d" + "\n\tlid to set: 0x%x" + "\n\tport number: 0x%X" + " \n\thops number: %d\n", + cl_ntoh64(remote_guid), remote_min_hop,current_min_hop + 1, + root_lid, pn_rem, current_min_hop + 1 ); + set_hop_return_value = osm_switch_set_hops(p_remote_sw, root_lid, pn_rem, current_min_hop + 1); + if (set_hop_return_value) + { + osm_log( p_log, OSM_LOG_ERROR, + "__updn_bfs_by_node (less) ERR AA01: " + "Invalid value returned from set min hop is: %d\n", + set_hop_return_value ); + } + /* Check if remote port is allready has been visited */ + updn_switch_iterator = cl_list_head(p_nextList); + while( updn_switch_iterator != cl_list_end(p_nextList) ) + { + updn_next_step_t *p_updn; + p_updn = (updn_next_step_t*)cl_list_obj(updn_switch_iterator); + /* Mark HasVisited only if: + 1. Same node guid + 2. Same direction + */ + if ((p_updn->p_sw->p_node == p_remote_node) && (p_updn->state == next_dir)) + HasVisited = TRUE; + updn_switch_iterator = cl_list_next(updn_switch_iterator); + } + if (!HasVisited) + { + /* Insert updn_switch item into the next list */ + if(!(p_tmp=__updn_create_updn_next_step_t(next_dir, p_remote_sw))) + { + osm_log( p_log, OSM_LOG_ERROR, + "__updn_bfs_by_node: ERR AA11: " + "Could not create updn_next_step_t\n" ); + return 1; + } + osm_log( p_log, OSM_LOG_DEBUG, + "__updn_bfs_by_node: " + "Inserting new element to the next list: guid=0x%" PRIx64 " %s\n", + cl_ntoh64(p_tmp->p_sw->p_node->node_info.port_guid), + (p_tmp->state == UP ? "UP" : "DOWN") + ); + cl_list_insert_tail(p_nextList, p_tmp); + } + /* If the same value only update entry - at the min hop table */ + } else if (current_min_hop + 1 == osm_switch_get_hop_count(p_remote_sw, + root_lid, + pn_rem)) + { + osm_log( p_log, OSM_LOG_DEBUG, + "__updn_bfs_by_node (equal):" + "Setting Min Hop Table of switch: 0x%" PRIx64 + "\n\t\tCurrent hop count is: %d, next hop count: %d" + "\n\tlid to set: 0x%x" + "\n\tport number: 0x%X" + "\n\thops number: %d\n", + cl_ntoh64(remote_guid), + osm_switch_get_hop_count(p_remote_sw, root_lid, pn_rem), + current_min_hop + 1, root_lid, pn_rem, current_min_hop + 1 ); + set_hop_return_value = osm_switch_set_hops(p_remote_sw, root_lid, pn_rem, current_min_hop + 1); + + if (set_hop_return_value) + { + osm_log( p_log, OSM_LOG_ERROR, + "__updn_bfs_by_node (less) ERR AA12: " + "Invalid value returned from set min hop is: %d\n", + set_hop_return_value ); + } + } + } + free (p_updn_switch); + p_updn_switch = (updn_next_step_t*)cl_list_remove_head( p_currList ); + } + /* Cleanup p_currList */ + cl_list_destroy( p_currList ); + free (p_currList); + + /* Reassign p_currList to p_nextList */ + p_currList = p_nextList; + } + /* Cleanup p_currList - Had the pointer to cl_list_t */ + cl_list_destroy( p_currList ); + free (p_currList); + osm_log( p_log, OSM_LOG_VERBOSE, + "__updn_bfs_by_node:" + "BFS the subnet ]\n" ); + OSM_LOG_EXIT( p_log ); + return 0; +} + +/********************************************************************** + **********************************************************************/ +static void +updn_destroy( + IN updn_t* const p_updn ) +{ + cl_map_item_t *p_map_item; + uint64_t *p_guid_list_item; + + /* Destroy the updn struct */ + p_map_item = cl_qmap_head( &p_updn->guid_rank_tbl); + while( p_map_item != cl_qmap_end( &p_updn->guid_rank_tbl)) + { + osm_log ( &p_updn->p_osm->log, OSM_LOG_DEBUG, + "osm_subn_calc_up_down_min_hop_table: " + "guid = 0x%" PRIx64 " rank = %u\n", + cl_ntoh64(cl_qmap_key(p_map_item)), + ((updn_rank_t *)p_map_item)->rank ); + cl_qmap_remove_item( &p_updn->guid_rank_tbl, p_map_item); + free( (updn_rank_t *)p_map_item); + p_map_item = cl_qmap_head( &p_updn->guid_rank_tbl); + } + + /* free the array of guids */ + if (p_updn->updn_ucast_reg_inputs.guid_list) + free(p_updn->updn_ucast_reg_inputs.guid_list); + + /* destroy the list of root nodes */ + while ((p_guid_list_item = cl_list_remove_head( p_updn->p_root_nodes ))) + free( p_guid_list_item ); + + cl_list_remove_all( p_updn->p_root_nodes ); + cl_list_destroy( p_updn->p_root_nodes ); + free ( p_updn->p_root_nodes ); + free (p_updn); +} + +/********************************************************************** + **********************************************************************/ +static updn_t* +updn_construct(osm_log_t *p_log) +{ + updn_t* p_updn; + + OSM_LOG_ENTER( p_log, updn_construct ); + p_updn = malloc(sizeof(updn_t)); + if (p_updn) + memset(p_updn, 0, sizeof(updn_t)); + OSM_LOG_EXIT( p_log ); + return(p_updn); +} + +/********************************************************************** + **********************************************************************/ +static cl_status_t +updn_init( + IN updn_t* const p_updn, + IN osm_opensm_t *p_osm ) +{ + cl_list_t * p_list; + FILE* p_updn_guid_file; + char line[MAX_UPDN_GUID_FILE_LINE_LENGTH]; + uint64_t * p_tmp; + cl_list_iterator_t guid_iterator; + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( &p_osm->log, updn_init ); + + p_updn->p_osm = p_osm; + p_updn->state = UPDN_INIT; + cl_qmap_init( &p_updn->guid_rank_tbl ); + p_list = (cl_list_t*)malloc(sizeof(cl_list_t)); + if (!p_list) + { + status = IB_ERROR; + goto Exit; + } + + cl_list_construct( p_list ); + cl_list_init( p_list, 10 ); + p_updn->p_root_nodes = p_list; + p_updn->updn_ucast_reg_inputs.num_guids = 0; + p_updn->updn_ucast_reg_inputs.guid_list = NULL; + p_updn->auto_detect_root_nodes = FALSE; + + /* + Check the source for root node list, if file parse it, otherwise + wait for a callback to activate auto detection + */ + if (p_osm->subn.opt.updn_guid_file) + { + /* Now parse guid from file */ + p_updn_guid_file = fopen(p_osm->subn.opt.updn_guid_file, "r"); + if (p_updn_guid_file == NULL) + { + osm_log( &p_osm->log, OSM_LOG_ERROR, + "osm_opensm_init : ERR AA02: " + "Failed to open guid list file (%s)\n", + p_osm->subn.opt.updn_guid_file ); + status = IB_NOT_FOUND; + goto Exit; + } + + while ( fgets(line, MAX_UPDN_GUID_FILE_LINE_LENGTH, p_updn_guid_file) ) + { + if (strcspn(line, " ,;.") == strlen(line)) + { + /* Skip empty lines anywhere in the file - only one char means the Null termination */ + if (strlen(line) > 1) + { + p_tmp = malloc(sizeof(uint64_t)); + *p_tmp = strtoull(line, NULL, 16); + cl_list_insert_tail(p_updn->p_root_nodes, p_tmp); + } + } + else + { + osm_log( &p_osm->log, OSM_LOG_ERROR, + "osm_opensm_init: ERR AA03: " + "Bad formatted guid in file (%s): %s\n", + p_osm->subn.opt.updn_guid_file, line ); + status = IB_NOT_FOUND; + break; + } + } + + /* For Debug Purposes ... */ + osm_log( &p_osm->log, OSM_LOG_DEBUG, + "osm_opensm_init: " + "UPDN - Root nodes fetching by file %s\n", + p_osm->subn.opt.updn_guid_file ); + guid_iterator = cl_list_head(p_updn->p_root_nodes); + while( guid_iterator != cl_list_end(p_updn->p_root_nodes) ) + { + osm_log( &p_osm->log, OSM_LOG_DEBUG, + "osm_opensm_init: " + "Inserting GUID 0x%" PRIx64 " as root node\n", + *((uint64_t*)cl_list_obj(guid_iterator)) ); + guid_iterator = cl_list_next(guid_iterator); + } + } + else + { + p_updn->auto_detect_root_nodes = TRUE; + } + /* If auto mode detection required - will be executed in main b4 the assignment of UI Ucast */ + +Exit : + OSM_LOG_EXIT( &p_osm->log ); + return (status); +} + +/********************************************************************** + **********************************************************************/ +/* NOTE : PLS check if we need to decide that the first */ +/* rank is a SWITCH for BFS purpose */ +static int +updn_subn_rank( + IN uint64_t root_guid, + IN uint8_t base_rank, + IN updn_t* p_updn ) +{ + /* Init local vars */ + osm_port_t *p_root_port = NULL; + uint16_t tbl_size; + uint8_t rank = base_rank; + osm_physp_t *p_physp, *p_remote_physp, *p_physp_temp; + cl_list_t *p_currList,*p_nextList; + cl_status_t did_cause_update; + uint8_t num_ports, port_num; + osm_log_t *p_log = &p_updn->p_osm->log; + + OSM_LOG_ENTER( p_log, updn_subn_rank ); + + osm_log( p_log, OSM_LOG_VERBOSE, + "updn_subn_rank: " + "Ranking starts from GUID 0x%" PRIx64 "\n", root_guid ); + + /* Init the list pointers */ + p_nextList = (cl_list_t*)malloc(sizeof(cl_list_t)); + cl_list_construct( p_nextList ); + cl_list_init( p_nextList, 10 ); + p_currList = p_nextList; + + /* Check valid subnet & guid */ + tbl_size = (uint16_t)(cl_qmap_count(&p_updn->p_osm->subn.port_guid_tbl)); + if (tbl_size == 0) + { + osm_log( p_log, OSM_LOG_ERROR, + "updn_subn_rank: ERR AA04: " + "Port guid table is empty, cannot perform ranking\n" ); + OSM_LOG_EXIT( p_log ); + return 1; + } + + p_root_port = (osm_port_t*) cl_qmap_get(&p_updn->p_osm->subn.port_guid_tbl, + cl_ntoh64(root_guid)); + if( p_root_port == (osm_port_t*)cl_qmap_end( &p_updn->p_osm->subn.port_guid_tbl ) ) + { + osm_log( p_log, OSM_LOG_ERROR, + "updn_subn_rank: ERR AA05: " + "Wrong guid value: 0x%" PRIx64 "\n", root_guid ); + OSM_LOG_EXIT( p_log ); + return 1; + } + + /* Rank the first chosen guid anyway since its the base rank */ + osm_log( p_log, OSM_LOG_DEBUG, + "updn_subn_rank: " + "Ranking port GUID 0x%" PRIx64 "\n", root_guid ); + + __updn_update_rank(&p_updn->guid_rank_tbl, cl_ntoh64(root_guid), rank); + /* + HACK: We are assuming SM is running on HCA, so when getting the default + port we'll get the port connected to the rest of the subnet. If SM is + running on SWITCH - we should try to get a dr path from all switch ports. + */ + p_physp = osm_port_get_default_phys_ptr( p_root_port ); + CL_ASSERT( p_physp ); + CL_ASSERT( osm_physp_is_valid( p_physp ) ); + /* We can safely add the node to the list */ + cl_list_insert_tail(p_nextList, p_physp); + /* Assign pointer to the list for BFS */ + p_currList = p_nextList; + + /* BFS the list till its empty */ + osm_log( p_log, OSM_LOG_VERBOSE, + "updn_subn_rank: " + "BFS the subnet [\n" ); + + while (!cl_is_list_empty(p_currList)) + { + rank++; + p_nextList = (cl_list_t*)malloc(sizeof(cl_list_t)); + cl_list_construct( p_nextList ); + cl_list_init( p_nextList, 10 ); + p_physp = (osm_physp_t*)cl_list_remove_head( p_currList ); + /* Go over all remote nodes and rank them (if not allready visited) till + no elemtent in the list p_currList */ + while ( p_physp != NULL ) + { + num_ports = osm_node_get_num_physp( p_physp->p_node ); + osm_log( p_log, OSM_LOG_DEBUG, + "updn_subn_rank: " + "Handling port GUID 0x%" PRIx64 "\n", + cl_ntoh64(p_physp->port_guid) ); + for (port_num = 1; port_num < num_ports; port_num++) + { + ib_net64_t port_guid; + + /* Current port fetched in order to get remote side */ + p_physp_temp = osm_node_get_physp_ptr( p_physp->p_node, port_num ); + p_remote_physp = p_physp_temp->p_remote_physp; + + /* + make sure that all the following occur on p_remote_physp: + 1. The port isn't NULL + 2. The port is a valid port + */ + if ( p_remote_physp && + osm_physp_is_valid ( p_remote_physp )) + { + port_guid = p_remote_physp->port_guid; + osm_log( p_log, OSM_LOG_DEBUG, + "updn_subn_rank: " + "Visiting remote port GUID 0x%" PRIx64 "\n", + cl_ntoh64(port_guid) ); + /* Was it visited ? + Only if the pointer equal to cl_qmap_end its not + found in the list */ + osm_log( p_log, OSM_LOG_DEBUG, + "updn_subn_rank: " + "Ranking port GUID 0x%" PRIx64 "\n", cl_ntoh64(port_guid) ); + did_cause_update = __updn_update_rank(&p_updn->guid_rank_tbl, port_guid, rank); + + osm_log( p_log, OSM_LOG_VERBOSE, + "updn_subn_rank: " + "Rank of port GUID 0x%" PRIx64 " = %u\n", cl_ntoh64(port_guid), + ((updn_rank_t*)cl_qmap_get(&p_updn->guid_rank_tbl, port_guid))->rank + ); + + if (did_cause_update) + { + cl_list_insert_tail(p_nextList, p_remote_physp); + } + } + } + /* Propagte through the next item in the p_currList */ + p_physp = (osm_physp_t*)cl_list_remove_head( p_currList ); + } + /* First free the allocation of cl_list pointer then reallocate */ + cl_list_destroy( p_currList ); + free(p_currList); + /* p_currList is empty - need to assign it to p_nextList */ + p_currList = p_nextList; + } + + osm_log( p_log, OSM_LOG_VERBOSE, + "updn_subn_rank: " + "BFS the subnet ]\n" ); + + cl_list_destroy( p_currList ); + free(p_currList); + + /* Print Summary of ranking */ + osm_log( p_log, OSM_LOG_VERBOSE, + "updn_subn_rank: " + "Rank Info :\n\t Root Guid = 0x%" PRIx64 "\n\t Max Node Rank = %d\n", + cl_ntoh64(p_root_port->guid), rank ); + p_updn->state = UPDN_RANK; + OSM_LOG_EXIT( p_log ); + return 0; +} + +/********************************************************************** + **********************************************************************/ +static int +__osm_subn_set_up_down_min_hop_table( + IN updn_t* p_updn ) +{ + /* Init local vars */ + osm_subn_t *p_subn = &p_updn->p_osm->subn; + osm_log_t *p_log = &p_updn->p_osm->log; + osm_switch_t *p_next_sw,*p_sw; + osm_port_t *p_next_port,*p_port; + ib_net64_t port_guid; + + OSM_LOG_ENTER( p_log, __osm_subn_set_up_down_min_hop_table ); + if (p_updn->state == UPDN_INIT) + { + osm_log( p_log, OSM_LOG_ERROR, + "__osm_subn_set_up_down_min_hop_table: ERR AA06: " + "Calculating Min Hop only allowed after ranking\n" ); + OSM_LOG_EXIT( p_log ); + return 1; + } + + /* Check if its a non switched subnet .. */ + if ( cl_is_qmap_empty( &p_subn->sw_guid_tbl ) ) + { + osm_log( p_log, OSM_LOG_ERROR, + "__osm_subn_set_up_down_min_hop_table: ERR AA10: " + "This is a non switched subnet, cannot perform UPDN algorithm\n" ); + OSM_LOG_EXIT( p_log ); + return 1; + } + /* Go over all the switches in the subnet - for each init their Min Hop + Table */ + osm_log( p_log, OSM_LOG_VERBOSE, + "__osm_subn_set_up_down_min_hop_table: " + "Init Min Hop Table of all switches [\n" ); + + p_next_sw = (osm_switch_t*)cl_qmap_head( &p_subn->sw_guid_tbl ); + while( p_next_sw != (osm_switch_t*)cl_qmap_end( &p_subn->sw_guid_tbl ) ) + { + p_sw = p_next_sw; + p_next_sw = (osm_switch_t*)cl_qmap_next( &p_sw->map_item ); + /* Clear Min Hop Table */ + osm_lid_matrix_clear(&(p_sw->lmx)); + } + + osm_log( p_log, OSM_LOG_VERBOSE, + "__osm_subn_set_up_down_min_hop_table: " + "Init Min Hop Table of all switches ]\n" ); + + /* Now do the BFS for each port in the subnet */ + osm_log( p_log, OSM_LOG_VERBOSE, + "__osm_subn_set_up_down_min_hop_table: " + "BFS through all port guids in the subnet [\n" ); + p_next_port = (osm_port_t*)cl_qmap_head( &p_subn->port_guid_tbl ); + while( p_next_port != (osm_port_t*)cl_qmap_end( &p_subn->port_guid_tbl ) ) + { + p_port = p_next_port; + p_next_port = (osm_port_t*)cl_qmap_next( &p_port->map_item ); + port_guid = cl_qmap_key(&(p_port->map_item)); + osm_log( p_log, OSM_LOG_DEBUG, + "__osm_subn_set_up_down_min_hop_table: " + "BFS through port GUID 0x%" PRIx64 "\n", + cl_ntoh64(port_guid) ); + if(__updn_bfs_by_node(p_updn, p_subn, p_port, + &p_updn->guid_rank_tbl)) + { + OSM_LOG_EXIT( p_log ); + return 1; + } + } + + osm_log( p_log, OSM_LOG_VERBOSE, + "__osm_subn_set_up_down_min_hop_table: " + "BFS through all port guids in the subnet ]\n" ); + /* Cleanup */ + OSM_LOG_EXIT( p_log ); + return 0; +} + +/********************************************************************** + **********************************************************************/ +static int +__osm_subn_calc_up_down_min_hop_table( + IN uint32_t num_guids, + IN uint64_t * guid_list, + IN updn_t* p_updn ) +{ + uint8_t idx = 0; + cl_map_item_t *p_map_item; + int status; + + OSM_LOG_ENTER( &p_updn->p_osm->log, osm_subn_calc_up_down_min_hop_table ); + osm_log( &p_updn->p_osm->log, OSM_LOG_VERBOSE, + "__osm_subn_calc_up_down_min_hop_table: " + "Ranking all port guids in the list\n" ); + if (num_guids == 0) + { + osm_log( &p_updn->p_osm->log, OSM_LOG_ERROR, + "__osm_subn_calc_up_down_min_hop_table: ERR AA0A: " + "No guids were given or number of guids is 0\n" ); + return 1; + } + + for (idx = 0; idx < num_guids; idx++) + { + /* Apply the ranking for each guid given by user - bypass illegal ones */ + updn_subn_rank(guid_list[idx], 0, p_updn); + } + /* After multiple ranking need to set Min Hop Table by UpDn algorithm */ + osm_log( &p_updn->p_osm->log, OSM_LOG_VERBOSE, + "__osm_subn_calc_up_down_min_hop_table: " + "Setting all switches' Min Hop Table\n" ); + + status = __osm_subn_set_up_down_min_hop_table (p_updn); + + /* Cleanup updn rank tbl */ + p_map_item = cl_qmap_head( &p_updn->guid_rank_tbl); + while( p_map_item != cl_qmap_end( &p_updn->guid_rank_tbl)) + { + osm_log( &p_updn->p_osm->log, OSM_LOG_DEBUG, + "__osm_subn_calc_up_down_min_hop_table: " + "guid = 0x%" PRIx64 " rank = %u\n", + cl_ntoh64(cl_qmap_key(p_map_item)), + ((updn_rank_t *)p_map_item)->rank ); + cl_qmap_remove_item( &p_updn->guid_rank_tbl, p_map_item); + free( (updn_rank_t *)p_map_item); + p_map_item = cl_qmap_head( &p_updn->guid_rank_tbl); + } + + OSM_LOG_EXIT( &p_updn->p_osm->log ); + return status; +} + +/********************************************************************** + **********************************************************************/ +/* UPDN callback function */ +static int +__osm_updn_call( + void *ctx ) +{ + updn_t *p_updn = ctx; + + OSM_LOG_ENTER( &p_updn->p_osm->log, __osm_updn_call ); + + /* First auto detect root nodes - if required */ + if ( p_updn->auto_detect_root_nodes ) + { + osm_ucast_mgr_build_lid_matrices( &p_updn->p_osm->sm.ucast_mgr ); + /* printf ("-V- b4 osm_updn_find_root_nodes_by_min_hop\n"); */ + __osm_updn_find_root_nodes_by_min_hop( p_updn ); + } + /* printf ("-V- after osm_updn_find_root_nodes_by_min_hop\n"); */ + /* Only if there are assigned root nodes do the algorithm , otherwise perform do nothing */ + if ( p_updn->updn_ucast_reg_inputs.num_guids > 0) + { + osm_log( &(p_updn->p_osm->log), OSM_LOG_DEBUG, + "__osm_updn_call: " + "activating UPDN algorithm\n" ); + __osm_subn_calc_up_down_min_hop_table( p_updn->updn_ucast_reg_inputs.num_guids, + p_updn->updn_ucast_reg_inputs.guid_list, + p_updn ); + } + else + osm_log( &p_updn->p_osm->log, OSM_LOG_INFO, + "__osm_updn_call: " + "disable UPDN algorithm, no root nodes were found\n" ); + + OSM_LOG_EXIT( &p_updn->p_osm->log ); + return 0; +} + +/********************************************************************** + **********************************************************************/ +/* UPDN convert cl_list to guid array in updn struct */ +static void +__osm_updn_convert_list2array( + IN updn_t * p_updn ) +{ + uint32_t i = 0, max_num = 0; + uint64_t *p_guid; + + OSM_LOG_ENTER( &p_updn->p_osm->log, __osm_updn_convert_list2array ); + + p_updn->updn_ucast_reg_inputs.num_guids = cl_list_count( + p_updn->p_root_nodes); + if (p_updn->updn_ucast_reg_inputs.guid_list) + free(p_updn->updn_ucast_reg_inputs.guid_list); + p_updn->updn_ucast_reg_inputs.guid_list = (uint64_t *)malloc( + p_updn->updn_ucast_reg_inputs.num_guids*sizeof(uint64_t)); + if (p_updn->updn_ucast_reg_inputs.guid_list) + memset(p_updn->updn_ucast_reg_inputs.guid_list, 0, + p_updn->updn_ucast_reg_inputs.num_guids*sizeof(uint64_t)); + if (!cl_is_list_empty(p_updn->p_root_nodes)) + { + while( (p_guid = (uint64_t*)cl_list_remove_head(p_updn->p_root_nodes)) ) + { + p_updn->updn_ucast_reg_inputs.guid_list[i] = *p_guid; + free(p_guid); + i++; + } + max_num = i; + for (i = 0; i < max_num; i++ ) + osm_log( &p_updn->p_osm->log, OSM_LOG_DEBUG, + "__osm_updn_convert_list2array: " + "Map GUID 0x%" PRIx64 " into UPDN array\n", + p_updn->updn_ucast_reg_inputs.guid_list[i] ); + } + /* Since we need the template list for other sweeps, we wont destroy & free it */ + OSM_LOG_EXIT( &p_updn->p_osm->log ); +} + +/********************************************************************** + **********************************************************************/ +/* Find Root nodes automatically by Min Hop Table info */ +static int +__osm_updn_find_root_nodes_by_min_hop( + OUT updn_t * p_updn ) +{ + osm_opensm_t *p_osm = p_updn->p_osm; + osm_switch_t *p_next_sw, *p_sw; + osm_port_t *p_next_port, *p_port; + osm_physp_t *p_physp; + uint32_t numCas = 0; + uint32_t numSws = cl_qmap_count(&p_osm->subn.sw_guid_tbl); + cl_qmap_t min_hop_hist; /* Histogram container */ + updn_hist_t *p_updn_hist, *p_up_ht; + uint8_t maxHops = 0; /* contain the max histogram index */ + uint64_t *p_guid; + cl_list_t *p_root_nodes_list = p_updn->p_root_nodes; + cl_map_t ca_by_lid_map; /* map holding all CA lids */ + uint16_t self_lid_ho; + + OSM_LOG_ENTER( &p_osm->log, osm_updn_find_root_nodes_by_min_hop ); + + osm_log( &p_osm->log, OSM_LOG_DEBUG, + "__osm_updn_find_root_nodes_by_min_hop: " + "current number of ports in the subnet is %d\n", + cl_qmap_count(&p_osm->subn.port_guid_tbl) ); + /* Init the required vars */ + cl_qmap_init( &min_hop_hist ); + cl_map_construct( &ca_by_lid_map ); + cl_map_init( &ca_by_lid_map, 10 ); + + /* EZ: + p_ca_list = (cl_list_t*)malloc(sizeof(cl_list_t)); + cl_list_construct( p_ca_list ); + cl_list_init( p_ca_list, 10 ); + */ + + /* Find the Maximum number of CAs (and routers) for histogram normalization */ + osm_log( &p_osm->log, OSM_LOG_VERBOSE, + "__osm_updn_find_root_nodes_by_min_hop: " + "Find the number of CAs and store them in cl_list\n" ); + p_next_port = (osm_port_t*)cl_qmap_head( &p_osm->subn.port_guid_tbl ); + while( p_next_port != (osm_port_t*)cl_qmap_end( &p_osm->subn.port_guid_tbl ) ) { + p_port = p_next_port; + p_next_port = (osm_port_t*)cl_qmap_next( &p_next_port->map_item ); + if ( osm_node_get_type(p_port->p_node) != IB_NODE_TYPE_SWITCH ) + { + p_physp = osm_port_get_default_phys_ptr(p_port); + self_lid_ho = cl_ntoh16( osm_physp_get_base_lid(p_physp) ); + numCas++; + /* EZ: + self = malloc(sizeof(uint16_t)); + *self = self_lid_ho; + cl_list_insert_tail(p_ca_list, self); + */ + cl_map_insert( &ca_by_lid_map, self_lid_ho, (void *)0x1); + osm_log( &p_osm->log, OSM_LOG_DEBUG, + "__osm_updn_find_root_nodes_by_min_hop: " + "Inserting into array GUID 0x%" PRIx64 ", Lid: 0x%X\n", + cl_ntoh64(osm_port_get_guid(p_port)), self_lid_ho ); + } + } + osm_log( &p_osm->log, OSM_LOG_DEBUG, + "__osm_updn_find_root_nodes_by_min_hop: " + "Found %u CA, %u SW in the subnet\n", numCas, numSws ); + p_next_sw = (osm_switch_t*)cl_qmap_head( &p_osm->subn.sw_guid_tbl ); + osm_log( &p_osm->log, OSM_LOG_VERBOSE, + "__osm_updn_find_root_nodes_by_min_hop: " + "Passing through all switches to collect Min Hop info\n" ); + while( p_next_sw != (osm_switch_t*)cl_qmap_end( &p_osm->subn.sw_guid_tbl ) ) + { + uint16_t max_lid_ho, lid_ho; + uint8_t hop_val; + uint16_t numHopBarsOverThd1 = 0; + uint16_t numHopBarsOverThd2 = 0; + double thd1, thd2; + + p_sw = p_next_sw; + /* Roll to the next switch */ + p_next_sw = (osm_switch_t*)cl_qmap_next( &p_sw->map_item ); + + /* Clear Min Hop Table && FWD Tbls - This should caused opensm to + rebuild its FWD tables , post setting Min Hop Tables */ + max_lid_ho = osm_switch_get_max_lid_ho(p_sw); + /* Get base lid of switch by retrieving port 0 lid of node pointer */ + self_lid_ho = cl_ntoh16( osm_node_get_base_lid( p_sw->p_node, 0 ) ); + osm_log( &p_osm->log, OSM_LOG_DEBUG, + "__osm_updn_find_root_nodes_by_min_hop: " + "Passing through switch lid 0x%X\n", self_lid_ho ); + for (lid_ho = 1; lid_ho <= max_lid_ho; lid_ho++) + { + /* Skip lids which are not CAs - + for the histogram purposes we care only about CAs */ + + /* EZ: + boolean_t LidFound = FALSE; + cl_list_iterator_t ca_lid_iterator= cl_list_head(p_ca_list); + while( (ca_lid_iterator != cl_list_end(p_ca_list)) && !LidFound ) + { + uint16_t *p_lid; + + p_lid = (uint16_t*)cl_list_obj(ca_lid_iterator); + if ( *p_lid == lid_ho ) + LidFound = TRUE; + ca_lid_iterator = cl_list_next(ca_lid_iterator); + + } + if ( LidFound ) + */ + if (cl_map_get( &ca_by_lid_map, lid_ho )) + { + hop_val = osm_switch_get_least_hops( p_sw, lid_ho ); + if (hop_val > maxHops) + maxHops = hop_val; + p_updn_hist = + (updn_hist_t*)cl_qmap_get( &min_hop_hist , (uint64_t)hop_val ); + if ( p_updn_hist == (updn_hist_t*)cl_qmap_end( &min_hop_hist)) + { + /* New entry in the histogram , first create it */ + p_updn_hist = (updn_hist_t*) malloc(sizeof(updn_hist_t)); + CL_ASSERT (p_updn_hist); + p_updn_hist->bar_value = 1; + cl_qmap_insert(&min_hop_hist, (uint64_t)hop_val, &p_updn_hist->map_item); + osm_log( &p_osm->log, OSM_LOG_DEBUG, + "__osm_updn_find_root_nodes_by_min_hop: " + "Creating new entry in histogram %u with bar value 1\n", + hop_val ); + } + else + { + /* Entry exist in the table , just increment the value */ + p_updn_hist->bar_value++; + osm_log( &p_osm->log, OSM_LOG_DEBUG, + "__osm_updn_find_root_nodes_by_min_hop: " + "Updating entry in histogram %u with bar value %d\n", + hop_val, p_updn_hist->bar_value ); + } + } + } + + /* Now recognize the spines by requiring one bar to be above 90% of the + number of CAs */ + thd1 = numCas * 0.9; + thd2 = numCas * 0.05; + osm_log( &p_osm->log, OSM_LOG_DEBUG, + "__osm_updn_find_root_nodes_by_min_hop: " + "Pass over the histogram value and find only one root node above " + "thd1 = %f && thd2 = %f\n", thd1, thd2 ); + + p_updn_hist = (updn_hist_t*) cl_qmap_head( &min_hop_hist ); + while( p_updn_hist != (updn_hist_t*)cl_qmap_end( &min_hop_hist ) ) + { + p_up_ht = p_updn_hist; + p_updn_hist = (updn_hist_t*)cl_qmap_next( &p_updn_hist->map_item ) ; + if ( p_up_ht->bar_value > thd1 ) + numHopBarsOverThd1++; + if ( p_up_ht->bar_value > thd2 ) + numHopBarsOverThd2++; + osm_log( &p_osm->log, OSM_LOG_DEBUG, + "__osm_updn_find_root_nodes_by_min_hop: " + "Passing through histogram - Hop Index %u: " + "numHopBarsOverThd1 = %u, numHopBarsOverThd2 = %u\n", + (uint16_t)cl_qmap_key((cl_map_item_t*)p_up_ht), + numHopBarsOverThd1, numHopBarsOverThd2 ); + } + + /* destroy the qmap table and all its content - no longer needed */ + osm_log( &p_osm->log, OSM_LOG_DEBUG, + "__osm_updn_find_root_nodes_by_min_hop: " + "Cleanup: delete histogram " + "UPDN - Root nodes fetching by auto detect\n" ); + p_updn_hist = (updn_hist_t*) cl_qmap_head( &min_hop_hist ); + while ( p_updn_hist != (updn_hist_t*)cl_qmap_end( &min_hop_hist ) ) + { + cl_qmap_remove_item( &min_hop_hist, (cl_map_item_t*)p_updn_hist ); + free( p_updn_hist ); + p_updn_hist = (updn_hist_t*) cl_qmap_head( &min_hop_hist ); + } + + /* If thd conditions are valid insert the root node to the list */ + if ( (numHopBarsOverThd1 == 1) && (numHopBarsOverThd2 == 1) ) + { + p_guid = malloc(sizeof(uint64_t)); + *p_guid = cl_ntoh64(osm_node_get_node_guid(p_sw->p_node)); + osm_log( &p_osm->log, OSM_LOG_DEBUG, + "__osm_updn_find_root_nodes_by_min_hop: " + "Inserting GUID 0x%" PRIx64 " as root node\n", + *p_guid ); + cl_list_insert_tail(p_root_nodes_list, p_guid); + } + } + + /* destroy the map of CA lids */ + cl_map_remove_all( &ca_by_lid_map ); + cl_map_destroy( &ca_by_lid_map ); + + /* Now convert the cl_list to array */ + __osm_updn_convert_list2array(p_updn); + + OSM_LOG_EXIT( &p_osm->log ); + return 0; +} + +/********************************************************************** + **********************************************************************/ +static void +__osm_updn_delete( + void *context ) +{ + updn_t *p_updn = context; + + updn_destroy(p_updn); +} + +int +osm_ucast_updn_setup( + osm_opensm_t *p_osm ) +{ + updn_t *p_updn; + + p_updn = updn_construct(&p_osm->log); + if (!p_updn) + return -1; + p_osm->routing_engine.context = p_updn; + p_osm->routing_engine.delete = __osm_updn_delete; + p_osm->routing_engine.build_lid_matrices = __osm_updn_call; + + if (updn_init(p_updn, p_osm) != IB_SUCCESS) + return -1; + if (!p_updn->auto_detect_root_nodes) + __osm_updn_convert_list2array(p_updn); + + return 0; +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_vl15intf.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_vl15intf.c new file mode 100644 index 00000000..432db640 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_vl15intf.c @@ -0,0 +1,544 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_vl15intf.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_vl15_t. + * This object represents the VL15 Interface object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.6 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/********************************************************************** + **********************************************************************/ +void +__osm_vl15_poller( + IN void *p_ptr ) +{ + ib_api_status_t status; + osm_madw_t *p_madw; + uint32_t mads_sent; + uint32_t unicasts_sent; + uint32_t mads_on_wire; + osm_vl15_t* const p_vl = (osm_vl15_t*)p_ptr; + cl_qlist_t* p_fifo; + + OSM_LOG_ENTER( p_vl->p_log, __osm_vl15_poller ); + + if ( p_vl->thread_state == OSM_THREAD_STATE_NONE) + { + p_vl->thread_state = OSM_THREAD_STATE_RUN; + } + + while( p_vl->thread_state == OSM_THREAD_STATE_RUN ) + { + /* + Start servicing the FIFOs by pulling off MAD wrappers + and passing them to the transport interface. + There are lots of corner cases here so tread carefully. + + The unicast FIFO has priority, since somebody is waiting + for a timely response. + */ + cl_spinlock_acquire( &p_vl->lock ); + + if( cl_qlist_count( &p_vl->ufifo ) != 0 ) + p_fifo = &p_vl->ufifo; + else + p_fifo = &p_vl->rfifo; + + p_madw = (osm_madw_t*)cl_qlist_remove_head( p_fifo ); + + cl_spinlock_release( &p_vl->lock ); + + if( p_madw != (osm_madw_t*)cl_qlist_end( p_fifo ) ) + { + if( osm_log_is_active( p_vl->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_vl->p_log, OSM_LOG_DEBUG, + "__osm_vl15_poller: " + "Servicing p_madw = %p\n", p_madw ); + } + + if( osm_log_is_active( p_vl->p_log, OSM_LOG_FRAMES ) ) + { + osm_dump_dr_smp( p_vl->p_log, + osm_madw_get_smp_ptr( p_madw ), OSM_LOG_FRAMES ); + } + + /* + Non-response-expected mads are not throttled on the wire + since we can have no confirmation that they arrived + at their destination. + */ + if( p_madw->resp_expected == TRUE ) + { + /* + Note that other threads may not see the response MAD + arrive before send() even returns. + In that case, the wire count would temporarily go negative. + To avoid this confusion, preincrement the counts on the + assumption that send() will succeed. + */ + mads_on_wire = cl_atomic_inc( + &p_vl->p_stats->qp0_mads_outstanding_on_wire ); + CL_ASSERT( mads_on_wire <= p_vl->max_wire_smps ); + } + else + { + unicasts_sent = cl_atomic_inc( + &p_vl->p_stats->qp0_unicasts_sent ); + } + + mads_sent = cl_atomic_inc( &p_vl->p_stats->qp0_mads_sent ); + + status = osm_vendor_send( + osm_madw_get_bind_handle( p_madw ), + p_madw, p_madw->resp_expected ); + + if( status != IB_SUCCESS ) + { + uint32_t outstanding; + cl_status_t cl_status; + + osm_log( p_vl->p_log, OSM_LOG_ERROR, + "__osm_vl15_poller: ERR 3E03: " + "MAD send failed (%s)\n", + ib_get_err_str( status ) ); + + /* + The MAD was never successfully sent, so + fix up the pre-incremented count values. + */ + + /* Decrement qp0_mads_sent and qp0_mads_outstanding_on_wire + that was incremented in the code above. */ + mads_sent = cl_atomic_dec( &p_vl->p_stats->qp0_mads_sent ); + if( p_madw->resp_expected == TRUE ) + cl_atomic_dec( &p_vl->p_stats->qp0_mads_outstanding_on_wire ); + + /* + The following code is similar to the code in + __osm_sm_mad_ctrl_retire_trans_mad. We need to decrement the + qp0_mads_outstanding counter, and if we reached 0 - need to call + the cl_disp_post with OSM_SIGNAL_NO_PENDING_TRANSACTION (in order + to wake up the state mgr). + There is one difference from the code in __osm_sm_mad_ctrl_retire_trans_mad. + This code is called on all mads, if osm_vendor_send() failed, unlike + __osm_sm_mad_ctrl_retire_trans_mad which is called only on mads where + resp_expected == TRUE. As a result, the qp0_mads_outstanding counter + should be decremented and handled accordingly only if this is a mad + with resp_expected == TRUE. + */ + if ( p_madw->resp_expected == TRUE ) + { + outstanding = cl_atomic_dec( &p_vl->p_stats->qp0_mads_outstanding ); + + osm_log( p_vl->p_log, OSM_LOG_DEBUG, + "__osm_vl15_poller: " + "%u QP0 MADs outstanding\n", + p_vl->p_stats->qp0_mads_outstanding ); + + if( outstanding == 0 ) + { + /* + The wire is clean. + Signal the state manager. + */ + if( osm_log_is_active( p_vl->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_vl->p_log, OSM_LOG_DEBUG, + "__osm_vl15_poller: " + "Posting Dispatcher message %s\n", + osm_get_disp_msg_str( OSM_MSG_NO_SMPS_OUTSTANDING ) ); + } + + cl_status = cl_disp_post( p_vl->h_disp, + OSM_MSG_NO_SMPS_OUTSTANDING, + (void *)OSM_SIGNAL_NO_PENDING_TRANSACTIONS, + NULL, + NULL ); + + if( cl_status != CL_SUCCESS ) + { + osm_log( p_vl->p_log, OSM_LOG_ERROR, + "__osm_vl15_poller: ERR 3E06: " + "Dispatcher post message failed (%s)\n", + CL_STATUS_MSG( cl_status ) ); + } + } + } + } + else + { + if( osm_log_is_active( p_vl->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_vl->p_log, OSM_LOG_DEBUG, + "__osm_vl15_poller: " + "%u QP0 MADs on wire, %u outstanding, %u unicasts sent, " + "%u total sent\n", + p_vl->p_stats->qp0_mads_outstanding_on_wire, + p_vl->p_stats->qp0_mads_outstanding, + p_vl->p_stats->qp0_unicasts_sent, + p_vl->p_stats->qp0_mads_sent ); + } + } + } + else + { + /* + The VL15 FIFO is empty, so we have nothing left to do. + */ + status = cl_event_wait_on( &p_vl->signal, + EVENT_NO_TIMEOUT, TRUE ); + } + + while( (p_vl->p_stats->qp0_mads_outstanding_on_wire >= + (int32_t)p_vl->max_wire_smps ) && + (p_vl->thread_state == OSM_THREAD_STATE_RUN ) ) + { + status = cl_event_wait_on( &p_vl->signal, + EVENT_NO_TIMEOUT, TRUE ); + } + + if( status != CL_SUCCESS ) + { + osm_log( p_vl->p_log, OSM_LOG_ERROR, + "__osm_vl15_poller: ERR 3E02: " + "Event wait failed (%s)\n", + CL_STATUS_MSG( status ) ); + } + } + + /* + since we abort immediately when the state != OSM_THREAD_STATE_RUN + we might have some mads on the queues. After the thread exits + the vl15 destroy routine should put back these mads... + */ + + OSM_LOG_EXIT( p_vl->p_log ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_vl15_construct( + IN osm_vl15_t* const p_vl ) +{ + memset( p_vl, 0, sizeof(*p_vl) ); + p_vl->state = OSM_VL15_STATE_INIT; + p_vl->thread_state = OSM_THREAD_STATE_NONE; + cl_event_construct( &p_vl->signal ); + cl_spinlock_construct( &p_vl->lock ); + cl_qlist_init( &p_vl->rfifo ); + cl_qlist_init( &p_vl->ufifo ); + cl_thread_construct( &p_vl->poller ); + p_vl->h_disp = CL_DISP_INVALID_HANDLE; +} + +/********************************************************************** + **********************************************************************/ +void +osm_vl15_destroy( + IN osm_vl15_t* const p_vl, + IN struct _osm_mad_pool *p_pool) +{ + osm_madw_t* p_madw; + + OSM_LOG_ENTER( p_vl->p_log, osm_vl15_destroy ); + + /* + Signal our threads that we're leaving. + */ + p_vl->thread_state = OSM_THREAD_STATE_EXIT; + + /* + Don't trigger unless event has been initialized. + Destroy the thread before we tear down the other objects. + */ + if( p_vl->state != OSM_VL15_STATE_INIT ) + cl_event_signal( &p_vl->signal ); + + cl_thread_destroy( &p_vl->poller ); + + /* + Return the outstanding messages to the pool + */ + + cl_spinlock_acquire( &p_vl->lock ); + + while (!cl_is_qlist_empty( &p_vl->rfifo)) + { + p_madw = (osm_madw_t*)cl_qlist_remove_head( &p_vl->rfifo); + osm_mad_pool_put( p_pool, p_madw ); + } + while (!cl_is_qlist_empty( &p_vl->ufifo)) + { + p_madw = (osm_madw_t*)cl_qlist_remove_head( &p_vl->ufifo); + osm_mad_pool_put( p_pool, p_madw ); + } + + cl_spinlock_release( &p_vl->lock ); + + cl_event_destroy( &p_vl->signal ); + p_vl->state = OSM_VL15_STATE_INIT; + cl_spinlock_destroy( &p_vl->lock ); + + OSM_LOG_EXIT( p_vl->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_vl15_init( + IN osm_vl15_t* const p_vl, + IN osm_vendor_t* const p_vend, + IN osm_log_t* const p_log, + IN osm_stats_t* const p_stats, + IN const int32_t max_wire_smps, + IN osm_subn_t* const p_subn, + IN cl_dispatcher_t* const p_disp, + IN cl_plock_t* const p_lock + ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_vl15_init ); + + p_vl->p_vend = p_vend; + p_vl->p_log = p_log; + p_vl->p_stats = p_stats; + p_vl->max_wire_smps = max_wire_smps; + p_vl->p_subn = p_subn; + p_vl->p_lock = p_lock; + + status = cl_event_init( &p_vl->signal, FALSE ); + if( status != IB_SUCCESS ) + goto Exit; + + p_vl->state = OSM_VL15_STATE_READY; + + status = cl_spinlock_init( &p_vl->lock ); + if( status != IB_SUCCESS ) + goto Exit; + + /* + Initialize the thread after all other dependent objects + have been initialized. + */ + status = cl_thread_init( &p_vl->poller, __osm_vl15_poller, p_vl, + "opensm poller" ); + if( status != IB_SUCCESS ) + goto Exit; + + p_vl->h_disp = cl_disp_register( + p_disp, + CL_DISP_MSGID_NONE, + NULL, + NULL ); + + if( p_vl->h_disp == CL_DISP_INVALID_HANDLE ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_vl15_init: ERR 3E01: " + "Dispatcher registration failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_vl15_poll( + IN osm_vl15_t* const p_vl ) +{ + OSM_LOG_ENTER( p_vl->p_log, osm_vl15_poll ); + + CL_ASSERT( p_vl->state == OSM_VL15_STATE_READY ); + + /* + If we have room for more VL15 MADs on the wire, + then signal the poller thread. + + This is not an airtight check, since the poller thread + could be just about to send another MAD as we signal + the event here. To cover this rare case, the poller + thread checks for a spurious wake-up. + */ + if( p_vl->p_stats->qp0_mads_outstanding_on_wire < + (int32_t)p_vl->max_wire_smps ) + { + if( osm_log_is_active( p_vl->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_vl->p_log, OSM_LOG_DEBUG, + "osm_vl15_poll: " + "Signalling poller thread\n" ); + } + + cl_event_signal( &p_vl->signal ); + } + + OSM_LOG_EXIT( p_vl->p_log ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_vl15_post( + IN osm_vl15_t* const p_vl, + IN osm_madw_t* const p_madw ) +{ + OSM_LOG_ENTER( p_vl->p_log, osm_vl15_post ); + + CL_ASSERT( p_vl->state == OSM_VL15_STATE_READY ); + + if( osm_log_is_active( p_vl->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_vl->p_log, OSM_LOG_DEBUG, + "osm_vl15_post: " + "Posting p_madw = 0x%p\n", p_madw ); + } + + /* + Determine in which fifo to place the pending madw. + */ + cl_spinlock_acquire( &p_vl->lock ); + if( p_madw->resp_expected == TRUE ) + { + cl_qlist_insert_tail( &p_vl->rfifo, (cl_list_item_t*)p_madw ); + cl_atomic_inc( &p_vl->p_stats->qp0_mads_outstanding ); + } + else + { + cl_qlist_insert_tail( &p_vl->ufifo, (cl_list_item_t*)p_madw ); + } + cl_spinlock_release( &p_vl->lock ); + + if( osm_log_is_active( p_vl->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_vl->p_log, OSM_LOG_DEBUG, + "osm_vl15_post: " + "%u QP0 MADs on wire, %u QP0 MADs outstanding\n", + p_vl->p_stats->qp0_mads_outstanding_on_wire, + p_vl->p_stats->qp0_mads_outstanding ); + } + + osm_vl15_poll( p_vl ); + + OSM_LOG_EXIT( p_vl->p_log ); +} + +void +osm_vl15_shutdown( + IN osm_vl15_t* const p_vl, + IN osm_mad_pool_t* const p_mad_pool) +{ + osm_madw_t* p_madw; + + OSM_LOG_ENTER( p_vl->p_log, osm_vl15_shutdown ); + + /* we only should get here after the VL15 interface was initialized */ + CL_ASSERT( p_vl->state == OSM_VL15_STATE_READY ); + + /* grap a lock on the object */ + cl_spinlock_acquire( &p_vl->lock ); + + cl_disp_unregister( p_vl->h_disp ); + + /* go over all outstanding MADs and retire their transactions */ + + /* first we handle the list of response MADs */ + p_madw = (osm_madw_t*)cl_qlist_remove_head( &p_vl->ufifo ); + while ( p_madw != (osm_madw_t*)cl_qlist_end( &p_vl->ufifo ) ) + { + if( osm_log_is_active( p_vl->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_vl->p_log, OSM_LOG_DEBUG, + "osm_vl15_shutdown: " + "Releasing Response p_madw = %p\n", p_madw ); + } + + osm_mad_pool_put( p_mad_pool, p_madw ); + + p_madw = (osm_madw_t*)cl_qlist_remove_head( &p_vl->ufifo ); + } + + /* Request MADs we send out */ + p_madw = (osm_madw_t*)cl_qlist_remove_head( &p_vl->rfifo ); + while ( p_madw != (osm_madw_t*)cl_qlist_end( &p_vl->rfifo ) ) + { + if( osm_log_is_active( p_vl->p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_vl->p_log, OSM_LOG_DEBUG, + "osm_vl15_shutdown: " + "Releasing Request p_madw = %p\n", p_madw ); + } + + osm_mad_pool_put( p_mad_pool, p_madw ); + cl_atomic_dec( &p_vl->p_stats->qp0_mads_outstanding ); + + p_madw = (osm_madw_t*)cl_qlist_remove_head( &p_vl->rfifo ); + } + + /* free the lock */ + cl_spinlock_release( &p_vl->lock ); + + OSM_LOG_EXIT( p_vl->p_log ); +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_vl_arb_rcv.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_vl_arb_rcv.c new file mode 100644 index 00000000..07683ddb --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_vl_arb_rcv.c @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_vl_arb_rcv.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_vla_rcv_t. + * This object represents the Vl Arbitration Receiver object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.6 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +osm_vla_rcv_construct( + IN osm_vla_rcv_t* const p_rcv ) +{ + memset( p_rcv, 0, sizeof(*p_rcv) ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_vla_rcv_destroy( + IN osm_vla_rcv_t* const p_rcv ) +{ + CL_ASSERT( p_rcv ); + + OSM_LOG_ENTER( p_rcv->p_log, osm_vla_rcv_destroy ); + + OSM_LOG_EXIT( p_rcv->p_log ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_vla_rcv_init( + IN osm_vla_rcv_t* const p_rcv, + IN osm_req_t* const p_req, + IN osm_subn_t* const p_subn, + IN osm_log_t* const p_log, + IN cl_plock_t* const p_lock ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_vla_rcv_init ); + + osm_vla_rcv_construct( p_rcv ); + + p_rcv->p_log = p_log; + p_rcv->p_subn = p_subn; + p_rcv->p_lock = p_lock; + p_rcv->p_req = p_req; + + OSM_LOG_EXIT( p_log ); + return( status ); +} + +/********************************************************************** + **********************************************************************/ +/* + * WE MIGHT ONLY RECEIVE GET or SET responses + */ +void +osm_vla_rcv_process( + IN const osm_vla_rcv_t* const p_rcv, + IN osm_madw_t* const p_madw ) +{ + cl_qmap_t *p_guid_tbl; + ib_vl_arb_table_t *p_vla_tbl; + ib_smp_t *p_smp; + osm_port_t *p_port; + osm_physp_t *p_physp; + osm_node_t *p_node; + osm_vla_context_t *p_context; + ib_net64_t port_guid; + ib_net64_t node_guid; + uint8_t port_num, block_num; + + CL_ASSERT( p_rcv ); + + OSM_LOG_ENTER( p_rcv->p_log, osm_vla_rcv_process ); + + CL_ASSERT( p_madw ); + + p_smp = osm_madw_get_smp_ptr( p_madw ); + + p_context = osm_madw_get_vla_context_ptr( p_madw ); + p_vla_tbl = (ib_vl_arb_table_t*)ib_smp_get_payload_ptr( p_smp ); + + port_guid = p_context->port_guid; + node_guid = p_context->node_guid; + + CL_ASSERT( p_smp->attr_id == IB_MAD_ATTR_VL_ARBITRATION ); + + p_guid_tbl = &p_rcv->p_subn->port_guid_tbl; + cl_plock_excl_acquire( p_rcv->p_lock ); + p_port = (osm_port_t*)cl_qmap_get( p_guid_tbl, port_guid ); + + if( p_port == (osm_port_t*)cl_qmap_end( p_guid_tbl ) ) + { + cl_plock_release( p_rcv->p_lock ); + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_vla_rcv_process: ERR 3F06: " + "No port object for port with GUID 0x%" PRIx64 + "\n\t\t\t\tfor parent node GUID 0x%" PRIx64 + ", TID 0x%" PRIx64 "\n", + cl_ntoh64( port_guid ), + cl_ntoh64( node_guid ), + cl_ntoh64( p_smp->trans_id ) ); + goto Exit; + } + + p_node = osm_port_get_parent_node( p_port ); + CL_ASSERT( p_node ); + + block_num = (uint8_t)(cl_ntoh32(p_smp->attr_mod) >> 16); + /* in case of a non switch node the attr modifier should be ignored */ + if (osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH) + { + port_num = (uint8_t)(cl_ntoh32(p_smp->attr_mod) & 0x000000FF); + p_physp = osm_node_get_physp_ptr( p_node, port_num ); + } + else + { + p_physp = osm_port_get_default_phys_ptr(p_port); + port_num = p_port->default_port_num; + } + + CL_ASSERT( p_physp ); + + /* + We do not mind if this is a result of a set or get - all we want is to update + the subnet. + */ + if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_VERBOSE, + "osm_vla_rcv_process: " + "Got GetResp(VLArb) block:%u port_num %u with GUID 0x%" PRIx64 + " for parent node GUID 0x%" PRIx64 + ", TID 0x%" PRIx64 "\n", + block_num, port_num, + cl_ntoh64( port_guid ), + cl_ntoh64( node_guid ), + cl_ntoh64( p_smp->trans_id ) ); + } + + /* + Determine if we encountered a new Physical Port. + If so, Ignore it. + */ + if( !osm_physp_is_valid( p_physp ) ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_vla_rcv_process: " + "Got invalid port number 0x%X\n", + port_num ); + goto Exit; + } + + osm_dump_vl_arb_table( p_rcv->p_log, + port_guid, block_num, + port_num, p_vla_tbl, + OSM_LOG_DEBUG ); + + if ( (block_num < 1) || (block_num > 4) ) + { + osm_log( p_rcv->p_log, OSM_LOG_ERROR, + "osm_vla_rcv_process: " + "Got invalid block number 0x%X\n", + block_num ); + goto Exit; + } + osm_physp_set_vla_tbl( p_physp, p_vla_tbl, block_num); + + Exit: + cl_plock_release( p_rcv->p_lock ); + + OSM_LOG_EXIT( p_rcv->p_log ); +} + + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_vl_arb_rcv_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_vl_arb_rcv_ctrl.c new file mode 100644 index 00000000..8e8fcc93 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_vl_arb_rcv_ctrl.c @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osm_vl_arb_rcv_ctrl.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* + * Abstract: + * Implementation of osm_vla_rcv_ctrl_t. + * This object represents the Vl Arbitration request controller object. + * This object is part of the opensm family of objects. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.4 $ + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/********************************************************************** + **********************************************************************/ +void +__osm_vla_rcv_ctrl_disp_callback( + IN void *context, + IN void *p_data ) +{ + /* ignore return status when invoked via the dispatcher */ + osm_vla_rcv_process( ((osm_vla_rcv_ctrl_t*)context)->p_rcv, + (osm_madw_t*)p_data ); +} + +/********************************************************************** + **********************************************************************/ +void +osm_vla_rcv_ctrl_construct( + IN osm_vla_rcv_ctrl_t* const p_ctrl ) +{ + memset( p_ctrl, 0, sizeof(*p_ctrl) ); + p_ctrl->h_disp = CL_DISP_INVALID_HANDLE; +} + +/********************************************************************** + **********************************************************************/ +void +osm_vla_rcv_ctrl_destroy( + IN osm_vla_rcv_ctrl_t* const p_ctrl ) +{ + CL_ASSERT( p_ctrl ); + cl_disp_unregister( p_ctrl->h_disp ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osm_vla_rcv_ctrl_init( + IN osm_vla_rcv_ctrl_t* const p_ctrl, + IN osm_vla_rcv_t* const p_rcv, + IN osm_log_t* const p_log, + IN cl_dispatcher_t* const p_disp ) +{ + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osm_vla_rcv_ctrl_init ); + + osm_vla_rcv_ctrl_construct( p_ctrl ); + p_ctrl->p_log = p_log; + + p_ctrl->p_rcv = p_rcv; + p_ctrl->p_disp = p_disp; + + p_ctrl->h_disp = cl_disp_register( + p_disp, + OSM_MSG_MAD_VL_ARB, + __osm_vla_rcv_ctrl_disp_callback, + p_ctrl ); + + if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osm_vla_rcv_ctrl_init: ERR 4001: " + "Dispatcher registration failed\n" ); + status = IB_INSUFFICIENT_RESOURCES; + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return( status ); +} + + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/st.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/st.c new file mode 100644 index 00000000..0597b9ed --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/st.c @@ -0,0 +1,625 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: st.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + + +/* static char sccsid[] = "@(#) st.c 5.1 89/12/14 Crucible"; */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +#ifdef _WIN32 +#include +#endif + +typedef struct st_table_entry st_table_entry; + +struct st_table_entry { + unsigned int hash; + st_data_t key; + st_data_t record; + st_table_entry *next; +}; + +#define ST_DEFAULT_MAX_DENSITY 5 +#define ST_DEFAULT_INIT_TABLE_SIZE 11 + +/* + * DEFAULT_MAX_DENSITY is the default for the largest we allow the + * average number of items per bin before increasing the number of + * bins + * + * DEFAULT_INIT_TABLE_SIZE is the default for the number of bins + * allocated initially + * + */ +static int numcmp(void *, void *); +static st_ptr_t numhash(void *); +static struct st_hash_type type_numhash = { + numcmp, + numhash, +}; + + +/* extern int strcmp(const char *, const char *); */ +static int strhash(const char *); + +static inline st_ptr_t st_strhash(void *key) +{ + return strhash((const char *)key); +} + +static inline int st_strcmp(void *key1, void *key2) +{ + return strcmp((const char *)key1, (const char *)key2); +} + +static struct st_hash_type type_strhash = { + st_strcmp, + st_strhash +}; + + +#define xmalloc malloc +#define xcalloc calloc +#define xrealloc realloc +#define xfree free + +static void rehash(st_table *); + +#define alloc(type) (type*)xmalloc(sizeof(type)) +#define Calloc(n,s) (char*)xcalloc((n), (s)) + +#define EQUAL(table,x,y) ((x)==(y) || (*table->type->compare)(((void*)x),((void *)y)) == 0) + +#define do_hash(key,table) (unsigned int)(*(table)->type->hash)(((void*)key)) +#define do_hash_bin(key,table) (do_hash(key, table)%(table)->num_bins) + +/* + * MINSIZE is the minimum size of a dictionary. + */ + +#define MINSIZE 8 + +/* + Table of prime numbers 2^n+a, 2<=n<=30. +*/ +static long primes[] = { + 8 + 3, + 16 + 3, + 32 + 5, + 64 + 3, + 128 + 3, + 256 + 27, + 512 + 9, + 1024 + 9, + 2048 + 5, + 4096 + 3, + 8192 + 27, + 16384 + 43, + 32768 + 3, + 65536 + 45, + 131072 + 29, + 262144 + 3, + 524288 + 21, + 1048576 + 7, + 2097152 + 17, + 4194304 + 15, + 8388608 + 9, + 16777216 + 43, + 33554432 + 35, + 67108864 + 15, + 134217728 + 29, + 268435456 + 3, + 536870912 + 11, + 1073741824 + 85, + 0 +}; + +static int +new_size(int size) +{ + int i; + +#if 0 + for (i=3; i<31; i++) { + if ((1< size) return 1< size) return primes[i]; + } + /* Ran out of polynomials */ + return -1; /* should raise exception */ +#endif +} + +#ifdef HASH_LOG +static int collision = 0; +static int init_st = 0; + +static void +stat_col() +{ + FILE *f = fopen("/var/log/osm_st_col", "w"); + fprintf(f, "collision: %d\n", collision); + fclose(f); +} +#endif + +st_table* +st_init_table_with_size(type, size) + struct st_hash_type *type; + size_t size; +{ + st_table *tbl; + +#ifdef HASH_LOG + if (init_st == 0) + { + init_st = 1; + atexit(stat_col); + } +#endif + + size = new_size(size); /* round up to prime number */ + + tbl = alloc(st_table); + tbl->type = type; + tbl->num_entries = 0; + tbl->num_bins = size; + tbl->bins = (st_table_entry **)Calloc(size, sizeof(st_table_entry*)); + + return tbl; +} + +st_table* +st_init_table(type) + struct st_hash_type *type; +{ + return st_init_table_with_size(type, 0); +} + +st_table* +st_init_numtable(void) +{ + return st_init_table(&type_numhash); +} + +st_table* +st_init_numtable_with_size(size) + size_t size; +{ + return st_init_table_with_size(&type_numhash, size); +} + +st_table* +st_init_strtable(void) +{ + return st_init_table(&type_strhash); +} + +st_table* +st_init_strtable_with_size(size) + size_t size; +{ + return st_init_table_with_size(&type_strhash, size); +} + +void +st_free_table(table) + st_table *table; +{ + register st_table_entry *ptr, *next; + int i; + + for (i = 0; i < table->num_bins; i++) { + ptr = table->bins[i]; + while (ptr != 0) { + next = ptr->next; + free(ptr); + ptr = next; + } + } + free(table->bins); + free(table); +} + +#define PTR_NOT_EQUAL(table, ptr, hash_val, key) \ +((ptr) != 0 && (ptr->hash != (hash_val) || !EQUAL((table), (key), (ptr)->key))) + +#ifdef HASH_LOG +#define COLLISION collision++ +#else +#define COLLISION +#endif + +#define FIND_ENTRY(table, ptr, hash_val, bin_pos) do {\ + bin_pos = hash_val%(table)->num_bins;\ + ptr = (table)->bins[bin_pos];\ + if (PTR_NOT_EQUAL(table, ptr, hash_val, key)) \ + {\ + COLLISION;\ + while (PTR_NOT_EQUAL(table, ptr->next, hash_val, key)) {\ + ptr = ptr->next;\ + }\ + ptr = ptr->next;\ + }\ +} while (0) + +int +st_lookup(table, key, value) + st_table *table; + register st_data_t key; + st_data_t *value; +{ + unsigned int hash_val, bin_pos; + register st_table_entry *ptr; + + hash_val = do_hash(key, table); + FIND_ENTRY(table, ptr, hash_val, bin_pos); + + if (ptr == 0) + { + return 0; + } + else + { + if (value != 0) + *value = ptr->record; + return 1; + } +} + +#define ADD_DIRECT(table, key, value, hash_val, bin_pos)\ +do {\ + st_table_entry *entry;\ + if (table->num_entries/(table->num_bins) > ST_DEFAULT_MAX_DENSITY) \ + {\ + rehash(table);\ + bin_pos = hash_val % table->num_bins;\ + }\ + \ + entry = alloc(st_table_entry);\ + \ + entry->hash = hash_val;\ + entry->key = key;\ + entry->record = value;\ + entry->next = table->bins[bin_pos];\ + table->bins[bin_pos] = entry;\ + table->num_entries++;\ +} while (0); + + +int +st_insert(table, key, value) + register st_table *table; + register st_data_t key; + st_data_t value; +{ + unsigned int hash_val, bin_pos; + register st_table_entry *ptr; + + hash_val = do_hash(key, table); + FIND_ENTRY(table, ptr, hash_val, bin_pos); + + if (ptr == 0) + { + ADD_DIRECT(table, key, value, hash_val, bin_pos); + return 0; + } + else + { + ptr->record = value; + return 1; + } +} + +void +st_add_direct(table, key, value) + st_table *table; + st_data_t key; + st_data_t value; +{ + unsigned int hash_val, bin_pos; + + hash_val = do_hash(key, table); + bin_pos = hash_val % table->num_bins; + ADD_DIRECT(table, key, value, hash_val, bin_pos); +} + +static void +rehash(table) + register st_table *table; +{ + register st_table_entry *ptr, *next, **new_bins; + int i, old_num_bins = table->num_bins, new_num_bins; + unsigned int hash_val; + + new_num_bins = new_size(old_num_bins+1); + new_bins = (st_table_entry**)Calloc(new_num_bins, sizeof(st_table_entry*)); + + for (i = 0; i < old_num_bins; i++) { + ptr = table->bins[i]; + while (ptr != 0) { + next = ptr->next; + hash_val = ptr->hash % new_num_bins; + ptr->next = new_bins[hash_val]; + new_bins[hash_val] = ptr; + ptr = next; + } + } + free(table->bins); + table->num_bins = new_num_bins; + table->bins = new_bins; +} + +st_table* +st_copy(old_table) + st_table *old_table; +{ + st_table *new_table; + st_table_entry *ptr, *entry; + size_t i, num_bins = old_table->num_bins; + + new_table = alloc(st_table); + if (new_table == 0) + { + return 0; + } + + *new_table = *old_table; + new_table->bins = (st_table_entry**) + Calloc(num_bins, sizeof(st_table_entry*)); + + if (new_table->bins == 0) + { + free(new_table); + return 0; + } + + for (i = 0; i < num_bins; i++) { + new_table->bins[i] = 0; + ptr = old_table->bins[i]; + while (ptr != 0) { + entry = alloc(st_table_entry); + if (entry == 0) + { + free(new_table->bins); + free(new_table); + return 0; + } + *entry = *ptr; + entry->next = new_table->bins[i]; + new_table->bins[i] = entry; + ptr = ptr->next; + } + } + return new_table; +} + +int +st_delete(table, key, value) + register st_table *table; + register st_data_t *key; + st_data_t *value; +{ + unsigned int hash_val; + st_table_entry *tmp; + register st_table_entry *ptr; + + hash_val = do_hash_bin(*key, table); + ptr = table->bins[hash_val]; + + if (ptr == 0) + { + if (value != 0) *value = 0; + return 0; + } + + if (EQUAL(table, *key, ptr->key)) + { + table->bins[hash_val] = ptr->next; + table->num_entries--; + if (value != 0) *value = ptr->record; + *key = ptr->key; + free(ptr); + return 1; + } + + for (; ptr->next != 0; ptr = ptr->next) { + if (EQUAL(table, ptr->next->key, *key)) + { + tmp = ptr->next; + ptr->next = ptr->next->next; + table->num_entries--; + if (value != 0) *value = tmp->record; + *key = tmp->key; + free(tmp); + return 1; + } + } + + return 0; +} + +int +st_delete_safe(table, key, value, never) + register st_table *table; + register st_data_t *key; + st_data_t *value; + st_data_t never; +{ + unsigned int hash_val; + register st_table_entry *ptr; + + hash_val = do_hash_bin(*key, table); + ptr = table->bins[hash_val]; + + if (ptr == 0) + { + if (value != 0) *value = 0; + return 0; + } + + for (; ptr != 0; ptr = ptr->next) { + if ((ptr->key != never) && EQUAL(table, ptr->key, *key)) + { + table->num_entries--; + *key = ptr->key; + if (value != 0) *value = ptr->record; + ptr->key = ptr->record = never; + return 1; + } + } + + return 0; +} + +static int +delete_never(st_data_t key, st_data_t value, st_data_t never) +{ + if (value == never) return ST_DELETE; + return ST_CONTINUE; +} + +void +st_cleanup_safe(table, never) + st_table *table; + st_data_t never; +{ + int num_entries = table->num_entries; + + st_foreach(table, delete_never, never); + table->num_entries = num_entries; +} + +void +st_foreach(table, func, arg) + st_table *table; + int (*func)(st_data_t key, st_data_t val, st_data_t arg); + st_data_t arg; +{ + st_table_entry *ptr, *last, *tmp; + enum st_retval retval; + int i; + + for (i = 0; i < table->num_bins; i++) { + last = 0; + for (ptr = table->bins[i]; ptr != 0;) { + retval = (*func)(ptr->key, ptr->record, arg); + switch (retval) { + case ST_CONTINUE: + last = ptr; + ptr = ptr->next; + break; + case ST_STOP: + return; + case ST_DELETE: + tmp = ptr; + if (last == 0) + { + table->bins[i] = ptr->next; + } + else + { + last->next = ptr->next; + } + ptr = ptr->next; + free(tmp); + table->num_entries--; + } + } + } +} + +static int +strhash(string) + register const char *string; +{ + register int c; + +#ifdef HASH_ELFHASH + register unsigned int h = 0, g; + + while ((c = *string++) != '\0') { + h = ( h << 4 ) + c; + if ( g = h & 0xF0000000 ) + h ^= g >> 24; + h &= ~g; + } + return h; +#elif HASH_PERL + register int val = 0; + + while ((c = *string++) != '\0') { + val = val*33 + c; + } + + return val + (val>>5); +#else + register int val = 0; + + while ((c = *string++) != '\0') { + val = val*997 + c; + } + + return val + (val>>5); +#endif +} + +static int +numcmp(x, y) + void *x, *y; +{ + return (st_ptr_t)x != (st_ptr_t)y; +} + +static st_ptr_t +numhash(n) + void *n; +{ + return (st_ptr_t)n; +} + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/Makefile b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/Makefile new file mode 100644 index 00000000..9c985f57 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/Makefile @@ -0,0 +1,7 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the driver components of the Windows NT DDK +# + +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/SOURCES b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/SOURCES new file mode 100644 index 00000000..3206e1ef --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/SOURCES @@ -0,0 +1,69 @@ +!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_MSVCRT=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 + +!else + $(LIBPATH)\*\ibald.lib \ + $(LIBPATH)\*\complibd.lib \ + $(TARGETPATH)\*\osmv_ibald.lib \ + $(TARGETPATH)\*\opensm_ibald.lib +!endif + +#DO NOT TOUCH the order of search path , until ib_types.h merging process will be done +INCLUDES= \ + $(OSM_HOME)\osmtest\include; \ + $(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 +C_DEFINES=$(C_DEFINES) -I.. -DHAVE_CONFIG_H +!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/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/error.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/error.h new file mode 100644 index 00000000..16e438ef --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/error.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: error.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of error code ranges for the various osmtest modules. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.2 $ + */ + + +/* + osmtest object + 0x0100 - 0x01FF + + parser object + 0x0200 - 0x02FF + + osmtest object + 0x0300 - 0x03FF + +*/ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/osmt_inform.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/osmt_inform.h new file mode 100644 index 00000000..1f432d89 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/osmt_inform.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osmt_inform.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +#ifndef __OSMT_INFORM__ +#define __OSMT_INFORM__ + +#ifdef OSM_VENDOR_INTF_MTL +#include +#include +#include "osmt_mtl_regular_qp.h" +#endif + +typedef struct _osmt_qp_ctx +{ +#ifdef OSM_VENDOR_INTF_MTL + osmt_mtl_mad_res_t qp_bind_hndl; +#endif + uint8_t *p_send_buf; + uint8_t *p_recv_buf; +#ifdef OSM_VENDOR_INTF_MTL + IB_MGT_mad_hndl_t ib_mgt_qp0_handle; +#endif +} +osmt_qp_ctx_t; + +ib_api_status_t +osmt_bind_inform_qp( IN osmtest_t * const p_osmt, + OUT osmt_qp_ctx_t *p_qp_ctx); + +void +osmt_unbind_inform_qp( IN osmtest_t * const p_osmt, + IN osmt_qp_ctx_t *p_qp_ctx); + + +ib_api_status_t +osmt_reg_unreg_inform_info( IN osmtest_t *p_osmt, + IN osmt_qp_ctx_t *p_qp_ctx, + IN ib_inform_info_t *p_inform_info, + IN uint8_t reg_flag + ); + +ib_api_status_t +osmt_trap_wait( IN osmtest_t * const p_osmt, + IN osmt_qp_ctx_t *p_qp_ctx + ); + +ib_api_status_t +osmt_init_inform_info(IN osmtest_t * const p_osmt, + OUT ib_inform_info_t* p_ii); + +ib_api_status_t +osmt_init_inform_info_by_trap (IN osmtest_t * const p_osmt, + IN ib_net16_t trap_num, + OUT ib_inform_info_t* p_ii); + +#endif /* __OSMT_INFORM__ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/osmt_mtl_regular_qp.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/osmt_mtl_regular_qp.h new file mode 100644 index 00000000..787619a9 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/osmt_mtl_regular_qp.h @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osmt_mtl_regular_qp.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * mad.h - + * Header file for common special QP resources creation code. + * + * Creation date: + * + * Version: osmt_mtl_regular_qp.h,v 1.2 2003/03/20 16:05:10 eitan + * + * Authors: + * Elazar Raab + * + * Changes: + */ + +#ifndef H_MAD_H +#define H_MAD_H + +#include +#include +#include +#include + + +#if defined(MAD_IN) || defined(MAD_OUT) +#error MACROS MAD_IN and MAD_OUT are in use, do not override +#endif +#define MAD_IN +#define MAD_OUT + + + +/* HCA Constants */ +#define HCA_ID "mt21108_pci0" +#define GRH_LEN 40 +#define KNOWN_QP1_QKEY 0x80010000 + + +#define MAX_OUTS_SQ 2 /* Max. buffers posted for requests in SQ */ +#define MAX_OUTS_RQ 5 /* Max. buffers posted for responses in RQ */ + +#define MAX_POLL_CNT 300 +#define POLL_SLEEP 1 /* for usleep */ + +#define MAD_SIZE 256 /* MADs are always 256B */ +#define MAD_ATTR_OFFSET 16 +#define MAD_TID_OFFSET 8 + + + + +/* Verbs SQP resources handles */ +typedef struct { + VAPI_hca_id_t hca_id; /*id of HCA*/ + u_int8_t port_num; /* the port num to use */ + VAPI_hca_hndl_t hca_hndl; /*handle of HCA*/ + VAPI_qp_hndl_t qp_hndl; /*handle of QP I use*/ + VAPI_mr_hndl_t mr_hndl; /*handle of memory region*/ + VAPI_cq_hndl_t rq_cq_hndl, sq_cq_hndl; /*handle of send & receive completion Queues*/ + VAPI_pd_hndl_t pd_hndl; /*handle of Partition Domain*/ + /* VAPI_ud_av_hndl_t av_hndl;*/ + IB_lid_t slid; /*LID*/ + void *buf_ptr; /*mem buffer for outstanding pkts*/ + MT_size_t buf_size; /*size of mem buffer for outstanding pkts*/ + + u_int32_t max_outs_sq; /*max # of outstanding pkts in send queue*/ + u_int32_t max_outs_rq; /*max # of outstanding pkts in receive queue*/ + + IB_rkey_t l_key; /*my l_key for memory regions*/ + VAPI_qkey_t qkey; /*my qkey*/ + + EVAPI_compl_handler_hndl_t rq_cq_eventh, sq_cq_eventh; /* event handlers for polling */ + + bool is_sqp; /* relate to union below - my QP*/ + union { + VAPI_special_qp_t sqp_type; + VAPI_qp_num_t qp_num; + } qp_id; + void *wait_q; +} osmt_mtl_mad_res_t; + + +/* init an osmt_mtl_mad_res_t with all resources initialized (use functions below) */ +VAPI_ret_t osmt_mtl_init( + osmt_mtl_mad_res_t* res /*pointer to res (resources) struct*/ + ); +VAPI_ret_t osmt_mtl_init_opened_hca( + osmt_mtl_mad_res_t* res /*pointer to res (resources) struct*/ + ); + +/* Cleanup all resources of (which are valid) in res */ +VAPI_ret_t osmt_mtl_mad_cleanup( + osmt_mtl_mad_res_t *res /*pointer to res (resources) struct*/ + ); + + +/* create CQs and QP as given in res->is_sqp (if TRUE, get special QP) */ +VAPI_ret_t osmt_mtl_get_qp_resources( + osmt_mtl_mad_res_t *res /*pointer to res (resources) struct*/ +); + + +/* move QP to RTS state */ +VAPI_ret_t osmt_mtl_mad_qp_init( + osmt_mtl_mad_res_t *res /*max number of outstanding packets allowed in send queue*/ + ); + + +/* create and register res->buf_ptr */ +VAPI_ret_t osmt_mtl_mad_create_mr( + osmt_mtl_mad_res_t *res /*pointer to res (resources) struct*/ + ); + +VAPI_ret_t osmt_mtl_create_av( + osmt_mtl_mad_res_t* res, /* pointer to res (resources) struct*/ + int16_t dlid, /*destination lid */ + VAPI_ud_av_hndl_t *avh_p /* address vectr handle to update */ +); + +/* Send MAD to given dest QP*/ +VAPI_ret_t osmt_mtl_mad_send( + osmt_mtl_mad_res_t* res, /*pointer to res (resources) struct*/ + VAPI_wr_id_t id, /*wqe ID*/ + void* mad, /*mad buffer to send*/ + VAPI_qp_num_t dest_qp, /*destination QP*/ + IB_sl_t sl, /*Service Level*/ + u_int32_t dest_qkey, /*Destination QP KEY*/ + VAPI_ud_av_hndl_t avh /* address vectr handle to use */ +); + + +/* post buffers to RQ. returns num of buffers actually posted */ +int osmt_mtl_mad_post_recv_bufs( + osmt_mtl_mad_res_t* res, /*pointer to res (resources) struct*/ + void *buf_array, /*array of receive buffers*/ + u_int32_t num_o_bufs, /*number of receive buffers*/ + u_int32_t size, /* size of expected receive packet - MAD*/ + VAPI_wr_id_t start_id /* start id for receive buffers*/ +); + + +/* Poll given CQ for completion max_poll times (POLL_SLEEP [usec] delays). result in wc_desc_p. */ +VAPI_ret_t osmt_mtl_mad_poll4cqe( + VAPI_hca_hndl_t hca, /*handle for HCA*/ + VAPI_cq_hndl_t cq, /*handle for Completion Queue - Rcv/Send */ + VAPI_wc_desc_t *wc_desc_p, /*handle of cqe */ + u_int32_t max_poll, /*number of polling iterations*/ + u_int32_t poll_sleep, /*timeout for each polling */ + VAPI_ud_av_hndl_t *avh_p /* address vectopr handle to cleanup */ + ); + + +#endif + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/osmtest.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/osmtest.h new file mode 100644 index 00000000..d4c74e84 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/osmtest.h @@ -0,0 +1,517 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osmtest.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osmtest_t. + * This object represents the OSMTest Test object. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.6 $ + */ + +#ifndef _OSMTEST_H_ +#define _OSMTEST_H_ + +#include +#include +#include +#include +#include +#include +#include "osmtest_base.h" +#include "osmtest_subnet.h" + +/****s* OpenSM: Subnet/osmtest_opt_t + * NAME + * osmtest_opt_t + * + * DESCRIPTION + * Subnet options structure. This structure contains the various + * site specific configuration parameters for osmtest. + * + * SYNOPSIS + */ +typedef struct _osmtest_opt +{ + uint32_t transaction_timeout; + boolean_t force_log_flush; + boolean_t create; + uint32_t retry_count; + uint32_t stress; + uint32_t mmode; + char file_name[OSMTEST_FILE_PATH_MAX]; + uint8_t flow; + uint8_t wait_time; + char *log_file; + boolean_t ignore_path_records; +} osmtest_opt_t; + +/* + * FIELDS + * + * SEE ALSO + *********/ + +/****h* OSMTest/OSMTest + * NAME + * OSMTest + * + * DESCRIPTION + * The OSMTest object tests an SM/SA for conformance to a known + * set of data about an Infiniband subnet. + * + * AUTHOR + * Steve King, Intel + * + *********/ + + +/****s* OSMTest/osmtest_t + * NAME + * osmtest_t + * + * DESCRIPTION + * OSMTest structure. + * + * This object should be treated as opaque and should + * be manipulated only through the provided functions. + * + * SYNOPSIS + */ +typedef struct _osmtest +{ + osm_log_t log; + struct _osm_vendor *p_vendor; + osm_bind_handle_t h_bind; + osm_mad_pool_t mad_pool; + + osmtest_opt_t opt; + ib_port_attr_t local_port; + subnet_t exp_subn; + cl_qpool_t node_pool; + cl_qpool_t port_pool; + cl_qpool_t link_pool; + + uint16_t max_lid; +} osmtest_t; + +/* + * FIELDS + * log + * Log facility used by all OSMTest components. + * + * p_vendor + * Pointer to the vendor transport layer. + * + * h_bind + * The bind handle obtained by osm_vendor_sa_api/osmv_bind_sa + * + * mad_pool + * The mad pool provided for teh vendor layer to allocate mad wrappers in + * + * opt + * osmtest options structure + * + * local_port + * Port attributes for the port over which osmtest is running. + * + * exp_subn + * Subnet object representing the expected subnet + * + * node_pool + * Pool of objects for use in populating the subnet databases. + * + * port_pool + * Pool of objects for use in populating the subnet databases. + * + * link_pool + * Pool of objects for use in populating the subnet databases. + * + * SEE ALSO + *********/ + +/****s* OpenSM: Subnet/osmtest_req_context_t + * NAME + * osmtest_req_context_t + * + * DESCRIPTION + * Query context for ib_query callback function. + * + * SYNOPSIS + */ +typedef struct _osmtest_req_context +{ + osmtest_t *p_osmt; + osmv_query_res_t result; +} osmtest_req_context_t; + +typedef struct _osmtest_mgrp_t +{ + cl_map_item_t map_item; + ib_member_rec_t mcmember_rec; +} osmtest_mgrp_t; + + +/* + * FIELDS + * + * SEE ALSO + *********/ + +/****f* OSMTest/osmtest_construct + * NAME + * osmtest_construct + * + * DESCRIPTION + * This function constructs an OSMTest object. + * + * SYNOPSIS + */ +void osmtest_construct( IN osmtest_t * const p_osmt ); + +/* + * PARAMETERS + * p_osmt + * [in] Pointer to a OSMTest object to construct. + * + * RETURN VALUE + * This function does not return a value. + * + * NOTES + * Allows calling osmtest_init, osmtest_destroy. + * + * Calling osmtest_construct is a prerequisite to calling any other + * method except osmtest_init. + * + * SEE ALSO + * SM object, osmtest_init, osmtest_destroy + *********/ + +/****f* OSMTest/osmtest_destroy + * NAME + * osmtest_destroy + * + * DESCRIPTION + * The osmtest_destroy function destroys an osmtest object, releasing + * all resources. + * + * SYNOPSIS + */ +void osmtest_destroy( IN osmtest_t * const p_osmt ); + +/* + * PARAMETERS + * p_osmt + * [in] Pointer to a OSMTest object to destroy. + * + * RETURN VALUE + * This function does not return a value. + * + * NOTES + * Performs any necessary cleanup of the specified OSMTest object. + * Further operations should not be attempted on the destroyed object. + * This function should only be called after a call to osmtest_construct or + * osmtest_init. + * + * SEE ALSO + * SM object, osmtest_construct, osmtest_init + *********/ + +/****f* OSMTest/osmtest_init + * NAME + * osmtest_init + * + * DESCRIPTION + * The osmtest_init function initializes a OSMTest object for use. + * + * SYNOPSIS + */ +ib_api_status_t osmtest_init( IN osmtest_t * const p_osmt, + IN const osmtest_opt_t * const p_opt, + IN const osm_log_level_t log_flags + ); + +/* + * PARAMETERS + * p_osmt + * [in] Pointer to an osmtest_t object to initialize. + * + * p_opt + * [in] Pointer to the options structure. + * + * log_flags + * [in] Log level flags to set. + * + * RETURN VALUES + * IB_SUCCESS if the OSMTest object was initialized successfully. + * + * NOTES + * Allows calling other OSMTest methods. + * + * SEE ALSO + * SM object, osmtest_construct, osmtest_destroy + *********/ + +/****f* OSMTest/osmtest_run + * NAME + * osmtest_run + * + * DESCRIPTION + * Runs the osmtest suite. + * + * SYNOPSIS + */ +ib_api_status_t osmtest_run( IN osmtest_t * const p_osmt ); + +/* + * PARAMETERS + * p_osmt + * [in] Pointer to an osmtest_t object. + * + * guid + * [in] Port GUID over which to run the test suite. + * + * RETURN VALUES + * IB_SUCCESS + * + * NOTES + * + * SEE ALSO + *********/ + +/****f* OSMTest/osmtest_bind + * NAME + * osmtest_bind + * + * DESCRIPTION + * Binds osmtest to a local port. + * + * SYNOPSIS + */ +ib_api_status_t osmtest_bind( IN osmtest_t * p_osmt, + IN uint16_t max_lid, + IN ib_net64_t guid OPTIONAL ); + +/* + * PARAMETERS + * p_osmt + * [in] Pointer to an osmtest_t object. + * + * max_lid + * [in] The maximal lid to query about (if RMPP is not supported) + * + * guid + * [in] Port GUID over which to run the test suite. + * If zero, the bind function will display a menu of local + * port guids and wait for user input. + * + * RETURN VALUES + * IB_SUCCESS + * + * NOTES + * + * SEE ALSO + *********/ + +/****f* OSMTest/osmtest_query_res_cb + * NAME + * osmtest_query_res_cb + * + * DESCRIPTION + * A Callback for the query to invoke on completion + * + * SYNOPSIS + */ +void +osmtest_query_res_cb( IN osmv_query_res_t * p_rec ); +/* + * PARAMETERS + * p_rec + * [in] Pointer to an ib_query_rec_t object used for the query. + * + * RETURN VALUES + * NONE + * + * NOTES + * + * SEE ALSO + *********/ + +/****f* OSMTest/ib_get_mad_status_str + * NAME + * ib_get_mad_status_str + * + * DESCRIPTION + * return the string representing the given mad status + * + * SYNOPSIS + */ +const char * +ib_get_mad_status_str( IN const ib_mad_t * const p_mad ); +/* + * PARAMETERS + * p_mad + * [in] Pointer to the mad payload + * + * RETURN VALUES + * NONE + * + * NOTES + * + * SEE ALSO + *********/ + +/****f* OSMTest/osmt_run_service_records_flow + * NAME + * osmt_run_service_records_flow + * + * DESCRIPTION + * Run the service record testing flow. + * + * SYNOPSIS + */ +ib_api_status_t osmt_run_service_records_flow( IN osmtest_t * const p_osmt ); +/* + * PARAMETERS + * p_osmt + * [in] Pointer to the osmtest obj + * + * RETURN VALUES + * IB_SUCCESS if PASS + * + * NOTES + * + * SEE ALSO + *********/ + +ib_api_status_t +osmt_run_inform_info_flow( IN osmtest_t * const p_osmt ); + +/****f* OSMTest/osmt_run_slvl_and_vlarb_records_flow + * NAME + * osmt_run_slvl_and_vlarb_records_flow + * + * DESCRIPTION + * Run the sl2vl and vlarb tables testing flow. + * + * SYNOPSIS + */ +ib_api_status_t +osmt_run_slvl_and_vlarb_records_flow( IN osmtest_t * const p_osmt ); +/* + * PARAMETERS + * p_osmt + * [in] Pointer to the osmtest obj + * + * RETURN VALUES + * IB_SUCCESS if PASS + * + * NOTES + * + * SEE ALSO + *********/ + +/****f* OSMTest/osmt_run_mcast_flow + * NAME + * osmt_run_mcast_flow + * + * DESCRIPTION + * Run the multicast test flow + * + * SYNOPSIS + */ +ib_api_status_t +osmt_run_mcast_flow( IN osmtest_t * const p_osmt ); +/* + * PARAMETERS + * p_osmt + * [in] Pointer to the osmtest obj + * + * RETURN VALUES + * IB_SUCCESS if PASS + * + * NOTES + * + * SEE ALSO + *********/ + +/****f* OSMTest/osmt_run_trap64_65_flow + * NAME + * osmt_run_trap64_65_flow + * + * DESCRIPTION + * Run the trap 64/65 test flow. This test is ran with + * an outside tool. + * + * SYNOPSIS + */ +ib_api_status_t +osmt_run_trap64_65_flow( IN osmtest_t * const p_osmt ); +/* + * PARAMETERS + * p_osmt + * [in] Pointer to the osmtest obj + * + * RETURN VALUES + * IB_SUCCESS if PASS + * + * NOTES + * + * SEE ALSO + *********/ + +ib_api_status_t +osmtest_get_all_recs( IN osmtest_t * const p_osmt, + IN ib_net16_t const attr_id, + IN size_t const attr_size, + IN OUT osmtest_req_context_t * const p_context ); + +ib_api_status_t +osmtest_get_local_port_lmc( IN osmtest_t * const p_osmt, + IN ib_net16_t lid, + OUT uint8_t * const p_lmc ); + + +/* + * A few auxiliary macros for logging + */ + +#define EXPECTING_ERRORS_START "[[ ===== Expecting Errors - START ===== " +#define EXPECTING_ERRORS_END " ===== Expecting Errors - END ===== ]]" + +#endif /* _OSMTEST_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/osmtest_base.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/osmtest_base.h new file mode 100644 index 00000000..70258f1d --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/osmtest_base.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osmtest_base.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osmtest_t. + * This object represents the OSMTest Test object. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.2 $ + */ +#ifndef _OSMTEST_BASE_H_ +#define _OSMTEST_BASE_H_ + +#ifndef __WIN__ +#include +#else +#include +#endif + +#define OSMTEST_MAX_LINE_LEN 120 +#ifdef WIN32 +#define OSMTEST_FILE_PATH_MAX 4096 +#else +#define OSMTEST_FILE_PATH_MAX PATH_MAX +#endif + +#define STRESS_SMALL_RMPP_THR 100000 +/* + Take long times when quering big clusters (over 40 nodes) , an average of : 0.25 sec for query + each query receives 1000 records +*/ +#define STRESS_LARGE_RMPP_THR 4000 +#define STRESS_LARGE_PR_RMPP_THR 20000 + +extern const char *const p_file; + +#endif /* _OSMTEST_BASE_H_ */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/osmtest_subnet.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/osmtest_subnet.h new file mode 100644 index 00000000..62815037 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/osmtest_subnet.h @@ -0,0 +1,349 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osmtest_subnet.h 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Declaration of osmtest_t. + * This object represents the OSMTest Test object. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.2 $ + */ + +#ifndef _OSMTEST_SUBNET_H_ +#define _OSMTEST_SUBNET_H_ + +#include +#include +#include +#include +#include +#include + + +/****s* Subnet Database/generic_t +* NAME +* generic_t +* +* DESCRIPTION +* Subnet database object for fields common to all record types. +* All other database types must be castable to this type. +* +* SYNOPSIS +*/ +typedef struct _generic +{ + cl_map_item_t map_item; /* must be first element! */ + uint32_t count; /* must be second element! */ +} generic_t; + +/* +* FIELDS +* +* SEE ALSO +*********/ + +/****s* Subnet Database/node_t +* NAME +* node_t +* +* DESCRIPTION +* Subnet database object for nodes. +* Must be castable to generic_t. +* +* SYNOPSIS +*/ +typedef struct _node +{ + cl_map_item_t map_item; /* must be first element! */ + uint32_t count; /* must be second element! */ + ib_node_record_t rec; + ib_node_record_t comp; +} node_t; + +/* +* FIELDS +* map_item +* Provides linkage for the qmap container. +* +* rec +* NodeRecord for this node as read from the database file. +* +* comp +* NodeRecord indicating which fields should be compared against rec. +* Bits set in the comp NodeRecord indicate that bit in the rec structure +* should be compared against real-time data from the SA. +* +* count +* Utility counter used by the validation logic. Typically used to +* to indicate the number of times a matching node was received from +* the SA. +* +* SEE ALSO +*********/ + +static inline node_t * +node_new( void ) +{ + node_t *p_obj; + + p_obj = malloc( sizeof( *p_obj ) ); + if (p_obj) + memset( p_obj, 0, sizeof( *p_obj ) ); + return ( p_obj ); +} + +static inline void +node_delete( IN node_t * p_obj ) +{ + free( p_obj ); +} + +/****s* Subnet Database/port_t +* NAME +* port_t +* +* DESCRIPTION +* Subnet database object for ports. +* Must be castable to generic_t. +* +* SYNOPSIS +*/ +typedef struct _port +{ + cl_map_item_t map_item; /* must be first element! */ + uint32_t count; /* must be second element! */ + /* Since there is no unique identifier for all ports we + must be able to have such a key by the lid and port num */ + uint64_t port_id; + ib_portinfo_record_t rec; + ib_portinfo_record_t comp; +} port_t; + +/* +* FIELDS +* +* map_item +* Provides linkage for the qmap container. +* +* rec +* PortInfoRecord for this port as read from the database file. +* +* comp +* PortInfoRecord indicating which fields should be compared against rec. +* Bits set in the comp NodeRecord indicate that bit in the rec structure +* should be compared against real-time data from the SA. +* +* count +* Utility counter used by the validation logic. Typically used to +* to indicate the number of times a matching node was received from +* the SA. +* +* SEE ALSO +*********/ + +static inline port_t * +port_new( void ) +{ + port_t *p_obj; + + p_obj = malloc( sizeof( *p_obj ) ); + if (p_obj) + memset( p_obj, 0, sizeof( *p_obj ) ); + return ( p_obj ); +} + +static inline void +port_delete( IN port_t * p_obj ) +{ + free( p_obj ); +} + +static inline uint64_t +port_gen_id( + IN ib_net16_t const lid, + IN uint8_t const port_num) +{ + return( lid << 8 | port_num ); +} + +static inline void +port_ext_id( IN uint64_t id, + IN ib_net16_t *p_lid, + IN uint8_t *p_port_num) +{ + CL_ASSERT( (id & 0xFF) < 0x100 ); + *p_port_num = (uint8_t)(id & 0xFF); + CL_ASSERT( ((id >> 8) & 0xFFFF) < 0x10000 ); + *p_lid = (uint16_t)((id >> 8) & 0xFFFF); +} + +static inline void +port_set_id( IN port_t * p_obj, + IN ib_net16_t const lid, + IN uint8_t const port_num) +{ + p_obj->port_id = port_gen_id(lid, port_num); +} + +static inline void +port_get_id( IN port_t * p_obj, + IN ib_net16_t *p_lid, + IN uint8_t *p_port_num) +{ + port_ext_id(p_obj->port_id, p_lid, p_port_num); +} + +/****s* Subnet Database/path_t +* NAME +* node_t +* +* DESCRIPTION +* Subnet database object for paths. +* Must be castable to generic_t. +* +* SYNOPSIS +*/ +typedef struct _path +{ + cl_map_item_t map_item; /* must be first element! */ + uint32_t count; /* must be second element! */ + ib_path_rec_t rec; + ib_path_rec_t comp; +} path_t; + +/* +* FIELDS +* map_item +* Provides linkage for the qmap container. +* +* rec +* PathRecord for this path as read from the database file. +* +* comp +* PathRecord indicating which fields should be compared against rec. +* Bits set in the comp PathRecord indicate that bit in the rec structure +* should be compared against real-time data from the SA. +* +* count +* Utility counter used by the validation logic. Typically used to +* to indicate the number of times a matching node was received from +* the SA. +* +* SEE ALSO +*********/ + +static inline path_t * +path_new( void ) +{ + path_t *p_obj; + + p_obj = malloc( sizeof( *p_obj ) ); + if (p_obj) + memset( p_obj, 0, sizeof( *p_obj ) ); + return ( p_obj ); +} + +static inline void +path_delete( IN path_t * p_obj ) +{ + free( p_obj ); +} + +/****s* Subnet Database/subnet_t +* NAME +* subnet_t +* +* DESCRIPTION +* Subnet database object. +* +* SYNOPSIS +*/ +typedef struct _subnet +{ + cl_qmap_t node_lid_tbl; + cl_qmap_t node_guid_tbl; + cl_qmap_t mgrp_mlid_tbl; + /* cl_qmap_t port_lid_tbl; */ + /* cl_qmap_t port_guid_tbl; */ + cl_qmap_t port_key_tbl; + cl_qmap_t link_tbl; + cl_qmap_t path_tbl; +} subnet_t; + +/* +* FIELDS +* +* SEE ALSO +*********/ + +/****f* Subnet Database/subnet_construct +* NAME +* subnet_construct +* +* DESCRIPTION +* This function constructs an subnet database object. +* This function cannot fail. +* +* SYNOPSIS +*/ +void subnet_construct( IN subnet_t * const p_subn ); + +/* +* FIELDS +* +* SEE ALSO +*********/ + +/****f* Subnet Database/subnet_init +* NAME +* subnet_init +* +* DESCRIPTION +* This function initializes an subnet database object. +* +* SYNOPSIS +*/ +cl_status_t subnet_init( IN subnet_t * const p_subn ); + +/* +* FIELDS +* +* SEE ALSO +*********/ + +#endif + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/main.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/main.c new file mode 100644 index 00000000..c8168eba --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/main.c @@ -0,0 +1,678 @@ +/* + * Copyright (c) 2004,2005 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: main.c 1940 2009-02-11 10:14:39Z tzachid $ + */ + +/* + * Abstract: + * Command line interface for osmtest. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.3 $ + */ + +#include +#include +#include +#include "osmtest.h" + +/******************************************************************** + D E F I N E G L O B A L V A R I A B L E S +*********************************************************************/ + +/* + This is the global osmtest object. + One osmtest object is required per subnet. + Future versions could support multiple subents by + instantiating more than one osmtest object. +*/ +#define GUID_ARRAY_SIZE 64 +#define OSMT_DEFAULT_RETRY_COUNT 3 +#define OSMT_DEFAULT_TRANS_TIMEOUT_MILLISEC 1000 +#define OSMT_DEFAULT_TRAP_WAIT_TIMEOUT_SEC 10 + +/********************************************************************** + **********************************************************************/ +boolean_t +osmt_is_debug(void) +{ +#if defined( _DEBUG_ ) + return TRUE; +#else + return FALSE; +#endif /* defined( _DEBUG_ ) */ +} + +/********************************************************************** + **********************************************************************/ +ib_net64_t +get_port_guid( + IN osmtest_t *p_osm, uint64_t port_guid, + IN boolean_t is_service) +{ + uint32_t i; + uint32_t choice = 0; + char junk[128]; + boolean_t done_flag = FALSE; + ib_api_status_t status; + uint32_t num_ports = GUID_ARRAY_SIZE; + ib_port_attr_t attr_array[GUID_ARRAY_SIZE]; + + /* + Call the transport layer for a list of local port + GUID values. + */ + status = osm_vendor_get_all_port_attr( p_osm->p_vendor, attr_array, &num_ports ); + if( status != IB_SUCCESS ) + { + printf( "\nError from osm_vendor_get_all_port_attr (%x)\n", status); + return( 0 ); + } + + /* if num_ports is 0 - return 0 */ + if( num_ports == 0 ) + { + printf( "\nNo local ports detected!\n" ); + return( 0 ); + } + /* If num_ports is 1, then there is only one possible port to use. Use it. */ + if ( num_ports == 1 ) + { + printf("Using default GUID 0x%" PRIx64 "\n", cl_hton64(attr_array[0].port_guid)); + return( attr_array[0].port_guid ); + } + +#if defined ( OSM_VENDOR_INTF_OPENIB ) + /* If port_guid is 0, and this is gen2 - use the default port whose info is in attr_array[0] */ + if ( port_guid == 0 ) + { + printf("Using default GUID 0x%" PRIx64 "\n", cl_hton64(attr_array[0].port_guid)); + return( attr_array[0].port_guid ); + } +#endif /* OSM_VENDOR_INTF_OPENIB */ + + /* If port_guid is 0, and we are in windows - find the first port with link_state != DOWN and + use it as default port. */ + if ( port_guid == 0 ) + { + for ( i = 0; i < num_ports; i++ ) + { + if (attr_array[i].link_state > IB_LINK_DOWN) + { + /* Use this port */ + printf("Using default guid 0x%" PRIx64 "\n", cl_hton64(attr_array[i].port_guid)); + return( attr_array[i].port_guid ); + } + } + /* If we are running as a service, and all ports are down we return the + first port (we can't open a window, as a service)*/ + if (is_service) { + return( attr_array[0].port_guid ); + } + } + + /* More than one possible port - list all ports and let the user to choose. */ + while( done_flag == FALSE ) + { + printf( "\nChoose a local port number with which to bind:\n\n" ); + /* If this is gen2 code - then port 0 has details of the default port used. + no need to print it. + If this is not gen2 code - need to print details of all ports. */ +#if defined ( OSM_VENDOR_INTF_OPENIB ) + for( i = 1; i < num_ports; i++ ) + { + printf("\t%u: GUID = 0x%8" PRIx64 ", lid = 0x%04X, state = %s\n", + i, cl_ntoh64( attr_array[i].port_guid ), + attr_array[i].lid, + ib_get_port_state_str( attr_array[i].link_state ) ); + } + printf( "\nEnter choice (1-%u): ", i-1 ); +# else + for( i = 0; i < num_ports; i++ ) + { + /* + Print the index + 1 since by convention, port numbers + start with 1 on host channel adapters. + */ + + printf("\t%u: GUID = 0x%8" PRIx64 ", lid = 0x%04X, state = %s\n", + i+1, cl_ntoh64( attr_array[i].port_guid ), + attr_array[i].lid, + ib_get_port_state_str( attr_array[i].link_state ) ); + } + printf( "\nEnter choice (1-%u): ", i ); +#endif /* OSM_VENDOR_INTF_OPENIB */ + + fflush( stdout ); + if (scanf( "%u", &choice )) + { + /* If gen2 code - choice can be between 1 to num_ports-1 + if not gen2 code - choice can be between 1 to num_ports */ +#if defined ( OSM_VENDOR_INTF_OPENIB ) + if( choice >= num_ports ) +# else + if( choice > num_ports || choice < 1 ) +#endif /* OSM_VENDOR_INTF_OPENIB */ + { + printf("\nError: Lame choice!\n"); + fflush( stdin ); + } + else + { + done_flag = TRUE; + } + } + else + { + /* get rid of the junk in the selection line */ + scanf( "%s", junk ); + printf("\nError: Lame choice!\n"); + fflush( stdin ); + } + } +#if defined ( OSM_VENDOR_INTF_OPENIB ) + printf("Choice guid=0x%8" PRIx64 "\n", cl_ntoh64( attr_array[choice].port_guid )); + return( attr_array[choice].port_guid ); +# else + return( attr_array[choice - 1].port_guid ); +#endif /* OSM_VENDOR_INTF_OPENIB */ +} +/********************************************************************** + **********************************************************************/ +void show_usage(void); + +void +show_usage( ) +{ + printf + ( "\n------- osmtest - Usage and options ----------------------\n" ); + printf( "Usage: osmtest [options]\n" ); + printf( "Options:\n" ); + printf( "-f \n" + "--flow \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 \n" + "--wait \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 \n" + "--debug \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 \n" + "--max_lid \n" + " This option specifies the maximal LID number to be searched\n" + " for during inventory file build (default to 100).\n"); + printf( "-g \n" + "--guid \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 \n" + "--inventory \n" + " This option specifies the name of the inventory file.\n" + " Normally, osmtest expects to find an inventory file,\n" + " which osmtest uses to validate real-time information\n" + " received from the SA during testing.\n" + " If -i is not specified, osmtest defaults to the file\n" + " 'osmtest.dat'.\n" + " See the -c option for related information.\n\n" ); + printf( "-s\n" + "--stress\n" + " This option runs the specified stress test instead\n" + " of the normal test suite.\n" + " Stress test options are as follows:\n" + " OPT Description\n" + " --- -----------------\n" + " -s1 - Single-MAD response SA queries .\n" + " -s2 - Multi-MAD (RMPP) response SA queries.\n" + " -s3 - Multi-MAD (RMPP) Path Record SA queries.\n" + " Without -s, stress testing is not performed.\n\n" ); + printf( "-M\n" + "--Multicast_Mode\n" + " This option specify length of Multicast test :\n" + " OPT Description\n" + " --- -----------------\n" + " -M1 - Short Multicast Flow (default) - single mode.\n" + " -M2 - Short Multicast Flow - multiple mode.\n" + " -M3 - Long Multicast Flow - single mode.\n" + " -M4 - Long Multicast Flow - multiple mode.\n" + " Single mode - Osmtest is tested alone , with no other \n" + " apps that interact vs. OpenSM MC.\n" + " Multiple mode - Could be run with other apps using MC vs.\n" + " OpenSM." + " Without -M, default flow testing is performed.\n\n" ); + + printf( "-t \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 \n" + " This option sets the log verbosity level.\n" + " A flags field must follow the -vf option.\n" + " A bit set/clear in the flags enables/disables a\n" + " specific log level as follows:\n" + " BIT LOG LEVEL ENABLED\n" + " ---- -----------------\n" + " 0x01 - ERROR (error messages)\n" + " 0x02 - INFO (basic messages, low volume)\n" + " 0x04 - VERBOSE (interesting stuff, moderate volume)\n" + " 0x08 - DEBUG (diagnostic, high volume)\n" + " 0x10 - FUNCS (function entry/exit, very high volume)\n" + " 0x20 - FRAMES (dumps all SMP and GMP frames)\n" + " 0x40 - currently unused.\n" + " 0x80 - currently unused.\n" + " Without -vf, osmtest defaults to ERROR + INFO (0x3).\n" + " Specifying -vf 0 disables all messages.\n" + " Specifying -vf 0xFF enables all messages (see -V).\n" + " High verbosity levels may require increasing\n" + " the transaction timeout with the -t option.\n\n" ); +} + +/********************************************************************** + **********************************************************************/ +void show_menu(void); + +void +show_menu( ) +{ + printf( "\n------- Interactive Menu -------\n" ); + printf( "X - Exit.\n\n" ); +} +void OsmReportState(IN const char *p_str) +{ +} + +/********************************************************************** + **********************************************************************/ +int OSM_CDECL +main( int argc, + char *argv[] ) +{ + static osmtest_t osm_test; + osmtest_opt_t opt = { 0 }; + ib_net64_t guid = 0; + int max_lid = 100; + ib_api_status_t status; + uint32_t log_flags = OSM_LOG_ERROR | OSM_LOG_INFO; + char flow_name[64]; + boolean_t mem_track = FALSE; + uint32_t next_option; + const char *const short_option = "f:l:m:M:d:g:s:t:i:cvVh"; + + /* + * In the array below, the 2nd parameter specified the number + * of arguments as follows: + * 0: no arguments + * 1: argument + * 2: optional + */ + const struct option long_option[] = { + {"create", 0, NULL, 'c'}, + {"debug", 1, NULL, 'd'}, + {"flow", 1, NULL, 'f'}, + {"wait", 1, NULL, 'w'}, + {"inventory", 1, NULL, 'i'}, + {"max_lid", 1, NULL, 'm'}, + {"guid", 1, NULL, 'g'}, + {"help", 0, NULL, 'h'}, + {"stress", 1, NULL, 's'}, + {"Multicast_Mode", 1, NULL, 'M'}, + {"timeout", 1, NULL, 't'}, + {"verbose", 0, NULL, 'v'}, + {"log_file", 1, NULL, 'l'}, + {"vf", 1, NULL, 'x'}, + {"V", 0, NULL, 'V'}, + + {NULL, 0, NULL, 0} /* Required at end of array */ + }; + + opt.transaction_timeout = OSMT_DEFAULT_TRANS_TIMEOUT_MILLISEC; + opt.wait_time = OSMT_DEFAULT_TRAP_WAIT_TIMEOUT_SEC; + opt.retry_count = OSMT_DEFAULT_RETRY_COUNT; + opt.force_log_flush = FALSE; + opt.stress = 0; + opt.log_file = NULL; + opt.create = FALSE; + opt.mmode = 1; + opt.ignore_path_records = FALSE; /* Do path Records too. */ + opt.flow = 0; /* run all validation tests */ + strcpy(flow_name, "All Validations"); + strcpy( opt.file_name, "osmtest.dat" ); + + printf( "\nCommand Line Arguments\n" ); + do + { + next_option = getopt_long_only( argc, argv, short_option, + long_option, NULL ); + switch ( next_option ) + { + case 'c': + /* + * Create the inventory file. + */ + opt.create = TRUE; + printf( "\tCreating inventory file\n" ); + break; + + case 'i': + /* + * Specifies inventory file name. + */ + if( strlen( optarg ) > OSMTEST_FILE_PATH_MAX ) + printf( "\nError: path name too long (ignored).\n" ); + else + strcpy( opt.file_name, optarg ); + + printf( "\tFile = %s\n", opt.file_name ); + break; + + case 'f': + /* + * Specifies Flow . + */ + if( strlen( optarg ) > OSMTEST_FILE_PATH_MAX ) + printf( "\nError: path name too long (ignored).\n" ); + else + strcpy( flow_name, optarg ); + + if (!strcmp("c",optarg)) { + strcpy(flow_name, "Create Inventory"); + opt.flow = 1; + } else if (!strcmp("v",optarg)) { + strcpy(flow_name, "Validate Inventory"); + opt.flow = 2; + } else if (!strcmp("s",optarg)) { + strcpy(flow_name, "Services Registration"); + opt.flow = 3; + } else if (!strcmp("e",optarg)) { + strcpy(flow_name, "Event Forwarding"); + opt.flow = 4; + } else if (!strcmp("f",optarg)) { + strcpy(flow_name, "Stress SA"); + opt.flow = 5; + } else if (!strcmp("m",optarg)) { + strcpy(flow_name, "Multicast"); + opt.flow = 6; + } else if (!strcmp("q",optarg)) { + strcpy(flow_name, "QoS: VLArb and SLtoVL"); + opt.flow = 7; + } else if (!strcmp("t", optarg)) { + strcpy(flow_name, "Trap 64/65"); + opt.flow = 8; + } else if (!strcmp("a",optarg)) { + strcpy(flow_name, "All Validations"); + opt.flow = 0; + } else { + printf( "\nError: un-known flow %s.\n",flow_name); + exit(2); + } + break; + + case 'w': + /* + * Specifies trap 64/65 wait time + */ + CL_ASSERT( strtol( optarg, NULL, 0 ) < 0x100 ); + opt.wait_time = (uint8_t)strtol( optarg, NULL, 0 ); + printf( "\tTrap 64/65 wait time = %d\n", opt.wait_time ); + break; + + case 'm': + /* + * Specifies the max LID to search for during exploration. + */ + max_lid = atoi( optarg ); + printf( "\tMAX-LID %u\n", max_lid ); + break; + + case 'g': + /* + * Specifies port guid with which to bind. + */ + guid = cl_hton64( strtoull( optarg, NULL, 16 )); + printf( "\tGUID 0x%016" PRIx64 "\n", guid ); + break; + case 't': + /* + * Specifies transaction timeout. + */ + opt.transaction_timeout = strtol( optarg, NULL, 0 ); + printf( "\tTransaction timeout = %d\n", opt.transaction_timeout ); + break; + + case 'l': + opt.log_file = optarg; + printf("\tLog File:%s\n", opt.log_file ); + break; + + case 'v': + /* + * Increases log verbosity. + */ + log_flags = ( log_flags << 1 ) | 1; + printf( "\tVerbose option -v (log flags = 0x%X)\n", log_flags ); + break; + + case 'V': + /* + * Specifies maximum log verbosity. + */ + log_flags = 0xFFFFFFFF; + opt.force_log_flush = TRUE; + printf( "\tEnabling maximum log verbosity\n" ); + break; + + case 's': + /* + * Perform stress test. + */ + opt.stress = strtol( optarg, NULL, 0 ); + printf( "\tStress test enabled: " ); + switch ( opt.stress ) + { + case 1: + printf( "Small SA queries\n" ); + break; + case 2: + printf( "Large SA queries\n" ); + break; + case 3: + printf( "Large Path Record SA queries\n" ); + break; + default: + printf( "Unknown value %u (ignored)\n", opt.stress ); + opt.stress = 0; + break; + } + break; + + case 'M': + /* + * Perform stress test. + */ + opt.mmode = strtol( optarg, NULL, 0 ); + printf( "\tMulticast test enabled: " ); + switch ( opt.mmode ) + { + case 1: + printf( "Short MC Flow - single mode (default)\n" ); + break; + case 2: + printf( "Short MC Flow - multiple mode\n" ); + break; + case 3: + printf( "Long MC Flow - single mode\n" ); + break; + case 4: + printf( "Long MC Flow - multiple mode\n" ); + break; + default: + printf( "Unknown value %u (ignored)\n", opt.stress ); + opt.mmode = 0; + break; + } + break; + + case 'd': + /* + * Debug Options + */ + printf( "\tDebug Option: " ); + switch ( strtol( optarg, NULL, 0 ) ) + { + case 1: + printf( "Ignore Path Records.\n" ); + opt.ignore_path_records = TRUE; + break; + case 2: + printf( "Force Log Flush.\n" ); + opt.force_log_flush = TRUE; + break; + case 3: + printf( "Use Mem Tracking.\n" ); + mem_track = TRUE; + break; + default: + printf( "Unknown value %ld (ignored)\n", strtol( optarg, NULL, 0 ) ); + break; + } + break; + + case 'h': + show_usage( ); + return 0; + + case 'x': + log_flags = strtol( optarg, NULL, 0 ); + printf( "\t\t\t\tVerbose option -vf (log flags = 0x%X)\n", + log_flags ); + break; + + case -1: + printf( "Done with args\n" ); + break; + + default: /* something wrong */ + abort( ); + } + + } + while( next_option != -1 ); + + printf( "\tFlow = %s\n", flow_name ); + + if (mem_track) __cl_mem_track(TRUE); + + + status = osmtest_init( &osm_test, &opt, ( osm_log_level_t ) log_flags ); + if( status != IB_SUCCESS ) + { + printf( "\nError from osmtest_init: %s.\n", + ib_get_err_str( status ) ); + goto Exit; + } + + /* + If the user didn't specify a GUID on the command line, + then get a port GUID value with which to bind. + */ + if (guid == 0 && !(guid = get_port_guid(&osm_test, guid,1))) { + printf("\nError: port guid 0x%" PRIx64 " not found\n", guid); + goto Exit; + } + + /* + * Guid may be zero going into this function if the user + * hasn't specified a binding port on the command line. + */ + + status = osmtest_bind( &osm_test, (uint16_t)max_lid, guid ); + if (status != IB_SUCCESS) exit(status); + + status = osmtest_run( &osm_test ); + if (status != IB_SUCCESS) { + printf("OSMTEST: TEST \"%s\" FAIL\n", flow_name); + } else { + printf("OSMTEST: TEST \"%s\" PASS\n", flow_name); + } + osmtest_destroy( &osm_test ); + + if (mem_track) cl_mem_display(); + + Exit: + return ( status ); +} diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmt_inform.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmt_inform.c new file mode 100644 index 00000000..dab89810 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmt_inform.c @@ -0,0 +1,961 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osmt_inform.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +#ifdef OSM_VENDOR_INTF_MTL +/* + * Abstract: + * Implementation of InformInfo testing flow.. + * Top level is osmt_run_inform_info_flow: + * osmt_bind_inform_qp + * osmt_reg_unreg_inform_info + * osmt_send_trap_wait_for_forward + * + * Environment: + * Linux User Mode + * + * $Revision: 1.2 $ + */ + +#include +#include +#include +#include +#include +#include +#include "osmtest.h" +#include "osmt_inform.h" + +/* + * Prepare an asynchronous QP (rcv) for sending inform info and + * handling the incoming reports. + * + */ +ib_api_status_t +osmt_bind_inform_qp( IN osmtest_t * const p_osmt, + OUT osmt_qp_ctx_t *p_qp_ctx) { + ib_net64_t port_guid; + VAPI_hca_hndl_t hca_hndl; + VAPI_hca_id_t hca_id; + uint32_t port_num; + VAPI_ret_t vapi_ret; + IB_MGT_ret_t mgt_ret; + uint8_t hca_index; + osm_log_t *p_log = &p_osmt->log; + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osmt_bind_inform_qp ); + + port_guid = p_osmt->local_port.port_guid; + + osm_log( p_log, OSM_LOG_DEBUG, + "osmt_bind_inform_qp: " + "Binding to port 0x%" PRIx64 "\n", cl_ntoh64( port_guid ) ); + + /* obtain the hca name and port num from the guid */ + osm_log( p_log, OSM_LOG_DEBUG, + "osmt_bind_inform_qp: " + "Finding CA and Port that owns port guid 0x%" PRIx64 "\n", + port_guid ); + + mgt_ret = + osm_vendor_get_guid_ca_and_port( + p_osmt->p_vendor, + port_guid, + &hca_hndl, + &hca_id[0], + &hca_index, + &port_num ); + if( mgt_ret != IB_MGT_OK ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osmt_bind_inform_qp: ERR 0109: " + "Unable to obtain CA and port (%d).\n" ); + status = IB_ERROR; + goto Exit; + } + +#define OSMT_MTL_REVERSE_QP1_WELL_KNOWN_Q_KEY 0x80010000 + + strncpy(p_qp_ctx->qp_bind_hndl.hca_id, hca_id, sizeof(hca_id)); + p_qp_ctx->qp_bind_hndl.hca_hndl = hca_hndl; + p_qp_ctx->qp_bind_hndl.port_num = port_num; + p_qp_ctx->qp_bind_hndl.max_outs_sq = 10; + p_qp_ctx->qp_bind_hndl.max_outs_rq = 10; + p_qp_ctx->qp_bind_hndl.qkey = OSMT_MTL_REVERSE_QP1_WELL_KNOWN_Q_KEY; + + vapi_ret = osmt_mtl_init_opened_hca(&p_qp_ctx->qp_bind_hndl); + if (vapi_ret != VAPI_OK) + { + osm_log( p_log, OSM_LOG_ERROR, + "osmt_bind_inform_qp: ERR 0114: " + "Error initializing QP.\n" ); + status = IB_ERROR; + goto Exit; + } + + /* we use the pre-allocated buffers for send and receive : + send from buf[0] + receive from buf[2] + */ + p_qp_ctx->p_send_buf = (uint8_t *)p_qp_ctx->qp_bind_hndl.buf_ptr + GRH_LEN; + p_qp_ctx->p_recv_buf = (uint8_t *)p_qp_ctx->qp_bind_hndl.buf_ptr + 2 * (GRH_LEN + MAD_BLOCK_SIZE); + + /* Need to clear assigned memory of p_send_buf - before using it to send any data */ + memset(p_qp_ctx->p_send_buf, 0, MAD_BLOCK_SIZE); + + status = IB_SUCCESS; + osm_log( p_log, OSM_LOG_DEBUG, + "osmt_bind_inform_qp: " + "Initialized QP:0x%X in VAPI Mode\n", + p_qp_ctx->qp_bind_hndl.qp_id + ); + + osm_log( p_log, OSM_LOG_DEBUG, + "osmt_bind_inform_qp: " "Binding to IB_MGT SMI\n" ); + + /* we also need a QP0 handle for sending packets */ + mgt_ret = IB_MGT_get_handle( hca_id, port_num, IB_MGT_SMI, + &( p_qp_ctx->ib_mgt_qp0_handle ) ); + if( IB_MGT_OK != mgt_ret ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osmt_bind_inform_qp: ERR 0115: " + "Error obtaining IB_MGT handle to SMI\n" ); + status = IB_ERROR; + goto Exit; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return status; +} + +/* + * Close the QP + */ +void +osmt_unbind_inform_qp( IN osmtest_t * const p_osmt, + IN osmt_qp_ctx_t *p_qp_ctx) { + osm_log_t *p_log = &p_osmt->log; + + OSM_LOG_ENTER( p_log, osmt_unbind_inform_qp ); + + osmt_mtl_mad_cleanup(&p_qp_ctx->qp_bind_hndl); + + IB_MGT_release_handle(p_qp_ctx->ib_mgt_qp0_handle); + + osm_log( p_log, OSM_LOG_DEBUG, + "osmt_unbind_inform_qp: " + "Unbind QP handles\n" ); + OSM_LOG_EXIT( &p_osmt->log ); +} + +/* + * Register/Unregister to receive the given InformInfo + * + * Uses the qp context to send the inform info mad. + * Wait for GetResp(InformInfoResp) + * + */ +ib_api_status_t +osmt_reg_unreg_inform_info( IN osmtest_t *p_osmt, + IN osmt_qp_ctx_t *p_qp_ctx, + IN ib_inform_info_t *p_inform_info, + IN uint8_t reg_flag + ) +{ + ib_sa_mad_t *p_sa_mad = (ib_sa_mad_t *)(p_qp_ctx->p_send_buf); + ib_inform_info_t *p_ii = ib_sa_mad_get_payload_ptr(p_sa_mad); /* SA Payload */ + VAPI_ret_t vapi_ret; + VAPI_wc_desc_t wc_desc; + VAPI_ud_av_hndl_t avh; + static VAPI_wr_id_t wrid = 16198; + osm_log_t *p_log = &p_osmt->log; + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( &p_osmt->log, osmt_reg_unreg_inform_info ); + + /* init the MAD */ + ib_mad_init_new( (ib_mad_t*)p_sa_mad, + IB_MCLASS_SUBN_ADM, + ( uint8_t ) 2, + IB_MAD_METHOD_SET, + cl_hton64( wrid ), + ( ib_net16_t ) 0, + 0 ); + wrid++; + p_sa_mad->attr_id = IB_MAD_ATTR_INFORM_INFO; + + /* copy the reference inform info */ + memcpy(p_ii, p_inform_info, sizeof(ib_inform_info_t)); + + if (reg_flag) + { + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_reg_unreg_inform_info: " + "Subscribing InformInfo: Traps from lid:0x%X to 0x%X, trap num :0x%X\n", + p_ii->lid_range_begin,p_ii->lid_range_end,p_ii->g_or_v.generic.trap_num); + } + else + { + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_reg_unreg_inform_info: " + "UnSubscribing InformInfo: Traps from lid:0x%X to 0x%X\n", + p_ii->lid_range_begin, p_ii->lid_range_end); + } + + /* set the subscribe bit */ + if (reg_flag) + { + p_ii->subscribe = 1; + } + else + { + p_ii->subscribe = 0; + /* + * we need to set the QPN on the mad if we unsubscribe: + * o13-2.1.1 - QPN Field need to be set when unsubscribing. + */ + ib_inform_info_set_qpn(p_ii, + cl_hton32(p_qp_ctx->qp_bind_hndl.qp_id.qp_num)); + } + + osm_dump_inform_info( &p_osmt->log, + p_ii, + OSM_LOG_DEBUG ); + + /* --------------------- PREP ------------------------- */ + if (osmt_mtl_mad_post_recv_bufs(&p_qp_ctx->qp_bind_hndl, + p_qp_ctx->p_recv_buf, + 1, /* but we need only one mad at a time */ + GRH_LEN + MAD_BLOCK_SIZE, + wrid) != 1) { + osm_log( p_log, OSM_LOG_ERROR, + "osmt_reg_unreg_inform_info: ERR 0120: " + "Error posting recv bufs\n"); + status = IB_ERROR; + goto Exit; + } + osm_log( p_log, OSM_LOG_DEBUG, + "osmt_reg_unreg_inform_info: " + "Posted recv bufs\n"); + + vapi_ret = osmt_mtl_create_av(&p_qp_ctx->qp_bind_hndl, p_osmt->local_port.sm_lid, &avh); + if (vapi_ret != VAPI_OK) + { + osm_log( p_log, OSM_LOG_ERROR, + "osmt_reg_unreg_inform_info: ERR 0121: " + "Error Preparing AVH (%s)\n", + VAPI_strerror_sym(vapi_ret) ); + status = IB_ERROR; + goto Exit; + } + osm_log( p_log, OSM_LOG_DEBUG, + "osmt_reg_unreg_inform_info: " + "Prepared AVH\n"); + + if( osm_log_is_active( p_log, OSM_LOG_DEBUG ) ) + { + osm_dump_sa_mad( p_log, (ib_sa_mad_t *)(p_qp_ctx->p_send_buf), OSM_LOG_DEBUG); +#if 0 + for (i = 56; i < 253; i++) { + if ( i % 8 == 0 ) { printf("\n %d : ", i); } + printf("0x%02X ", p_qp_ctx->p_send_buf[i]); + } +#endif + printf("\n"); + } + + /* --------------------- SEND ------------------------- */ + vapi_ret = osmt_mtl_mad_send(&p_qp_ctx->qp_bind_hndl, + wrid, + p_qp_ctx->p_send_buf, + 1, /* SA is QP1 */ + 0, /* SL is 0 */ + OSMT_MTL_REVERSE_QP1_WELL_KNOWN_Q_KEY, + avh + ); + if (vapi_ret != VAPI_OK) + { + osm_log( p_log, OSM_LOG_ERROR, + "osmt_reg_unreg_inform_info: ERR 0122: " + "Error sending mad (%s)\n", + VAPI_strerror_sym(vapi_ret) ); + status = IB_ERROR; + goto Exit; + } + + vapi_ret = osmt_mtl_mad_poll4cqe(p_qp_ctx->qp_bind_hndl.hca_hndl, + p_qp_ctx->qp_bind_hndl.sq_cq_hndl, + &wc_desc, + 20, + 10000, + NULL); + if (vapi_ret != VAPI_OK) + { + osm_log( p_log, OSM_LOG_ERROR, + "osmt_reg_unreg_inform_info: ERR 0123: " + "Error getting send completion (%s)\n", + VAPI_strerror_sym(vapi_ret) ); + status = IB_ERROR; + goto Exit; + } + + if (wc_desc.status != VAPI_SUCCESS) + { + osm_log( p_log, OSM_LOG_ERROR, + "osmt_reg_unreg_inform_info: ERR 0124: " + "Error on send completion (%s) (%d)\n", + VAPI_strerror_sym(wc_desc.status), wc_desc.status ); + status = IB_ERROR; + goto Exit; + } + osm_log( p_log, OSM_LOG_DEBUG, + "osmt_reg_unreg_inform_info: " + "Sent MAD\n"); + + /* --------------------- RECV ------------------------- */ + vapi_ret = osmt_mtl_mad_poll4cqe(p_qp_ctx->qp_bind_hndl.hca_hndl, + p_qp_ctx->qp_bind_hndl.rq_cq_hndl, + &wc_desc, + 20, + 10000, + &avh); + if (vapi_ret != VAPI_SUCCESS) + { + if (vapi_ret == VAPI_CQ_EMPTY) + { + status = IB_TIMEOUT; + } + else + { + osm_log( p_log, OSM_LOG_ERROR, + "osmt_reg_unreg_inform_info: ERR 0125: " + "Error receiving mad (%s)\n", + VAPI_strerror_sym(vapi_ret) ); + status = IB_ERROR; + } + goto Exit; + } + + /* check to see if successful - by examination of the subscribe bit */ + p_sa_mad = (ib_sa_mad_t *)(p_qp_ctx->p_recv_buf + GRH_LEN); + + if (p_sa_mad->status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_reg_unreg_inform_info: " + "Remote error = %s\n", + ib_get_mad_status_str( (ib_mad_t *)p_sa_mad )); + status = IB_REMOTE_ERROR; + goto Exit; + } + + if (p_sa_mad->method != IB_MAD_METHOD_GET_RESP) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_reg_unreg_inform_info: " + "Expected IB_MAD_METHOD_GET_RESP but got:(%X)\n", + p_sa_mad->method); + status = IB_REMOTE_ERROR; + goto Exit; + } + + if (p_sa_mad->attr_id != IB_MAD_ATTR_INFORM_INFO) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_reg_unreg_inform_info: " + "Expected IB_MAD_ATTR_INFORM_INFO but got:(%X)\n", + cl_ntoh16(p_sa_mad->attr_id)); + status = IB_REMOTE_ERROR; + goto Exit; + } + + p_ii = ib_sa_mad_get_payload_ptr(p_sa_mad); + if (!p_ii->subscribe) + { + osm_log( p_log, OSM_LOG_ERROR, + "osmt_reg_unreg_inform_info: ERR 0126: " + "Subscribe/Unsubscribe Failed\n"); + status = IB_REMOTE_ERROR; + } + + Exit: + OSM_LOG_EXIT( &p_osmt->log ); + return status; +} + +/* + * Send a trap (Subn LID Route) Trap(Notice) through the regular + * connection QP connection (targeted at QP0) + * + * Wait for the trap repress + */ +ib_api_status_t +osmt_send_trap_wait_for_forward( IN osmtest_t * const p_osmt, + IN osmt_qp_ctx_t *p_qp_ctx + ) +{ + ib_smp_t *p_smp = (ib_smp_t *)(p_qp_ctx->p_send_buf); + ib_mad_notice_attr_t *p_ntc = ib_smp_get_payload_ptr(p_smp); + ib_sa_mad_t * p_sa_mad; + IB_MGT_ret_t mgt_res; + VAPI_ret_t vapi_ret; + VAPI_wc_desc_t wc_desc; + VAPI_ud_av_hndl_t avh; + IB_ud_av_t av; + static VAPI_wr_id_t wrid = 2222; + osm_log_t *p_log = &p_osmt->log; + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osmt_send_trap_wait_for_forward ); + + osm_log( p_log, OSM_LOG_INFO, + "osmt_send_trap_wait_for_forward: " + "Sending Traps to QP0 of SA LID:0x%X\n", + p_osmt->local_port.sm_lid); + + /* init the MAD */ + memset(p_smp, 0, sizeof(ib_smp_t)); + ib_mad_init_new( (ib_mad_t*)p_smp, + IB_MCLASS_SUBN_LID, + ( uint8_t ) 2, + IB_MAD_METHOD_TRAP, + cl_hton64( wrid), + ( ib_net16_t ) 0, + 0 ); + + wrid++; + p_smp->attr_id = IB_MAD_ATTR_NOTICE; + + /* prepare the notice */ + p_ntc->generic_type = 0x82;/* generic, type = 2 */ + ib_notice_set_prod_type_ho(p_ntc, 1); + p_ntc->g_or_v.generic.trap_num = cl_hton16(0x26); + p_ntc->issuer_lid = cl_hton16(2); + + /* --------------------- PREP ------------------------- */ + if (osmt_mtl_mad_post_recv_bufs(&p_qp_ctx->qp_bind_hndl, + p_qp_ctx->p_recv_buf, + 1, /* we need to receive both trap repress and report */ + GRH_LEN + MAD_BLOCK_SIZE, + wrid) != 1) { + osm_log( p_log, OSM_LOG_ERROR, + "osmt_send_trap_wait_for_forward: ERR 0127: " + "Error posting recv bufs\n"); + status = IB_ERROR; + goto Exit; + } + osm_log( p_log, OSM_LOG_DEBUG, + "osmt_send_trap_wait_for_forward: " + "Posted recv bufs\n"); + + av.dlid = p_osmt->local_port.sm_lid; + av.grh_flag = FALSE; + + /* EZ: returned in HACK: use constants */ + av.static_rate = 0; /* p_mad_addr->static_rate; */ + av.src_path_bits = 1 ; /* p_mad_addr->path_bits; */ + av.sl = 0 ; /* p_mad_addr->addr_type.gsi.service_level; */ + + if( osm_log_is_active( p_log, OSM_LOG_DEBUG ) ) + { + osm_log( p_log, OSM_LOG_DEBUG, + "osmt_send_trap_wait_for_forward: " + "av.dlid 0x%X, " + "av.static_rate %d, " + "av.path_bits %d\n", + cl_ntoh16( av.dlid ), av.static_rate, av.src_path_bits ); + } + + /* send it */ + mgt_res = IB_MGT_send_mad( p_qp_ctx->ib_mgt_qp0_handle, p_smp, /* actual payload */ + &av, /* address vector */ + wrid, /* casting the mad wrapper pointer for err cb */ + p_osmt->opt.transaction_timeout ); + if( mgt_res != IB_MGT_OK ) + { + osm_log( p_log, OSM_LOG_ERROR, + "osmt_send_trap_wait_for_forward: ERR 0128: " + "Error sending mad (%d)\n", mgt_res ); + status = IB_ERROR; + goto Exit; + } + + vapi_ret = osmt_mtl_create_av(&p_qp_ctx->qp_bind_hndl, p_osmt->local_port.sm_lid, &avh); + if (vapi_ret != VAPI_OK) + { + osm_log( p_log, OSM_LOG_ERROR, + "osmt_send_trap_wait_for_forward: ERR 0129: " + "Error Preparing AVH (%s)\n", + VAPI_strerror_sym(vapi_ret) ); + status = IB_ERROR; + goto Exit; + } + osm_log( p_log, OSM_LOG_DEBUG, + "osmt_send_trap_wait_for_forward: " + "Prepared AVH\n"); + + osm_log( p_log, OSM_LOG_DEBUG, + "osmt_send_trap_wait_for_forward: " + "Trap MAD Sent\n"); + + /* --------------------- RECV ------------------------- */ + vapi_ret = osmt_mtl_mad_poll4cqe(p_qp_ctx->qp_bind_hndl.hca_hndl, + p_qp_ctx->qp_bind_hndl.rq_cq_hndl, + &wc_desc, + 200, + 10000, + &avh); + if (vapi_ret != VAPI_SUCCESS) + { + if (vapi_ret == VAPI_CQ_EMPTY) + { + osm_log( p_log, OSM_LOG_ERROR, + "osmt_send_trap_wait_for_forward: ERR 0130: " + "Timeout receiving mad (%s)\n", + VAPI_strerror_sym(vapi_ret) ); + status = IB_TIMEOUT; + } + else + { + osm_log( p_log, OSM_LOG_ERROR, + "osmt_send_trap_wait_for_forward: ERR 0131: " + "Error receiving mad (%s)\n", + VAPI_strerror_sym(vapi_ret) ); + status = IB_ERROR; + } + goto Exit; + } + + /* check to see if successful - by examination of the subscribe bit */ + p_sa_mad = (ib_sa_mad_t *)(p_qp_ctx->p_recv_buf + GRH_LEN); + + if (p_sa_mad->method == IB_MAD_METHOD_REPORT) + { + if (p_sa_mad->attr_id == IB_MAD_ATTR_NOTICE) + { + osm_log( p_log, OSM_LOG_INFO, + "osmt_send_trap_wait_for_forward: " + "Received the Report!\n"); + status = IB_SUCCESS; + } + else + { + osm_log( p_log, OSM_LOG_ERROR, + "osmt_send_trap_wait_for_forward: ERR 1020" + "Did not receive a Report(Notice) but attr:%d\n", + cl_ntoh16(p_sa_mad->attr_id) + ); + status = IB_ERROR; + } + } + else + { + osm_log( p_log, OSM_LOG_ERROR, + "osmt_send_trap_wait_for_forward: ERR 1020" + "Received an Unexpected Method:%d\n", + p_smp->method + ); + status = IB_ERROR; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return status; +} + +/* + * Wait for a trap on QPn + * + */ +ib_api_status_t +osmt_trap_wait( IN osmtest_t * const p_osmt, + IN osmt_qp_ctx_t *p_qp_ctx + ) +{ + ib_smp_t *p_smp = (ib_smp_t *)(p_qp_ctx->p_send_buf); + ib_sa_mad_t * p_sa_mad; + VAPI_ret_t vapi_ret; + VAPI_wc_desc_t wc_desc; + osm_log_t *p_log = &p_osmt->log; + ib_api_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( p_log, osmt_trap_wait ); + + osm_log( p_log, OSM_LOG_INFO, + "osmt_trap_wait: " + "Waiting for Traps under QP:0x%X of SA LID:0x%X\n", + cl_ntoh16(p_osmt->local_port.sm_lid)); + + /* --------------------- RECV ------------------------- */ + vapi_ret = osmt_mtl_mad_poll4cqe(p_qp_ctx->qp_bind_hndl.hca_hndl, + p_qp_ctx->qp_bind_hndl.rq_cq_hndl, + &wc_desc, + // 200, + p_osmt->opt.wait_time * 100, + 10000, + NULL); + if (vapi_ret != VAPI_SUCCESS) + { + if (vapi_ret == VAPI_CQ_EMPTY) + { + osm_log( p_log, OSM_LOG_ERROR, + "osmt_trap_wait: ERR 0130: " + "Timeout receiving mad (%s)\n", + VAPI_strerror_sym(vapi_ret) ); + status = IB_TIMEOUT; + } + else + { + osm_log( p_log, OSM_LOG_ERROR, + "osmt_trap_wait: ERR 0131: " + "Error receiving mad (%s)\n", + VAPI_strerror_sym(vapi_ret) ); + status = IB_ERROR; + } + goto Exit; + } + + /* check to see if successful - by examination of the subscribe bit */ + p_sa_mad = (ib_sa_mad_t *)(p_qp_ctx->p_recv_buf + GRH_LEN); + + if (p_sa_mad->method == IB_MAD_METHOD_REPORT) + { + if (p_sa_mad->attr_id == IB_MAD_ATTR_NOTICE) + { + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_trap_wait: " + "Received the Report!\n"); + status = IB_SUCCESS; + } + else + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_trap_wait: ERR 1020" + "Did not receive a Report(Notice) but attr:%d\n", + cl_ntoh16(p_sa_mad->attr_id) + ); + status = IB_ERROR; + } + } + else + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_trap_wait: ERR 1020" + "Received an Unexpected Method:%d\n", + p_smp->method + ); + status = IB_ERROR; + } + + Exit: + OSM_LOG_EXIT( p_log ); + return status; +} + +/* + * Initialize an inform info attribute: + * Catch all traps in the lid range of the p_osmt + * + */ +ib_api_status_t +osmt_init_inform_info(IN osmtest_t * const p_osmt, + OUT ib_inform_info_t* p_ii) { + + memset(p_ii, 0, sizeof(ib_inform_info_t)); + /* p_ii->lid_range_begin = cl_hton16(1); */ + p_ii->lid_range_begin = 0xFFFF; + p_ii->lid_range_end = cl_hton16(p_osmt->max_lid); + p_ii->is_generic = 1; /* have to choose */ + p_ii->trap_type = 0xFFFF; /* ALL */ + p_ii->g_or_v.generic.trap_num = 0xFFFF; /* ALL */ + p_ii->g_or_v.generic.node_type_lsb = 0xFFFF; /* ALL */ + p_ii->g_or_v.generic.node_type_msb = 0xFF; /* ALL */ + return IB_SUCCESS; +} + +ib_api_status_t +osmt_init_inform_info_by_trap (IN osmtest_t * const p_osmt, + IN ib_net16_t trap_num, + OUT ib_inform_info_t* p_ii) { + + memset(p_ii, 0, sizeof(ib_inform_info_t)); + /* p_ii->lid_range_begin = cl_hton16(1); */ + p_ii->lid_range_begin = 0xFFFF; + p_ii->lid_range_end = cl_hton16(p_osmt->max_lid); + p_ii->is_generic = 1; /* have to choose */ + p_ii->trap_type = 0xFFFF; /* ALL */ + p_ii->g_or_v.generic.trap_num = trap_num; /* ALL */ + p_ii->g_or_v.generic.node_type_lsb = 0xFFFF; /* ALL */ + p_ii->g_or_v.generic.node_type_msb = 0xFF; /* ALL */ + return IB_SUCCESS; +} + +/* + * Run a complete inform info test flow: + * - try to unregister inform info (should fail) + * - register an inform info + * - try to unregister inform info (should succeed) + * - register an inform info + * - send a trap - sleep + * - check that a Report(Notice) arrived that match the sent one + * + */ +ib_api_status_t +osmt_run_inform_info_flow( IN osmtest_t * const p_osmt ) { + ib_inform_info_t inform_info; + ib_api_status_t status; + osmt_qp_ctx_t qp_ctx; + + OSM_LOG_ENTER( &p_osmt->log, osmt_run_inform_info_flow); + + /* bind the QP */ + status = osmt_bind_inform_qp( p_osmt, &qp_ctx); + if (status != IB_SUCCESS) + { + goto Exit; + } + + /* init the inform info */ + osmt_init_inform_info(p_osmt, &inform_info); + + /* first try to unsubscribe */ + status = osmt_reg_unreg_inform_info(p_osmt, + &qp_ctx, + &inform_info, + 0); + /* WAS IB_REMOTE_ERROR */ + if (status != IB_REMOTE_ERROR) + { + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_inform_info_flow:" + "Error during UnSubscribe: (%s)\n", + ib_get_err_str( status )); + goto Exit; + } + else + { + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_inform_info_flow:" + "Expected Failure to UnSubscribe non existing InformInfo\n"); + status = IB_ERROR; + goto Exit; + } + } + + /* send the inform info registration */ + status = osmt_reg_unreg_inform_info(p_osmt, + &qp_ctx, + &inform_info, + 1); + if (status != IB_SUCCESS) + { + goto Exit; + } + + /* send a trap through QP0 and wait on QPN */ + status = osmt_send_trap_wait_for_forward(p_osmt, &qp_ctx); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_inform_info_flow:" + "Error during Send Trap and Wait For Report: (%s)\n", + ib_get_err_str( status )); + goto Exit; + } + + /* try to unsubscribe for cleanup */ + status = osmt_reg_unreg_inform_info(p_osmt, + &qp_ctx, + &inform_info, + 0); + + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_inform_info_flow:" + "Error during UnSubscribe: (%s)\n", + ib_get_err_str( status )); + goto Exit; + } + else + { + if (status == IB_REMOTE_ERROR) + { + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_inform_info_flow:" + "Remote Error during UnSubscribe\n"); + status = IB_ERROR; + goto Exit; + } + } + + Exit: + osmt_unbind_inform_qp( p_osmt, &qp_ctx); + OSM_LOG_EXIT( &p_osmt->log ); + return status; +} + +/* + * Run a complete inform info test flow: + * - try to unregister inform info (should fail) + * - register an inform info + * - try to unregister inform info (should succeed) + * - register an inform info + * - send a trap - sleep + * - check that a Report(Notice) arrived that match the sent one + * + */ +ib_api_status_t +osmt_run_trap64_65_flow( IN osmtest_t * const p_osmt) { + ib_inform_info_t inform_info; + ib_api_status_t status; + osmt_qp_ctx_t qp_ctx; + + OSM_LOG_ENTER( &p_osmt->log, osmt_run_trap64_65_flow); + + /* bind the QP */ + status = osmt_bind_inform_qp( p_osmt, &qp_ctx); + if (status != IB_SUCCESS) + { + goto Exit; + } + + /* init the inform info */ + osmt_init_inform_info_by_trap(p_osmt, + cl_hton16(64), + &inform_info); + + /* send the inform info registration */ + status = osmt_reg_unreg_inform_info(p_osmt, + &qp_ctx, + &inform_info, + 1); + if (status != IB_SUCCESS) + { + goto Exit; + } + + /*--------------------- PREP -------------------------*/ + if (osmt_mtl_mad_post_recv_bufs( + &qp_ctx.qp_bind_hndl, + qp_ctx.p_recv_buf, + 1, /* we need to receive the report */ + GRH_LEN + MAD_BLOCK_SIZE, + 1) != 1) { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_trap64_65_flow: ERR 0127: " + "Error posting recv bufs for trap 64\n"); + status = IB_ERROR; + goto Exit; + } + + osm_log( &p_osmt->log, OSM_LOG_DEBUG, + "osmt_run_trap64_65_flow: " + "Posted recv bufs for trap 64\n"); + + /* init the inform info */ + osmt_init_inform_info_by_trap(p_osmt, + cl_hton16(65), + &inform_info); + + /* send the inform info registration */ + status = osmt_reg_unreg_inform_info(p_osmt, + &qp_ctx, + &inform_info, + 1); + if (status != IB_SUCCESS) + { + goto Exit; + } + + /*--------------------- PREP -------------------------*/ + if (osmt_mtl_mad_post_recv_bufs( + &qp_ctx.qp_bind_hndl, + qp_ctx.p_recv_buf, + 1, /* we need to reveive the report */ + GRH_LEN + MAD_BLOCK_SIZE, + 1) != 1) { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_trap64_65_flow: ERR 0127: " + "Error posting recv bufs for trap 65\n"); + status = IB_ERROR; + goto Exit; + } + osm_log( &p_osmt->log, OSM_LOG_DEBUG, + "osmt_run_trap64_65_flow: " + "Posted recv bufs for trap 65\n"); + + /* Sleep for x seconds in order to allow external script trap generation */ +#if 0 + sleep (p_osmt->opt.wait_time); +#endif + + /* wait for a trap on QPN */ + status = osmt_trap_wait(p_osmt, &qp_ctx); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_trap64_65_flow:" + "Error during Send Trap and Wait For Report: (%s)\n", + ib_get_err_str( status )); + goto Exit; + } + + /* try to unsubscribe for cleanup */ + status = osmt_reg_unreg_inform_info(p_osmt, + &qp_ctx, + &inform_info, + 0); + + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_trap64_65_flow:" + "Error during UnSubscribe: (%s)\n", + ib_get_err_str( status )); + goto Exit; + } + + Exit: + osmt_unbind_inform_qp( p_osmt, &qp_ctx); + OSM_LOG_EXIT( &p_osmt->log ); + return status; +} + +#endif /* OSM_VENDOR_INTF_MTL */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmt_mtl_regular_qp.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmt_mtl_regular_qp.c new file mode 100644 index 00000000..1df7e3bd --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmt_mtl_regular_qp.c @@ -0,0 +1,447 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osmt_mtl_regular_qp.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +#ifdef OSM_VENDOR_INTF_MTL + +/* - Mellanox Confidential and Proprietary - + * + * Copyright (C) Jul. 2001, Mellanox Technologies Ltd. ALL RIGHTS RESERVED. + * + * Except as specifically permitted herein, no portion of the information, + * including but not limited to object code and source code, may be reproduced, + * modified, distributed, republished or otherwise exploited in any form or by + * any means for any purpose without the prior written permission of Mellanox + * Technologies Ltd. Use of software subject to the terms and conditions + * detailed in the file "LICENSE.txt". + * + * End of legal section ...................................................... + * + * osmt_mtl_regular_qp.c - + * Provide Simple Interface for Sending and Receiving MADS through a regular QP + * + * Creation date: + * + * Version: $Id: osmt_mtl_regular_qp.c 571 2007-01-25 12:58:44Z sleybo $ + * + * Authors: + * Eitan Zahavi + * + * Changes: + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +/* + * Initialize the QP etc. + * Given in res: port_num, max_outs_sq, max_outs_rq + */ +VAPI_ret_t osmt_mtl_get_qp_resources(IN OUT osmt_mtl_mad_res_t *res) +{ + VAPI_ret_t ret; + VAPI_hca_port_t hca_port_info; + VAPI_qp_init_attr_t qp_init_attr; + VAPI_qp_prop_t qp_prop; + VAPI_cqe_num_t act_num; + + /* Get HCA LID */ + ret = VAPI_query_hca_port_prop(res->hca_hndl, res->port_num, &hca_port_info); VAPI_CHECK_RET; + res->slid = hca_port_info.lid; + + /* Get a PD */ + ret = VAPI_alloc_pd(res->hca_hndl, &(res->pd_hndl)); VAPI_CHECK_RET; + + /* Create CQ for RQ and SQ*/ /* TBD - Check we have enough act nums */ + ret = VAPI_create_cq(res->hca_hndl, res->max_outs_sq + 1, &(res->sq_cq_hndl), &act_num); + VAPI_CHECK_RET; + ret = VAPI_create_cq(res->hca_hndl, res->max_outs_rq + 1, &(res->rq_cq_hndl), &act_num); + VAPI_CHECK_RET; + + + /* register event handlers for polling(block mode) internal use*/ + /* ret= EVAPI_set_comp_eventh(res->hca_hndl,res->rq_cq_hndl, */ + /* EVAPI_POLL_CQ_UNBLOCK_HANDLER,NULL,&(res->rq_cq_eventh)); */ + /* VAPI_CHECK_RET; */ + /* ret= EVAPI_set_comp_eventh(res->hca_hndl,res->sq_cq_hndl, */ + /* EVAPI_POLL_CQ_UNBLOCK_HANDLER,NULL,&(res->sq_cq_eventh)); */ + /* VAPI_CHECK_RET; */ + + /* Create QP */ + qp_init_attr.cap.max_oust_wr_sq = res->max_outs_sq + 1; + qp_init_attr.cap.max_oust_wr_rq = res->max_outs_rq + 1; + qp_init_attr.cap.max_sg_size_sq = 4; + qp_init_attr.cap.max_sg_size_rq = 4; + + qp_init_attr.pd_hndl = res->pd_hndl; + qp_init_attr.rdd_hndl = 0; + qp_init_attr.rq_cq_hndl = res->rq_cq_hndl; + qp_init_attr.rq_sig_type = VAPI_SIGNAL_ALL_WR; /* That's default for IB */ + qp_init_attr.sq_cq_hndl = res->sq_cq_hndl; + qp_init_attr.sq_sig_type = VAPI_SIGNAL_REQ_WR; + qp_init_attr.ts_type = VAPI_TS_UD; + + ret= VAPI_create_qp(res->hca_hndl,&qp_init_attr,&(res->qp_hndl),&qp_prop); + VAPI_CHECK_RET; + res->qp_id.qp_num= qp_prop.qp_num; + + return(VAPI_OK); +} + +VAPI_ret_t osmt_mtl_qp_init(osmt_mtl_mad_res_t *res) +{ + VAPI_ret_t ret; + + VAPI_qp_attr_t qp_attr; + VAPI_qp_attr_mask_t qp_attr_mask; + VAPI_qp_cap_t qp_cap; + + + /* + * Change QP to INIT + * + */ + QP_ATTR_MASK_CLR_ALL(qp_attr_mask); + qp_attr.qp_state = VAPI_INIT; + QP_ATTR_MASK_SET(qp_attr_mask,QP_ATTR_QP_STATE); + qp_attr.pkey_ix = 0; + QP_ATTR_MASK_SET(qp_attr_mask,QP_ATTR_PKEY_IX); + qp_attr.port = res->port_num; + QP_ATTR_MASK_SET(qp_attr_mask,QP_ATTR_PORT); + qp_attr.qkey = res->qkey; + QP_ATTR_MASK_SET(qp_attr_mask,QP_ATTR_QKEY); + + /* If I do not set this mask, I get an error from HH. QPM should catch it */ + ret = VAPI_modify_qp(res->hca_hndl, res->qp_hndl, &qp_attr, &qp_attr_mask, &qp_cap); VAPI_CHECK_RET; + + return(ret); + +} + +VAPI_ret_t osmt_mtl_qp_2_rtr_rts(osmt_mtl_mad_res_t *res) +{ + VAPI_ret_t ret; + + VAPI_qp_attr_t qp_attr; + VAPI_qp_attr_mask_t qp_attr_mask; + VAPI_qp_cap_t qp_cap; + + /* + * Change QP to RTR + * + */ + QP_ATTR_MASK_CLR_ALL(qp_attr_mask); + qp_attr.qp_state = VAPI_RTR; + QP_ATTR_MASK_SET(qp_attr_mask,QP_ATTR_QP_STATE); + /* qp_attr.rq_psn = 0; */ + /* QP_ATTR_MASK_SET(qp_attr_mask,QP_ATTR_RQ_PSN); */ + + ret = VAPI_modify_qp(res->hca_hndl, res->qp_hndl, &qp_attr, &qp_attr_mask, &qp_cap); VAPI_CHECK_RET; + + /* + * Change QP to RTS + * + */ + QP_ATTR_MASK_CLR_ALL(qp_attr_mask); + qp_attr.qp_state = VAPI_RTS; + QP_ATTR_MASK_SET(qp_attr_mask,QP_ATTR_QP_STATE); + qp_attr.sq_psn = 0; + QP_ATTR_MASK_SET(qp_attr_mask,QP_ATTR_SQ_PSN); + + ret = VAPI_modify_qp(res->hca_hndl,res->qp_hndl,&qp_attr,&qp_attr_mask,&qp_cap); VAPI_CHECK_RET; + + return(ret); +} + +VAPI_ret_t osmt_mtl_mad_create_mr(osmt_mtl_mad_res_t *res) +{ + + VAPI_ret_t ret; + + VAPI_mrw_t mr_in, mr_out; + + + res->buf_size = (MAD_SIZE + GRH_LEN) * (res->max_outs_sq + res->max_outs_rq + 1); + + /* Register single memory address region for all buffers */ + res->buf_ptr = VMALLOC(res->buf_size); + + if (res->buf_ptr == ((VAPI_virt_addr_t)NULL)) { + ret = VAPI_EAGAIN; + VAPI_CHECK_RET; + } + + /* Enable local and remote access to memory region */ + mr_in.acl = VAPI_EN_LOCAL_WRITE | VAPI_EN_REMOTE_WRITE; + mr_in.l_key =0; + mr_in.pd_hndl = res->pd_hndl; + mr_in.r_key =0; + mr_in.size = res->buf_size; + ASSERT_VOIDP2UINTN(res->buf_ptr); + mr_in.start = (VAPI_virt_addr_t)(uintn_t)(res->buf_ptr); + mr_in.type = VAPI_MR; + + ret = VAPI_register_mr(res->hca_hndl, &mr_in, &(res->mr_hndl), &mr_out); VAPI_CHECK_RET; + + res->l_key = mr_out.l_key; + + return(ret); +} + +VAPI_ret_t osmt_mtl_init_opened_hca(osmt_mtl_mad_res_t* res) +{ + VAPI_ret_t ret; + + res->pd_hndl= VAPI_INVAL_HNDL; + res->rq_cq_hndl= VAPI_INVAL_HNDL; + res->sq_cq_hndl= VAPI_INVAL_HNDL; + res->sq_cq_eventh= VAPI_INVAL_HNDL; + res->rq_cq_eventh= VAPI_INVAL_HNDL; + res->qp_hndl= VAPI_INVAL_HNDL; + res->mr_hndl= VAPI_INVAL_HNDL; + + /* + * Create QP + * + */ + ret = osmt_mtl_get_qp_resources(res); + if (ret != VAPI_OK) { + return ret; + } + + /* + * Move to init + * + */ + ret = osmt_mtl_qp_init(res); + if (ret != VAPI_OK) { + return ret; + } + + + /* + * Initialize memory regions + * + */ + ret = osmt_mtl_mad_create_mr(res); + if (ret != VAPI_OK) { + return ret; + } + + /* only now move to RTR and RTS */ + ret = osmt_mtl_qp_2_rtr_rts(res); + if (ret != VAPI_OK) { + return ret; + } + + return VAPI_OK; +} + + + +VAPI_ret_t osmt_mtl_mad_cleanup(osmt_mtl_mad_res_t *res) +{ + if (res->qp_hndl != VAPI_INVAL_HNDL) { + VAPI_destroy_qp(res->hca_hndl,res->qp_hndl); + } + if (res->sq_cq_eventh != VAPI_INVAL_HNDL) { + EVAPI_clear_comp_eventh(res->hca_hndl,res->sq_cq_eventh); + } + if (res->rq_cq_eventh != VAPI_INVAL_HNDL) { + EVAPI_clear_comp_eventh(res->hca_hndl,res->rq_cq_eventh); + } + if (res->rq_cq_hndl != VAPI_INVAL_HNDL) { + VAPI_destroy_cq(res->hca_hndl,res->rq_cq_hndl); + } + if (res->sq_cq_hndl != VAPI_INVAL_HNDL) { + VAPI_destroy_cq(res->hca_hndl,res->sq_cq_hndl); + } + if (res->mr_hndl != VAPI_INVAL_HNDL) { + VAPI_deregister_mr(res->hca_hndl,res->mr_hndl); + } + if (res->pd_hndl != VAPI_INVAL_HNDL) { + VAPI_dealloc_pd(res->hca_hndl,res->pd_hndl); + } +#if 0 + /* open/close of HCA should be done system wide - not per application */ + if (res->hca_hndl != VAPI_INVAL_HNDL) { + VAPI_close_hca(res->hca_hndl); /* TBD: HCA_open/close should be done on a system wide basis */ + } +#endif + return VAPI_OK; +} + +VAPI_ret_t osmt_mtl_create_av(osmt_mtl_mad_res_t* res, int16_t dlid, VAPI_ud_av_hndl_t *avh_p) +{ + VAPI_ud_av_t av; + VAPI_ret_t ret; + + av.dlid= dlid; + av.port= res->port_num; + av.sl = 0; /* dest->sl; */ + av.src_path_bits= 0; /* dest->ee_dlid.dst_path_bits; */ + av.static_rate = 0; + /* GRH ? */ + av.grh_flag= 0; + + ret= VAPI_create_addr_hndl(res->hca_hndl,res->pd_hndl, &av,avh_p); + if (ret != VAPI_OK) { + MTL_ERROR1("%s: failed VAPI_create_addr_hndl (%s)\n", __func__, + VAPI_strerror_sym(ret)); + return ret; + } + return VAPI_OK; +} + +VAPI_ret_t osmt_mtl_mad_send(osmt_mtl_mad_res_t* res, VAPI_wr_id_t id, void* mad, + VAPI_qp_num_t dest_qp, IB_sl_t sl,u_int32_t dest_qkey, VAPI_ud_av_hndl_t avh) +{ + VAPI_sr_desc_t sr; + VAPI_sg_lst_entry_t sg_entry; + VAPI_ret_t ret; + + /* building SEND request */ + sr.opcode= VAPI_SEND; + sr.remote_ah= avh; + sr.remote_qp= dest_qp; + sr.remote_qkey= dest_qkey; + + sr.id = id; + sr.set_se= FALSE; + sr.fence= FALSE; + sr.comp_type= VAPI_SIGNALED; + sr.sg_lst_len= 1; + sr.sg_lst_p= &sg_entry; + ASSERT_VOIDP2UINTN(mad); + sg_entry.addr= (VAPI_virt_addr_t)(uintn_t)(mad); + sg_entry.len= MAD_SIZE; + sg_entry.lkey= res->l_key; + + ret= VAPI_post_sr(res->hca_hndl,res->qp_hndl,&sr); + if (ret != VAPI_OK) { + MTL_ERROR1(__FUNCTION__ ": failed VAPI_post_sr (%s)\n", + VAPI_strerror_sym(ret)); + return ret; + } + + return VAPI_OK; +} + +int osmt_mtl_mad_post_recv_bufs(osmt_mtl_mad_res_t* res, void *buf_array, + u_int32_t num_o_bufs,u_int32_t size, VAPI_wr_id_t start_id) +{ + uint32_t i; + void* cur_buf; + VAPI_rr_desc_t rr; + VAPI_sg_lst_entry_t sg_entry; + VAPI_ret_t ret; + + rr.opcode= VAPI_RECEIVE; + rr.comp_type= VAPI_SIGNALED; /* All with CQE (IB compliant) */ + rr.sg_lst_len= 1; /* single buffers */ + rr.sg_lst_p= &sg_entry; + sg_entry.lkey= res->l_key; + cur_buf = buf_array; + for (i= 0; i < num_o_bufs ; i++ ) { + rr.id= start_id+i; /* WQE id used is the index to buffers ptr array */ + ASSERT_VOIDP2UINTN(cur_buf); + sg_entry.addr= (VAPI_virt_addr_t)(uintn_t)cur_buf; + sg_entry.len= size; + memset(cur_buf,0x00,size); /* fill with 0 */ + ret= VAPI_post_rr(res->hca_hndl,res->qp_hndl,&rr); + if (ret != VAPI_OK) { + MTL_ERROR1(__FUNCTION__ ": failed posting RQ WQE (%s)\n",VAPI_strerror_sym(ret)); + return i; + } + MTL_DEBUG4(__FUNCTION__ ": posted buf at %p\n",cur_buf); + cur_buf += size; + } + + return i; /* num of buffers posted */ +} + + +VAPI_ret_t osmt_mtl_mad_poll4cqe(VAPI_hca_hndl_t hca,VAPI_cq_hndl_t cq, + VAPI_wc_desc_t *wc_desc_p, + u_int32_t max_poll, u_int32_t poll_sleep, + VAPI_ud_av_hndl_t *avh_p) +{ + VAPI_ret_t ret = VAPI_CQ_EMPTY; + u_int32_t poll_cnt= 0; + + + /* wait for something to arrive */ + while ((ret == VAPI_CQ_EMPTY) && (poll_cnt < max_poll)) { + ret= VAPI_poll_cq(hca,cq,wc_desc_p); + /* don't sleep if we already succeeded) */ + if (ret != VAPI_CQ_EMPTY) { + break; + } + usleep(poll_sleep); + poll_cnt++; + } + + /* if passed an AVH to destory - do it */ + if (avh_p != NULL) { + VAPI_destroy_addr_hndl(hca,*avh_p); + } + + if ((poll_cnt == max_poll) && (ret == VAPI_CQ_EMPTY)) { + MTL_DEBUG1(__FUNCTION__ ": Failed to get completion on wq after %d polls.\n",max_poll); + return VAPI_CQ_EMPTY; + } + + if (ret != VAPI_OK) { + MTL_DEBUG1(__FUNCTION__ ": VAPI_poll_cq failed with ret=%s on sq_cq\n",mtl_strerror_sym(ret)); + return ret; + } + + if (wc_desc_p->status != VAPI_SUCCESS) { + MTL_DEBUG1(__FUNCTION__ ": completion error (%d) detected\n",wc_desc_p->status); + } + + return VAPI_OK; +} + +#endif /* OSM_VENDOR_INTF_MTL */ + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmt_multicast.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmt_multicast.c new file mode 100644 index 00000000..a393a425 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmt_multicast.c @@ -0,0 +1,3500 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osmt_multicast.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Implementation of Multicast Member testing flow.. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.2 $ + */ + +#ifndef __WIN__ +#include +#endif +#include +#include +#include +#include +#include +#include "osmtest.h" + +/********************************************************************** + **********************************************************************/ + +static void +__osmt_print_all_multicast_records( + IN osmtest_t * const p_osmt ) +{ + uint32_t i; + ib_api_status_t status; + osmv_query_req_t req; + osmv_user_query_t user; + osmtest_req_context_t context; + ib_member_rec_t *mcast_record; + + memset( &context, 0, sizeof( context ) ); + memset( &req, 0, sizeof( req ) ); + memset( &user, 0, sizeof( user ) ); + + user.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD; + user.attr_offset = ib_get_attr_offset(sizeof(*mcast_record)); + + req.query_type = OSMV_QUERY_USER_DEFINED; + req.timeout_ms = p_osmt->opt.transaction_timeout; + req.retry_cnt = 1; + req.flags = OSM_SA_FLAGS_SYNC; + context.p_osmt = p_osmt; + req.query_context = &context; + req.pfn_query_cb = osmtest_query_res_cb; + req.p_query_input = &user; + + /* UnTrusted (SMKey of 0) - get the multicast groups */ + status = osmv_query_sa(p_osmt->h_bind, &req); + + if (status != IB_SUCCESS || context.result.status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "__osmt_print_all_multicast_records: ERR 02B5: " + "Failed getting the multicast groups records - %s/%s\n", + ib_get_err_str(status), + ib_get_err_str(context.result.status) ); + return; + } + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "\n |------------------------------------------|" + "\n | Remaining Multicast Groups |" + "\n |------------------------------------------|\n" ); + + for (i = 0; i < context.result.result_cnt; i++) { + mcast_record = osmv_get_query_mc_rec(context.result.p_result_madw, i); + osm_dump_mc_record(&p_osmt->log, mcast_record,OSM_LOG_INFO); + } + + /* Trusted - now get the multicast group members */ + req.sm_key = OSM_DEFAULT_SM_KEY; + status = osmv_query_sa(p_osmt->h_bind, &req); + + if (status != IB_SUCCESS || context.result.status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "__osmt_print_all_multicast_records: ERR 02B6: " + "Failed getting the multicast group members records - %s/%s\n", + ib_get_err_str(status), + ib_get_err_str(context.result.status) ); + return; + } + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "\n |--------------------------------------------------|" + "\n | Remaining Multicast Group Members |" + "\n |--------------------------------------------------|\n" ); + + for (i = 0; i < context.result.result_cnt; i++) { + mcast_record = osmv_get_query_mc_rec(context.result.p_result_madw, i); + osm_dump_mc_record(&p_osmt->log, mcast_record,OSM_LOG_INFO); + } + +} + +/********************************************************************** + **********************************************************************/ + +static cl_status_t +__match_mgids( + IN const void* const p_object, + IN void* context ) +{ + ib_gid_t* p_mgid_context = (ib_gid_t *)context; + ib_gid_t* p_mgid_list_item = (ib_gid_t*)p_object; + int32_t count; + + count = memcmp(p_mgid_context, p_mgid_list_item, sizeof(ib_gid_t)); + if(count == 0) + return CL_SUCCESS; + else + return CL_NOT_FOUND; +} + +/********************************************************************** + **********************************************************************/ + +ib_api_status_t +osmt_query_mcast( IN osmtest_t * const p_osmt ) { + ib_api_status_t status = IB_SUCCESS; + osmv_user_query_t user; + osmv_query_req_t req; + osmtest_req_context_t context; + ib_member_rec_t *p_rec; + uint32_t i,num_recs = 0; + cl_list_t mgids_list; + cl_list_t* p_mgids_list; + cl_list_iterator_t p_mgids_res; + cl_status_t cl_status; + cl_map_item_t *p_item,*p_next_item; + osmtest_mgrp_t *p_mgrp; + + OSM_LOG_ENTER( &p_osmt->log, osmt_query_mcast ); + + /* + * Do a blocking query for all Multicast Records in the subnet. + * The result is returned in the result field of the caller's + * context structure. + * + * The query structures are locals. + */ + + memset( &req, 0, sizeof( req ) ); + memset( &user, 0, sizeof( user ) ); + + context.p_osmt = p_osmt; + user.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD; + user.attr_offset = ib_get_attr_offset( sizeof( ib_member_rec_t ) ); + + req.query_type = OSMV_QUERY_USER_DEFINED; + req.timeout_ms = p_osmt->opt.transaction_timeout; + req.retry_cnt = p_osmt->opt.retry_count; + req.flags = OSM_SA_FLAGS_SYNC; + req.query_context = &context; + req.pfn_query_cb = osmtest_query_res_cb; + req.p_query_input = &user; + + status = osmv_query_sa( p_osmt->h_bind, &req ); + + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_query_mcast: ERR 0203: " + "ib_query failed (%s)\n", ib_get_err_str( status ) ); + goto Exit; + } + + status = context.result.status; + + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_query_mcast: ERR 0264: " + "ib_query failed (%s)\n", ib_get_err_str( status ) ); + if( status == IB_REMOTE_ERROR ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_query_mcast: " + "Remote error = %s.\n", + ib_get_mad_status_str( osm_madw_get_mad_ptr + ( context.result. + p_result_madw ) ) ); + } + goto Exit; + } + + /* ok we have got something */ + /* First Delete the old MGID Table */ + p_next_item = cl_qmap_head( &p_osmt->exp_subn.mgrp_mlid_tbl ); + while( p_next_item != cl_qmap_end( &p_osmt->exp_subn.mgrp_mlid_tbl ) ) + { + p_item = p_next_item; + p_next_item = cl_qmap_next( p_item ); + cl_qmap_remove_item(&p_osmt->exp_subn.mgrp_mlid_tbl,p_item); + free( p_item ); + + } + + cl_list_construct(&mgids_list); + cl_list_init( &mgids_list, num_recs ); + p_mgids_list = &mgids_list; + num_recs = context.result.result_cnt; + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_query_mcast: " + "Received %u records\n", num_recs ); + + for( i = 0; i < num_recs; i++ ) + { + p_rec = osmv_get_query_result( context.result.p_result_madw, i ); + p_mgids_res = cl_list_find_from_head ( p_mgids_list,__match_mgids,&(p_rec->mgid)); + /* If returns iterator other than end of list, same mgid exists already */ + if( p_mgids_res != cl_list_end( p_mgids_list ) ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_query_mcast: ERR 0265: " + "MCG MGIDs are the same - invalid MGID : 0x%016" PRIx64 " 0x%016" + PRIx64 "\n", + cl_ntoh64(p_rec->mgid.unicast.prefix), + cl_ntoh64(p_rec->mgid.unicast.interface_id)); + status = IB_ERROR; + goto Exit; + + } + osm_dump_mc_record( &p_osmt->log, p_rec, OSM_LOG_VERBOSE ); + cl_status = cl_list_insert_head(p_mgids_list,&(p_rec->mgid)); + if (cl_status) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_query_mcast: ERR 0205: " + "Could not add MGID to cl_list\n" ); + status = IB_ERROR; + goto Exit; + } + p_mgrp = (osmtest_mgrp_t*)malloc( sizeof(*p_mgrp) ); + if (!p_mgrp) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_query_mcast: ERR 0204: " + "Could not allocate new MCG\n" ); + status = IB_ERROR; + goto Exit; + } + memcpy(&p_mgrp->mcmember_rec,p_rec,sizeof(p_mgrp->mcmember_rec)); + cl_qmap_insert(&p_osmt->exp_subn.mgrp_mlid_tbl, + cl_ntoh16(p_rec->mlid),&p_mgrp->map_item); + } + + Exit: + if( context.result.p_result_madw != NULL ) + { + osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw ); + context.result.p_result_madw = NULL; + } + + OSM_LOG_EXIT( &p_osmt->log ); + return ( status ); +} + +/********************************************************************** + **********************************************************************/ + +/* given a multicast request send and wait for response. */ +ib_api_status_t +osmt_send_mcast_request( IN osmtest_t * const p_osmt, + IN uint8_t is_set, + IN ib_member_rec_t *p_mc_req, + IN uint64_t comp_mask, + OUT ib_sa_mad_t *p_res + ) { + osmtest_req_context_t context; + ib_api_status_t status = IB_SUCCESS; + osmv_user_query_t user; + osmv_query_req_t req; + + OSM_LOG_ENTER( &p_osmt->log, osmt_send_mcast_request ); + + /* + * Do a blocking query for this record in the subnet. + * + * The query structures are locals. + */ + memset( &req, 0, sizeof( req ) ); + memset( &user, 0, sizeof( user ) ); + memset( &context, 0, sizeof( context ) ); + memset( p_res, 0, sizeof( ib_sa_mad_t ) ); + + context.p_osmt = p_osmt; + + user.p_attr = p_mc_req; + user.comp_mask = comp_mask; + + if (is_set == 1) + { + req.query_type = OSMV_QUERY_UD_MULTICAST_SET; + } else if (is_set == 0) { + req.query_type = OSMV_QUERY_UD_MULTICAST_DELETE; + } else if (is_set == 0xee) { + + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_send_mcast_request: Set USER DEFINED QUERY\n" ); + req.query_type = OSMV_QUERY_USER_DEFINED; + user.method = IB_MAD_METHOD_GET; + user.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD; + user.attr_offset = ib_get_attr_offset( sizeof( ib_member_rec_t ) ); + } else if (is_set == 0xff) + { + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_send_mcast_request: Set USER DEFINED QUERY\n" ); + req.query_type = OSMV_QUERY_USER_DEFINED; + user.method = IB_MAD_METHOD_SET; + user.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD; + user.attr_offset = ib_get_attr_offset( sizeof( ib_member_rec_t ) ); + } + + /* TODO : Check the validity of all user fields in order to use + OSMV_QUERY_USER_DEFINED + p_user_query = ( osmv_user_query_t * ) p_query_req->p_query_input; + if (p_user_query->method) sa_mad_data.method = p_user_query->method; + sa_mad_data.attr_offset = p_user_query->attr_offset; + sa_mad_data.attr_id = p_user_query->attr_id; + sa_mad_data.comp_mask = p_user_query->comp_mask; + sa_mad_data.p_attr = p_user_query->p_attr; + */ + + req.timeout_ms = p_osmt->opt.transaction_timeout; + req.retry_cnt = p_osmt->opt.retry_count; + req.flags = OSM_SA_FLAGS_SYNC; + req.query_context = &context; + req.pfn_query_cb = osmtest_query_res_cb; + req.p_query_input = &user; + + status = osmv_query_sa( p_osmt->h_bind, &req ); + + if ( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_send_mcast_request: ERR 0206: " + "ib_query failed (%s)\n", ib_get_err_str( status ) ); + goto Exit; + } + + /* ok it worked */ + memcpy(p_res, + osm_madw_get_mad_ptr(context.result.p_result_madw), + sizeof(ib_sa_mad_t)); + + status = context.result.status; + + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_send_mcast_request: ERR 0224: " + "ib_query failed (%s)\n", ib_get_err_str( status ) ); + if( status == IB_REMOTE_ERROR ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_send_mcast_request: " + "Remote error = %s\n", + ib_get_mad_status_str( osm_madw_get_mad_ptr + ( context.result.p_result_madw ) ) ); + } + } + + Exit: + /* + * Return the IB query MAD to the pool as necessary. + */ + if( context.result.p_result_madw != NULL ) + { + osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw ); + context.result.p_result_madw = NULL; + } + + OSM_LOG_EXIT( &p_osmt->log ); + return ( status ); +} + +/********************************************************************** + **********************************************************************/ + +void +osmt_init_mc_query_rec(IN osmtest_t * const p_osmt, + IN OUT ib_member_rec_t *p_mc_req) { + /* use default values so we can change only what we want later */ + memset(p_mc_req, 0, sizeof(ib_member_rec_t)); + + /* we leave the MGID to the user */ + memcpy(&p_mc_req->port_gid.unicast.interface_id, + &p_osmt->local_port.port_guid, + sizeof(p_osmt->local_port.port_guid) + ); + + /* use our own subnet prefix: */ + p_mc_req->port_gid.unicast.prefix = CL_HTON64(0xFE80000000000000ULL); + + /* ib_net32_t qkey; */ + /* ib_net16_t mlid; - we keep it zero for upper level to decide. */ + /* uint8_t mtu; - keep it zero means - anything you have please. */ + /* uint8_t tclass; can leave as zero for now (between subnets) */ + /* ib_net16_t pkey; leave as zero */ + p_mc_req->rate = IB_LINK_WIDTH_ACTIVE_4X; + /* uint8_t pkt_life; zero means greater than zero ... */ + /* ib_net32_t sl_flow_hop; keep it all zeros */ + /* we want to use a link local scope: 0x02 */ + p_mc_req->scope_state = ib_member_set_scope_state(0x02, 0); +} + +/*********************************************************************** + * UD Multicast testing flow: + * o15.0.1.3: + * - Request new MCG with not enough components in comp_mask : + * ERR_INSUFFICIENT_COMPONENTS + * o15.0.1.8: + * - Request a join with irrelevant RATE and get a ERR_INVALID_REQ + * o15.0.1.4: + * - Create an MGID by asking for a join with MGID = 0 + * providing P_Key, Q_Key, SL, FlowLabel, Tclass. + * o15.0.1.5: + * - Check the returned MGID is valid. (p 804) + * o15.0.1.6: + * - Create a new MCG with valid requested MGID. + * - Try to create a new MCG with invalid MGID : get back ERR_REQ_INVALID + * - Try again with MGID prefix = 0xA01B (maybe 0x1BA0 little or big ?) + * - Try to create again the already created group: ERR_REQ_INVALID + * o15.0.1.7 - implicitlly checked during the prev steps. + * o15.0.1.9 + * - Create MCG with Invalid JoinState.FullMember != 1 : get ERR_REQ_INVALID + * o15.0.1.10 - can't check on a single client . + * o15.0.1.11: + * - Try to join into a MGID that exists with JoinState=SendOnlyMember - + * see that it updates JoinState. What is the routing change? + * - We can not check simple join since we have only one tester (for now) + * o15.0.1.12: + * - The last join should have a special treatment in the SA (sender only) + * but what is it ? + * o15.0.1.13: + * - Try joining with wrong rate - ERR_REQ_INVALID + * o15.0.1.14: + * - Try partial delete - actually updating the join state. check it. + * - Register by InformInfo flow to receive trap 67 on MCG delete. + * - Try full delete (JoinState and should be 0) + * - Wait for trap 67. + * - Try joining (not full mem) again to see the group was deleted. + * (should fail - o15.0.1.13) + * o15.0.1.15: + * - Try deletion of the IPoIB MCG and get: ERR_REQ_INVALID + * o15.0.1.16: + * - Try GetTable with PortGUID wildcarded and get back some groups. + ***********************************************************************/ + +/* The following macro can be used only within the osmt_run_mcast_flow() function */ +#define IS_IPOIB_MGID(p_mgid) \ + ( !memcmp(&osm_ipoib_good_mgid, (p_mgid), sizeof(osm_ipoib_good_mgid)) || \ + !memcmp(&osm_ts_ipoib_good_mgid, (p_mgid), sizeof(osm_ts_ipoib_good_mgid)) ) + +ib_api_status_t +osmt_run_mcast_flow( IN osmtest_t * const p_osmt ) { + ib_api_status_t status; + ib_member_rec_t mc_req_rec; + ib_member_rec_t *p_mc_res; + ib_sa_mad_t res_sa_mad; + uint64_t comp_mask = 0; + ib_net64_t remote_port_guid = 0x0; + cl_qmap_t *p_mgrp_mlid_tbl; + osmtest_mgrp_t *p_mgrp; + ib_gid_t special_mgid, tmp_mgid, proxy_mgid; + ib_net16_t invalid_mlid = 0x0; + ib_net16_t max_mlid = cl_hton16(0xFFFE), tmp_mlid; + boolean_t ReachedMlidLimit = FALSE; + int start_cnt = 0, cnt, middle_cnt = 0, end_cnt = 0; + int start_ipoib_cnt = 0, end_ipoib_cnt = 0; + int mcg_outside_test_cnt = 0, fail_to_delete_mcg = 0; + osmtest_req_context_t context; + ib_node_record_t *p_rec; + uint32_t num_recs = 0, i; + uint8_t mtu_phys = 0, rate_phys = 0; + cl_map_t test_created_mlids; /* List of all mlids created in this test */ + ib_member_rec_t* p_recvd_rec; + boolean_t got_error = FALSE; + + static ib_gid_t good_mgid = { + { + 0xFF, 0x12, 0xA0, 0x1C, + 0xFE, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x12, 0x34, 0x56, 0x78 + } + }; + static ib_gid_t osm_ipoib_mgid = { + { + 0xff, /* multicast field */ + 0x12, /* scope */ + 0x40, 0x1b, /* IPv4 signature */ + 0xff, 0xff, /* 16 bits of P_Key (to be filled in) */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 48 bits of zeros */ + 0xff, 0xff, 0xff, 0xee, /* 32 bit IPv4 broadcast address */ + }, + }; + static ib_gid_t osm_ts_ipoib_good_mgid = { + { + 0xff, /* multicast field */ + 0x12, /* non-permanent bit,scope */ + 0x40, 0x1b, /* IPv4 signature */ + 0xff, 0xff, /* 16 bits of P_Key (to be filled in) */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 48 bits of zeros */ + 0x00, 0x00, 0x00, 0x01, /* 32 bit IPv4 broadcast address */ + }, + }; + static ib_gid_t osm_ipoib_good_mgid = { + { + 0xff, /* multicast field */ + 0x12, /* non-permanent bit,scope */ + 0x40, 0x1b, /* IPv4 signature */ + 0xff, 0xff, /* 16 bits of P_Key (to be filled in) */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 48 bits of zeros */ + 0xff, 0xff, 0xff, 0xff, /* 32 bit IPv4 broadcast address */ + }, + }; + static ib_gid_t osm_link_local_mgid = { + { + 0xFF, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01 + }, + }; + + OSM_LOG_ENTER( &p_osmt->log, osmt_run_mcast_flow ); + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "GetTable of all current MCGs...\n" + ); + status = osmt_query_mcast( p_osmt ); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 2FF " + "GetTable of all records has failed!\n" ); + goto Exit; + } + + /* Initialize the test_created_mgrps map */ + cl_map_construct(&test_created_mlids); + cl_map_init(&test_created_mlids, 1000); + + p_mgrp_mlid_tbl = &p_osmt->exp_subn.mgrp_mlid_tbl; + osmt_init_mc_query_rec(p_osmt, &mc_req_rec); + + p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad); + + /* Only when we are on single mode check flow - do the count comparison, otherwise skip */ + if (p_osmt->opt.mmode == 1 || p_osmt->opt.mmode == 3) + { + start_cnt = cl_qmap_count(p_mgrp_mlid_tbl); + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow (start): " + "Number of MC Records found in SA DB is %d\n", start_cnt); + } + + /* This flow is being added due to bug discovered using SilverStorm stack - + The bug was initializing MCast with MTU & RATE min values that do + not match the subnet capability, even though that OpenSM + reponds with the correct value it does not store it in the MCG. + We want the check a join request to already existing group (ipoib) + without using MTU or RATE then getting response from OpenSM with + the correct values then join again with them and get IB_SUCCESS + all the way + */ + + /* First validate IPoIB exist in the SA DB */ + p_mgrp = (osmtest_mgrp_t*)cl_qmap_head( p_mgrp_mlid_tbl ); + /* scan all available multicast groups in the DB and fill in the table */ + while( p_mgrp != (osmtest_mgrp_t*)cl_qmap_end( p_mgrp_mlid_tbl ) ) + { + /* search for ipoib mgid */ + if (IS_IPOIB_MGID(&p_mgrp->mcmember_rec.mgid)) + { + start_ipoib_cnt++; + } + else + { + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Non-IPoIB MC Groups exist: mgid=0x%016" PRIx64 ":0x%016" PRIx64 "\n", + cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.prefix), + cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.interface_id) ); + mcg_outside_test_cnt++; + } + + p_mgrp = (osmtest_mgrp_t*)cl_qmap_next( &p_mgrp->map_item ); + } + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Found %d non-IPoIB MC Groups\n", mcg_outside_test_cnt ); + + if (start_ipoib_cnt) + { + /* o15-0.2.4 - Check a join request to already created MCG */ + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Found IPoIB MC Group, so we run SilverStorm Bug Flow...\n" ); + /* Try to join first like IPoIB of SilverStorm */ + memcpy(&mc_req_rec.mgid,&osm_ipoib_good_mgid,sizeof(ib_gid_t)); + /* Request Join */ + ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER); + comp_mask = + IB_MCR_COMPMASK_MGID | + IB_MCR_COMPMASK_PORT_GID | + IB_MCR_COMPMASK_JOIN_STATE; + + status = osmt_send_mcast_request( + p_osmt, 0xff, /* User Defined query Set */ + &mc_req_rec, + comp_mask, + &res_sa_mad ); + + osm_log(&p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Joining an existing IPoIB multicast group\n"); + osm_log(&p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Sent Join request with :\n\t\tport_gid=0x%016"PRIx64 + ":0x%016" PRIx64 ", mgid=0x%016" PRIx64 ":0x%016" PRIx64 + "\n\t\tjoin state= 0x%x, response is : %s\n", + cl_ntoh64(mc_req_rec.port_gid.unicast.prefix), + cl_ntoh64(mc_req_rec.port_gid.unicast.interface_id), + cl_ntoh64(mc_req_rec.mgid.unicast.prefix), + cl_ntoh64(mc_req_rec.mgid.unicast.interface_id), + (mc_req_rec.scope_state & 0x0F), + ib_get_err_str(status)); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02B3: " + "Failed joining existing IPoIB MCGroup - got %s\n", + ib_get_err_str(status)); + goto Exit; + } + /* Check MTU & Rate Value and resend with SA suggested values */ + p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad); + + /* Prepare the mc_req_rec for the rest of the flow */ + osmt_init_mc_query_rec(p_osmt, &mc_req_rec); + /* + We simulate the same situation as in SilverStorm - a response with the + exact RATE & MTU as the SA responded with. Actually the query + has included some more fields but we know that problem was + genereated by the RATE + */ + osm_log(&p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Received attributes of MCG : \n\t\tMTU=0x%02X, RATE=0x%02X\n" + , p_mc_res->mtu,p_mc_res->rate); + + mc_req_rec.mtu = p_mc_res->mtu; + mc_req_rec.rate = p_mc_res->rate; + /* Set feasible mtu & rate that will allow check the + exact statement of OpenSM */ + mtu_phys = p_mc_res->mtu; + rate_phys = p_mc_res->rate; + + memcpy(&mc_req_rec.mgid, &osm_ipoib_good_mgid, sizeof(ib_gid_t)); + /* Request Join */ + ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER); + comp_mask = + IB_MCR_COMPMASK_MGID | + IB_MCR_COMPMASK_PORT_GID | + IB_MCR_COMPMASK_JOIN_STATE | + IB_MCR_COMPMASK_MTU_SEL | + IB_MCR_COMPMASK_MTU | + IB_MCR_COMPMASK_RATE_SEL | + IB_MCR_COMPMASK_RATE; + + osm_log(&p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Sending attributes of MCG : \n\t\tMTU=0x%02X, RATE=0x%02X\n" + , mc_req_rec.mtu, mc_req_rec.rate); + status = osmt_send_mcast_request( p_osmt, 0xff, /* User Defined query */ + &mc_req_rec, + comp_mask, + &res_sa_mad ); + osm_log(&p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Sent Join request using response values, response is : %s\n" + , ib_get_err_str(status)); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02EF: " + "Query as Full Member of already existing ipoib group 0x%016" + PRIx64 ":0x%016" PRIx64 " has failed\n", + cl_ntoh64(mc_req_rec.mgid.unicast.prefix), + cl_ntoh64(mc_req_rec.mgid.unicast.interface_id)); + + goto Exit; + } + /* We do not want to leave the MCG since its IPoIB */ + } + + /**************************************************************************/ + /* Check Get with invalid mlid */ + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking Get with invalid mlid...\n" + ); + /* Request Get */ + ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER); + mc_req_rec.mlid = invalid_mlid; + comp_mask = IB_MCR_COMPMASK_MLID; + + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" ); + status = osmt_send_mcast_request( p_osmt, 0xee, /* User Defined query Get */ + &mc_req_rec, + comp_mask, + &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" ); + + if (status == IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow : ERR 2E0 " + "SubnAdmGet with invalid mlid 0x%x succeeded\n", + cl_ntoh16(mc_req_rec.mlid)); + status = IB_ERROR; + goto Exit; + } + + /* Prepare the mc_req_rec for the rest of the flow */ + osmt_init_mc_query_rec(p_osmt, &mc_req_rec); + /**************************************************************************/ + /* Check Get with invalid port guid */ + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking Get with invalid port guid (0x0) but valid interface ID : 0x%" + PRIx64 "...\n", + cl_ntoh64(mc_req_rec.port_gid.unicast.interface_id)); + + /* Request Get */ + ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER); + memset(&mc_req_rec.port_gid.unicast.interface_id, 0, sizeof(ib_net64_t)); + comp_mask = IB_MCR_COMPMASK_GID; + + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" ); + status = osmt_send_mcast_request( p_osmt, 0xee, /* User Defined query Get */ + &mc_req_rec, + comp_mask, + &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" ); + + if (status == IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow : ERR 2E4 " + "SubnAdmGet with invalid port guid succeeded\n" ); + status = IB_ERROR; + goto Exit; + } + + /* Prepare the mc_req_rec for the rest of the flow */ + osmt_init_mc_query_rec(p_osmt, &mc_req_rec); + /**************************************************************************/ + + /* o15.0.1.3: */ + /* - Request Join with insufficient comp_mask */ + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking Join with insufficient comp mask qkey & pkey (o15.0.1.3)...\n" + ); + + /* no MGID */ + memset(&mc_req_rec.mgid, 0, sizeof(ib_gid_t)); + /* Request Join */ + ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER); + + comp_mask = + IB_MCR_COMPMASK_MGID | + IB_MCR_COMPMASK_PORT_GID | + /* IB_MCR_COMPMASK_QKEY | */ + /* IB_MCR_COMPMASK_PKEY | intentionaly missed to raise the error */ + IB_MCR_COMPMASK_SL | + IB_MCR_COMPMASK_FLOW | + IB_MCR_COMPMASK_JOIN_STATE | + IB_MCR_COMPMASK_TCLASS | /* all above are required */ + IB_MCR_COMPMASK_RATE_SEL | + IB_MCR_COMPMASK_RATE; + + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" ); + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" ); + + if (status != IB_REMOTE_ERROR || + (( ib_net16_t ) (res_sa_mad.status & IB_SMP_STATUS_MASK )) != + IB_SA_MAD_STATUS_INSUF_COMPS) { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02EE: " + "Expectedd REMOTE ERROR IB_SA_MAD_STATUS_INSUF_COMPS got:%s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + status = IB_ERROR; + goto Exit; + } + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking Join with insufficient comp mask - sl (15.0.1.3)...\n" + ); + + /* no MGID */ + memset(&mc_req_rec.mgid, 0, sizeof(ib_gid_t)); + /* Request Join */ + ib_member_set_join_state(&mc_req_rec,IB_MC_REC_STATE_FULL_MEMBER ); + + comp_mask = + IB_MCR_COMPMASK_MGID | + IB_MCR_COMPMASK_PORT_GID | + IB_MCR_COMPMASK_QKEY | + IB_MCR_COMPMASK_PKEY | + /* IB_MCR_COMPMASK_SL | */ + IB_MCR_COMPMASK_FLOW | + IB_MCR_COMPMASK_JOIN_STATE | + IB_MCR_COMPMASK_TCLASS | /* all above are required */ + IB_MCR_COMPMASK_RATE_SEL | + IB_MCR_COMPMASK_RATE; + + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" ); + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" ); + + if (status != IB_REMOTE_ERROR || + (( ib_net16_t ) (res_sa_mad.status & IB_SMP_STATUS_MASK )) != + IB_SA_MAD_STATUS_INSUF_COMPS) { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02ED: " + "Expectedd REMOTE ERROR IB_SA_MAD_STATUS_INSUF_COMPS got:%s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + status = IB_ERROR; + goto Exit; + } + + osmt_init_mc_query_rec(p_osmt, &mc_req_rec); + /* no MGID */ + memset(&mc_req_rec.mgid, 0, sizeof(ib_gid_t)); + + mc_req_rec.mgid.raw[15] = 0x01; + + p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad); + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking Join with insufficient comp mask - flow label (o15.0.1.3)...\n" + ); + + /* Request Join */ + ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER); + + comp_mask = + IB_MCR_COMPMASK_MGID | + IB_MCR_COMPMASK_PORT_GID | + IB_MCR_COMPMASK_QKEY | + IB_MCR_COMPMASK_PKEY | + IB_MCR_COMPMASK_SL | + /* IB_MCR_COMPMASK_FLOW | intentionaly missed to raise the error */ + IB_MCR_COMPMASK_JOIN_STATE | + IB_MCR_COMPMASK_TCLASS | /* all above are required */ + IB_MCR_COMPMASK_RATE_SEL | + IB_MCR_COMPMASK_RATE; + + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" ); + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" ); + + if (status != IB_REMOTE_ERROR || + (( ib_net16_t ) (res_sa_mad.status & IB_SMP_STATUS_MASK )) != + IB_SA_MAD_STATUS_INSUF_COMPS) { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02EC: " + "Expected REMOTE ERROR IB_SA_MAD_STATUS_INSUF_COMPS got:%s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + status = IB_ERROR; + goto Exit; + } + + osmt_init_mc_query_rec(p_osmt, &mc_req_rec); + + p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad); + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking Join with insufficient comp mask - tclass (o15.0.1.3)...\n" + ); + + /* Request Join */ + ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER) ; + + comp_mask = + IB_MCR_COMPMASK_MGID | + IB_MCR_COMPMASK_PORT_GID | + IB_MCR_COMPMASK_QKEY | + IB_MCR_COMPMASK_PKEY | + IB_MCR_COMPMASK_SL | + IB_MCR_COMPMASK_FLOW | + IB_MCR_COMPMASK_JOIN_STATE | + /* IB_MCR_COMPMASK_TCLASS | Intentionally missed to raise an error */ + IB_MCR_COMPMASK_RATE_SEL | + IB_MCR_COMPMASK_RATE; + + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" ); + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" ); + + if (status != IB_REMOTE_ERROR || + (( ib_net16_t ) (res_sa_mad.status & IB_SMP_STATUS_MASK )) != + IB_SA_MAD_STATUS_INSUF_COMPS) { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02EA: " + "Expected REMOTE ERROR IB_SA_MAD_STATUS_INSUF_COMPS got:%s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + status = IB_ERROR; + goto Exit; + } + + osmt_init_mc_query_rec(p_osmt, &mc_req_rec); + + p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad); + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking Join with insufficient comp mask - tclass qkey (o15.0.1.3)...\n" + ); + + /* no MGID */ + /* memset(&mc_req_rec.mgid, 0, sizeof(ib_gid_t)); */ + /* Request Join */ + ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER); + + comp_mask = + IB_MCR_COMPMASK_MGID | + IB_MCR_COMPMASK_PORT_GID | + /* IB_MCR_COMPMASK_QKEY | intentionaly missed to raise the error */ + IB_MCR_COMPMASK_PKEY | + IB_MCR_COMPMASK_SL | + IB_MCR_COMPMASK_FLOW | + IB_MCR_COMPMASK_JOIN_STATE | + /* IB_MCR_COMPMASK_TCLASS | intentionaly missed to raise the error */ + IB_MCR_COMPMASK_RATE_SEL | + IB_MCR_COMPMASK_RATE; + + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" ); + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" ); + + if (status != IB_REMOTE_ERROR || + (( ib_net16_t ) (res_sa_mad.status & IB_SMP_STATUS_MASK )) != + IB_SA_MAD_STATUS_INSUF_COMPS) { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02E9: " + "Expected REMOTE ERROR IB_SA_MAD_STATUS_INSUF_COMPS got:%s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + status = IB_ERROR; + goto Exit; + } + + /* o15.0.1.8: */ + /* - Request join with irrelevant RATE : get a ERR_INSUFFICIENT_COMPONENTS */ + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking Join with unrealistic rate (o15.0.1.8)...\n" + ); + + /* impossible requested rate */ + mc_req_rec.rate = + IB_LINK_WIDTH_ACTIVE_12X | + IB_PATH_SELECTOR_GREATER_THAN << 6; + + comp_mask = + IB_MCR_COMPMASK_GID | + IB_MCR_COMPMASK_PORT_GID | + IB_MCR_COMPMASK_QKEY | + IB_MCR_COMPMASK_PKEY | + IB_MCR_COMPMASK_SL | + IB_MCR_COMPMASK_FLOW | + IB_MCR_COMPMASK_JOIN_STATE | + IB_MCR_COMPMASK_TCLASS | /* all above are required */ + IB_MCR_COMPMASK_RATE_SEL | + IB_MCR_COMPMASK_RATE; + + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" ); + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" ); + + if (status != IB_REMOTE_ERROR || + res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID) { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 0207: " + "Expected REMOTE ERROR IB_SA_MAD_STATUS_REQ_INVALID got:%s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + status = IB_ERROR; + goto Exit; + } + + /* Check Valid value which is unreasonable now */ + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking Join with unrealistic rate 120GB (o15.0.1.8)...\n" + ); + + /* impossible requested rate */ + mc_req_rec.rate = + IB_PATH_RECORD_RATE_120_GBS | + IB_PATH_SELECTOR_GREATER_THAN << 6; + + comp_mask = + IB_MCR_COMPMASK_GID | + IB_MCR_COMPMASK_PORT_GID | + IB_MCR_COMPMASK_QKEY | + IB_MCR_COMPMASK_PKEY | + IB_MCR_COMPMASK_SL | + IB_MCR_COMPMASK_FLOW | + IB_MCR_COMPMASK_JOIN_STATE | + IB_MCR_COMPMASK_TCLASS | /* all above are required */ + IB_MCR_COMPMASK_RATE_SEL | + IB_MCR_COMPMASK_RATE; + + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" ); + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" ); + + if (status != IB_REMOTE_ERROR || + res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID) { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 0208: " + "Expected REMOTE ERROR IB_SA_MAD_STATUS_REQ_INVALID got:%s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + status = IB_ERROR; + goto Exit; + } + + /* Check Valid value which is unreasonable now */ + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking Join with less than min rate 2.5GB (o15.0.1.8)...\n" + ); + + /* impossible requested rate */ + mc_req_rec.rate = + IB_PATH_RECORD_RATE_2_5_GBS | + IB_PATH_SELECTOR_LESS_THAN << 6; + + comp_mask = + IB_MCR_COMPMASK_GID | + IB_MCR_COMPMASK_PORT_GID | + IB_MCR_COMPMASK_QKEY | + IB_MCR_COMPMASK_PKEY | + IB_MCR_COMPMASK_SL | + IB_MCR_COMPMASK_FLOW | + IB_MCR_COMPMASK_JOIN_STATE | + IB_MCR_COMPMASK_TCLASS | /* all above are required */ + IB_MCR_COMPMASK_RATE_SEL | + IB_MCR_COMPMASK_RATE; + + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" ); + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" ); + + if (status != IB_REMOTE_ERROR || + res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID) { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02AB: " + "Expected REMOTE ERROR IB_SA_MAD_STATUS_REQ_INVALID got:%s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + status = IB_ERROR; + goto Exit; + } + + /* Checking above max value of MTU which is impossible */ + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking Join with unrealistic mtu : \n\t\tmore than 4096 -" + " max (o15.0.1.8)...\n" + ); + + /* impossible requested mtu */ + mc_req_rec.mtu = IB_MTU_LEN_4096 | IB_PATH_SELECTOR_GREATER_THAN << 6; + + comp_mask = + IB_MCR_COMPMASK_GID | + IB_MCR_COMPMASK_PORT_GID | + IB_MCR_COMPMASK_QKEY | + IB_MCR_COMPMASK_PKEY | + IB_MCR_COMPMASK_SL | + IB_MCR_COMPMASK_FLOW | + IB_MCR_COMPMASK_JOIN_STATE | + IB_MCR_COMPMASK_TCLASS | /* all above are required */ + IB_MCR_COMPMASK_MTU_SEL | + IB_MCR_COMPMASK_MTU; + + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" ); + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" ); + + if (status != IB_REMOTE_ERROR || + res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID) { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02AC: " + "Expected REMOTE ERROR IB_SA_MAD_STATUS_REQ_INVALID got:%s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + status = IB_ERROR; + goto Exit; + } + + /* Checking below min value of MTU which is impossible */ + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking Join with unrealistic mtu : \n\t\tless than 256 -" + " min (o15.0.1.8)...\n" + ); + + /* impossible requested mtu */ + mc_req_rec.mtu = IB_MTU_LEN_256 | IB_PATH_SELECTOR_LESS_THAN << 6; + + comp_mask = + IB_MCR_COMPMASK_GID | + IB_MCR_COMPMASK_PORT_GID | + IB_MCR_COMPMASK_QKEY | + IB_MCR_COMPMASK_PKEY | + IB_MCR_COMPMASK_SL | + IB_MCR_COMPMASK_FLOW | + IB_MCR_COMPMASK_JOIN_STATE | + IB_MCR_COMPMASK_TCLASS | /* all above are required */ + IB_MCR_COMPMASK_MTU_SEL | + IB_MCR_COMPMASK_MTU; + + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" ); + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" ); + + if (status != IB_REMOTE_ERROR || + res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID) { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02AD: " + "Expected REMOTE ERROR IB_SA_MAD_STATUS_REQ_INVALID got:%s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + status = IB_ERROR; + goto Exit; + } + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking Join with unrealistic mtu (o15.0.1.8)...\n" + ); + + /* impossible requested mtu */ + mc_req_rec.mtu = 0x6 | IB_PATH_SELECTOR_GREATER_THAN << 6; + + comp_mask = + IB_MCR_COMPMASK_GID | + IB_MCR_COMPMASK_PORT_GID | + IB_MCR_COMPMASK_QKEY | + IB_MCR_COMPMASK_PKEY | + IB_MCR_COMPMASK_SL | + IB_MCR_COMPMASK_FLOW | + IB_MCR_COMPMASK_JOIN_STATE | + IB_MCR_COMPMASK_TCLASS | /* all above are required */ + IB_MCR_COMPMASK_MTU_SEL | + IB_MCR_COMPMASK_MTU; + + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" ); + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" ); + + if (status != IB_REMOTE_ERROR || + res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID) { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02AE: " + "Expected REMOTE ERROR IB_SA_MAD_STATUS_REQ_INVALID got:%s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + status = IB_ERROR; + goto Exit; + } + +#if 0 + /* Currently PacketLifeTime isn't checked in opensm */ + /* Check PacketLifeTime as 0 */ + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking Create with unrealistic packet life value less than 0 (o15.0.1.8)...\n" + ); + + /* impossible requested packet life */ + mc_req_rec.pkt_life = 0 | IB_PATH_SELECTOR_LESS_THAN << 6; + + comp_mask = + IB_MCR_COMPMASK_GID | + IB_MCR_COMPMASK_PORT_GID | + IB_MCR_COMPMASK_QKEY | + IB_MCR_COMPMASK_PKEY | + IB_MCR_COMPMASK_SL | + IB_MCR_COMPMASK_FLOW | + IB_MCR_COMPMASK_JOIN_STATE | + IB_MCR_COMPMASK_TCLASS | /* all above are required */ + IB_MCR_COMPMASK_LIFE | + IB_MCR_COMPMASK_LIFE_SEL; + + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" ); + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" ); + + if (status != IB_REMOTE_ERROR || + res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID) { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02AF: " + "Expected REMOTE ERROR IB_SA_MAD_STATUS_REQ_INVALID got:%s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + status = IB_ERROR; + goto Exit; + } +#endif + + /* o15.0.1.4: */ + /* - Create an MGID by asking for a join with MGID = 0 */ + /* providing P_Key, Q_Key, SL, FlowLabel, Tclass. */ + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking Create given MGID=0 skip service level (o15.0.1.4)...\n" + ); + + osmt_init_mc_query_rec(p_osmt, &mc_req_rec); + + p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad); + + /* no MGID */ + memset(&mc_req_rec.mgid, 0, sizeof(ib_gid_t)); + /* Request Join */ + ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER); + + comp_mask = + IB_MCR_COMPMASK_MGID | + IB_MCR_COMPMASK_PORT_GID | + IB_MCR_COMPMASK_QKEY | + IB_MCR_COMPMASK_PKEY | + /* IB_MCR_COMPMASK_SL | Intentionally missed */ + IB_MCR_COMPMASK_FLOW | + IB_MCR_COMPMASK_JOIN_STATE | + IB_MCR_COMPMASK_TCLASS | /* all above are required */ + IB_MCR_COMPMASK_RATE_SEL | + IB_MCR_COMPMASK_RATE; + + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" ); + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" ); + + if (status != IB_REMOTE_ERROR || + (( ib_net16_t ) (res_sa_mad.status & IB_SMP_STATUS_MASK )) != + IB_SA_MAD_STATUS_INSUF_COMPS) { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02A8: " + "Expected REMOTE ERROR IB_SA_MAD_STATUS_INSUF_COMPS got:%s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + status = IB_ERROR; + goto Exit; + } + + /* Check that no same MCG in the SMDB */ + status = osmt_query_mcast( p_osmt); + + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02AA: " + "Could not get all MC Records in subnet, got:%s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + goto Exit; + } + + /* Only when we are on single mode check flow - do the count comparison, otherwise skip */ + if (p_osmt->opt.mmode == 1 || p_osmt->opt.mmode == 3) + { + middle_cnt = cl_qmap_count(&p_osmt->exp_subn.mgrp_mlid_tbl); + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow (post false create): " + "Number of MC Records found in SA DB is %d\n", middle_cnt); + if (middle_cnt != start_cnt) + { + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Got different number of records stored in SA DB (before any creation)\n" + "Instead of %d got %d\n", start_cnt, middle_cnt); + } + } + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking Create given MGID=0 skip Qkey and Pkey (o15.0.1.4)...\n" + ); + + osmt_init_mc_query_rec(p_osmt, &mc_req_rec); + + p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad); + + /* no MGID */ + memset(&mc_req_rec.mgid, 0, sizeof(ib_gid_t)); + /* Request Join */ + ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER); + + comp_mask = + IB_MCR_COMPMASK_MGID | + IB_MCR_COMPMASK_PORT_GID | + /* IB_MCR_COMPMASK_QKEY | */ + /* IB_MCR_COMPMASK_PKEY | Intentionally missed */ + IB_MCR_COMPMASK_SL | + IB_MCR_COMPMASK_FLOW | + IB_MCR_COMPMASK_JOIN_STATE | + IB_MCR_COMPMASK_TCLASS | /* all above are required */ + IB_MCR_COMPMASK_RATE_SEL | + IB_MCR_COMPMASK_RATE; + + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" ); + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" ); + + if (status != IB_REMOTE_ERROR || + (( ib_net16_t ) (res_sa_mad.status & IB_SMP_STATUS_MASK )) != + IB_SA_MAD_STATUS_INSUF_COMPS) { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02A7: " + "Expected REMOTE ERROR IB_SA_MAD_STATUS_INSUF_COMPS got:%s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + status = IB_ERROR; + goto Exit; + } + + /* Bad Query o15.0.1.4 */ + + status = osmt_query_mcast( p_osmt); + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking Create given MGID=0 skip TClass (o15.0.1.4)...\n" + ); + + osmt_init_mc_query_rec(p_osmt, &mc_req_rec); + + p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad); + + /* no MGID */ + memset(&mc_req_rec.mgid, 0, sizeof(ib_gid_t)); + /* Request Join */ + ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER); + + comp_mask = + IB_MCR_COMPMASK_MGID | + IB_MCR_COMPMASK_PORT_GID | + IB_MCR_COMPMASK_QKEY | + IB_MCR_COMPMASK_PKEY | + IB_MCR_COMPMASK_SL | + IB_MCR_COMPMASK_FLOW | + IB_MCR_COMPMASK_JOIN_STATE | + /* IB_MCR_COMPMASK_TCLASS | Intentionally missed */ + /* all above are required */ + IB_MCR_COMPMASK_RATE_SEL | + IB_MCR_COMPMASK_RATE; + + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" ); + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" ); + + if (status != IB_REMOTE_ERROR || + (( ib_net16_t ) (res_sa_mad.status & IB_SMP_STATUS_MASK )) != + IB_SA_MAD_STATUS_INSUF_COMPS) { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02A6: " + "Expected REMOTE ERROR IB_SA_MAD_STATUS_INSUF_COMPS got:%s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + status = IB_ERROR; + goto Exit; + } + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking Create given MGID=0 valid Set several options :\n\t\t" + "First above min RATE, Second less than max RATE\n\t\t" + "Third above min MTU, Second less than max MTU\n\t\t" + "Fifth exact MTU & RATE feasible, Sixth exact RATE feasible\n\t\t" + "Seventh exact MTU feasible (o15.0.1.4)...\n" + ); + + /* Good Flow - mgid is 0 while giving all required fields for join : P_Key, Q_Key, SL, FlowLabel, Tclass */ + + mc_req_rec.rate = + IB_LINK_WIDTH_ACTIVE_1X | + IB_PATH_SELECTOR_GREATER_THAN << 6; + + comp_mask = + IB_MCR_COMPMASK_MGID | + IB_MCR_COMPMASK_PORT_GID | + IB_MCR_COMPMASK_QKEY | + IB_MCR_COMPMASK_PKEY | + IB_MCR_COMPMASK_SL | + IB_MCR_COMPMASK_FLOW | + IB_MCR_COMPMASK_JOIN_STATE | + IB_MCR_COMPMASK_TCLASS | /* all above are required */ + IB_MCR_COMPMASK_RATE_SEL | + IB_MCR_COMPMASK_RATE; + + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02A5: " + "Failed to create MCG for MGID=0 with higher than minimum RATE - got %s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + goto Exit; + } + + /* Save the mlid created in test_created_mlids map */ + p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_run_mcast_flow: " + "created MGID:0x%016" PRIx64 " : " + "0x%016" PRIx64 " MLID:0x%04X\n", + cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ), + cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ), + cl_ntoh16( p_recvd_rec->mlid )); + cl_map_insert(&test_created_mlids, + cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec ); + + /* Good Flow - mgid is 0 while giving all required fields for join : P_Key, Q_Key, SL, FlowLabel, Tclass */ + + mc_req_rec.rate = + IB_LINK_WIDTH_ACTIVE_12X | + IB_PATH_SELECTOR_LESS_THAN << 6; + + comp_mask = + IB_MCR_COMPMASK_MGID | + IB_MCR_COMPMASK_PORT_GID | + IB_MCR_COMPMASK_QKEY | + IB_MCR_COMPMASK_PKEY | + IB_MCR_COMPMASK_SL | + IB_MCR_COMPMASK_FLOW | + IB_MCR_COMPMASK_JOIN_STATE | + IB_MCR_COMPMASK_TCLASS | /* all above are required */ + IB_MCR_COMPMASK_RATE_SEL | + IB_MCR_COMPMASK_RATE; + + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 0211: " + "Failed to create MCG for MGID=0 with less than highest RATE - got %s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + goto Exit; + } + + /* Save the mlid created in test_created_mlids map */ + p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_run_mcast_flow: " + "Created MGID:0x%016" PRIx64 " : " + "0x%016" PRIx64 " MLID:0x%04X\n", + cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ), + cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ), + cl_ntoh16( p_recvd_rec->mlid )); + cl_map_insert(&test_created_mlids, + cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec ); + + /* Good Flow - mgid is 0 while giving all required fields for join : P_Key, Q_Key, SL, FlowLabel, Tclass */ + + mc_req_rec.mtu = IB_MTU_LEN_4096 | + IB_PATH_SELECTOR_LESS_THAN << 6; + + comp_mask = + IB_MCR_COMPMASK_MGID | + IB_MCR_COMPMASK_PORT_GID | + IB_MCR_COMPMASK_QKEY | + IB_MCR_COMPMASK_PKEY | + IB_MCR_COMPMASK_SL | + IB_MCR_COMPMASK_FLOW | + IB_MCR_COMPMASK_JOIN_STATE | + IB_MCR_COMPMASK_TCLASS | /* all above are required */ + IB_MCR_COMPMASK_MTU_SEL | + IB_MCR_COMPMASK_MTU; + + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 0238: " + "Failed to create MCG for MGID=0 with less than highest MTU - got %s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + goto Exit; + } + + /* Save the mlid created in test_created_mlids map */ + p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_run_mcast_flow: " + "Created MGID:0x%016" PRIx64 " : " + "0x%016" PRIx64 " MLID:0x%04X\n", + cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ), + cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ), + cl_ntoh16( p_recvd_rec->mlid )); + cl_map_insert(&test_created_mlids, + cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec ); + + /* Good Flow - mgid is 0 while giving all required fields for join : P_Key, Q_Key, SL, FlowLabel, Tclass */ + mc_req_rec.mtu = IB_MTU_LEN_256 | + IB_PATH_SELECTOR_GREATER_THAN << 6; + + comp_mask = + IB_MCR_COMPMASK_MGID | + IB_MCR_COMPMASK_PORT_GID | + IB_MCR_COMPMASK_QKEY | + IB_MCR_COMPMASK_PKEY | + IB_MCR_COMPMASK_SL | + IB_MCR_COMPMASK_FLOW | + IB_MCR_COMPMASK_JOIN_STATE | + IB_MCR_COMPMASK_TCLASS | /* all above are required */ + IB_MCR_COMPMASK_MTU_SEL | + IB_MCR_COMPMASK_MTU; + + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 0239: " + "Failed to create MCG for MGID=0 with higher than lowest MTU - got %s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + goto Exit; + } + + /* Save the mlid created in test_created_mlids map */ + p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_run_mcast_flow: " + "Created MGID:0x%016" PRIx64 " : " + "0x%016" PRIx64 " MLID:0x%04X\n", + cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ), + cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ), + cl_ntoh16( p_recvd_rec->mlid )); + cl_map_insert( &test_created_mlids, + cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec ); + + /* Good Flow - mgid is 0 while giving all required fields for join : P_Key, Q_Key, SL, FlowLabel, Tclass */ + /* Using Exact feasible MTU & RATE */ + + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_run_mcast_flow: " + "Using Exact feasible MTU & RATE: " + "MTU = 0x%02X, RATE = 0x%02X\n", + mtu_phys, rate_phys ); + + mc_req_rec.mtu = mtu_phys; + mc_req_rec.rate = rate_phys; + + comp_mask = + IB_MCR_COMPMASK_MGID | + IB_MCR_COMPMASK_PORT_GID | + IB_MCR_COMPMASK_QKEY | + IB_MCR_COMPMASK_PKEY | + IB_MCR_COMPMASK_SL | + IB_MCR_COMPMASK_FLOW | + IB_MCR_COMPMASK_JOIN_STATE | + IB_MCR_COMPMASK_TCLASS | /* all above are required */ + IB_MCR_COMPMASK_MTU_SEL | + IB_MCR_COMPMASK_MTU | + IB_MCR_COMPMASK_RATE_SEL | + IB_MCR_COMPMASK_RATE; + + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 0240: " + "Failed to create MCG for MGID=0 with exact MTU & RATE - got %s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + goto Exit; + } + + /* Save the mlid created in test_created_mlids map */ + p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_run_mcast_flow: " + "Created MGID:0x%016" PRIx64 " : " + "0x%016" PRIx64 " MLID:0x%04X\n", + cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ), + cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ), + cl_ntoh16( p_recvd_rec->mlid )); + cl_map_insert(&test_created_mlids, + cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec ); + + /* Good Flow - mgid is 0 while giving all required fields for join : P_Key, Q_Key, SL, FlowLabel, Tclass */ + /* Using Exact feasible RATE */ + + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_run_mcast_flow: " + "Using Exact feasible RATE: 0x%02X\n", + rate_phys ); + + mc_req_rec.rate = rate_phys; + + comp_mask = + IB_MCR_COMPMASK_MGID | + IB_MCR_COMPMASK_PORT_GID | + IB_MCR_COMPMASK_QKEY | + IB_MCR_COMPMASK_PKEY | + IB_MCR_COMPMASK_SL | + IB_MCR_COMPMASK_FLOW | + IB_MCR_COMPMASK_JOIN_STATE | + IB_MCR_COMPMASK_TCLASS | /* all above are required */ + IB_MCR_COMPMASK_RATE_SEL | + IB_MCR_COMPMASK_RATE; + + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 0241: " + "Failed to create MCG for MGID=0 with exact RATE - got %s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + goto Exit; + } + + /* Save the mlid created in test_created_mlids map */ + p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_run_mcast_flow: " + "Created MGID:0x%016" PRIx64 " : " + "0x%016" PRIx64 " MLID:0x%04X\n", + cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ), + cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ), + cl_ntoh16( p_recvd_rec->mlid )); + cl_map_insert(&test_created_mlids, + cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec ); + + /* Good Flow - mgid is 0 while giving all required fields for join : P_Key, Q_Key, SL, FlowLabel, Tclass */ + /* Using Exact feasible MTU */ + + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_run_mcast_flow: " + "Using Exact feasible MTU: 0x%02X\n", + mtu_phys ); + + mc_req_rec.mtu = mtu_phys; + + comp_mask = + IB_MCR_COMPMASK_MGID | + IB_MCR_COMPMASK_PORT_GID | + IB_MCR_COMPMASK_QKEY | + IB_MCR_COMPMASK_PKEY | + IB_MCR_COMPMASK_SL | + IB_MCR_COMPMASK_FLOW | + IB_MCR_COMPMASK_JOIN_STATE | + IB_MCR_COMPMASK_TCLASS | /* all above are required */ + IB_MCR_COMPMASK_MTU_SEL | + IB_MCR_COMPMASK_MTU; + + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 0242: " + "Failed to create MCG for MGID=0 with exact MTU - got %s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + goto Exit; + } + + /* Save the mlid created in test_created_mlids map */ + p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_run_mcast_flow: " + "Created MGID:0x%016" PRIx64 " : " + "0x%016" PRIx64 " MLID:0x%04X\n", + cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ), + cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ), + cl_ntoh16( p_recvd_rec->mlid )); + cl_map_insert(&test_created_mlids, + cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec ); + + /* o15.0.1.5: */ + /* - Check the returned MGID is valid. (p 804) */ + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Validating resulting MGID (o15.0.1.5)...\n" + ); + /* prefix 0xFF1 Scope 0xA01B */ + /* Since we did not directly specified SCOPE in comp mask + we should get the comp mask that is link-local scope */ + if ( (p_mc_res->mgid.multicast.header[0] != 0xFF) || + (p_mc_res->mgid.multicast.header[1] != 0x12) || + (p_mc_res->mgid.multicast.raw_group_id[0] != 0xA0) || + (p_mc_res->mgid.multicast.raw_group_id[1] != 0x1B) ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 0209: " + "Validating MGID failed. MGID:0x%016" PRIx64 ":%016" PRIx64 "\n", + cl_ntoh64( p_mc_res->mgid.unicast.prefix ), + cl_ntoh64( p_mc_res->mgid.unicast.interface_id ) + ); + status = IB_ERROR; + goto Exit; + } + + /* Good Flow - mgid is 0 while giving all required fields for join : P_Key, Q_Key, SL, FlowLabel, Tclass */ + /* Using feasible GREATER_THAN 0 packet lifitime */ + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking Create given MGID=0 (o15.0.1.4)...\n" + ); + + status = osmt_query_mcast(p_osmt); + + osmt_init_mc_query_rec(p_osmt, &mc_req_rec); + + p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad); + + /* no MGID */ + memset(&mc_req_rec.mgid, 0, sizeof(ib_gid_t)); + /* Request Join */ + ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER); + + mc_req_rec.pkt_life = 0 | IB_PATH_SELECTOR_GREATER_THAN << 6; + + comp_mask = + IB_MCR_COMPMASK_MGID | + IB_MCR_COMPMASK_PORT_GID | + IB_MCR_COMPMASK_QKEY | + IB_MCR_COMPMASK_PKEY | + IB_MCR_COMPMASK_SL | + IB_MCR_COMPMASK_FLOW | + IB_MCR_COMPMASK_JOIN_STATE | + IB_MCR_COMPMASK_TCLASS | /* all above are required */ + IB_MCR_COMPMASK_LIFE | + IB_MCR_COMPMASK_LIFE_SEL; + + + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 0210: " + "Failed to create MCG for MGID=0 - got %s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + goto Exit; + } + + /* Save the mlid created in test_created_mlids map */ + p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_run_mcast_flow: " + "Created MGID:0x%016" PRIx64 " : " + "0x%016" PRIx64 " MLID:0x%04X\n", + cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ), + cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ), + cl_ntoh16( p_recvd_rec->mlid )); + cl_map_insert(&test_created_mlids, + cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec ); + + /* o15.0.1.6: */ + /* - Create a new MCG with valid requested MGID. */ + osmt_init_mc_query_rec(p_osmt, &mc_req_rec); + mc_req_rec.mgid = good_mgid; + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking Create given valid MGID=0x%016" PRIx64 " : " + "0x%016" PRIx64 " (o15.0.1.6)...\n", + cl_ntoh64(mc_req_rec.mgid.unicast.prefix), + cl_ntoh64(mc_req_rec.mgid.unicast.interface_id)); + + /* Before creation, need to check that this group doesn't exist */ + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Verifying that MCGroup with this MGID doesn't exist by trying to Join it (o15.0.1.13)...\n" ); + + ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_NON_MEMBER); + + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" ); + status = osmt_send_mcast_request( p_osmt, 1, /* join */ + &mc_req_rec, + comp_mask, + &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" ); + + if ((status != IB_REMOTE_ERROR) || + (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 0301: " + "Tried joining group that shouldn't have existed - got %s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + status = IB_ERROR; + goto Exit; + } + + /* Set State to full member to allow group creation */ + ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER); + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Now creating group with given valid MGID=0x%016" PRIx64 " : " + "0x%016" PRIx64 " (o15.0.1.6)...\n", + cl_ntoh64(mc_req_rec.mgid.unicast.prefix), + cl_ntoh64(mc_req_rec.mgid.unicast.interface_id)); + + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 0211: " + "Failed to create MCG for MGID=0x%016" PRIx64 " : " + "0x%016" PRIx64 " (o15.0.1.6) - got %s/%s\n", + cl_ntoh64(good_mgid.unicast.prefix), + cl_ntoh64(good_mgid.unicast.interface_id), + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad)) ); + goto Exit; + } + + /* Save the mlid created in test_created_mlids map */ + p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_run_mcast_flow: " + "Created MGID:0x%016" PRIx64 " : " + "0x%016" PRIx64 " MLID:0x%04X\n", + cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ), + cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ), + cl_ntoh16( p_recvd_rec->mlid )); + cl_map_insert(&test_created_mlids, + cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec ); + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Validating resulting MGID (o15.0.1.6)...\n" + ); + /* prefix 0xFF1 Scope 0xA01B */ + if ( (p_mc_res->mgid.multicast.header[0] != 0xFF) || + (p_mc_res->mgid.multicast.header[1] != 0x12) || /* HACK hardcoded scope = 0x02 */ + (p_mc_res->mgid.multicast.raw_group_id[0] != 0xA0) || + (p_mc_res->mgid.multicast.raw_group_id[1] != 0x1C) ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 0212: " + "Validating MGID failed. MGID:0x%016" PRIx64 ":%016" PRIx64 "\n", + cl_ntoh64( p_mc_res->mgid.unicast.prefix ), + cl_ntoh64( p_mc_res->mgid.unicast.interface_id ) + ); + status = IB_ERROR; + goto Exit; + } + + /* - Try to create a new MCG with invalid MGID : get back ERR_REQ_INVALID */ + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking BAD MGID=0xFA..... (o15.0.1.6)...\n" + ); + + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" ); + + mc_req_rec.mgid.raw[0] = 0xFA; + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" ); + + if ((status != IB_REMOTE_ERROR) || + (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 0213: " + "Failed to recognize MGID error for MGID=0xFA - got %s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + status = IB_ERROR; + goto Exit; + } + + /* - Try again with MGID prefix = 0xA01B (maybe 0x1BA0 little or big ?) */ + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking BAD MGID=0xFF12A01B..... with link-local scope (o15.0.1.6)...\n" + ); + + mc_req_rec.mgid.raw[0] = 0xFF; + mc_req_rec.mgid.raw[3] = 0x1B; + comp_mask = comp_mask | IB_MCR_COMPMASK_SCOPE; + mc_req_rec.scope_state = mc_req_rec.scope_state & 0x2F; /* local scope */ + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" ); + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" ); + + if ((status != IB_REMOTE_ERROR) || + (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 0214: " + "Failed to recognize MGID error for A01B with link-local bit (status %s) (rem status %s)\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + status = IB_ERROR; + goto Exit; + } + + /* Change the mgid prefix - get back ERR_REQ_INVALID */ + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking BAD MGID PREFIX=0xEF... (o15.0.1.6)...\n" + ); + + mc_req_rec.mgid = good_mgid; + + mc_req_rec.mgid.raw[0] = 0xEF; + + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" ); + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" ); + + if ((status != IB_REMOTE_ERROR) || + (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 0215: " + "Failed to recognize MGID PREFIX error for MGID=0xEF - got %s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + status = IB_ERROR; + goto Exit; + } + + /* Change the scope to reserved - get back VALID REQ */ + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking local scope with full member \n\t\tand valid mgid 0x%016" + PRIx64 ":0x%016" PRIx64 " ... (o15.0.1.6)...\n", + cl_ntoh64(mc_req_rec.mgid.unicast.prefix), + cl_ntoh64(mc_req_rec.mgid.unicast.interface_id)); + + mc_req_rec.mgid = good_mgid; + + mc_req_rec.mgid.raw[1] = 0x1F; + + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 0216: " + "Failed to create MCG for MGID=0x%016" PRIx64 " : " + "0x%016" PRIx64 " - got %s/%s\n", + cl_ntoh64(good_mgid.unicast.prefix), + cl_ntoh64(good_mgid.unicast.interface_id), + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) ); + goto Exit; + } + + /* Save the mlid created in test_created_mlids map */ + p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_run_mcast_flow: " + "Created MGID:0x%016" PRIx64 " : " + "0x%016" PRIx64 " MLID:0x%04X\n", + cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ), + cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ), + cl_ntoh16( p_recvd_rec->mlid )); + cl_map_insert(&test_created_mlids, + cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec ); + + /* Change the flags to invalid value 0x2 - get back INVALID REQ */ + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking invalid flags=0xFF 22 ... (o15.0.1.6)...\n" + ); + + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" ); + + mc_req_rec.mgid = good_mgid; + + mc_req_rec.mgid.raw[1] = 0x22; + + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" ); + + if ((status != IB_REMOTE_ERROR) || + (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 0217: " + "Failed to recognize create with invalid flags value 0x2 - got %s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + status = IB_ERROR; + goto Exit; + } + + /* Change the MGID to link local MGID - get back VALID REQ */ + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking link local MGID 0xFF02:0:0:0:0:0:0:1 (o15.0.1.6)...\n" + ); + + mc_req_rec.mgid = osm_link_local_mgid; + + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 0218: " + "Failed to create MCG for MGID=0xFF02:0:0:0:0:0:0:1 - got %s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + goto Exit; + } + + /* Save the mlid created in test_created_mlids map */ + p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_run_mcast_flow: " + "Created MGID:0x%016" PRIx64 " : " + "0x%016" PRIx64 " MLID:0x%04X\n", + cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ), + cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ), + cl_ntoh16( p_recvd_rec->mlid )); + cl_map_insert(&test_created_mlids, + cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec ); + + /* o15.0.1.7 - implicitlly checked during the prev steps. */ + /* o15.0.1.8 - implicitlly checked during the prev steps. */ + + /* o15.0.1.9 */ + /* - Create MCG with Invalid JoinState.FullMember != 1 : get ERR_REQ_INVALID */ + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking new MGID with invalid join state (o15.0.1.9)...\n" + ); + + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" ); + + mc_req_rec.mgid = good_mgid; + mc_req_rec.mgid.raw[12] = 0xFF; + mc_req_rec.scope_state = 0x22; /* link-local scope, non-member state */ + + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" ); + + if ((status != IB_REMOTE_ERROR) || + (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 0219: " + "Failed to recognize create with JoinState != FullMember - got %s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + status = IB_ERROR; + goto Exit; + } + + /* Lets try a valid join scope state */ + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking new MGID with valid join state (o15.0.1.9)...\n" + ); + + mc_req_rec.mgid = good_mgid; + mc_req_rec.scope_state = 0x23; /* link-local scope, non member and full member */ + + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 0220: " + "Failed to create MCG with valid join state 0x3 - got %s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + goto Exit; + } + + /* Save the mlid created in test_created_mlids map */ + p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_run_mcast_flow: " + "Created MGID:0x%016" PRIx64 " : " + "0x%016" PRIx64 " MLID:0x%04X\n", + cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ), + cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ), + cl_ntoh16( p_recvd_rec->mlid ) ); + cl_map_insert( &test_created_mlids, + cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec ); + + /* Lets try another invalid join scope state */ + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking new MGID with invalid join state (o15.0.1.9)...\n" + ); + + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" ); + + /* We have created a new MCG so now we need different mgid when cresting group otherwise it will be counted as join request .*/ + mc_req_rec.mgid = good_mgid; + mc_req_rec.mgid.raw[12] = 0xFC; + + mc_req_rec.scope_state = 0x24; /* link-local scope, send only member */ + + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" ); + + if ((status != IB_REMOTE_ERROR) || + (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 0221: " + "Failed to recognize create with JoinState != FullMember - got %s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + status = IB_ERROR; + goto Exit; + } + + /* Lets try another valid join scope state */ + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking new MGID creation with valid join state (o15.0.1.9)...\n" + ); + + mc_req_rec.mgid = good_mgid; + mc_req_rec.mgid.raw[12] = 0xFB; + memcpy(&special_mgid, &mc_req_rec.mgid, sizeof(ib_gid_t)); + mc_req_rec.scope_state = 0x2F; /* link-local scope, Full member with all other bits turned on */ + + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 0222: " + "Failed to create MCG with valid join state 0xF - got %s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + goto Exit; + } + + /* Save the mlid created in test_created_mlids map */ + p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_run_mcast_flow: " + "Created MGID:0x%016" PRIx64 " : " + "0x%016" PRIx64 " MLID:0x%04X\n", + cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ), + cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ), + cl_ntoh16( p_recvd_rec->mlid )); + cl_map_insert(&test_created_mlids, + cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec ); + + /* o15.0.1.10 - can't check on a single client .-- obsolete - + checked by SilverStorm bug o15-0.2.4, never the less recheck */ + /* o15-0.2.4 - Check a join request to already created MCG */ + p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad); + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Check o15-0.2.4 statement...\n" ); + /* Try to join */ + memcpy(&mc_req_rec.mgid,&p_mc_res->mgid,sizeof(ib_gid_t)); + /* Request Join */ + ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_NON_MEMBER); + comp_mask = + IB_MCR_COMPMASK_MGID | + IB_MCR_COMPMASK_PORT_GID | + IB_MCR_COMPMASK_JOIN_STATE; + + status = osmt_send_mcast_request( p_osmt, 0x1, /* User Defined query */ + &mc_req_rec, + comp_mask, + &res_sa_mad ); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02CC: " + "Failed to join MCG with valid req, returned status = %s\n", + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )); + goto Exit; + } + + /* o15.0.1.11: */ + /* - Try to join into a MGID that exists with JoinState=SendOnlyMember - */ + /* see that it updates JoinState. What is the routing change? */ + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking Retry of existing MGID - See JoinState update (o15.0.1.11)...\n" + ); + + mc_req_rec.mgid = good_mgid; + mc_req_rec.scope_state = 0x22; /* link-local scope, send only member */ + + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02CD: " + "Failed to update existing MGID - got %s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + goto Exit; + } + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Validating Join State update with NonMember (o15.0.1.11)...\n" + ); + + if (p_mc_res->scope_state != 0x23) /* scope is LSB */ + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02CE: " + "Validating JoinState update failed. Expected 0x23 got: 0x%02X\n", + p_mc_res->scope_state + ); + status = IB_ERROR; + goto Exit; + } + + /* Try delete current join state then update it with another value */ + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking JoinState update request should return 0x22 (o15.0.1.11)...\n" + ); + + mc_req_rec.rate = + IB_LINK_WIDTH_ACTIVE_1X | + IB_PATH_SELECTOR_GREATER_THAN << 6; + mc_req_rec.mgid = good_mgid; + /* link-local scope, non member (so we should not be able to delete) */ + /* but the FullMember bit should be gone */ + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking Partially delete JoinState (o15.0.1.14)...\n" + ); + mc_req_rec.scope_state = 0x22; + status = osmt_send_mcast_request( p_osmt, 0, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + if ((status != IB_SUCCESS) || (p_mc_res->scope_state != 0x21)) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02CF: " + "Failed to partially update JoinState : %s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + status = IB_ERROR; + goto Exit; + } + + /* So far successfully delete state - Now change it */ + mc_req_rec.mgid = good_mgid; + mc_req_rec.scope_state = 0x24; /* link-local scope, send only member */ + + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02C0: " + "Failed to update existing MCG - got %s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + goto Exit; + } + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Validating Join State update with Send Only Member (o15.0.1.11)...\n" + ); + + if (p_mc_res->scope_state != 0x25) /* scope is MSB */ + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02C1: " + "Validating JoinState update failed. Expected 0x25 got: 0x%02X\n", + p_mc_res->scope_state + ); + status = IB_ERROR; + goto Exit; + } + /* Now try to update value of join state */ + mc_req_rec.scope_state = 0x21; /* link-local scope, full member */ + + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02C2: " + "Failed to update existing MGID - got %s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + goto Exit; + } + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Validating Join State update with Full Member\n\t\t" + "to an existing 0x5 state MCG (o15.0.1.11)...\n" ); + + if (p_mc_res->scope_state != 0x25) /* scope is LSB */ + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02C3: " + "Validating JoinState update failed. Expected 0x25 got: 0x%02X\n", + p_mc_res->scope_state + ); + status = IB_ERROR; + goto Exit; + } + + /* Now try to update value of join state */ + mc_req_rec.scope_state = 0x22; /* link-local scope,non member */ + + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02C4: " + "Failed to update existing MGID - got %s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + goto Exit; + } + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Validating Join State update with Non Member\n\t\t" + "to an existing 0x5 state MCG (o15.0.1.11)...\n" ); + + if (p_mc_res->scope_state != 0x27) /* scope is LSB */ + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02C5: " + "Validating JoinState update failed. Expected 0x27 got: 0x%02X\n", + p_mc_res->scope_state + ); + status = IB_ERROR; + goto Exit; + } + + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "DEBUG - Current scope_state value : 0x%02X...\n", p_mc_res->scope_state ); + + /* - We can not check simple join since we have only one tester (for now) */ + + /* o15.0.1.12: Not Supported */ + /* - The SendOnlyNonMem join should have a special treatment in the + SA but what is it ? */ + + /* o15.0.1.13: */ + /* - Try joining with rate that does not exist in any MCG - + ERR_REQ_INVALID */ + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking BAD RATE when connecting to existing MGID (o15.0.1.13)...\n" + ); + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" ); + + mc_req_rec.mgid = good_mgid; + mc_req_rec.rate = + IB_LINK_WIDTH_ACTIVE_1X | + IB_PATH_SELECTOR_LESS_THAN << 6; + comp_mask = + IB_MCR_COMPMASK_GID | + IB_MCR_COMPMASK_PORT_GID | + IB_MCR_COMPMASK_QKEY | + IB_MCR_COMPMASK_PKEY | + IB_MCR_COMPMASK_SL | + IB_MCR_COMPMASK_FLOW | + IB_MCR_COMPMASK_JOIN_STATE | + IB_MCR_COMPMASK_TCLASS | /* all above are required */ + IB_MCR_COMPMASK_RATE_SEL | + IB_MCR_COMPMASK_RATE; + + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" ); + + if ((status != IB_REMOTE_ERROR) || + (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02C6: " + "Failed to catch BAD RATE joining an exiting MGID: %s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + status = IB_ERROR; + goto Exit; + } + + /* Try MTU that does not exist in any MCG */ + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking BAD MTU (higher them max) when connecting to " + "existing MGID (o15.0.1.13)...\n" + ); + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" ); + + mc_req_rec.mgid = osm_ipoib_mgid; + mc_req_rec.mtu = + IB_MTU_LEN_4096 | + IB_PATH_SELECTOR_GREATER_THAN << 6; + comp_mask = + IB_MCR_COMPMASK_GID | + IB_MCR_COMPMASK_PORT_GID | + IB_MCR_COMPMASK_QKEY | + IB_MCR_COMPMASK_PKEY | + IB_MCR_COMPMASK_SL | + IB_MCR_COMPMASK_FLOW | + IB_MCR_COMPMASK_JOIN_STATE | + IB_MCR_COMPMASK_TCLASS | /* all above are required */ + IB_MCR_COMPMASK_MTU_SEL | + IB_MCR_COMPMASK_MTU; + + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" ); + + if ((status != IB_REMOTE_ERROR) || + (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02C7: " + "Failed to catch BAD RATE (higher them max) joining an exiting MGID: %s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + status = IB_ERROR; + goto Exit; + } + + /* Try another MTU that does not exist in any MCG */ + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking BAD MTU (less than min) when connecting " + "to existing MGID (o15.0.1.13)...\n" + ); + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" ); + + mc_req_rec.mgid = osm_ipoib_mgid; + mc_req_rec.mtu = + IB_MTU_LEN_256 | + IB_PATH_SELECTOR_LESS_THAN << 6; + comp_mask = + IB_MCR_COMPMASK_GID | + IB_MCR_COMPMASK_PORT_GID | + IB_MCR_COMPMASK_QKEY | + IB_MCR_COMPMASK_PKEY | + IB_MCR_COMPMASK_SL | + IB_MCR_COMPMASK_FLOW | + IB_MCR_COMPMASK_JOIN_STATE | + IB_MCR_COMPMASK_TCLASS | /* all above are required */ + IB_MCR_COMPMASK_MTU_SEL | + IB_MCR_COMPMASK_MTU; + + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" ); + + if ((status != IB_REMOTE_ERROR) || + (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02C8: " + "Failed to catch BAD RATE (less them min) joining an exiting MGID: %s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + status = IB_ERROR; + goto Exit; + } + + /* o15.0.1.14: */ + /* - Try partial delete - actually updating the join state. check it. */ + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking partial JoinState delete request - removing NonMember (o15.0.1.14)...\n" + ); + + mc_req_rec.rate = + IB_LINK_WIDTH_ACTIVE_1X | + IB_PATH_SELECTOR_GREATER_THAN << 6; + mc_req_rec.mgid = good_mgid; + comp_mask = + IB_MCR_COMPMASK_GID | + IB_MCR_COMPMASK_PORT_GID | + IB_MCR_COMPMASK_QKEY | + IB_MCR_COMPMASK_PKEY | + IB_MCR_COMPMASK_SL | + IB_MCR_COMPMASK_FLOW | + IB_MCR_COMPMASK_JOIN_STATE | + IB_MCR_COMPMASK_TCLASS | /* all above are required */ + IB_MCR_COMPMASK_RATE_SEL | + IB_MCR_COMPMASK_RATE; + /* link-local scope, non member (so we should not be able to delete) */ + /* but the FullMember bit should be gone */ + mc_req_rec.scope_state = 0x22; + + status = osmt_send_mcast_request( p_osmt, 0, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02C9: " + "Fail to partially update JoinState during delete: %s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + status = IB_ERROR; + goto Exit; + } + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Validating Join State removal of Non Member bit (o15.0.1.14)...\n" + ); + if (p_mc_res->scope_state != 0x25) /* scope is MSB - now only the non member & send only member have left */ + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02CA: " + "Validating JoinState update failed. Expected 0x25 got: 0x%02X\n", + p_mc_res->scope_state + ); + status = IB_ERROR; + goto Exit; + } + + /* Now use the same scope_state and delete all JoinState - leave multicast group since state is 0x0 */ + + mc_req_rec.scope_state = 0x25; + status = osmt_send_mcast_request( p_osmt, 0, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02CB: " + "Failed to update JoinState during delete: %s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + status = IB_ERROR; + goto Exit; + } + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Validating Join State update remove (o15.0.1.14)...\n" + ); + + if (p_mc_res->scope_state != 0x25) /* scope is MSB - now only 0x0 so port is removed from MCG */ + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02BF: " + "Validating JoinState update failed. Expected 0x25 got: 0x%02X\n", + p_mc_res->scope_state + ); + status = IB_ERROR; + goto Exit; + } + + /* - Try joining (not full mem) again to see the group was deleted. (should fail) */ + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking Delete by trying to Join deleted group (o15.0.1.13)...\n" + ); + + mc_req_rec.scope_state = 0x22; /* use non member - so if no group fail */ + + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" ); + status = osmt_send_mcast_request( p_osmt, 1, /* join */ + &mc_req_rec, + comp_mask, + &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" ); + + if (status != IB_REMOTE_ERROR) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02BC: " + "Succeeded Joining Deleted Group: %s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + status = IB_ERROR; + goto Exit; + } + + /* - Try deletion of the IPoIB MCG and get: ERR_REQ_INVALID */ + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking BAD Delete of Mgid membership (no prev join) (o15.0.1.15)...\n" + ); + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" ); + + mc_req_rec.mgid = osm_ipoib_mgid; + mc_req_rec.rate = + IB_LINK_WIDTH_ACTIVE_1X | + IB_PATH_SELECTOR_GREATER_THAN << 6; + mc_req_rec.scope_state = 0x21; /* delete full member */ + + status = osmt_send_mcast_request( p_osmt, 0, /* delete flag */ + &mc_req_rec, + comp_mask, + &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" ); + + if ((status != IB_REMOTE_ERROR) || + (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02BD: " + "Failed to catch BAD delete from IPoIB: %s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + status = IB_ERROR; + goto Exit; + } + + /* Prepare another MCG for the following tests : */ + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking Create given MGID=0x%016" PRIx64 " : " + "0x%016" PRIx64 "\n\t\t(o15.0.1.4)...\n", + cl_ntoh64(osm_ipoib_mgid.unicast.prefix), + cl_ntoh64(osm_ipoib_mgid.unicast.interface_id) ); + + mc_req_rec.mgid = good_mgid; + mc_req_rec.mgid.raw[12] = 0xAA; + mc_req_rec.pkt_life = 0 | IB_PATH_SELECTOR_GREATER_THAN << 6; + mc_req_rec.scope_state = 0x21; /* Full memeber */ + comp_mask = + IB_MCR_COMPMASK_GID | + IB_MCR_COMPMASK_PORT_GID | + IB_MCR_COMPMASK_QKEY | + IB_MCR_COMPMASK_PKEY | + IB_MCR_COMPMASK_SL | + IB_MCR_COMPMASK_FLOW | + IB_MCR_COMPMASK_JOIN_STATE | + IB_MCR_COMPMASK_TCLASS | /* all above are required */ + IB_MCR_COMPMASK_LIFE | + IB_MCR_COMPMASK_LIFE_SEL; + + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02BE: " + "Failed to create MCG for 0x%016" PRIx64 " : " + "0x%016" PRIx64 " - got %s/%s\n", + cl_ntoh64(good_mgid.unicast.prefix), + cl_ntoh64(good_mgid.unicast.interface_id), + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) ); + goto Exit; + } + + /* - Try delete with valid join state */ + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking Full Delete of a group (o15.0.1.14)...\n" + ); + mc_req_rec.scope_state = 0x21; /* the FullMember is the current JoinState */ + status = osmt_send_mcast_request( p_osmt, 0, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + + if (status != IB_SUCCESS) + { + goto Exit; + } + + /* o15.0.1.15: */ + /* - Try deletion of the IPoIB MCG and get: ERR_REQ_INVALID */ + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking BAD Delete of IPoIB membership (no prev join) (o15.0.1.15)...\n" + ); + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" ); + + mc_req_rec.mgid = osm_ipoib_mgid; + mc_req_rec.rate = + IB_LINK_WIDTH_ACTIVE_1X | + IB_PATH_SELECTOR_GREATER_THAN << 6; + mc_req_rec.scope_state = 0x21; /* delete full member */ + + status = osmt_send_mcast_request( p_osmt, 0, /* delete flag */ + &mc_req_rec, + comp_mask, + &res_sa_mad ); + + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" ); + + if ((status != IB_REMOTE_ERROR) || + (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 0223: " + "Failed to catch BAD delete from IPoIB: %s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + status = IB_ERROR; + goto Exit; + } + + /**************************************************************************/ + /* Checking join with invalid MTU */ + osmt_init_mc_query_rec(p_osmt, &mc_req_rec); + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking Join with unrealistic mtu : \n" + "\t\tFirst create new MCG than try to join it \n" + "\t\twith unrealistic MTU greater than 4096 (o15.0.1.8)...\n" + ); + + /* First create new mgrp */ + ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER); + mc_req_rec.mtu = IB_MTU_LEN_1024 | IB_PATH_SELECTOR_EXACTLY << 6; + memset(&mc_req_rec.mgid, 0, sizeof(ib_gid_t)); + comp_mask = + IB_MCR_COMPMASK_MGID | + IB_MCR_COMPMASK_PORT_GID | + IB_MCR_COMPMASK_QKEY | + IB_MCR_COMPMASK_PKEY | + IB_MCR_COMPMASK_SL | + IB_MCR_COMPMASK_FLOW | + IB_MCR_COMPMASK_JOIN_STATE | + IB_MCR_COMPMASK_TCLASS | /* all above are required */ + IB_MCR_COMPMASK_MTU_SEL | + IB_MCR_COMPMASK_MTU; + + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02EB: " + "Failed to create new mgrp\n" ); + goto Exit; + } + memcpy(&tmp_mgid,&p_mc_res->mgid,sizeof(ib_gid_t)); + osm_dump_mc_record( &p_osmt->log, p_mc_res, OSM_LOG_INFO ); + /* tmp_mtu = p_mc_res->mtu & 0x3F; */ + + /* impossible requested mtu always greater than exist in MCG */ + mc_req_rec.mtu = IB_MTU_LEN_4096 | IB_PATH_SELECTOR_GREATER_THAN << 6; + memcpy(&mc_req_rec.mgid,&tmp_mgid,sizeof(ib_gid_t)); + ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER); + comp_mask = + IB_MCR_COMPMASK_GID | + IB_MCR_COMPMASK_PORT_GID | + IB_MCR_COMPMASK_JOIN_STATE | + IB_MCR_COMPMASK_MTU_SEL | + IB_MCR_COMPMASK_MTU; + + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" ); + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" ); + + if (status == IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02E4: " + "Expected REMOTE ERROR got:%s/%s\n", + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) + ); + status = IB_ERROR; + goto Exit; + } + + /* - Try GetTable with PortGUID wildcarded and get back some groups. */ + status = osmt_query_mcast( p_osmt); + cnt = cl_qmap_count(&p_osmt->exp_subn.mgrp_mlid_tbl); + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow (Before checking Max MCG creation): " + "Number of MC Records found in SA DB is %d\n", cnt ); + + /**************************************************************************/ + /* Checking join on behalf of remote port gid */ + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking Proxy Join...\n" + ); + osmt_init_mc_query_rec(p_osmt, &mc_req_rec); + memset( &context, 0, sizeof( context ) ); + + /* + * Do a blocking query for all NodeRecords in the subnet. + */ + status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_NODE_RECORD, + sizeof( *p_rec ), &context ); + + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02E5: " + "osmtest_get_all_recs failed on getting all node records(%s)\n", + ib_get_err_str( status ) ); + goto Exit; + } + + /* + * Populate the database with the received records. + */ + num_recs = context.result.result_cnt; + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_run_mcast_flow: " + "Received %u records\n", num_recs ); + + for( i = 0; i < num_recs; i++ ) + { + p_rec = osmv_get_query_node_rec( context.result.p_result_madw, i ); + if (p_rec->node_info.port_guid != p_osmt->local_port.port_guid && + p_rec->node_info.node_type == IB_NODE_TYPE_CA) + { + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_run_mcast_flow: " + "remote port_guid = 0x%" PRIx64 "\n", + cl_ntoh64(p_rec->node_info.port_guid) ); + + remote_port_guid = p_rec->node_info.port_guid; + i = num_recs; + break; + } + } + + if (remote_port_guid != 0x0) + { + ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER); + memset(&mc_req_rec.mgid, 0, sizeof(ib_gid_t)); + mc_req_rec.port_gid.unicast.interface_id = remote_port_guid; + comp_mask = + IB_MCR_COMPMASK_MGID | + IB_MCR_COMPMASK_PORT_GID | + IB_MCR_COMPMASK_QKEY | + IB_MCR_COMPMASK_PKEY | + IB_MCR_COMPMASK_SL | + IB_MCR_COMPMASK_FLOW | + IB_MCR_COMPMASK_JOIN_STATE | + IB_MCR_COMPMASK_TCLASS; /* all above are required */ + + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + + + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02B4: " + "Could not join on behalf of remote port 0x%016" PRIx64 + " remote status: %s\n", + cl_ntoh64(remote_port_guid), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) ); + status = IB_ERROR; + goto Exit; + } + + p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad); + memcpy(&proxy_mgid,&p_mc_res->mgid,sizeof(ib_gid_t)); + + /* First try a bad deletion then good one */ + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Trying deletion of remote port with local port guid\n" ); + + osmt_init_mc_query_rec(p_osmt, &mc_req_rec); + ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER); + comp_mask = + IB_MCR_COMPMASK_MGID | + IB_MCR_COMPMASK_PORT_GID | + IB_MCR_COMPMASK_JOIN_STATE; + + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" ); + + status = osmt_send_mcast_request( p_osmt, 0, /* delete flag */ + &mc_req_rec, + comp_mask, + &res_sa_mad ); + + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" ); + + if (status == IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02A9: " + "Successful deletion of remote port guid with local one MGID : " + "0x%016" PRIx64 " : 0x%016" PRIx64 ", Got : %s/%s\n", + cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.prefix), + cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.interface_id), + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) ); + status = IB_ERROR; + goto Exit; + } + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Trying deletion of remote port with the right port guid\n" ); + + osmt_init_mc_query_rec(p_osmt, &mc_req_rec); + ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER); + mc_req_rec.mgid = proxy_mgid; + mc_req_rec.port_gid.unicast.interface_id = remote_port_guid; + comp_mask = + IB_MCR_COMPMASK_MGID | + IB_MCR_COMPMASK_PORT_GID | + IB_MCR_COMPMASK_JOIN_STATE; + status = osmt_send_mcast_request( p_osmt, 0, /* delete flag */ + &mc_req_rec, + comp_mask, + &res_sa_mad ); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02B0: " + "Failed to delete mgid with remote port guid MGID : " + "0x%016" PRIx64 " : 0x%016" PRIx64 ", Got : %s/%s\n", + cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.prefix), + cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.interface_id), + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) ); + goto Exit; + } + } + else + { + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Could not check proxy join since could not found remote port, different from local port\n" ); + } + + /* prepare init for next check */ + osmt_init_mc_query_rec(p_osmt, &mc_req_rec); + + /**************************************************************************/ + if (p_osmt->opt.mmode > 2) + { + /* Check invalid Join with max mlid which is more than the + Mellanox switches support 0xC000+0x1000 = 0xd000 */ + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Checking Creation of Maximum avaliable Groups (MulticastFDBCap)...\n" + ); + tmp_mlid = cl_ntoh16(max_mlid) - cnt; + + while (tmp_mlid > 0 && !ReachedMlidLimit) { + uint16_t cur_mlid = 0; + + /* Request Set */ + ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER); + /* Good Flow - mgid is 0 while giving all required fields for + join : P_Key, Q_Key, SL, FlowLabel, Tclass */ + + mc_req_rec.rate = + IB_LINK_WIDTH_ACTIVE_1X | + IB_PATH_SELECTOR_GREATER_THAN << 6; + mc_req_rec.mlid = max_mlid; + memset(&mc_req_rec.mgid, 0, sizeof(ib_gid_t)); + comp_mask = + IB_MCR_COMPMASK_MGID | + IB_MCR_COMPMASK_PORT_GID | + IB_MCR_COMPMASK_QKEY | + IB_MCR_COMPMASK_PKEY | + IB_MCR_COMPMASK_SL | + IB_MCR_COMPMASK_FLOW | + IB_MCR_COMPMASK_JOIN_STATE | + IB_MCR_COMPMASK_TCLASS | /* all above are required */ + IB_MCR_COMPMASK_MLID; + status = osmt_send_mcast_request( p_osmt, 1, + &mc_req_rec, + comp_mask, + &res_sa_mad ); + + p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad); + if (status != IB_SUCCESS) + { + + if (cur_mlid > cl_ntoh16(max_mlid)) + { + + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow : ERR 2E1 " + "Successful Join with greater mlid than switches support (MulticastFDBCap) 0x%04X\n", + cur_mlid ); + status = IB_ERROR; + osm_dump_mc_record( &p_osmt->log, p_mc_res, OSM_LOG_VERBOSE ); + goto Exit; + } else if (( res_sa_mad.status & IB_SMP_STATUS_MASK ) == IB_SA_MAD_STATUS_NO_RESOURCES) { + /* You can quitly exit the loop since no available mlid in SA DB + i.e. reached the maximum valiad avalable mlid */ + ReachedMlidLimit = TRUE; + } + } + else + { + cur_mlid = cl_ntoh16(p_mc_res->mlid); + /* Save the mlid created in test_created_mlids map */ + p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad ); + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_run_mcast_flow : " + "Created MGID:0x%016" PRIx64 " : " + "0x%016" PRIx64 " MLID:0x%04X\n", + cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ), + cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ), + cl_ntoh16( p_recvd_rec->mlid )); + cl_map_insert(&test_created_mlids, + cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec ); + } + tmp_mlid--; + } + } + + /* Prepare the mc_req_rec for the rest of the flow */ + osmt_init_mc_query_rec(p_osmt, &mc_req_rec); + + /**************************************************************************/ + /* o15.0.1.16: */ + /* - Try GetTable with PortGUID wildcarded and get back some groups. */ + + status = osmt_query_mcast( p_osmt); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02B1: " + "Failed to query multicast groups: %s\n", + ib_get_err_str(status) ); + goto Exit; + } + + cnt = cl_qmap_count(&p_osmt->exp_subn.mgrp_mlid_tbl); + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow (Before Deletion of all MCG): " + "Number of MC Records found in SA DB is %d\n", cnt ); + + /* Delete all MCG that are not of IPoIB */ + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow : " + "Cleanup all MCG that are not IPoIB...\n" ); + + p_mgrp_mlid_tbl = &p_osmt->exp_subn.mgrp_mlid_tbl; + p_mgrp = (osmtest_mgrp_t*)cl_qmap_head( p_mgrp_mlid_tbl ); + /* scan all available multicast groups in the DB and fill in the table */ + while( p_mgrp != (osmtest_mgrp_t*)cl_qmap_end( p_mgrp_mlid_tbl ) ) + { + /* Only if different from IPoIB Mgid try to delete */ + if (!IS_IPOIB_MGID(&p_mgrp->mcmember_rec.mgid)) + { + osmt_init_mc_query_rec(p_osmt, &mc_req_rec); + mc_req_rec.mgid = p_mgrp->mcmember_rec.mgid; + + /* o15-0.1.4 - need to specify the oppsite state for a valid delete */ + if (!memcmp(&special_mgid, &p_mgrp->mcmember_rec.mgid, sizeof(special_mgid))) + { + mc_req_rec.scope_state = 0x2F; + } + else + { + mc_req_rec.scope_state = 0x21; + } + comp_mask = + IB_MCR_COMPMASK_MGID | + IB_MCR_COMPMASK_PORT_GID | + IB_MCR_COMPMASK_JOIN_STATE; + + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_run_mcast_flow : " + "Sending request to delete MGID : 0x%016" PRIx64 + " : 0x%016" PRIx64 ", scope_state : 0x%02X\n", + cl_ntoh64(mc_req_rec.mgid.unicast.prefix), + cl_ntoh64(mc_req_rec.mgid.unicast.interface_id), + mc_req_rec.scope_state ); + status = osmt_send_mcast_request( p_osmt, 0, /* delete flag */ + &mc_req_rec, + comp_mask, + &res_sa_mad ); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02FF: " + "Failed to delete MGID : 0x%016" PRIx64 " : 0x%016" PRIx64 + " ,\n\t\t it is not our MCG, Status : %s/%s\n", + cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.prefix), + cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.interface_id), + ib_get_err_str( status ), + ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) ); + fail_to_delete_mcg++; + } + } + else + { + end_ipoib_cnt++; + } + p_mgrp = (osmtest_mgrp_t*)cl_qmap_next( &p_mgrp->map_item ); + } + + status = osmt_query_mcast( p_osmt); + + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02B2 " + "GetTable of all records has failed - got %s\n", + ib_get_err_str( status ) ); + goto Exit; + } + + /* If we are in single mode check flow - need to make sure all the multicast groups + that are left are not ones created during the flow. + */ + if (p_osmt->opt.mmode == 1 || p_osmt->opt.mmode == 3) + { + end_cnt = cl_qmap_count(&p_osmt->exp_subn.mgrp_mlid_tbl); + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Status of MC Records in SA DB during the test flow:\n" + " Beginning of test\n" + " Unrelated to the test: %d\n" + " IPoIB MC Records : %d\n" + " Total : %d\n" + " End of test\n" + " Failed to delete : %d\n" + " IPoIB MC Records : %d\n" + " Total : %d\n", + mcg_outside_test_cnt, /* Non-IPoIB that existed at the beginning */ + start_ipoib_cnt, /* IPoIB records */ + start_cnt, /* Total: IPoIB and MC Records unrelated to the test */ + fail_to_delete_mcg, /* Failed to delete at the end */ + end_ipoib_cnt, /* IPoIB records */ + end_cnt); /* Total MC Records at the end */ + + /* when we compare num of MCG we should consider an outside source which create other MCGs */ + if ((end_cnt - fail_to_delete_mcg-end_ipoib_cnt) != (start_cnt - mcg_outside_test_cnt - start_ipoib_cnt)) + { + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Got different number of non-IPoIB records stored in SA DB\n\t\t" + "at Start got %d, at End got %d (IPoIB groups only)\n", + (start_cnt - mcg_outside_test_cnt - start_ipoib_cnt), + (end_cnt - fail_to_delete_mcg-end_ipoib_cnt) ); + } + + p_mgrp_mlid_tbl = &p_osmt->exp_subn.mgrp_mlid_tbl; + p_mgrp = (osmtest_mgrp_t*)cl_qmap_head( p_mgrp_mlid_tbl ); + while( p_mgrp != (osmtest_mgrp_t*)cl_qmap_end( p_mgrp_mlid_tbl ) ) + { + uint16_t mlid = (uint16_t)cl_qmap_key((cl_map_item_t*)p_mgrp); + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Found MLID:0x%04X\n", + mlid ); + /* Check if the mlid is in the test_created_mlids. If TRUE, then we + didn't delete a MCgroup that was created in this flow. */ + if ( cl_map_get (&test_created_mlids, mlid) != NULL ) + { + /* This means that we still have an mgrp that we created!! */ + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_mcast_flow: ERR 02FE: " + "Wasn't able to erase mgrp with MGID:0x%016" PRIx64 " : 0x%016" + PRIx64 " MLID:0x%04X\n", + cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.prefix), + cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.interface_id), + mlid ); + got_error = TRUE; + } + else + { + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_run_mcast_flow: " + "Still exists %s MGID:0x%016" PRIx64 " : 0x%016" PRIx64 "\n", + (IS_IPOIB_MGID(&p_mgrp->mcmember_rec.mgid)) ? "IPoIB" : "non-IPoIB", + cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.prefix), + cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.interface_id) ); + } + p_mgrp = (osmtest_mgrp_t*)cl_qmap_next( &p_mgrp->map_item ); + } + + if (got_error) + { + __osmt_print_all_multicast_records(p_osmt); + status = IB_ERROR; + } + } + Exit: + OSM_LOG_EXIT( &p_osmt->log ); + return status; +} + + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmt_service.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmt_service.c new file mode 100644 index 00000000..62a06123 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmt_service.c @@ -0,0 +1,1833 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osmt_service.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Implementation of service records testing flow.. + * Top level is osmt_run_service_records_flow: + * osmt_register_service + * osmt_get_service_by_name + * osmt_get_all_services + * osmt_delete_service_by_name + * + * Environment: + * Linux User Mode + * + * $Revision: 1.1 $ + */ + +#ifndef __WIN__ +#include +#else +#include +#endif +#include +#include +#include +#include +#include "osmtest.h" + +/********************************************************************** + **********************************************************************/ + +ib_api_status_t +osmt_register_service( IN osmtest_t * const p_osmt, + IN ib_net64_t service_id, + IN ib_net16_t service_pkey, + IN ib_net32_t service_lease, + IN uint8_t service_key_lsb, + IN char *service_name) { + osmv_query_req_t req; + osmv_user_query_t user; + osmtest_req_context_t context; + ib_service_record_t svc_rec; + osm_log_t *p_log = &p_osmt->log; + ib_api_status_t status; + + OSM_LOG_ENTER( p_log, osmt_register_service ); + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_register_service: " + "Registering service: name: %s id: 0x%" PRIx64 "\n", + service_name, cl_ntoh64(service_id)); + + memset( &req, 0, sizeof( req ) ); + memset( &context, 0, sizeof( context ) ); + memset( &user, 0, sizeof( user ) ); + memset( &svc_rec, 0, sizeof( svc_rec ) ); + + /* set the new service record fields */ + svc_rec.service_id = service_id; + svc_rec.service_pkey = service_pkey; + svc_rec.service_gid.unicast.prefix = 0; + svc_rec.service_gid.unicast.interface_id = p_osmt->local_port.port_guid; + svc_rec.service_lease = service_lease; + memset(&svc_rec.service_key, 0, 16*sizeof(uint8_t)); + svc_rec.service_key[0] = service_key_lsb; + memset(svc_rec.service_name, 0, sizeof(svc_rec.service_name)); + memcpy(svc_rec.service_name, service_name, + (strlen(service_name)+1)*sizeof(char)); + + /* prepare the data used for this query */ + /* sa_mad_data.method = IB_MAD_METHOD_SET; */ + /* sa_mad_data.sm_key = 0; */ + + context.p_osmt = p_osmt; + req.query_context = &context; + req.query_type = OSMV_QUERY_USER_DEFINED; + req.pfn_query_cb = osmtest_query_res_cb; + req.p_query_input = &user; + req.flags = OSM_SA_FLAGS_SYNC; + req.sm_key = 0; + req.timeout_ms = p_osmt->opt.transaction_timeout; + + user.method = IB_MAD_METHOD_SET; + user.attr_id = IB_MAD_ATTR_SERVICE_RECORD; + if (ib_pkey_is_invalid(service_pkey)) + { + /* if given an invalid service_pkey - don't turn the PKEY compmask on */ + user.comp_mask = IB_SR_COMPMASK_SID | + IB_SR_COMPMASK_SGID | + IB_SR_COMPMASK_SLEASE | + IB_SR_COMPMASK_SKEY | + IB_SR_COMPMASK_SNAME; + } + else + { + user.comp_mask = IB_SR_COMPMASK_SID | + IB_SR_COMPMASK_SGID | + IB_SR_COMPMASK_SPKEY | + IB_SR_COMPMASK_SLEASE | + IB_SR_COMPMASK_SKEY | + IB_SR_COMPMASK_SNAME; + } + user.attr_offset = ib_get_attr_offset( sizeof( ib_service_record_t ) ); + user.p_attr = &svc_rec; + + status = osmv_query_sa( p_osmt->h_bind, &req ); + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_register_service: ERR 4A01: " + "ib_query failed (%s)\n", ib_get_err_str( status ) ); + goto Exit; + } + + status = context.result.status; + + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_register_service: ERR 4A02: " + "ib_query failed (%s)\n", ib_get_err_str( status ) ); + + if( status == IB_REMOTE_ERROR ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_register_service: " + "Remote error = %s\n", + ib_get_mad_status_str( osm_madw_get_mad_ptr + ( context.result. + p_result_madw ) ) ); + } + goto Exit; + } + + Exit: + if( context.result.p_result_madw != NULL ) + { + osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw ); + context.result.p_result_madw = NULL; + } + + OSM_LOG_EXIT( &p_osmt->log ); + return status; +} + +/********************************************************************** + **********************************************************************/ + +ib_api_status_t +osmt_register_service_with_full_key ( IN osmtest_t * const p_osmt, + IN ib_net64_t service_id, + IN ib_net16_t service_pkey, + IN ib_net32_t service_lease, + IN uint8_t *service_key, + IN char *service_name) { + osmv_query_req_t req; + osmv_user_query_t user; + osmtest_req_context_t context; + ib_service_record_t svc_rec,*p_rec; + osm_log_t *p_log = &p_osmt->log; + ib_api_status_t status; + uint8_t i,skey[16]; + + OSM_LOG_ENTER( p_log, osmt_register_service_with_full_key ); + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_register_service_with_full_key: " + "Registering service: name: %s id: 0x%" PRIx64 "\n", + service_name, cl_ntoh64(service_id)); + + memset( &req, 0, sizeof( req ) ); + memset( &context, 0, sizeof( context ) ); + memset( &user, 0, sizeof( user ) ); + memset( &svc_rec, 0, sizeof( svc_rec ) ); + + /* set the new service record fields */ + svc_rec.service_id = service_id; + svc_rec.service_pkey = service_pkey; + svc_rec.service_gid.unicast.prefix = 0; + svc_rec.service_gid.unicast.interface_id = p_osmt->local_port.port_guid; + svc_rec.service_lease = service_lease; + memset(&svc_rec.service_key, 0, 16*sizeof(uint8_t)); + memcpy(svc_rec.service_key,service_key, 16*sizeof(uint8_t)); + memset(svc_rec.service_name, 0, sizeof(svc_rec.service_name)); + memset(skey, 0, 16*sizeof(uint8_t)); + memcpy(svc_rec.service_name, service_name, + (strlen(service_name)+1)*sizeof(char)); + + /* prepare the data used for this query */ + /* sa_mad_data.method = IB_MAD_METHOD_SET; */ + /* sa_mad_data.sm_key = 0; */ + + context.p_osmt = p_osmt; + req.query_context = &context; + req.query_type = OSMV_QUERY_USER_DEFINED; + req.pfn_query_cb = osmtest_query_res_cb; + req.p_query_input = &user; + req.flags = OSM_SA_FLAGS_SYNC; + req.sm_key = 0; + req.timeout_ms = p_osmt->opt.transaction_timeout; + + user.method = IB_MAD_METHOD_SET; + user.attr_id = IB_MAD_ATTR_SERVICE_RECORD; + if (ib_pkey_is_invalid(service_pkey)) + { + /* if given an invalid service_pkey - don't turn the PKEY compmask on */ + user.comp_mask = IB_SR_COMPMASK_SID | + IB_SR_COMPMASK_SGID | + IB_SR_COMPMASK_SLEASE | + IB_SR_COMPMASK_SKEY | + IB_SR_COMPMASK_SNAME; + } + else + { + user.comp_mask = IB_SR_COMPMASK_SID | + IB_SR_COMPMASK_SGID | + IB_SR_COMPMASK_SPKEY | + IB_SR_COMPMASK_SLEASE | + IB_SR_COMPMASK_SKEY | + IB_SR_COMPMASK_SNAME; + } + user.attr_offset = ib_get_attr_offset( sizeof( ib_service_record_t ) ); + user.p_attr = &svc_rec; + + status = osmv_query_sa( p_osmt->h_bind, &req ); + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_register_service_with_full_key: ERR 4A03: " + "ib_query failed (%s)\n", ib_get_err_str( status ) ); + goto Exit; + } + + status = context.result.status; + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_register_service_with_full_key: ERR 4A04: " + "ib_query failed (%s)\n", ib_get_err_str( status ) ); + + if( status == IB_REMOTE_ERROR ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_register_service_with_full_key: " + "Remote error = %s\n", + ib_get_mad_status_str( osm_madw_get_mad_ptr + ( context.result. + p_result_madw ) ) ); + } + goto Exit; + } + + /* Check service key on context to see if match */ + p_rec = osmv_get_query_svc_rec( context.result.p_result_madw, 0 ); + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "Comparing service key...\n" + "return key is:\n"); + for (i = 0; i <= 15; i++) + { + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "service_key sent[%u] = %u, service_key returned[%u] = %u\n", + i,service_key[i],i,p_rec->service_key[i]); + } + /* since c15-0.1.14 not supported all key association queries should bring in return zero in service key */ + if (memcmp(skey,p_rec->service_key, 16*sizeof(uint8_t)) != 0) + { + status = IB_REMOTE_ERROR; + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_register_service_with_full_key: ERR 4A33: " + "Data mismatch in service_key\n" + ); + goto Exit; + } + + Exit: + if( context.result.p_result_madw != NULL ) + { + osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw ); + context.result.p_result_madw = NULL; + } + + OSM_LOG_EXIT( &p_osmt->log ); + return status; +} + +/********************************************************************** + **********************************************************************/ + +ib_api_status_t +osmt_register_service_with_data( IN osmtest_t * const p_osmt, + IN ib_net64_t service_id, + IN ib_net16_t service_pkey, + IN ib_net32_t service_lease, + IN uint8_t service_key_lsb, + IN uint8_t *service_data8, + IN ib_net16_t *service_data16, + IN ib_net32_t *service_data32, + IN ib_net64_t *service_data64, + IN char *service_name) { + osmv_query_req_t req; + osmv_user_query_t user; + osmtest_req_context_t context; + ib_service_record_t svc_rec,*p_rec; + osm_log_t *p_log = &p_osmt->log; + ib_api_status_t status; + /* ib_service_record_t* p_rec; */ + + OSM_LOG_ENTER( p_log, osmt_register_service_with_data ); + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_register_service_with_data: " + "Registering service: name: %s id: 0x%" PRIx64 "\n", + service_name, cl_ntoh64(service_id)); + + memset( &req, 0, sizeof( req ) ); + memset( &context, 0, sizeof( context ) ); + memset( &user, 0, sizeof( user ) ); + memset( &svc_rec, 0, sizeof( svc_rec ) ); + + /* set the new service record fields */ + svc_rec.service_id = service_id; + svc_rec.service_pkey = service_pkey; + svc_rec.service_gid.unicast.prefix = 0; + svc_rec.service_gid.unicast.interface_id = p_osmt->local_port.port_guid; + svc_rec.service_lease = service_lease; + memset(&svc_rec.service_key, 0, 16*sizeof(uint8_t)); + svc_rec.service_key[0] = service_key_lsb; + + /* Copy data to service_data arrays */ + memcpy(svc_rec.service_data8, service_data8, 16*sizeof(uint8_t)); + memcpy(svc_rec.service_data16, service_data16, 8*sizeof(ib_net16_t)); + memcpy(svc_rec.service_data32, service_data32, 4*sizeof(ib_net32_t)); + memcpy(svc_rec.service_data64, service_data64, 2*sizeof(ib_net64_t)); + + memset(svc_rec.service_name, 0, sizeof(svc_rec.service_name)); + memcpy(svc_rec.service_name, service_name, + (strlen(service_name)+1)*sizeof(char)); + + /* prepare the data used for this query */ + /* sa_mad_data.method = IB_MAD_METHOD_SET; */ + /* sa_mad_data.sm_key = 0; */ + + context.p_osmt = p_osmt; + req.query_context = &context; + req.query_type = OSMV_QUERY_USER_DEFINED; + req.pfn_query_cb = osmtest_query_res_cb; + req.p_query_input = &user; + req.flags = OSM_SA_FLAGS_SYNC; + req.sm_key = 0; + req.timeout_ms = p_osmt->opt.transaction_timeout; + + user.method = IB_MAD_METHOD_SET; + user.attr_id = IB_MAD_ATTR_SERVICE_RECORD; + if (ib_pkey_is_invalid(service_pkey)) + { + /* if given an invalid service_pkey - don't turn the PKEY compmask on */ + user.comp_mask = IB_SR_COMPMASK_SID | + IB_SR_COMPMASK_SGID | + IB_SR_COMPMASK_SLEASE | + IB_SR_COMPMASK_SKEY | + IB_SR_COMPMASK_SNAME | + IB_SR_COMPMASK_SDATA8_0 | + IB_SR_COMPMASK_SDATA8_1 | + IB_SR_COMPMASK_SDATA16_0 | + IB_SR_COMPMASK_SDATA16_1 | + IB_SR_COMPMASK_SDATA32_0 | + IB_SR_COMPMASK_SDATA32_1 | + IB_SR_COMPMASK_SDATA64_0 | + IB_SR_COMPMASK_SDATA64_1; + } + else + { + user.comp_mask = IB_SR_COMPMASK_SID | + IB_SR_COMPMASK_SGID | + IB_SR_COMPMASK_SPKEY | + IB_SR_COMPMASK_SLEASE | + IB_SR_COMPMASK_SKEY | + IB_SR_COMPMASK_SNAME| + IB_SR_COMPMASK_SDATA8_0 | + IB_SR_COMPMASK_SDATA8_1 | + IB_SR_COMPMASK_SDATA16_0 | + IB_SR_COMPMASK_SDATA16_1 | + IB_SR_COMPMASK_SDATA32_0 | + IB_SR_COMPMASK_SDATA32_1 | + IB_SR_COMPMASK_SDATA64_0 | + IB_SR_COMPMASK_SDATA64_1; + } + user.attr_offset = ib_get_attr_offset( sizeof( ib_service_record_t ) ); + user.p_attr = &svc_rec; + + /* Dump to Service Data b4 send */ + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_register_service_with_data:" + "Dumping service data b4 send\n"); + osm_dump_service_record(&p_osmt->log,&svc_rec,OSM_LOG_VERBOSE); + + status = osmv_query_sa( p_osmt->h_bind, &req ); + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_register_service_with_data: ERR 4A05: " + "ib_query failed (%s)\n", ib_get_err_str( status ) ); + goto Exit; + } + + status = context.result.status; + + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_register_service_with_data: ERR 4A06: " + "ib_query failed (%s)\n", ib_get_err_str( status ) ); + + if( status == IB_REMOTE_ERROR ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_register_service_with_data: " + "Remote error = %s\n", + ib_get_mad_status_str( osm_madw_get_mad_ptr + ( context.result. + p_result_madw ) ) ); + } + goto Exit; + } + + /* Check data on context to see if match */ + p_rec = osmv_get_query_svc_rec( context.result.p_result_madw, 0 ); + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "Comparing service data...\n"); + if (memcmp(service_data8, p_rec->service_data8,16*sizeof(uint8_t)) != 0 || + memcmp(service_data16, p_rec->service_data16,8*sizeof(uint16_t)) != 0 || + memcmp(service_data32, p_rec->service_data32,4*sizeof(uint32_t)) != 0 || + memcmp(service_data64, p_rec->service_data64,2*sizeof(uint64_t)) != 0 + ) + { + status = IB_REMOTE_ERROR; + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_register_service_with_data: " + "Data mismatch in service_data8\n" + ); + goto Exit; + } + + Exit: + if( context.result.p_result_madw != NULL ) + { + osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw ); + context.result.p_result_madw = NULL; + } + + OSM_LOG_EXIT( &p_osmt->log ); + return status; +} + +/********************************************************************** + **********************************************************************/ + +ib_api_status_t +osmt_get_service_by_id_and_name ( IN osmtest_t * const p_osmt, + IN uint32_t rec_num, + IN ib_net64_t sid, + IN char *sr_name, + OUT ib_service_record_t *p_out_rec) { + + ib_api_status_t status = IB_SUCCESS; + osmtest_req_context_t context; + osmv_query_req_t req; + ib_service_record_t svc_rec,*p_rec; + uint32_t num_recs = 0; + osmv_user_query_t user; + + OSM_LOG_ENTER( &p_osmt->log, osmt_get_service_by_id ); + + if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) ) + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_get_service_by_id_and_name: " + "Getting service record: id: 0x%016" PRIx64 " and name: %s\n", + cl_ntoh64(sid),sr_name); + + /* + * Do a blocking query for this record in the subnet. + * The result is returned in the result field of the caller's + * context structure. + * + * The query structures are locals. + */ + memset( &req, 0, sizeof( req ) ); + memset( &context, 0, sizeof( context ) ); + + context.p_osmt = p_osmt; + + /* prepare the data used for this query */ + req.query_type = OSMV_QUERY_USER_DEFINED; + req.timeout_ms = p_osmt->opt.transaction_timeout; + req.retry_cnt = p_osmt->opt.retry_count; + req.flags = OSM_SA_FLAGS_SYNC; + req.query_context = &context; + req.pfn_query_cb = osmtest_query_res_cb; + req.sm_key = 0; + + memset( &svc_rec, 0, sizeof( svc_rec ) ); + memset( &user, 0, sizeof( user ) ); + /* set the new service record fields */ + memset(svc_rec.service_name, 0, sizeof(svc_rec.service_name)); + memcpy(svc_rec.service_name, sr_name, + (strlen(sr_name)+1)*sizeof(char)); + svc_rec.service_id = sid; + req.p_query_input = &user; + + user.method = IB_MAD_METHOD_GET; + user.attr_id = IB_MAD_ATTR_SERVICE_RECORD; + user.comp_mask = IB_SR_COMPMASK_SID | IB_SR_COMPMASK_SNAME; + user.attr_offset = ib_get_attr_offset( sizeof( ib_service_record_t ) ); + user.p_attr = &svc_rec; + + status = osmv_query_sa( p_osmt->h_bind, &req ); + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_get_service_by_id_and_name: ERR 4A07: " + "ib_query failed (%s)\n", ib_get_err_str( status ) ); + goto Exit; + } + + status = context.result.status; + num_recs = context.result.result_cnt; + + if( status != IB_SUCCESS ) + { + char mad_stat_err[256]; + + /* If the failure is due to IB_SA_MAD_STATUS_NO_RECORDS and rec_num is 0, + then this is fine */ + if( status == IB_REMOTE_ERROR ) + strcpy(mad_stat_err, ib_get_mad_status_str( + osm_madw_get_mad_ptr(context.result.p_result_madw) ) ); + else + strcpy(mad_stat_err, ib_get_err_str(status) ); + if( status == IB_REMOTE_ERROR && + !strcmp(mad_stat_err, "IB_SA_MAD_STATUS_NO_RECORDS") && + rec_num == 0 ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_get_service_by_id_and_name: " + "IS EXPECTED ERROR ^^^^\n"); + status = IB_SUCCESS; + } + else + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_get_service_by_id_and_name: ERR 4A08: " + "Query failed: %s (%s)\n", + ib_get_err_str(status), + mad_stat_err ); + goto Exit; + } + } + + if ( rec_num && num_recs != rec_num ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_get_service_by_id_and_name: " + "Unmatched number of records: expected: %d, received: %d\n", + rec_num, num_recs); + status = IB_REMOTE_ERROR; + goto Exit; + } + + p_rec = osmv_get_query_svc_rec( context.result.p_result_madw, 0 ); + *p_out_rec = *p_rec; + + if (num_recs) + { + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_get_service_by_id_and_name: " + "Found service record: name: %s id: 0x%016" PRIx64 "\n", + p_rec->service_name, cl_ntoh64(p_rec->service_id)); + + osm_dump_service_record(&p_osmt->log, p_rec, OSM_LOG_DEBUG); + } + + Exit: + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_get_service_by_id_and_name: " + "Expected and found %d records\n", + rec_num ); + + if( context.result.p_result_madw != NULL ) + { + osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw ); + context.result.p_result_madw = NULL; + } + + OSM_LOG_EXIT( &p_osmt->log ); + return status; +} + +/********************************************************************** + **********************************************************************/ + +ib_api_status_t +osmt_get_service_by_id ( IN osmtest_t * const p_osmt, + IN uint32_t rec_num, + IN ib_net64_t sid, + OUT ib_service_record_t *p_out_rec) { + + ib_api_status_t status = IB_SUCCESS; + osmtest_req_context_t context; + osmv_query_req_t req; + ib_service_record_t svc_rec,*p_rec; + uint32_t num_recs = 0; + osmv_user_query_t user; + + OSM_LOG_ENTER( &p_osmt->log, osmt_get_service_by_id ); + + if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) ) + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_get_service_by_id: " + "Getting service record: id: 0x%016" PRIx64 "\n", + cl_ntoh64(sid)); + + /* + * Do a blocking query for this record in the subnet. + * The result is returned in the result field of the caller's + * context structure. + * + * The query structures are locals. + */ + memset( &req, 0, sizeof( req ) ); + memset( &context, 0, sizeof( context ) ); + + context.p_osmt = p_osmt; + + /* prepare the data used for this query */ + req.query_type = OSMV_QUERY_USER_DEFINED; + req.timeout_ms = p_osmt->opt.transaction_timeout; + req.retry_cnt = p_osmt->opt.retry_count; + req.flags = OSM_SA_FLAGS_SYNC; + req.query_context = &context; + req.pfn_query_cb = osmtest_query_res_cb; + req.sm_key = 0; + + memset( &svc_rec, 0, sizeof( svc_rec ) ); + memset( &user, 0, sizeof( user ) ); + /* set the new service record fields */ + svc_rec.service_id = sid; + req.p_query_input = &user; + + user.method = IB_MAD_METHOD_GET; + user.attr_id = IB_MAD_ATTR_SERVICE_RECORD; + user.comp_mask = IB_SR_COMPMASK_SID; + user.attr_offset = ib_get_attr_offset( sizeof( ib_service_record_t ) ); + user.p_attr = &svc_rec; + + status = osmv_query_sa( p_osmt->h_bind, &req ); + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_get_service_by_id: ERR 4A09: " + "ib_query failed (%s)\n", ib_get_err_str( status ) ); + goto Exit; + } + + status = context.result.status; + num_recs = context.result.result_cnt; + + if( status != IB_SUCCESS ) + { + char mad_stat_err[256]; + + /* If the failure is due to IB_SA_MAD_STATUS_NO_RECORDS and rec_num is 0, + then this is fine */ + if( status == IB_REMOTE_ERROR ) + strcpy(mad_stat_err, ib_get_mad_status_str( + osm_madw_get_mad_ptr(context.result.p_result_madw) ) ); + else + strcpy(mad_stat_err, ib_get_err_str(status) ); + + if( status == IB_REMOTE_ERROR && + !strcmp(mad_stat_err, "IB_SA_MAD_STATUS_NO_RECORDS") && + rec_num == 0 ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_get_service_by_id: " + "IS EXPECTED ERROR ^^^^\n"); + status = IB_SUCCESS; + } + else + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_get_service_by_id: ERR 4A0A: " + "Query failed: %s (%s)\n", + ib_get_err_str(status), + mad_stat_err ); + goto Exit; + } + } + + if ( rec_num && num_recs != rec_num ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_get_service_by_id: ERR 4A0B: " + "Unmatched number of records: expected: %d received: %d\n", + rec_num, num_recs); + status = IB_REMOTE_ERROR; + goto Exit; + } + + p_rec = osmv_get_query_svc_rec( context.result.p_result_madw, 0 ); + *p_out_rec = *p_rec; + + if (num_recs) + { + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_get_service_by_id: " + "Found service record: name: %s id: 0x%016" PRIx64 "\n", + p_rec->service_name, cl_ntoh64(p_rec->service_id)); + + osm_dump_service_record(&p_osmt->log, p_rec, OSM_LOG_DEBUG); + } + + Exit: + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_get_service_by_id: " + "Expected and found %d records\n", + rec_num ); + + if( context.result.p_result_madw != NULL ) + { + osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw ); + context.result.p_result_madw = NULL; + } + + OSM_LOG_EXIT( &p_osmt->log ); + return status; +} + +/********************************************************************** + **********************************************************************/ + +ib_api_status_t +osmt_get_service_by_name_and_key ( IN osmtest_t * const p_osmt, + IN char * sr_name, + IN uint32_t rec_num, + IN uint8_t *skey, + OUT ib_service_record_t *p_out_rec) { + + ib_api_status_t status = IB_SUCCESS; + osmtest_req_context_t context; + osmv_query_req_t req; + ib_service_record_t svc_rec,*p_rec; + uint32_t num_recs = 0, i; + osmv_user_query_t user; + + OSM_LOG_ENTER( &p_osmt->log, osmt_get_service_by_name_and_key ); + + if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) ) + { + char buf_service_key[33]; + + sprintf(buf_service_key, + "0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + skey[0], skey[1], skey[2], skey[3], skey[4], skey[5], skey[6], skey[7], + skey[8], skey[9], skey[10], skey[11], skey[12], skey[13], skey[14], + skey[15]); + + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_get_service_by_name_and_key: " + "Getting service record: name: %s and key: %s\n", + sr_name, buf_service_key ); + } + + /* + * Do a blocking query for this record in the subnet. + * The result is returned in the result field of the caller's + * context structure. + * + * The query structures are locals. + */ + memset( &req, 0, sizeof( req ) ); + memset( &context, 0, sizeof( context ) ); + + context.p_osmt = p_osmt; + + /* prepare the data used for this query */ + req.query_type = OSMV_QUERY_USER_DEFINED; + req.timeout_ms = p_osmt->opt.transaction_timeout; + req.retry_cnt = p_osmt->opt.retry_count; + req.flags = OSM_SA_FLAGS_SYNC; + req.query_context = &context; + req.pfn_query_cb = osmtest_query_res_cb; + req.sm_key = 0; + + memset( &svc_rec, 0, sizeof( svc_rec ) ); + memset( &user, 0, sizeof( user ) ); + /* set the new service record fields */ + memset(svc_rec.service_name, 0, sizeof(svc_rec.service_name)); + memcpy(svc_rec.service_name, sr_name, + (strlen(sr_name)+1)*sizeof(char)); + for (i = 0; i <= 15; i++) + svc_rec.service_key[i] = skey[i]; + + req.p_query_input = &user; + + user.method = IB_MAD_METHOD_GET; + user.attr_id = IB_MAD_ATTR_SERVICE_RECORD; + user.comp_mask = IB_SR_COMPMASK_SNAME | IB_SR_COMPMASK_SKEY; + user.attr_offset = ib_get_attr_offset( sizeof( ib_service_record_t ) ); + user.p_attr = &svc_rec; + status = osmv_query_sa( p_osmt->h_bind, &req ); + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_get_service_by_name_and_key: ERR 4A0C: " + "ib_query failed (%s)\n", ib_get_err_str( status ) ); + goto Exit; + } + + status = context.result.status; + num_recs = context.result.result_cnt; + + if( status != IB_SUCCESS ) + { + char mad_stat_err[256]; + + /* If the failure is due to IB_SA_MAD_STATUS_NO_RECORDS and rec_num is 0, + then this is fine */ + if( status == IB_REMOTE_ERROR ) + strcpy(mad_stat_err, ib_get_mad_status_str( + osm_madw_get_mad_ptr(context.result.p_result_madw) ) ); + else + strcpy(mad_stat_err, ib_get_err_str(status) ); + + if( status == IB_REMOTE_ERROR && + !strcmp(mad_stat_err, "IB_SA_MAD_STATUS_NO_RECORDS") && + rec_num == 0 ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_get_service_by_name_and_key: " + "IS EXPECTED ERROR ^^^^\n"); + status = IB_SUCCESS; + } + else + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_get_service_by_name_and_key: ERR 4A0D: " + "Query failed:%s (%s)\n", + ib_get_err_str(status), + mad_stat_err ); + goto Exit; + } + } + + if ( rec_num && num_recs != rec_num ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_get_service_by_name_and_key: " + "Unmatched number of records: expected: %d, received: %d\n", + rec_num, num_recs); + status = IB_REMOTE_ERROR; + goto Exit; + } + + p_rec = osmv_get_query_svc_rec( context.result.p_result_madw, 0 ); + *p_out_rec = *p_rec; + + if ( num_recs ) + { + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_get_service_by_name_and_key: " + "Found service record: name: %s id: 0x%016" PRIx64 "\n", + sr_name, cl_ntoh64(p_rec->service_id)); + + osm_dump_service_record(&p_osmt->log, p_rec, OSM_LOG_DEBUG); + } + + Exit: + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_get_service_by_name_and_key: " + "Expected and found %d records\n", + rec_num ); + + if( context.result.p_result_madw != NULL ) + { + osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw ); + context.result.p_result_madw = NULL; + } + + OSM_LOG_EXIT( &p_osmt->log ); + return status; +} + +/********************************************************************** + **********************************************************************/ + +ib_api_status_t +osmt_get_service_by_name( IN osmtest_t * const p_osmt, + IN char * sr_name, + IN uint32_t rec_num, + OUT ib_service_record_t *p_out_rec) { + + ib_api_status_t status = IB_SUCCESS; + osmtest_req_context_t context; + osmv_query_req_t req; + ib_service_record_t* p_rec; + ib_svc_name_t service_name; + uint32_t num_recs = 0; + + OSM_LOG_ENTER( &p_osmt->log, osmt_get_service_by_name ); + + if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) ) + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_get_service_by_name: " + "Getting service record: name: %s\n", + sr_name); + + /* + * Do a blocking query for this record in the subnet. + * The result is returned in the result field of the caller's + * context structure. + * + * The query structures are locals. + */ + memset( &req, 0, sizeof( req ) ); + memset( &context, 0, sizeof( context ) ); + + context.p_osmt = p_osmt; + + /* prepare the data used for this query */ + req.query_type = OSMV_QUERY_SVC_REC_BY_NAME; + req.timeout_ms = p_osmt->opt.transaction_timeout; + req.retry_cnt = p_osmt->opt.retry_count; + req.flags = OSM_SA_FLAGS_SYNC; + req.query_context = &context; + req.pfn_query_cb = osmtest_query_res_cb; + req.sm_key = 0; + + memset(service_name, 0, sizeof(service_name)); + memcpy(service_name, sr_name, (strlen(sr_name)+1)*sizeof(char)); + req.p_query_input = service_name; + + status = osmv_query_sa( p_osmt->h_bind, &req ); + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_get_service_by_name: ERR 4A0E: " + "ib_query failed (%s)\n", ib_get_err_str( status ) ); + goto Exit; + } + + status = context.result.status; + num_recs = context.result.result_cnt; + + if( status != IB_SUCCESS ) + { + char mad_stat_err[256]; + + /* If the failure is due to IB_SA_MAD_STATUS_NO_RECORDS and rec_num is 0, + then this is fine */ + if( status == IB_REMOTE_ERROR ) + strcpy(mad_stat_err, ib_get_mad_status_str( + osm_madw_get_mad_ptr(context.result.p_result_madw) ) ); + else + strcpy(mad_stat_err, ib_get_err_str(status) ); + + if( status == IB_REMOTE_ERROR && + !strcmp(mad_stat_err, "IB_SA_MAD_STATUS_NO_RECORDS") && + rec_num == 0 ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_get_service_by_name: " + "IS EXPECTED ERROR ^^^^\n"); + status = IB_SUCCESS; + } + else + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_get_service_by_name: ERR 4A0F: " + "Query failed: %s (%s)\n", + ib_get_err_str(status), + mad_stat_err ); + goto Exit; + } + } + + if ( rec_num && num_recs != rec_num ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_get_service_by_name: ERR 4A10: " + "Unmatched number of records: expected: %d, received: %d\n", + rec_num, num_recs); + status = IB_REMOTE_ERROR; + goto Exit; + } + + p_rec = osmv_get_query_svc_rec( context.result.p_result_madw, 0 ); + *p_out_rec = *p_rec; + + if (num_recs) + { + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_get_service_by_name: " + "Found service record: name: %s id: 0x%016" PRIx64 "\n", + sr_name, cl_ntoh64(p_rec->service_id)); + + osm_dump_service_record(&p_osmt->log, p_rec, OSM_LOG_DEBUG); + } + + Exit: + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_get_service_by_name: " + "Expected and found %d records\n", + rec_num ); + + if( context.result.p_result_madw != NULL ) + { + osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw ); + context.result.p_result_madw = NULL; + } + + OSM_LOG_EXIT( &p_osmt->log ); + return status; +} + +/********************************************************************** + **********************************************************************/ + +#ifdef VENDOR_RMPP_SUPPORT +ib_api_status_t +osmt_get_all_services_and_check_names( IN osmtest_t * const p_osmt, + IN ib_svc_name_t * const p_valid_service_names_arr, + IN uint8_t num_of_valid_names, + OUT uint32_t *num_services) { + ib_api_status_t status = IB_SUCCESS; + osmtest_req_context_t context; + osmv_query_req_t req; + ib_service_record_t* p_rec; + uint32_t num_recs = 0,i,j; + uint8_t *p_checked_names; + + OSM_LOG_ENTER(&p_osmt->log, osmt_get_all_services_and_check_names ); + + /* Prepare tracker for the checked names */ + p_checked_names = (uint8_t*)malloc(sizeof(uint8_t)*num_of_valid_names); + for (j = 0 ; j < num_of_valid_names ; j++) + { + p_checked_names[j] = 0; + } + + if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) ) + { + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_get_all_services_and_check_names: " + "Getting all service records\n"); + } + /* + * Do a blocking query for this record in the subnet. + * The result is returned in the result field of the caller's + * context structure. + * + * The query structures are locals. + */ + memset( &req, 0, sizeof( req ) ); + memset( &context, 0, sizeof( context ) ); + + context.p_osmt = p_osmt; + + req.query_type = OSMV_QUERY_ALL_SVC_RECS; + req.timeout_ms = p_osmt->opt.transaction_timeout; + req.retry_cnt = p_osmt->opt.retry_count; + req.flags = OSM_SA_FLAGS_SYNC; + req.query_context = &context; + req.pfn_query_cb = osmtest_query_res_cb; + req.sm_key = 0; + + status = osmv_query_sa( p_osmt->h_bind, &req ); + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_get_all_services_and_check_names: ERR 4A12: " + "ib_query failed (%s)\n", ib_get_err_str( status ) ); + goto Exit; + } + + status = context.result.status; + + if( status != IB_SUCCESS ) + { + if (status != IB_INVALID_PARAMETER) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_get_all_services_and_check_names: ERR 4A13: " + "ib_query failed (%s)\n", ib_get_err_str( status ) ); + } + if( status == IB_REMOTE_ERROR ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_get_all_services_and_check_names: " + "Remote error = %s\n", + ib_get_mad_status_str( osm_madw_get_mad_ptr + ( context.result. + p_result_madw ) ) ); + } + goto Exit; + } + + num_recs = context.result.result_cnt; + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_get_all_services_and_check_names: " + "Received %u records\n", num_recs ); + + for( i = 0; i < num_recs; i++ ) + { + p_rec = osmv_get_query_svc_rec( context.result.p_result_madw, i ); + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_get_all_services_and_check_names: " + "Found service record: name: %s id: 0x%016" PRIx64 "\n", + p_rec->service_name, cl_ntoh64(p_rec->service_id)); + osm_dump_service_record(&p_osmt->log, p_rec, OSM_LOG_VERBOSE); + for ( j = 0; j < num_of_valid_names; j++) + { + /* If the service names exist in the record, mark it as checked (1) */ + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_get_all_services_and_check_names: " + "-I- Comparing source name : >%s<, with record name : >%s<, idx : %d\n", + p_valid_service_names_arr[j], p_rec->service_name, p_checked_names[j]); + if ( strcmp((char *)p_valid_service_names_arr[j], + (char *)p_rec->service_name) == 0 ) + { + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_get_all_services_and_check_names: " + "-I- The service %s is valid\n", p_valid_service_names_arr[j]); + p_checked_names[j] = 1; + break; + } + } + } + /* Check that all service names have been identified */ + for ( j = 0; j < num_of_valid_names; j++) + if (p_checked_names[j] == 0) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_get_all_services_and_check_names: ERR 4A14: " + "Missing valid service: name: %s\n", p_valid_service_names_arr[j]); + status = IB_ERROR; + goto Exit; + } + *num_services = num_recs; + + Exit: + if( context.result.p_result_madw != NULL ) + { + osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw ); + context.result.p_result_madw = NULL; + } + + OSM_LOG_EXIT( &p_osmt->log ); + return status; +} +#endif + +/********************************************************************** + **********************************************************************/ + +ib_api_status_t +osmt_delete_service_by_name(IN osmtest_t * const p_osmt, + IN uint8_t IsServiceExist, + IN char * sr_name, IN uint32_t rec_num) { + osmv_query_req_t req; + osmv_user_query_t user; + osmtest_req_context_t context; + ib_service_record_t svc_rec; + ib_api_status_t status; + + OSM_LOG_ENTER( &p_osmt->log, osmt_delete_service_by_name); + + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_delete_service_by_name: " + "Trying to Delete service name: %s\n", + sr_name); + + memset( &svc_rec, 0, sizeof( svc_rec ) ); + + status = osmt_get_service_by_name(p_osmt, sr_name,rec_num, &svc_rec); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_delete_service_by_name: ERR 4A15: " + "Failed to get service: name: %s\n", + sr_name ); + goto ExitNoDel; + } + + memset( &req, 0, sizeof( req ) ); + memset( &context, 0, sizeof( context ) ); + memset( &user, 0, sizeof( user ) ); + + /* set the new service record fields */ + memset(svc_rec.service_name, 0, sizeof(svc_rec.service_name)); + memcpy(svc_rec.service_name, sr_name, + (strlen(sr_name)+1)*sizeof(char)); + + /* prepare the data used for this query */ + context.p_osmt = p_osmt; + req.timeout_ms = p_osmt->opt.transaction_timeout; + req.query_context = &context; + req.query_type = OSMV_QUERY_USER_DEFINED; /* basically a don't care here */ + req.pfn_query_cb = osmtest_query_res_cb; + req.p_query_input = &user; + req.flags = OSM_SA_FLAGS_SYNC; + req.sm_key = 0; + + user.method = IB_MAD_METHOD_DELETE; + user.attr_id = IB_MAD_ATTR_SERVICE_RECORD; + user.comp_mask = IB_SR_COMPMASK_SNAME; + user.attr_offset = ib_get_attr_offset( sizeof( ib_service_record_t ) ); + user.p_attr = &svc_rec; + + status = osmv_query_sa( p_osmt->h_bind, &req ); + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_delete_service_by_name: ERR 4A16: " + "ib_query failed (%s)\n", ib_get_err_str( status ) ); + goto Exit; + } + + status = context.result.status; + if ( IsServiceExist ) + { + /* If IsServiceExist = 1 then we should succeed here */ + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_delete_service_by_name: ERR 4A17: " + "ib_query failed (%s)\n", ib_get_err_str( status ) ); + + if( status == IB_REMOTE_ERROR ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_delete_service_by_name: ERR 4A18: " + "Remote error = %s\n", + ib_get_mad_status_str( osm_madw_get_mad_ptr + ( context.result. + p_result_madw ) ) ); + } + } + } + else + { + /* If IsServiceExist = 0 then we should fail here */ + if ( status == IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_delete_service_by_name: ERR 4A19: " + "Succeeded to delete service: %s which " + "shouldn't exist", + sr_name ); + status = IB_ERROR; + } + else + { + /* The deletion should have failed, since the service_name + shouldn't exist. */ + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_service_records_flow: " + "IS EXPECTED ERROR ^^^^\n"); + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmt_delete_service_by_name: " + "Failed to delete service_name: %s\n", + sr_name ); + status = IB_SUCCESS; + } + } + + Exit: + if( context.result.p_result_madw != NULL ) + { + osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw ); + context.result.p_result_madw = NULL; + } + + ExitNoDel: + OSM_LOG_EXIT( &p_osmt->log ); + return status; +} + +/********************************************************************** + **********************************************************************/ + +/* + * Run a complete service records flow: + * - register a service + * - register a service (with a lease period) + * - get a service by name + * - get all services / must be 2 + * - delete a service + * - get all services / must be 1 + * - wait for the lease to expire + * - get all services / must be 0 + * - get / set service by data + */ +ib_api_status_t +osmt_run_service_records_flow( IN osmtest_t * const p_osmt ) { + ib_service_record_t srv_rec; + ib_api_status_t status; + uint8_t instance,i; + uint8_t service_data8[16],service_key[16]; + ib_net16_t service_data16[8]; + ib_net32_t service_data32[4]; + ib_net64_t service_data64[2]; + uint64_t pid = getpid(); + uint64_t id[7]; + /* We use up to seven service names - we use the extra for bad flow*/ + ib_svc_name_t service_name[7]; +#ifdef VENDOR_RMPP_SUPPORT + /* This array contain only the valid names after registering vs SM */ + ib_svc_name_t service_valid_names[3]; + uint32_t num_recs = 0; +#endif + + OSM_LOG_ENTER( &p_osmt->log, osmt_run_service_records_flow); + + /* Init Service names */ + for (i = 0; i <= 6; i++) { +#ifdef __WIN__ + uint64_t rand_val = rand()-(uint64_t)i; +#else + uint64_t rand_val = random()-(uint64_t)i; +#endif + id[i] = abs((int)(pid - rand_val)); + /* Just to be unique any place on any host */ + sprintf((char*)(service_name[i]), + "osmt.srvc.%" PRIu64 ".%" PRIu64, rand_val,pid); + /*printf("-I- Service Name is : %s, ID is : 0x%" PRIx64 "\n",service_name[i],id[i]);*/ + } + status = osmt_register_service( + p_osmt, + cl_ntoh64(id[0]), /* IN ib_net64_t service_id, */ + IB_DEFAULT_PKEY,/* IN ib_net16_t service_pkey, */ + 0xFFFFFFFF, /* IN ib_net32_t service_lease, */ + 11, /* IN uint8_t service_key_lsb, */ + (char*)service_name[0] /* IN char *service_name */ + ); + if (status != IB_SUCCESS) + { + goto Exit; + } + + status = osmt_register_service( + p_osmt, + cl_ntoh64(id[1]), /* IN ib_net64_t service_id, */ + IB_DEFAULT_PKEY,/* IN ib_net16_t service_pkey, */ + cl_hton32(0x00000004), /* IN ib_net32_t service_lease, */ + 11, /* IN uint8_t service_key_lsb, */ + (char*)service_name[1] /* IN char *service_name */ + ); + if (status != IB_SUCCESS) + { + goto Exit; + } + + status = osmt_register_service( + p_osmt, + cl_ntoh64(id[2]), /* IN ib_net64_t service_id, */ + 0, /* IN ib_net16_t service_pkey, */ + 0xFFFFFFFF, /* IN ib_net32_t service_lease, */ + 11, /* Remove Service Record IN uint8_t service_key_lsb, */ + (char*)service_name[2] /* IN char *service_name */ + ); + + if (status != IB_SUCCESS) + { + goto Exit; + } + + /* Generate 2 instances of service record with consecutive data */ + for (instance = 0 ; instance < 2 ; instance++) { + /* First, clear all arrays */ + memset (service_data8, 0, 16*sizeof(uint8_t)); + memset (service_data16, 0, 8*sizeof(uint16_t)); + memset (service_data32, 0, 4*sizeof(uint32_t)); + memset (service_data64, 0, 2*sizeof(uint64_t)); + service_data8[instance] = instance+1; + service_data16[instance] = cl_hton16(instance+2); + service_data32[instance] = cl_hton32(instance+3); + service_data64[instance] = cl_hton64(instance+4); + status = osmt_register_service_with_data( + p_osmt, + cl_ntoh64(id[3]), /* IN ib_net64_t service_id, */ + IB_DEFAULT_PKEY, /* IN ib_net16_t service_pkey, */ + cl_ntoh32(10), /* IN ib_net32_t service_lease, */ + 12, /* IN uint8_t service_key_lsb, */ + service_data8,service_data16,service_data32,service_data64, /* service data structures */ + (char*)service_name[3] /* IN char *service_name */ + ); + + if (status != IB_SUCCESS) + { + goto Exit; + } + + } + + /* Trying to create service with zero key */ + memset (service_key, 0, 16*sizeof(uint8_t)); + status = osmt_register_service_with_full_key( + p_osmt, + cl_ntoh64(id[5]), /* IN ib_net64_t service_id, */ + 0, /* IN ib_net16_t service_pkey, */ + 0xFFFFFFFF, /* IN ib_net32_t service_lease, */ + service_key, /* full service_key, */ + (char*)service_name[5] /* IN char *service_name */ + ); + + if (status != IB_SUCCESS) + { + goto Exit; + } + + /* Now update it with Unique key and different service name */ + for (i = 0; i <= 15; i++) { + service_key[i] = i + 1; + } + status = osmt_register_service_with_full_key( + p_osmt, + cl_ntoh64(id[5]), /* IN ib_net64_t service_id, */ + 0, /* IN ib_net16_t service_pkey, */ + 0xFFFFFFFF, /* IN ib_net32_t service_lease, */ + service_key, /* full service_key, */ + (char*)service_name[6] /* IN char *service_name */ + ); + if (status != IB_SUCCESS) + { + goto Exit; + } + + /* Let OpenSM handle it */ + usleep(100); + + /* Make sure service_name[0] exists */ + status = osmt_get_service_by_name(p_osmt, + (char*)service_name[0], 1, &srv_rec); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_service_records_flow: ERR 4A1A: " + "Fail to find service: name: %s\n", + (char*)service_name[0] ); + status = IB_ERROR; + goto Exit; + } + + /* Make sure service_name[1] exists */ + status = osmt_get_service_by_name(p_osmt, + (char*)service_name[1], 1, &srv_rec); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_service_records_flow: ERR 4A1B: " + "Fail to find service: name: %s\n", + (char*)service_name[1] ); + status = IB_ERROR; + goto Exit; + } + + /* Make sure service_name[2] exists */ + status = osmt_get_service_by_name(p_osmt, + (char*)service_name[2], 1, &srv_rec); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_service_records_flow: ERR 4A1C: " + "Fail to find service: name: %s\n", + (char*)service_name[2] ); + status = IB_ERROR; + goto Exit; + } + + /* Make sure service_name[3] exists. */ + /* After 10 seconds the service should not exist: service_lease = 10 */ + status = osmt_get_service_by_name(p_osmt, + (char*)service_name[3], 1, &srv_rec); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_service_records_flow: ERR 4A1D: " + "Fail to find service: name: %s\n", + (char*)service_name[3] ); + status = IB_ERROR; + goto Exit; + } + + sleep(10); + + status = osmt_get_service_by_name(p_osmt, + (char*)service_name[3], 0, &srv_rec); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_service_records_flow: ERR 4A1E: " + "Found service: name: %s that should have been " + "deleted due to service lease expiring\n", + (char*)service_name[3] ); + status = IB_ERROR; + goto Exit; + } + + /* Check that for service: id[5] only one record exists */ + status = osmt_get_service_by_id(p_osmt, 1, cl_ntoh64(id[5]), &srv_rec); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_service_records_flow: ERR 4A1F: " + "Found number of records != 1 for " + "service: id: 0x%016" PRIx64 "\n", + id[5] ); + status = IB_ERROR; + goto Exit; + } + + /* Bad Flow of Get with invalid Service ID: id[7] */ + status = osmt_get_service_by_id(p_osmt, 0, cl_ntoh64(id[7]), &srv_rec); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_service_records_flow: ERR 4A20: " + "Found service: id: 0x%016" PRIx64 " " + "that is invalid\n", + id[7] ); + status = IB_ERROR; + goto Exit; + } + + /* Check by both id and service name: id[0], service_name[0] */ + status = osmt_get_service_by_id_and_name(p_osmt, 1, cl_ntoh64(id[0]), + (char*)service_name[0], &srv_rec); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_service_records_flow: ERR 4A21: " + "Fail to find service: id: 0x%016" PRIx64 " " + "name: %s\n", + id[0], + (char*)service_name[0] ); + status = IB_ERROR; + goto Exit; + } + + /* Check by both id and service name: id[5], service_name[6] */ + status = osmt_get_service_by_id_and_name(p_osmt, 1, cl_ntoh64(id[5]), + (char*)service_name[6], &srv_rec); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_service_records_flow: ERR 4A22: " + "Fail to find service: id: 0x%016" PRIx64 " " + "name: %s\n", + id[5], + (char*)service_name[6] ); + status = IB_ERROR; + goto Exit; + } + + /* Bad Flow of Get with invalid name(service_name[3]) and valid ID(id[0]) */ + status = osmt_get_service_by_id_and_name(p_osmt, 0, cl_ntoh64(id[0]), + (char*)service_name[3], &srv_rec); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_service_records_flow: ERR 4A23: " + "Found service: id: 0x%016" PRIx64 + "name: %s which is an invalid service\n", + id[0], + (char*)service_name[3] ); + status = IB_ERROR; + goto Exit; + } + + /* Bad Flow of Get with unmatched name(service_name[5]) and id(id[3]) (both valid) */ + status = osmt_get_service_by_id_and_name(p_osmt, 0, cl_ntoh64(id[3]), + (char*)service_name[5], &srv_rec); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_service_records_flow: ERR 4A24: " + "Found service: id: 0x%016" PRIx64 + "name: %s which is an invalid service\n", + id[3], + (char*)service_name[5] ); + status = IB_ERROR; + goto Exit; + } + + /* Bad Flow of Get with service name that doesn't exist (service_name[4]) */ + status = osmt_get_service_by_name(p_osmt, + (char*)service_name[4], 0, &srv_rec); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_service_records_flow: ERR 4A25: " + "Found service: name: %s that shouldn't exist\n", + (char*)service_name[4] ); + status = IB_ERROR; + goto Exit; + } + + /* Bad Flow : Check that getting service_name[5] brings no records since another service + has been updated with the same ID (service_name[6] */ + status = osmt_get_service_by_name(p_osmt, + (char*)service_name[5], 0, &srv_rec); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_service_records_flow: ERR 4A26: " + "Found service: name: %s which is an " + "invalid service\n", + (char*)service_name[5] ); + status = IB_ERROR; + goto Exit; + } + + /* Check that getting service_name[6] by name ONLY is valid, + since we do not support key&name association, also trusted queries */ + status = osmt_get_service_by_name(p_osmt, + (char*)service_name[6], 1, &srv_rec); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_service_records_flow: ERR 4A27: " + "Fail to find service: name: %s\n", + (char*)service_name[6] ); + status = IB_ERROR; + goto Exit; + } + + /* Test Service Key */ + memset(service_key, 0, 16*sizeof(uint8_t)); + + /* Check for service_name[5] with service_key=0 - the service shouldn't + exist with this name. */ + status = osmt_get_service_by_name_and_key (p_osmt, + (char*)service_name[5], + 0, service_key,&srv_rec); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_service_records_flow: ERR 4A28: " + "Found service: name: %s key:0 which is an " + "invalid service (wrong name)\n", + (char*)service_name[5] ); + status = IB_ERROR; + goto Exit; + } + + /* Check for service_name[6] with service_key=0 - the service should + exist with different key. */ + status = osmt_get_service_by_name_and_key (p_osmt, + (char*)service_name[6], + 0, service_key,&srv_rec); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_service_records_flow: ERR 4A29: " + "Found service: name: %s key: 0 which is an " + "invalid service (wrong service_key)\n", + (char*)service_name[6] ); + status = IB_ERROR; + goto Exit; + } + + /* check for service_name[6] with the correct service_key */ + for (i = 0; i <= 15; i++) + service_key[i]=i + 1; + status = osmt_get_service_by_name_and_key (p_osmt, + (char*)service_name[6], + 1, service_key, &srv_rec); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_service_records_flow: ERR 4A2A: " + "Fail to find service: name: %s with " + "correct service key\n", + (char*)service_name[6] ); + status = IB_ERROR; + goto Exit; + } + +#ifdef VENDOR_RMPP_SUPPORT + /* These ar the only service_names which are valid */ + memcpy(&service_valid_names[0], &service_name[0], sizeof(uint8_t)*64); + memcpy(&service_valid_names[1], &service_name[2], sizeof(uint8_t)*64); + memcpy(&service_valid_names[2], &service_name[6], sizeof(uint8_t)*64); + + status = osmt_get_all_services_and_check_names(p_osmt,service_valid_names, 3, &num_recs); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_service_records_flow: ERR 4A2B: " + "Fail to find all services that should exist\n" ); + status = IB_ERROR; + goto Exit; + } +#endif + + /* Delete service_name[0] */ + status = osmt_delete_service_by_name(p_osmt, 1, + (char*)service_name[0], 1); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_service_records_flow: ERR 4A2C: " + "Fail to delete service: name: %s\n", + (char*)service_name[0] ); + status = IB_ERROR; + goto Exit; + } + + /* Make sure deletion of service_name[0] succeeded */ + status = osmt_get_service_by_name(p_osmt, + (char*)service_name[0], 0, &srv_rec); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_service_records_flow: ERR 4A2D: " + "Found service: name: %s that was deleted\n", + (char*)service_name[0] ); + status = IB_ERROR; + goto Exit; + } + + /* Make sure service_name[1] doesn't exist (expired service lease) */ + status = osmt_get_service_by_name(p_osmt, + (char*)service_name[1], 0, &srv_rec); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_service_records_flow: ERR 4A2E: " + "Found service: name: %s that should have expired\n", + (char*)service_name[1] ); + status = IB_ERROR; + goto Exit; + } + + /* Make sure service_name[2] exists */ + status = osmt_get_service_by_name(p_osmt, + (char*)service_name[2], 1, &srv_rec); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_service_records_flow: ERR 4A2F: " + "Fail to find service: name: %s\n", + (char*)service_name[2] ); + status = IB_ERROR; + goto Exit; + } + + /* Bad Flow - try to delete non-existent service_name[5] */ + status = osmt_delete_service_by_name(p_osmt, 0, + (char*)service_name[5], 0); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_service_records_flow: ERR 4A30: " + "Succeed to delete non-existent service: name: %s\n", + (char*)service_name[5] ); + status = IB_ERROR; + goto Exit; + } + + /* Delete service_name[2] */ + status = osmt_delete_service_by_name(p_osmt, 1, + (char*)service_name[2], 1); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_service_records_flow: ERR 4A31: " + "Fail to delete service: name: %s\n", + (char*)service_name[2] ); + status = IB_ERROR; + goto Exit; + } + + /* Delete service_name[6] */ + status = osmt_delete_service_by_name(p_osmt, 1, + (char*)service_name[6], 1); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_run_service_records_flow: ERR 4A32: " + "Failed to delete service name: %s\n", + (char*)service_name[6] ); + goto Exit; + } + + Exit: + OSM_LOG_EXIT( &p_osmt->log ); + return status; +} + + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmt_slvl_vl_arb.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmt_slvl_vl_arb.c new file mode 100644 index 00000000..bb8c97ad --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmt_slvl_vl_arb.c @@ -0,0 +1,570 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osmt_slvl_vl_arb.c 571 2007-01-25 12:58:44Z sleybo $ + */ + + +/* + * Abstract: + * Implementation of SLtoVL and VL Arbitration testing flow.. + * Top level is osmt_run_slvl_and_vlarb_records_flow: + * osmt_query_all_ports_vl_arb + * osmt_query_all_ports_slvl_map + * + * Environment: + * Linux User Mode + * + * $Revision: 1.2 $ + */ + +#ifndef __WIN__ +#include +#endif +#include +#include +#include +#include +#include "osmtest.h" + +/********************************************************************** + **********************************************************************/ +static ib_api_status_t +osmtest_write_vl_arb_table( IN osmtest_t * const p_osmt, + IN FILE * fh, + IN const ib_vl_arb_table_record_t * const p_rec ) +{ + int result,i; + cl_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( &p_osmt->log, osmtest_write_vl_arb_table ); + + result = fprintf( fh, + "VL_ARBITRATION_TABLE\n" + "lid 0x%X\n" + "port_num 0x%X\n" + "block 0x%X\n", + cl_ntoh16( p_rec->lid ), + p_rec->port_num, + p_rec->block_num ); + + fprintf( fh, " "); + for (i = 0; i < 32; i++) + fprintf( fh,"| %-2u ", i); + fprintf( fh, "|\nVL: "); + + for (i = 0; i < 32; i++) + fprintf( fh,"|0x%02X",p_rec->vl_arb_tbl.vl_entry[i].vl); + fprintf( fh, "|\nWEIGHT:"); + + for (i = 0; i < 32; i++) + fprintf( fh,"|0x%02X",p_rec->vl_arb_tbl.vl_entry[i].weight); + fprintf( fh,"|\nEND\n\n"); + + /* Exit: */ + OSM_LOG_EXIT( &p_osmt->log ); + return ( status ); +} + +/********************************************************************** + * GET A SINGLE PORT INFO BY NODE LID AND PORT NUMBER + **********************************************************************/ +ib_api_status_t +osmt_query_vl_arb( + IN osmtest_t * const p_osmt, + IN ib_net16_t const lid, + IN uint8_t const port_num, + IN uint8_t const block_num, + IN FILE *fh ) +{ + osmtest_req_context_t context; + ib_api_status_t status = IB_SUCCESS; + osmv_user_query_t user; + osmv_query_req_t req; + ib_vl_arb_table_record_t record, *p_rec; + + OSM_LOG_ENTER( &p_osmt->log, osmt_query_vl_arb ); + + if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) ) + { + osm_log( &p_osmt->log, OSM_LOG_DEBUG, + "osmt_query_vl_arb: " + "Getting VL_Arbitration Table for port with LID 0x%X Num:0x%X\n", + cl_ntoh16( lid ), + port_num ); + } + + /* + * Do a blocking query for this record in the subnet. + * The result is returned in the result field of the caller's + * context structure. + * + * The query structures are locals. + */ + memset( &req, 0, sizeof( req ) ); + memset( &user, 0, sizeof( user ) ); + memset( &context, 0, sizeof( context ) ); + + context.p_osmt = p_osmt; + + record.lid = lid; + record.port_num = port_num; + record.block_num = block_num; + user.p_attr = &record; + + req.query_type = OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK; + req.timeout_ms = p_osmt->opt.transaction_timeout; + req.retry_cnt = p_osmt->opt.retry_count; + req.flags = OSM_SA_FLAGS_SYNC; + req.query_context = &context; + req.pfn_query_cb = osmtest_query_res_cb; + req.p_query_input = &user; + req.sm_key = 0; + + status = osmv_query_sa( p_osmt->h_bind, &req ); + + if ( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_query_vl_arb: ERR 0405: " + "ib_query failed (%s)\n", ib_get_err_str( status ) ); + goto Exit; + } + + status = context.result.status; + + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_query_vl_arb: ERR 0466: " + "ib_query failed (%s)\n", ib_get_err_str( status ) ); + + if( status == IB_REMOTE_ERROR ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_query_vl_arb: " + "Remote error = %s\n", + ib_get_mad_status_str( osm_madw_get_mad_ptr + ( context.result.p_result_madw ) ) ); + } + goto Exit; + } + + /* ok it worked */ + p_rec = osmv_get_query_result( context.result.p_result_madw, 0); + if ( fh ) + { + osmtest_write_vl_arb_table( p_osmt, fh, p_rec ); + } + + Exit: + /* + * Return the IB query MAD to the pool as necessary. + */ + if( context.result.p_result_madw != NULL ) + { + osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw ); + context.result.p_result_madw = NULL; + } + + OSM_LOG_EXIT( &p_osmt->log ); + return ( status ); +} + +static ib_api_status_t +osmt_query_all_ports_vl_arb( IN osmtest_t * const p_osmt, + IN FILE * fh ) +{ + cl_status_t status = CL_SUCCESS; + cl_qmap_t *p_tbl; + port_t *p_src_port; + uint8_t block, anyErr = 0; + + OSM_LOG_ENTER( &p_osmt->log, osmt_query_all_ports_vl_arb ); + + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_query_all_ports_vl_arb: " + "Obtaining ALL Ports VL Arbitration Tables\n"); + + /* + * Go over all ports that exist in the subnet + * get the relevant VLarbs + */ + + p_tbl = &p_osmt->exp_subn.port_key_tbl; + + p_src_port = ( port_t * ) cl_qmap_head( p_tbl ); + + while( p_src_port != ( port_t * ) cl_qmap_end( p_tbl ) ) + { + + /* HACK we use capability_mask to know diff a CA port from switch port */ + if( p_src_port->rec.port_info.capability_mask ) + { + /* this is an hca port */ + for (block = 1; block <= 4; block++) + { + /* NOTE to comply we must set port number to 0 and the SA should figure it out */ + /* since it is a CA port */ + status = osmt_query_vl_arb(p_osmt, p_src_port->rec.lid, 0, block, fh); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_query_all_ports_vl_arb: ERR 0467: " + "Failed to get Lid:0x%X Port:0x%X (%s)\n", + cl_ntoh16(p_src_port->rec.lid), 0, + ib_get_err_str( status ) ); + anyErr = 1; + } + } + } + else + { + /* this is a switch port */ + for (block = 1; block <= 4; block++) + { + status = osmt_query_vl_arb(p_osmt, p_src_port->rec.lid, + p_src_port->rec.port_num, block, fh); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_query_all_ports_vl_arb: ERR 0468: " + "Failed to get Lid:0x%X Port:0x%X (%s)\n", + cl_ntoh16(p_src_port->rec.lid), p_src_port->rec.port_num, + ib_get_err_str( status ) ); + anyErr = 1; + } + } + } + + p_src_port = ( port_t * ) cl_qmap_next( &p_src_port->map_item ); + } + + OSM_LOG_EXIT( &p_osmt->log ); + if (anyErr) + { + status = IB_ERROR; + } + return ( status ); +} + +/******************************************************************************* + SLtoVL +*******************************************************************************/ +static ib_api_status_t +osmtest_write_slvl_map_table( IN osmtest_t * const p_osmt, + IN FILE * fh, + IN const ib_slvl_table_record_t * const p_rec ) +{ + int result, i; + cl_status_t status = IB_SUCCESS; + + OSM_LOG_ENTER( &p_osmt->log, osmtest_write_slvl_map_table ); + + result = fprintf( fh, + "SLtoVL_MAP_TABLE\n" + "lid 0x%X\n" + "in_port_num 0x%X\n" + "out_port_num 0x%X\n", + cl_ntoh16( p_rec->lid ), + p_rec->in_port_num, + p_rec->out_port_num ); + + fprintf( fh, "SL:"); + for (i = 0; i < 16; i++) + fprintf( fh,"| %-2u ", i); + fprintf( fh, "|\nVL:"); + + for (i = 0; i < 16; i++) + fprintf( fh,"| 0x%01X ", ib_slvl_table_get( &p_rec->slvl_tbl, (uint8_t)i)); + fprintf( fh,"|\nEND\n\n"); + + /* Exit: */ + OSM_LOG_EXIT( &p_osmt->log ); + return ( status ); +} + +/********************************************************************** + * GET A SINGLE PORT INFO BY NODE LID AND PORT NUMBER + **********************************************************************/ +ib_api_status_t +osmt_query_slvl_map( + IN osmtest_t * const p_osmt, + IN ib_net16_t const lid, + IN uint8_t const out_port_num, + IN uint8_t const in_port_num, + IN FILE *fh ) +{ + osmtest_req_context_t context; + ib_api_status_t status = IB_SUCCESS; + osmv_user_query_t user; + osmv_query_req_t req; + ib_slvl_table_record_t record, *p_rec; + + OSM_LOG_ENTER( &p_osmt->log, osmt_query_slvl_map ); + + if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) ) + { + osm_log( &p_osmt->log, OSM_LOG_DEBUG, + "osmt_query_slvl_map: " + "Getting SLtoVL Map Table for out-port with LID 0x%X Num:0x%X from In-Port:0x%X\n", + cl_ntoh16( lid ), + out_port_num, in_port_num ); + } + + /* + * Do a blocking query for this record in the subnet. + * The result is returned in the result field of the caller's + * context structure. + * + * The query structures are locals. + */ + memset( &req, 0, sizeof( req ) ); + memset( &user, 0, sizeof( user ) ); + memset( &context, 0, sizeof( context ) ); + + context.p_osmt = p_osmt; + + record.lid = lid; + record.in_port_num = in_port_num; + record.out_port_num = out_port_num; + user.p_attr = &record; + + req.query_type = OSMV_QUERY_SLVL_BY_LID_AND_PORTS; + req.timeout_ms = p_osmt->opt.transaction_timeout; + req.retry_cnt = p_osmt->opt.retry_count; + req.flags = OSM_SA_FLAGS_SYNC; + req.query_context = &context; + req.pfn_query_cb = osmtest_query_res_cb; + req.p_query_input = &user; + req.sm_key = 0; + + status = osmv_query_sa( p_osmt->h_bind, &req ); + + if ( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_query_slvl_map: ERR 0469: " + "ib_query failed (%s)\n", ib_get_err_str( status ) ); + goto Exit; + } + + status = context.result.status; + + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_query_slvl_map: ERR 0470: " + "ib_query failed (%s)\n", ib_get_err_str( status ) ); + + if( status == IB_REMOTE_ERROR ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_query_slvl_map: " + "Remote error = %s\n", + ib_get_mad_status_str( osm_madw_get_mad_ptr + ( context.result.p_result_madw ) ) ); + } + goto Exit; + } + + /* ok it worked */ + p_rec = osmv_get_query_result( context.result.p_result_madw, 0); + if ( fh ) + { + osmtest_write_slvl_map_table( p_osmt, fh, p_rec ); + } + + Exit: + /* + * Return the IB query MAD to the pool as necessary. + */ + if( context.result.p_result_madw != NULL ) + { + osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw ); + context.result.p_result_madw = NULL; + } + + OSM_LOG_EXIT( &p_osmt->log ); + return ( status ); +} + +static ib_api_status_t +osmt_query_all_ports_slvl_map( IN osmtest_t * const p_osmt, + IN FILE * fh ) +{ + cl_status_t status = CL_SUCCESS; + cl_qmap_t *p_tbl; + port_t *p_src_port; + uint8_t in_port,anyErr = 0, num_ports; + node_t *p_node; + const cl_qmap_t *p_node_tbl; + + OSM_LOG_ENTER( &p_osmt->log, osmt_query_all_ports_slvl_map ); + + /* + * Go over all ports that exist in the subnet + * get the relevant SLtoVLs + */ + + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmt_query_all_ports_slvl_map: " + "Obtaining ALL Ports (to other ports) SLtoVL Maps\n"); + + p_tbl = &p_osmt->exp_subn.port_key_tbl; + p_node_tbl = &p_osmt->exp_subn.node_lid_tbl; + + p_src_port = ( port_t * ) cl_qmap_head( p_tbl ); + + while( p_src_port != ( port_t * ) cl_qmap_end( p_tbl ) ) + { + + /* HACK we use capability_mask to know diff a CA port from switch port */ + if( p_src_port->rec.port_info.capability_mask ) + { + /* this is an hca port */ + /* NOTE to comply we must set port number to 0 and the SA should figure it out */ + /* since it is a CA port */ + status = osmt_query_slvl_map(p_osmt, p_src_port->rec.lid, 0, 0, fh); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_query_all_ports_slvl_map: ERR 0471: " + "Failed to get Lid:0x%X In-Port:0x%X Out-Port:0x%X(%s)\n", + cl_ntoh16(p_src_port->rec.lid), 0, 0, + ib_get_err_str( status ) ); + anyErr = 1; + } + } + else + { + /* this is a switch port */ + /* get the node */ + p_node = ( node_t * ) cl_qmap_get( p_node_tbl, p_src_port->rec.lid ); + if( p_node == ( node_t * ) cl_qmap_end( p_node_tbl ) ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_query_all_ports_slvl_map: ERR 0472: " + "Failed to get Node by Lid:0x%X\n", + p_src_port->rec.lid ); + goto Exit; + } + + num_ports = p_node->rec.node_info.num_ports; + + for (in_port = 1; in_port <= num_ports; in_port++) + { + status = osmt_query_slvl_map(p_osmt, p_src_port->rec.lid, + p_src_port->rec.port_num, in_port, fh ); + if (status != IB_SUCCESS) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmt_query_all_ports_slvl_map: ERR 0473: " + "Failed to get Lid:0x%X In-Port:0x%X Out-Port:0x%X (%s)\n", + cl_ntoh16(p_src_port->rec.lid), p_src_port->rec.port_num, in_port, + ib_get_err_str( status ) ); + anyErr = 1; + } + } + } + + p_src_port = ( port_t * ) cl_qmap_next( &p_src_port->map_item ); + } + + Exit: + OSM_LOG_EXIT( &p_osmt->log ); + if (anyErr) + { + status = IB_ERROR; + } + return ( status ); +} + +/* + * Run a vl arbitration queries and sl2vl maps queries flow: + * Good flow: + * - for each physical port on the network - obtain the VL Arb + * - for each CA physical port obtain its SLtoVL Map + * - for each SW physical port (out) obtain the SLtoVL Map to each other port + * BAD flow: + * - Try get with multiple results + * - Try gettable + * - Try providing non existing port + */ +ib_api_status_t +osmt_run_slvl_and_vlarb_records_flow( IN osmtest_t * const p_osmt ) +{ + ib_api_status_t status; + FILE *fh; + ib_net16_t test_lid; + uint8_t lmc; + + OSM_LOG_ENTER( &p_osmt->log, osmt_run_slvl_and_vlarb_records_flow ); + + fh = fopen("qos.txt","w"); + + /* go over all ports in the subnet */ + status = osmt_query_all_ports_vl_arb( p_osmt, fh ); + if (status != IB_SUCCESS) + { + goto Exit; + } + + status = osmt_query_all_ports_slvl_map( p_osmt, fh ); + if (status != IB_SUCCESS) + { + goto Exit; + } + + /* If LMC > 0, test non base LID SA QoS Record requests */ + status = osmtest_get_local_port_lmc( p_osmt, p_osmt->local_port.lid, &lmc ); + if ( status != IB_SUCCESS ) + goto Exit; + + if (lmc != 0) + { + test_lid = cl_ntoh16( p_osmt->local_port.lid + 1); + + status = osmt_query_vl_arb( p_osmt, test_lid, 0, 1, NULL ); + if ( status != IB_SUCCESS ) + goto Exit; + + status = osmt_query_slvl_map( p_osmt, test_lid, 0, 0, NULL ); + if ( status != IB_SUCCESS ) + goto Exit; + } + + Exit: + fclose(fh); + OSM_LOG_EXIT( &p_osmt->log ); + return status; +} + + diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmtest.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmtest.c new file mode 100644 index 00000000..32825350 --- /dev/null +++ b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmtest.c @@ -0,0 +1,7489 @@ +/* + * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: osmtest.c 1928 2009-02-04 15:23:03Z tzachid $ + */ + + +/* TODO : Check why we dont free the cl_qmap_items we store when reading DB */ + +/* + * Abstract: + * Implementation of osmtest_t. + * This object represents the OSMTest Test object. + * + * Environment: + * Linux User Mode + * + * $Revision: 1.10 $ + */ + +#ifdef __WIN__ +#pragma warning(disable : 4996) +#endif + +#include +#include +#include +#ifdef __WIN__ +#include +#else +#include +#include +#endif +#include +#include "osmtest.h" + +#ifndef __WIN__ +#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_FROMLID, + OSMTEST_TOKEN_FROMPORTNUM, + OSMTEST_TOKEN_TOPORTNUM, + OSMTEST_TOKEN_TOLID, + 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_FROMLID, 8, "from_lid"}, + {OSMTEST_TOKEN_FROMPORTNUM, 13, "from_port_num"}, + {OSMTEST_TOKEN_TOPORTNUM, 11, "to_port_num"}, + {OSMTEST_TOKEN_TOLID, 6, "to_lid"}, + {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_INVALID_FIELD ) == 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_INVALID_FIELD ) == 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_INVALID_FIELD ) == 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 ) == 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 ); + cl_qmap_init( &p_subn->mgrp_mlid_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->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 ) +{ + memset( p_osmt, 0, 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_item,*p_next_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 __WIN__ + 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 ); + 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 ); + 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 ); + 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 ); + 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 ); + 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 ); + 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_v2( &p_osmt->log, p_opt->force_log_flush, + 0x0001, p_opt->log_file, 0, TRUE ); + if( status != IB_SUCCESS ) + return ( status ); + + /* but we do not want any extra stuff 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" ); + status = IB_ERROR; + 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 ) + { + 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 records in the subnet. + * The result is returned in the result field of the caller's + * context structure. + * + * The query structures are locals. + */ + memset( &req, 0, sizeof( req ) ); + memset( &user, 0, sizeof( user ) ); + + 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_validate_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 ClassPortInfo\n"); + } + + /* + * Do a blocking query for this record in the subnet. + * The result is returned in the result field of the caller's + * context structure. + * + * The query structures are locals. + */ + memset( &req, 0, sizeof( req ) ); + + 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 ) + { + 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, cl_ntoh16(p_cpi->cap_mask), p_cpi->cap_mask2_resp_time + ); + + Exit: +#if 0 + 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; + } +#endif + + 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. + */ + memset( &req, 0, sizeof( req ) ); + memset( &user, 0, sizeof( user ) ); + memset( &record, 0, 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 ) + { + 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. + */ + memset( &req, 0, sizeof( req ) ); + memset( &user, 0, sizeof( user ) ); + memset( &record, 0, 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 ) + { + 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); + + memset( &req, 0, sizeof( req ) ); + memset( p_context, 0, 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 0066: " + "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 ); +} + +/********************************************************************** + **********************************************************************/ +static ib_api_status_t +osmtest_get_path_rec_by_gid_pair( IN osmtest_t * const p_osmt, + IN ib_gid_t sgid, + IN ib_gid_t dgid, + IN osmtest_req_context_t *p_context) +{ + cl_status_t status = IB_SUCCESS; + osmv_query_req_t req; + osmv_gid_pair_t gid_pair; + + OSM_LOG_ENTER( &p_osmt->log, osmtest_get_path_rec_by_gid_pair); + + memset( &req, 0, sizeof( req ) ); + memset( p_context, 0, 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_GIDS; + + gid_pair.dest_gid = dgid; + gid_pair.src_gid = sgid; + + req.p_query_input = &gid_pair; + req.sm_key = 0; + + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmtest_get_path_rec_by_gid_pair: " + "Query for path from 0x%016" PRIx64 " 0x%016" PRIx64 " to 0x%016" PRIx64 " 0x%016" PRIx64"\n", + sgid.unicast.prefix, sgid.unicast.interface_id, + dgid.unicast.prefix, dgid.unicast.interface_id ); + + 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_gid_pair: ERR 006A: " + "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_gid_pair: ERR 006B: " + "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_gid_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 ); +} + +#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP) +/********************************************************************** + **********************************************************************/ +static ib_api_status_t +osmtest_get_multipath_rec( IN osmtest_t * const p_osmt, + IN osmv_multipath_req_t *p_request, + IN osmtest_req_context_t *p_context) +{ + cl_status_t status = IB_SUCCESS; + osmv_query_req_t req; + + OSM_LOG_ENTER( &p_osmt->log, osmtest_get_multipath_rec ); + + /* + * Do a blocking query for this record in the subnet. + * The result is returned in the result field of the caller's + * context structure. + * + * The query structures are locals. + */ + memset( &req, 0, sizeof( req ) ); + + 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_MULTIPATH_REC; + + req.p_query_input = p_request; + 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_multipath_rec: ERR 0068: " + "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_multipath_rec: ERR 0069: " + "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_multipath_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 ); +} +#endif + +/********************************************************************** + **********************************************************************/ +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 PortInfoRecord 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. + */ + memset( &req, 0, sizeof( req ) ); + memset( &user, 0, sizeof( user ) ); + memset( &record, 0, 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_by_num ); + + 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 PortInfoRecord for port with LID 0x%X Num:0x%X\n", + cl_ntoh16( lid ), + port_num); + } + + /* + * Do a blocking query for this record in the subnet. + * The result is returned in the result field of the caller's + * context structure. + * + * The query structures are locals. + */ + memset( &req, 0, sizeof( req ) ); + memset( &user, 0, sizeof( user ) ); + memset( &record, 0, 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 ) + { + 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 ); + + memset( &context, 0, sizeof( context ) ); + /* + * Do a blocking query for all PortInfoRecords 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 ); + + memset( &context, 0, sizeof( context ) ); + + /* + * Do a blocking query for all NodeRecords in the subnet. + */ + status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_NODE_RECORD, + sizeof( *p_rec ), &context ); + + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "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 ); + + memset( &context, 0, 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_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 ); + + memset( &context, 0, 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 0009: " + "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 ); + + memset( &context, 0, sizeof( context ) ); + + /* + * Do a blocking query for our own PortInfoRecord 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 0010: " + "osmtest_get_port_rec 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 ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osmtest_get_local_port_lmc( IN osmtest_t * const p_osmt, + IN ib_net16_t lid, + OUT uint8_t * const p_lmc ) +{ + 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_get_local_port_lmc ); + + memset( &context, 0, sizeof( context ) ); + + /* + * Do a blocking query for our own PortInfoRecord in the subnet. + */ + status = osmtest_get_port_rec( p_osmt, + cl_ntoh16( lid ), + &context ); + + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_get_local_port_lmc: ERR 001A: " + "osmtest_get_port_rec 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_get_local_port_lmc: " + "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 ); + if ( p_lmc) + { + *p_lmc = ib_port_info_get_lmc( &p_rec->port_info ); + osm_log( &p_osmt->log, OSM_LOG_DEBUG, + "osmtest_get_local_port_lmc: " + "LMC %d\n", *p_lmc ); + } + } + + 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_wrong_sm_key_ignored ); + + if( osm_log_is_active( &p_osmt->log, OSM_LOG_INFO ) ) + { + osm_log( &p_osmt->log, OSM_LOG_INFO, + "osmtest_wrong_sm_key_ignored: " + "Trying PortInfoRecord for port with LID 0x%X Num:0x%X\n", + 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. + */ + memset( &req, 0, sizeof( req ) ); + memset( &user, 0, sizeof( user ) ); + memset( &record, 0, 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; + + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_wrong_sm_key_ignored: " EXPECTING_ERRORS_START "\n" ); + status = osmv_query_sa( p_osmt->h_bind, &req ); + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_wrong_sm_key_ignored: " EXPECTING_ERRORS_END "\n" ); + + /* since we use a wrong sm_key we should get a timeout */ + if( status != IB_TIMEOUT ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_wrong_sm_key_ignored: ERR 0011: " + "Did not get a timeout but got (%s)\n", ib_get_err_str( status ) ); + if ( status == IB_SUCCESS ) + { + /* assign some error value to status, since IB_SUCCESS is a bad rc */ + status = IB_ERROR; + } + 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 0161: " "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->qos_class_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 0162: " "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; + char desc[IB_NODE_DESCRIPTION_SIZE + 1]; + + OSM_LOG_ENTER( &p_osmt->log, osmtest_write_node_info ); + + memcpy(desc, p_rec->node_desc.description, IB_NODE_DESCRIPTION_SIZE); + desc[IB_NODE_DESCRIPTION_SIZE] = '\0'; + + 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 ) ), + desc ); + + if( result < 0 ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_write_node_info: ERR 0163: " "Write failed\n" ); + status = IB_ERROR; + goto Exit; + } + + Exit: + OSM_LOG_EXIT( &p_osmt->log ); + return ( status ); +} + +/********************************************************************** + **********************************************************************/ +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 0164: " "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 ); + + memset( &context, 0, sizeof( context ) ); + + /* + * Do a blocking query for all NodeRecords in the subnet. + */ + status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_LINK_RECORD, + sizeof( *p_rec ), &context ); + + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_write_all_link_recs: ERR 0165: " + "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 %zu 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 0166: " + "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 ); +} + +/********************************************************************** + **********************************************************************/ +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 ); + + memset( &req, 0, sizeof( req ) ); + memset( p_context, 0, 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 + **********************************************************************/ +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 ); + + memset( &context, 0, sizeof( context ) ); + + /* + * Do a blocking query for all NodeRecords in the subnet. + */ + status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_NODE_RECORD, + sizeof( *p_rec ), &context ); + + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "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 %zu 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 ); + + memset( &context, 0, sizeof( context ) ); + + /* + * Do a blocking query for all NodeRecords in the subnet. + */ + status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_PORTINFO_RECORD, + sizeof( *p_rec ), &context ); + + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_write_all_port_recs: ERR 0167: " + "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 %zu 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 + **********************************************************************/ +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 ); + + memset( &context, 0, 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_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 %zu 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 query context */ + memset( &context, 0, sizeof( context ) ); + + status = osmtest_get_node_rec_by_lid( p_osmt, cl_ntoh16( lid ), &context ); + if( status != IB_SUCCESS ) + { + if ( 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 ); + + memset( &context, 0, 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 query context */ + memset( &context, 0, 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_SA_MAD_STATUS_NO_RECORDS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_write_all_port_recs: WRN 0122: " + "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 0123: " + "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; + ib_api_status_t got_status = IB_SUCCESS; + + OSM_LOG_ENTER( &p_osmt->log, osmtest_write_all_path_recs ); + + memset( &context, 0, 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_ERROR, + "osmtest_write_all_path_recs: ERR 012D: " + "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 ) ); + /* remember the first error status */ + got_status = ( got_status == IB_SUCCESS ) ? status : got_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 ); + } + + if( got_status != IB_SUCCESS ) + status = got_status; + + /* + * 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", + p_osmt->opt.file_name ); + 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- Querying %" 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 / (float)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- Querying %" 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; + long sec_diff,usec_diff; + + OSM_LOG_ENTER( &p_osmt->log, osmtest_stress_large_rmpp ); + 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_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, 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- Querying %" 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, 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- Querying %" 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; + long sec_diff,usec_diff; + + OSM_LOG_ENTER( &p_osmt->log, osmtest_stress_small_rmpp ); + 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_SMALL_RMPP_THR) && (num_timeouts < 100) ) + { + delta_recs = 0; + delta_queries = 0; + + status = osmtest_stress_port_recs_small( 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 > 5000 ) + { + gettimeofday( &end_tv, NULL ); + 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- Querying %" PRId64 " port_info queries (single mad) took %04ld:%06ld [sec:usec]\n", + num_queries, sec_diff, usec_diff); + 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- Querying %" 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 0168: " + "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; + uint8_t lmc = 0; + + 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 ) ); + } + + status = osmtest_get_local_port_lmc( p_osmt, p_osmt->local_port.lid, &lmc ); + if (status != IB_SUCCESS) + goto Exit; + + /* HACK: Assume uniform LMC across endports in the subnet */ + /* This is the only LMC mode which OpenSM currently supports */ + /* In absence of this assumption, validation of this is much more complicated */ + if ( lmc == 0 ) + { + /* + * 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; + } + } + else + { + /* Also, this doesn't detect fewer than the correct number of paths being returned */ + if ( p_path->count >= (uint32_t)( 1 << (2*lmc) ) ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_validate_path_data: ERR 0052: " + "Already received path SLID 0x%X to DLID 0x%X count %d LMC %d\n", + cl_ntoh16( p_rec->slid ), cl_ntoh16( p_rec->dlid ), + p_path->count, lmc ); + 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 0169: " + "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 0057: " + "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_ntoh16( p_path->rec.pkey ), + cl_ntoh16( 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 0055: " + "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; + } + +#if 0 + /* 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 012F: " + "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; + } +#endif + + 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, + cl_ntoh16( p_port->rec.port_info.m_key_violations ), + cl_ntoh16( 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, + cl_ntoh16( p_port->rec.port_info.p_key_violations ), + cl_ntoh16( 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, + cl_ntoh16( p_port->rec.port_info.q_key_violations ), + cl_ntoh16( 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 +ib_net64_t portguid = 0; + +/********************************************************************** + **********************************************************************/ +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 ); + + memset( &context, 0, sizeof( context ) ); + + /* + * Do a blocking query for all NodeRecords in the subnet. + */ + status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_NODE_RECORD, + sizeof( *p_rec ), &context ); + + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "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 %zu 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; + } + if (!portguid) + portguid = p_rec->node_info.port_guid; + } + + 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 ); +} + +/********************************************************************** + **********************************************************************/ +static ib_api_status_t +osmtest_validate_all_guidinfo_recs( IN osmtest_t * const p_osmt ) +{ + osmtest_req_context_t context; + const ib_guidinfo_record_t *p_rec; + cl_status_t status; + size_t num_recs; + + OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_all_guidinfo_recs ); + + memset( &context, 0, sizeof( context ) ); + + /* + * Do a blocking query for all GuidInfoRecords in the subnet. + */ + status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_GUIDINFO_RECORD, + sizeof( *p_rec ), &context ); + + + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_validate_all_guidinfo_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_guidinfo_recs: " + "Received %zu records\n", num_recs ); + } + + /* No validation as yet */ + + 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_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 ); + + memset( &context, 0, 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 009A: " + "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 %zu 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 0100: " + "osmtest_validate_path_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 0101: " + "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 ); +} + +/********************************************************************** + * Get link record by LID + **********************************************************************/ +ib_api_status_t +osmtest_get_link_rec_by_lid( IN osmtest_t * const p_osmt, + IN ib_net16_t const from_lid, + IN ib_net16_t const to_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_link_record_t record; + ib_mad_t *p_mad; + + OSM_LOG_ENTER( &p_osmt->log, osmtest_get_link_rec_by_lid ); + + if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) ) + { + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmtest_get_link_rec_by_lid: " + "Getting link record from LID 0x%02X to LID 0x%02X\n", + cl_ntoh16( from_lid ), cl_ntoh16( to_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. + */ + memset( &req, 0, sizeof( req ) ); + memset( &user, 0, sizeof( user ) ); + memset( &record, 0, sizeof( record ) ); + + record.from_lid = from_lid; + record.to_lid = to_lid; + p_context->p_osmt = p_osmt; + if (from_lid) + user.comp_mask |= IB_LR_COMPMASK_FROM_LID; + if (to_lid) + user.comp_mask |= IB_LR_COMPMASK_TO_LID; + user.attr_id = IB_MAD_ATTR_LINK_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_link_rec_by_lid: ERR 007A: " + "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_link_rec_by_lid: ERR 007B: " + "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_link_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 ); +} + +/********************************************************************** + * Get GUIDInfo record by LID + **********************************************************************/ +ib_api_status_t +osmtest_get_guidinfo_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_guidinfo_record_t record; + ib_mad_t *p_mad; + + OSM_LOG_ENTER( &p_osmt->log, osmtest_get_guidinfo_rec_by_lid ); + + if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) ) + { + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmtest_get_guidinfo_rec_by_lid: " + "Getting GUIDInfo 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. + */ + memset( &req, 0, sizeof( req ) ); + memset( &user, 0, sizeof( user ) ); + memset( &record, 0, sizeof( record ) ); + + record.lid = lid; + p_context->p_osmt = p_osmt; + user.comp_mask = IB_GIR_COMPMASK_LID; + user.attr_id = IB_MAD_ATTR_GUIDINFO_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_guidinfo_rec_by_lid: ERR 007C: " + "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_guidinfo_rec_by_lid: ERR 007D: " + "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_guidinfo_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 ); +} + +/********************************************************************** + * Get PKeyTable record by LID + **********************************************************************/ +ib_api_status_t +osmtest_get_pkeytbl_rec_by_lid( IN osmtest_t * const p_osmt, + IN ib_net16_t const lid, + IN ib_net64_t const sm_key, + 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_pkey_table_record_t record; + ib_mad_t *p_mad; + + OSM_LOG_ENTER( &p_osmt->log, osmtest_get_pkeytbl_rec_by_lid ); + + if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) ) + { + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmtest_get_pkeytbl_rec_by_lid: " + "Getting PKeyTable 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. + */ + memset( &req, 0, sizeof( req ) ); + memset( &user, 0, sizeof( user ) ); + memset( &record, 0, sizeof( record ) ); + + record.lid = lid; + p_context->p_osmt = p_osmt; + user.comp_mask = IB_PKEY_COMPMASK_LID; + user.attr_id = IB_MAD_ATTR_PKEY_TBL_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 = sm_key; + + status = osmv_query_sa( p_osmt->h_bind, &req ); + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_get_pkeytbl_rec_by_lid: ERR 007E: " + "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_pkeytbl_rec_by_lid: ERR 007F: " + "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_pkeytbl_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 ); +} + +/********************************************************************** + * Get LFT record by LID + **********************************************************************/ +ib_api_status_t +osmtest_get_lft_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_lft_record_t record; + ib_mad_t *p_mad; + + OSM_LOG_ENTER( &p_osmt->log, osmtest_get_lft_rec_by_lid ); + + if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) ) + { + osm_log( &p_osmt->log, OSM_LOG_VERBOSE, + "osmtest_get_lft_rec_by_lid: " + "Getting LFT 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. + */ + memset( &req, 0, sizeof( req ) ); + memset( &user, 0, sizeof( user ) ); + memset( &record, 0, sizeof( record ) ); + + record.lid = lid; + p_context->p_osmt = p_osmt; + user.comp_mask = IB_LFTR_COMPMASK_LID; + user.attr_id = IB_MAD_ATTR_LFT_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_lft_rec_by_lid: ERR 008A: " + "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_lft_rec_by_lid: ERR 008B: " + "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_lft_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 ); +} + +/********************************************************************** + **********************************************************************/ +ib_api_status_t +osmtest_sminfo_record_request( + IN osmtest_t * const p_osmt, + 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_sminfo_record_t record; + ib_mad_t *p_mad; + + OSM_LOG_ENTER( &p_osmt->log, osmtest_sminfo_record_request ); + + /* + * Do a blocking query for these records in the subnet. + * The result is returned in the result field of the caller's + * context structure. + * + * The query structures are locals. + */ + memset( &req, 0, sizeof( req ) ); + memset( &user, 0, sizeof( user ) ); + memset( &record, 0, sizeof( record ) ); + + p_context->p_osmt = p_osmt; + user.attr_id = IB_MAD_ATTR_SMINFO_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_sminfo_record_request: ERR 008C: " + "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_sminfo_record_request: ERR 008D: " + "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_sminfo_record_request: " + "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 ); +} +#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 ); + + memset( &context, 0, 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 0102: " + "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 0103: " + "Too many records. Expected 1, received %zu\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 0104: " + "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 ) ); + } + + memset( &context, 0, sizeof( context ) ); + memset( &req, 0, sizeof( req ) ); + memset( &user, 0, sizeof( user ) ); + memset( &record, 0, 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 0105: " + "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 0106: " + "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 0107: " + "osmtest_validate_node_data 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 ); +} + +/********************************************************************** + **********************************************************************/ +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 ); + + memset( &context, 0, 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 0108: " + "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 0109: " + "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; + boolean_t got_error = FALSE; + + OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_single_path_rec_guid_pair ); + + memset( &req, 0, sizeof( req ) ); + memset( &context, 0, 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 0110: " + "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 0111: " + "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: %zu 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 0112: " + "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 ) ); + got_error = TRUE; + } + + 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 0113: " + "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 ) ); + got_error = TRUE; + } + + 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 0114: " + "osmtest_validate_path_rec failed (%s)\n", + ib_get_err_str( status ) ); + got_error = TRUE; + } + if( got_error || (status != IB_SUCCESS) ) + { + osm_dump_path_record( &p_osmt->log, p_rec, OSM_LOG_VERBOSE ); + if( status == IB_SUCCESS ) + status = IB_ERROR; + 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 ); +} + +/********************************************************************** + **********************************************************************/ +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 + NONEXISTENT 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 0115: " + "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 0116: " + "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 ); + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_validate_single_node_recs: ERR 011A: " + "osmtest_validate_single_node_rec_lid (%s)\n", + ib_get_err_str( status ) ); + goto Exit; + } + 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 0117: " + "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 ); + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_validate_single_port_recs: ERR 011B: " + "osmtest_validate_single_port_rec_lid (%s)\n", + ib_get_err_str( status ) ); + goto Exit; + } + 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 0118: " + "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; + ib_gid_t portgid, mgid; +#ifdef VENDOR_RMPP_SUPPORT + ib_net64_t sm_key; + ib_net16_t test_lid; + uint8_t lmc; + osmtest_req_context_t context; +#ifdef DUAL_SIDED_RMPP + osmv_multipath_req_t request; +#endif +#endif + + 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; + + /* Exercise SA PathRecord multicast destination code */ + memset( &context, 0, sizeof( context ) ); + ib_gid_set_default( &portgid, portguid ); + /* Set IPoIB broadcast MGID */ + mgid.unicast.prefix = CL_HTON64(0xff12401bffff0000ULL); + mgid.unicast.interface_id = CL_HTON64(0x00000000ffffffffULL); + /* Can't check status as don't know whether port is running IPoIB */ + osmtest_get_path_rec_by_gid_pair( p_osmt, portgid, mgid, &context); + +#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP) + memset( &context, 0, sizeof( context ) ); + memset( &request, 0, sizeof( request ) ); + request.comp_mask = IB_MPR_COMPMASK_SGIDCOUNT | IB_MPR_COMPMASK_DGIDCOUNT; + request.sgid_count = 1; + request.dgid_count = 1; + ib_gid_set_default( &request.gids[0], portguid ); + ib_gid_set_default( &request.gids[1], portguid ); + status = osmtest_get_multipath_rec( p_osmt, &request, &context ); + if( status != IB_SUCCESS ) + goto Exit; + + memset( &context, 0, sizeof( context ) ); + memset( &request, 0, sizeof( request ) ); + + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_get_multipath_rec: " EXPECTING_ERRORS_START "\n" ); + status = osmtest_get_multipath_rec( p_osmt, &request, &context ); + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_get_multipath_rec: " + "Got error %s\n", ib_get_err_str(status) ); + } + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_get_multipath_rec: " EXPECTING_ERRORS_END "\n" ); + + if( status == IB_SUCCESS ) + { + status = IB_ERROR; + goto Exit; + } + + memset( &context, 0, sizeof( context ) ); + memset( &request, 0, sizeof( request ) ); + request.comp_mask = IB_MPR_COMPMASK_SGIDCOUNT; + request.sgid_count = 1; + ib_gid_set_default( &request.gids[0], portguid ); + + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_get_multipath_rec: " EXPECTING_ERRORS_START "\n" ); + status = osmtest_get_multipath_rec( p_osmt, &request, &context ); + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_get_multipath_rec: " + "Got error %s\n", ib_get_err_str(status) ); + } + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_get_multipath_rec: " EXPECTING_ERRORS_END "\n" ); + + if( status == IB_SUCCESS ) + { + status = IB_ERROR; + goto Exit; + } + + memset( &context, 0, sizeof( context ) ); + memset( &request, 0, sizeof( request ) ); + request.comp_mask = IB_MPR_COMPMASK_SGIDCOUNT | IB_MPR_COMPMASK_DGIDCOUNT; + request.sgid_count = 1; + request.dgid_count = 1; + ib_gid_set_default( &request.gids[0], portguid ); + /* Set IPoIB broadcast MGID */ + request.gids[1].unicast.prefix = CL_HTON64(0xff12401bffff0000ULL); + request.gids[1].unicast.interface_id = CL_HTON64(0x00000000ffffffffULL); + + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_get_multipath_rec: " EXPECTING_ERRORS_START "\n" ); + status = osmtest_get_multipath_rec( p_osmt, &request, &context ); + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_get_multipath_rec: " + "Got error %s\n", ib_get_err_str(status) ); + } + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_get_multipath_rec: " EXPECTING_ERRORS_END "\n" ); + + if( status == IB_SUCCESS ) + { + status = IB_ERROR; + goto Exit; + } + + memset( &context, 0, sizeof( context ) ); + request.comp_mask = IB_MPR_COMPMASK_SGIDCOUNT | IB_MPR_COMPMASK_DGIDCOUNT; + request.sgid_count = 1; + request.dgid_count = 1; + /* Set IPoIB broadcast MGID */ + request.gids[0].unicast.prefix = CL_HTON64(0xff12401bffff0000ULL); + request.gids[0].unicast.interface_id = CL_HTON64(0x00000000ffffffffULL); + ib_gid_set_default( &request.gids[1], portguid ); + + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_get_multipath_rec: " EXPECTING_ERRORS_START "\n" ); + status = osmtest_get_multipath_rec( p_osmt, &request, &context ); + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_get_multipath_rec: " + "Got error %s\n", ib_get_err_str(status) ); + } + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_get_multipath_rec: " EXPECTING_ERRORS_END "\n" ); + + if( status == IB_SUCCESS ) + { + status = IB_ERROR; + goto Exit; + } + + memset( &context, 0, sizeof( context ) ); + memset( &request, 0, sizeof( request ) ); + request.comp_mask = IB_MPR_COMPMASK_SGIDCOUNT | IB_MPR_COMPMASK_DGIDCOUNT | + IB_MPR_COMPMASK_NUMBPATH; + request.sgid_count = 2; + request.dgid_count = 2; + request.num_path = 2; + ib_gid_set_default( &request.gids[0], portguid ); + ib_gid_set_default( &request.gids[1], portguid ); + ib_gid_set_default( &request.gids[2], portguid ); + ib_gid_set_default( &request.gids[3], portguid ); + status = osmtest_get_multipath_rec( p_osmt, &request, &context ); + if( status != IB_SUCCESS ) + goto Exit; +#endif + +#ifdef VENDOR_RMPP_SUPPORT + /* GUIDInfoRecords */ + status = osmtest_validate_all_guidinfo_recs( p_osmt ); + if( status != IB_SUCCESS ) + goto Exit; + + /* If LMC > 0, test non base LID SA PortInfoRecord request */ + status = osmtest_get_local_port_lmc( p_osmt, p_osmt->local_port.lid, &lmc ); + if ( status != IB_SUCCESS ) + goto Exit; + + if (lmc != 0) + { + status = osmtest_get_local_port_lmc( p_osmt, p_osmt->local_port.lid + 1, NULL ); + if ( status != IB_SUCCESS ) + goto Exit; + } + + status = osmtest_get_local_port_lmc( p_osmt, 0xffff, NULL ); + if ( status != IB_SUCCESS ) + goto Exit; + + test_lid = cl_ntoh16( p_osmt->local_port.lid ); + + /* More GUIDInfo Record tests */ + memset( &context, 0, sizeof( context ) ); + status = osmtest_get_guidinfo_rec_by_lid( p_osmt, test_lid, &context ); + if ( status != IB_SUCCESS ) + goto Exit; + + memset( &context, 0, sizeof( context ) ); + status = osmtest_get_guidinfo_rec_by_lid( p_osmt, 0xffff, &context ); + if ( status != IB_SUCCESS ) + goto Exit; + + /* Some PKeyTable Record tests */ + sm_key = OSM_DEFAULT_SM_KEY; + memset( &context, 0, sizeof( context ) ); + status = osmtest_get_pkeytbl_rec_by_lid( p_osmt, test_lid, sm_key, &context ); + if ( status != IB_SUCCESS ) + goto Exit; + + memset( &context, 0, sizeof( context ) ); + + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_get_multipath_rec: " EXPECTING_ERRORS_START "\n" ); + status = osmtest_get_pkeytbl_rec_by_lid( p_osmt, test_lid, 0, &context ); + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_get_multipath_rec: " + "Got error %s\n", ib_get_err_str(status) ); + } + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_get_multipath_rec: " EXPECTING_ERRORS_END "\n" ); + + if( status == IB_SUCCESS ) + { + status = IB_ERROR; + goto Exit; + } + + memset( &context, 0, sizeof( context ) ); + status = osmtest_get_pkeytbl_rec_by_lid( p_osmt, 0xffff, sm_key, &context ); + if ( status != IB_SUCCESS ) + goto Exit; + + /* LFT Record test */ + memset( &context, 0, sizeof( context ) ); + status = osmtest_get_lft_rec_by_lid( p_osmt, test_lid, &context ); + if ( status != IB_SUCCESS ) + goto Exit; + + /* Some LinkRecord tests */ + /* FromLID */ + memset( &context, 0, sizeof( context ) ); + status = osmtest_get_link_rec_by_lid( p_osmt, test_lid, 0, &context ); + if ( status != IB_SUCCESS ) + goto Exit; + + /* ToLID */ + memset( &context, 0, sizeof( context ) ); + status = osmtest_get_link_rec_by_lid( p_osmt, 0, test_lid, &context ); + if ( status != IB_SUCCESS ) + goto Exit; + + /* FromLID & ToLID */ + memset( &context, 0, sizeof( context ) ); + status = osmtest_get_link_rec_by_lid( p_osmt, test_lid, test_lid, &context ); + if ( status != IB_SUCCESS ) + goto Exit; + + /* NodeRecord test */ + memset( &context, 0, sizeof( context ) ); + status = osmtest_get_node_rec_by_lid( p_osmt, 0xffff , &context ); + if ( status != IB_SUCCESS ) + goto Exit; + + /* SMInfoRecord test */ + memset( &context, 0, sizeof( context ) ); + status = osmtest_sminfo_record_request( p_osmt, &context ); + if ( status != IB_SUCCESS ) + goto Exit; + + if (lmc != 0) + { + test_lid = cl_ntoh16( p_osmt->local_port.lid + 1 ); + + /* Another GUIDInfo Record test */ + memset( &context, 0, sizeof( context ) ); + status = osmtest_get_guidinfo_rec_by_lid( p_osmt, test_lid, &context ); + if ( status != IB_SUCCESS ) + goto Exit; + + /* Another PKeyTable Record test */ + memset( &context, 0, sizeof( context ) ); + status = osmtest_get_pkeytbl_rec_by_lid( p_osmt, test_lid, sm_key, &context ); + if ( status != IB_SUCCESS ) + goto Exit; + + /* Another LFT Record test */ + memset( &context, 0, sizeof( context ) ); + status = osmtest_get_lft_rec_by_lid( p_osmt, test_lid, &context ); + if ( status != IB_SUCCESS ) + goto Exit; + + /* More LinkRecord tests */ + /* FromLID */ + memset( &context, 0, sizeof( context ) ); + status = osmtest_get_link_rec_by_lid( p_osmt, test_lid, 0, &context ); + if ( status != IB_SUCCESS ) + goto Exit; + + /* ToLID */ + memset( &context, 0, sizeof( context ) ); + status = osmtest_get_link_rec_by_lid( p_osmt, 0, test_lid, &context ); + if ( status != IB_SUCCESS ) + goto Exit; + + /* Another NodeRecord test */ + memset( &context, 0, sizeof( context ) ); + status = osmtest_get_node_rec_by_lid( p_osmt, test_lid, &context ); + if ( status != IB_SUCCESS ) + goto Exit; + } + + /* PathRecords */ + if (! p_osmt->opt.ignore_path_records) + { + status = osmtest_validate_all_path_recs( p_osmt ); + if( status != IB_SUCCESS ) + goto Exit; + + if (lmc != 0) + { + memset( &context, 0, sizeof( context ) ); + status = osmtest_get_path_rec_by_lid_pair( p_osmt, test_lid, + test_lid, &context ); + if (status != IB_SUCCESS ) + goto Exit; + + memset( &context, 0, sizeof( context ) ); + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_get_path_rec_by_lid_pair: " EXPECTING_ERRORS_START "\n" ); + status = osmtest_get_path_rec_by_lid_pair( p_osmt, 0xffff, + 0xffff, &context ); + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_get_path_rec_by_lid_pair: " + "Got error %s\n", ib_get_err_str(status) ); + } + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_get_path_rec_by_lid_pair: " EXPECTING_ERRORS_END "\n" ); + + if( status == IB_SUCCESS ) + { + status = IB_ERROR; + goto Exit; + } + + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_get_path_rec_by_lid_pair: " EXPECTING_ERRORS_START "\n" ); + + status = osmtest_get_path_rec_by_lid_pair( p_osmt, test_lid, + 0xffff, &context ); + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_get_path_rec_by_lid_pair: " + "Got error %s\n", ib_get_err_str(status) ); + } + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_get_path_rec_by_lid_pair: " EXPECTING_ERRORS_END "\n" ); + + if( status == IB_SUCCESS ) + { + status = IB_ERROR; + 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 0119: " + "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 0120: " + "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 0121: " + "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 0122: " + "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 0123: " + "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 0124: " + "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 0125: " + "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 0126: " + "LID must be specified for defined ports\n" ); + port_delete( p_port ); + status = IB_ERROR; + 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; + boolean_t got_error = FALSE; + + 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 0127: " + "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 0128: " + "Ignoring line %u with unknown token: %s\n", + *p_line_num, &line[offset] ); + got_error = TRUE; + 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 0129: " + "Ignoring line %u with unknown token: %s\n", + *p_line_num, &line[offset] ); + got_error = TRUE; + break; + } + } + + if( got_error ) + { + status = IB_ERROR; + goto Exit; + } + /* + * 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 ); + status = IB_ERROR; + 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_parse_link( 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; + const osmtest_token_t *p_tok; + boolean_t got_error = FALSE; + + OSM_LOG_ENTER( &p_osmt->log, osmtest_parse_link); + + /* + * 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_link: ERR 012A: " + "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_link: ERR 012B: " + "Ignoring line %u with unknown token: %s\n", + *p_line_num, &line[offset] ); + got_error = TRUE; + continue; + } + + if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) ) + { + osm_log( &p_osmt->log, OSM_LOG_DEBUG, + "osmtest_parse_link: " + "Found '%s' (line %u)\n", p_tok->str, *p_line_num ); + } + + str_skip_token( line, &offset ); + + switch ( p_tok->val ) + { + case OSMTEST_TOKEN_FROMLID: + case OSMTEST_TOKEN_FROMPORTNUM: + case OSMTEST_TOKEN_TOPORTNUM: + case OSMTEST_TOKEN_TOLID: + /* For now */ + break; + + case OSMTEST_TOKEN_END: + done = TRUE; + break; + + default: + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_parse_link: ERR 012C: " + "Ignoring line %u with unknown token: %s\n", + *p_line_num, &line[offset] ); + got_error = TRUE; + break; + } + } + + if( got_error ) + status = IB_ERROR; + + 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; + boolean_t got_error = FALSE; + + 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 0130: " + "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 0131: " + "Ignoring line %u: %s\n", line_num, &line[offset] ); + got_error = TRUE; + 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; + + case OSMTEST_TOKEN_DEFINE_LINK: + status = osmtest_parse_link( p_osmt, fh, &line_num ); + break; + + default: + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_create_db: ERR 0132: " + "Ignoring line %u: %s\n", line_num, &line[offset] ); + got_error = TRUE; + break; + } + + if( got_error ) + status = IB_ERROR; + + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_create_db: ERR 0133: " + "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 0134: " + "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 0135: " + "No local ports. Unable to proceed\n" ); + 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 0136: " + "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. + */ + 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 with 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 0137: " + "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 0138: " + "Could not obtain SA ClassPortInfo (%s)\n", + ib_get_err_str( status ) ); + goto Exit; + } + + if( p_osmt->opt.flow == 1 ) + { + /* + * Creating an inventory file with all nodes, ports and paths + */ + status = osmtest_create_inventory_file( p_osmt ); + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_run: ERR 0139: " + "Inventory file create failed (%s)\n", + ib_get_err_str( status ) ); + goto Exit; + } + } + else + { + if( p_osmt->opt.flow == 5 ) + { + /* + * Stress SA - flood the it with queries + */ + 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 0140: " + "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 0141: " + "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 0142: " + "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 0143: " + "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 0144: " + "Unknown stress test value %u\n", + p_osmt->opt.stress ); + break; + } + } + else + { + + /* + * Run normal validition tests. + */ + if (p_osmt->opt.flow == 0 || p_osmt->opt.flow == 2) + { + /* + * Only validate the given inventory file + */ + status = osmtest_create_db( p_osmt ); + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_run: ERR 0145: " + "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 0146: " + "SA validation database failure (%s)\n", + ib_get_err_str( status ) ); + goto Exit; + } + } + + if (p_osmt->opt.flow == 0) + { + status = osmtest_wrong_sm_key_ignored( p_osmt ); + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_run: ERR 0147: " + "Try wrong SM_Key failed (%s)\n", + ib_get_err_str( status ) ); + goto Exit; + } + } + + if (p_osmt->opt.flow == 0 || p_osmt->opt.flow == 3) + { + /* + * run service registration, deregistration, and lease test + */ + status = osmt_run_service_records_flow( p_osmt ); + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_run: ERR 0148: " + "Service Flow failed (%s)\n", + ib_get_err_str( status ) ); + goto Exit; + } + } + + if (p_osmt->opt.flow == 0 || p_osmt->opt.flow == 4) + { + /* + * Run event forwarding test + */ +#ifdef OSM_VENDOR_INTF_MTL + status = osmt_run_inform_info_flow( p_osmt ); + + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_run: ERR 0149: " + "Inform Info Flow failed: (%s)\n", + ib_get_err_str( status ) ); + goto Exit; + } +#else + osm_log (&p_osmt->log, OSM_LOG_INFO, + "osmtest_run: The event forwarding flow " + "is not implemented yet!\n"); + status = IB_SUCCESS; + goto Exit; +#endif + } + + if (p_osmt->opt.flow == 7) + { + /* + * QoS info: dump VLArb and SLtoVL tables. + * Since it generates a huge file, we run it only + * if explicitly required to + */ + status = osmtest_create_db( p_osmt ); + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_run: ERR 014A: " + "Database creation failed (%s)\n", + ib_get_err_str( status ) ); + goto Exit; + } + + 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 0150: " + "Failed to get SLtoVL and VL Arbitration Tables (%s)\n", + ib_get_err_str( status ) ); + goto Exit; + } + } + + if (p_osmt->opt.flow == 8) + { + /* + * Run trap 64/65 flow (this flow requires running of external tool) + */ +#ifdef OSM_VENDOR_INTF_MTL + status = osmt_run_trap64_65_flow( p_osmt ); + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_run: ERR 0151: " + "Trap 64/65 Flow failed: (%s)\n", + ib_get_err_str( status ) ); + goto Exit; + } +#else + osm_log (&p_osmt->log, OSM_LOG_INFO, + "osmtest_run: The event forwarding flow " + "is not implemented yet!\n"); + status = IB_SUCCESS; + goto Exit; +#endif + } + + if (p_osmt->opt.flow == 0 || p_osmt->opt.flow == 6) + { + /* + * Multicast flow + */ + status = osmt_run_mcast_flow( p_osmt ); + if( status != IB_SUCCESS ) + { + osm_log( &p_osmt->log, OSM_LOG_ERROR, + "osmtest_run: ERR 0152: " + "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 ); +} + -- 2.46.0