PageRenderTime 47ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/opensm/osm_req.c

https://gitlab.com/domke/osm-routing-dev
C | 433 lines | 292 code | 68 blank | 73 comment | 44 complexity | f53238412c90ec8cb99579c2e20da8df MD5 | raw file
  1. /*
  2. * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
  3. * Copyright (c) 2002-2015 Mellanox Technologies LTD. All rights reserved.
  4. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
  5. * Copyright (c) 2009 HNR Consulting. All rights reserved.
  6. *
  7. * This software is available to you under a choice of one of two
  8. * licenses. You may choose to be licensed under the terms of the GNU
  9. * General Public License (GPL) Version 2, available from the file
  10. * COPYING in the main directory of this source tree, or the
  11. * OpenIB.org BSD license below:
  12. *
  13. * Redistribution and use in source and binary forms, with or
  14. * without modification, are permitted provided that the following
  15. * conditions are met:
  16. *
  17. * - Redistributions of source code must retain the above
  18. * copyright notice, this list of conditions and the following
  19. * disclaimer.
  20. *
  21. * - Redistributions in binary form must reproduce the above
  22. * copyright notice, this list of conditions and the following
  23. * disclaimer in the documentation and/or other materials
  24. * provided with the distribution.
  25. *
  26. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  27. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  28. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  29. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  30. * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  31. * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  32. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  33. * SOFTWARE.
  34. *
  35. */
  36. /*
  37. * Abstract:
  38. * Implementation of osm_req_t.
  39. * This object represents the generic attribute requester.
  40. * This object is part of the opensm family of objects.
  41. */
  42. #if HAVE_CONFIG_H
  43. # include <config.h>
  44. #endif /* HAVE_CONFIG_H */
  45. #include <string.h>
  46. #include <iba/ib_types.h>
  47. #include <complib/cl_debug.h>
  48. #include <opensm/osm_file_ids.h>
  49. #define FILE_ID OSM_FILE_REQ_C
  50. #include <opensm/osm_madw.h>
  51. #include <opensm/osm_attrib_req.h>
  52. #include <opensm/osm_log.h>
  53. #include <opensm/osm_helper.h>
  54. #include <opensm/osm_mad_pool.h>
  55. #include <opensm/osm_vl15intf.h>
  56. #include <opensm/osm_msgdef.h>
  57. #include <opensm/osm_opensm.h>
  58. #include <opensm/osm_db_pack.h>
  59. /**********************************************************************
  60. The plock must be held before calling this function.
  61. **********************************************************************/
  62. static ib_net64_t req_determine_mkey(IN osm_sm_t * sm,
  63. IN const osm_dr_path_t * p_path)
  64. {
  65. osm_node_t *p_node;
  66. osm_port_t *p_sm_port;
  67. osm_physp_t *p_physp;
  68. ib_net64_t dest_port_guid = 0, m_key;
  69. uint8_t hop;
  70. OSM_LOG_ENTER(sm->p_log);
  71. p_physp = NULL;
  72. p_sm_port = osm_get_port_by_guid(sm->p_subn, sm->p_subn->sm_port_guid);
  73. /* hop_count == 0: destination port guid is SM */
  74. if (p_path->hop_count == 0) {
  75. dest_port_guid = sm->p_subn->sm_port_guid;
  76. goto Remote_Guid;
  77. }
  78. if (p_sm_port) {
  79. p_node = p_sm_port->p_node;
  80. if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH)
  81. p_physp = osm_node_get_physp_ptr(p_node, p_path->path[1]);
  82. else
  83. p_physp = p_sm_port->p_physp;
  84. }
  85. /* hop_count == 1: outgoing physp is SM physp */
  86. for (hop = 2; p_physp && hop <= p_path->hop_count; hop++) {
  87. p_physp = p_physp->p_remote_physp;
  88. if (!p_physp)
  89. break;
  90. p_node = p_physp->p_node;
  91. p_physp = osm_node_get_physp_ptr(p_node, p_path->path[hop]);
  92. }
  93. /* At this point, p_physp points at the outgoing physp on the
  94. last hop, or NULL if we don't know it.
  95. */
  96. if (!p_physp) {
  97. OSM_LOG(sm->p_log, OSM_LOG_ERROR,
  98. "ERR 1107: Outgoing physp is null on non-hop_0!\n");
  99. osm_dump_dr_path_v2(sm->p_log, p_path, FILE_ID, OSM_LOG_ERROR);
  100. dest_port_guid = 0;
  101. goto Remote_Guid;
  102. }
  103. if (p_physp->p_remote_physp) {
  104. dest_port_guid = p_physp->p_remote_physp->port_guid;
  105. goto Remote_Guid;
  106. }
  107. OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Target port guid unknown, "
  108. "using persistent DB\n");
  109. if (!osm_db_neighbor_get(sm->p_subn->p_neighbor,
  110. cl_ntoh64(p_physp->port_guid),
  111. p_physp->port_num,
  112. &dest_port_guid, NULL)) {
  113. dest_port_guid = cl_hton64(dest_port_guid);
  114. }
  115. Remote_Guid:
  116. if (dest_port_guid) {
  117. if (!osm_db_guid2mkey_get(sm->p_subn->p_g2m,
  118. cl_ntoh64(dest_port_guid), &m_key)) {
  119. m_key = cl_hton64(m_key);
  120. OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
  121. "Found mkey for guid 0x%"
  122. PRIx64 "\n", cl_ntoh64(dest_port_guid));
  123. } else {
  124. OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
  125. "Target port mkey unknown, using default\n");
  126. m_key = sm->p_subn->opt.m_key;
  127. }
  128. } else {
  129. OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
  130. "Target port guid unknown, using default\n");
  131. m_key = sm->p_subn->opt.m_key;
  132. }
  133. OSM_LOG_EXIT(sm->p_log);
  134. return m_key;
  135. }
  136. /**********************************************************************
  137. The plock must be held before calling this function.
  138. **********************************************************************/
  139. ib_api_status_t osm_req_get(IN osm_sm_t * sm, IN const osm_dr_path_t * p_path,
  140. IN ib_net16_t attr_id, IN ib_net32_t attr_mod,
  141. IN boolean_t find_mkey, IN ib_net64_t m_key,
  142. IN uint32_t timeout, IN cl_disp_msgid_t err_msg,
  143. IN const osm_madw_context_t * p_context)
  144. {
  145. osm_madw_t *p_madw;
  146. ib_api_status_t status = IB_SUCCESS;
  147. ib_net64_t m_key_calc;
  148. ib_net64_t tid;
  149. CL_ASSERT(sm);
  150. OSM_LOG_ENTER(sm->p_log);
  151. CL_ASSERT(p_path);
  152. CL_ASSERT(attr_id);
  153. /* do nothing if we are exiting ... */
  154. if (osm_exit_flag)
  155. goto Exit;
  156. /* p_context may be NULL. */
  157. p_madw = osm_mad_pool_get(sm->p_mad_pool, sm->mad_ctrl.h_bind,
  158. MAD_BLOCK_SIZE, NULL);
  159. if (p_madw == NULL) {
  160. OSM_LOG(sm->p_log, OSM_LOG_ERROR,
  161. "ERR 1101: Unable to acquire MAD\n");
  162. status = IB_INSUFFICIENT_RESOURCES;
  163. goto Exit;
  164. }
  165. tid = cl_hton64((uint64_t) cl_atomic_inc(&sm->sm_trans_id)
  166. & (uint64_t)(0xFFFFFFFF));
  167. if (tid == 0)
  168. tid = cl_hton64((uint64_t) cl_atomic_inc(&sm->sm_trans_id)
  169. & (uint64_t)(0xFFFFFFFF));
  170. if (sm->p_subn->opt.m_key_lookup == TRUE) {
  171. if (find_mkey == TRUE)
  172. m_key_calc = req_determine_mkey(sm, p_path);
  173. else
  174. m_key_calc = m_key;
  175. } else
  176. m_key_calc = sm->p_subn->opt.m_key;
  177. OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
  178. "Getting %s (0x%X), modifier 0x%X, TID 0x%" PRIx64
  179. ", MKey 0x%016" PRIx64 "\n",
  180. ib_get_sm_attr_str(attr_id), cl_ntoh16(attr_id),
  181. cl_ntoh32(attr_mod), cl_ntoh64(tid), cl_ntoh64(m_key_calc));
  182. ib_smp_init_new(osm_madw_get_smp_ptr(p_madw), IB_MAD_METHOD_GET,
  183. tid, attr_id, attr_mod, p_path->hop_count,
  184. m_key_calc, p_path->path,
  185. IB_LID_PERMISSIVE, IB_LID_PERMISSIVE);
  186. p_madw->mad_addr.dest_lid = IB_LID_PERMISSIVE;
  187. p_madw->mad_addr.addr_type.smi.source_lid = IB_LID_PERMISSIVE;
  188. p_madw->resp_expected = TRUE;
  189. p_madw->timeout = timeout;
  190. p_madw->fail_msg = err_msg;
  191. /*
  192. Fill in the mad wrapper context for the recipient.
  193. In this case, the only thing the recipient needs is the
  194. guid value.
  195. */
  196. if (p_context)
  197. p_madw->context = *p_context;
  198. osm_vl15_post(sm->p_vl15, p_madw);
  199. Exit:
  200. OSM_LOG_EXIT(sm->p_log);
  201. return status;
  202. }
  203. /**********************************************************************
  204. The plock must be held before calling this function.
  205. **********************************************************************/
  206. osm_madw_t *osm_prepare_req_set(IN osm_sm_t * sm, IN const osm_dr_path_t * p_path,
  207. IN const uint8_t * p_payload,
  208. IN size_t payload_size,
  209. IN ib_net16_t attr_id, IN ib_net32_t attr_mod,
  210. IN boolean_t find_mkey, IN ib_net64_t m_key,
  211. IN uint32_t timeout,
  212. IN cl_disp_msgid_t err_msg,
  213. IN const osm_madw_context_t * p_context)
  214. {
  215. osm_madw_t *p_madw = NULL;
  216. ib_net64_t m_key_calc;
  217. ib_net64_t tid;
  218. CL_ASSERT(sm);
  219. OSM_LOG_ENTER(sm->p_log);
  220. CL_ASSERT(p_path);
  221. CL_ASSERT(attr_id);
  222. CL_ASSERT(p_payload);
  223. /* do nothing if we are exiting ... */
  224. if (osm_exit_flag)
  225. goto Exit;
  226. /* p_context may be NULL. */
  227. p_madw = osm_mad_pool_get(sm->p_mad_pool, sm->mad_ctrl.h_bind,
  228. MAD_BLOCK_SIZE, NULL);
  229. if (p_madw == NULL) {
  230. OSM_LOG(sm->p_log, OSM_LOG_ERROR,
  231. "ERR 1102: Unable to acquire MAD\n");
  232. goto Exit;
  233. }
  234. tid = cl_hton64((uint64_t) cl_atomic_inc(&sm->sm_trans_id)
  235. & (uint64_t)(0xFFFFFFFF));
  236. if (tid == 0)
  237. tid = cl_hton64((uint64_t) cl_atomic_inc(&sm->sm_trans_id)
  238. & (uint64_t)(0xFFFFFFFF));
  239. if (sm->p_subn->opt.m_key_lookup == TRUE) {
  240. if (find_mkey == TRUE)
  241. m_key_calc = req_determine_mkey(sm, p_path);
  242. else
  243. m_key_calc = m_key;
  244. } else
  245. m_key_calc = sm->p_subn->opt.m_key;
  246. OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
  247. "Setting %s (0x%X), modifier 0x%X, TID 0x%" PRIx64
  248. ", MKey 0x%016" PRIx64 "\n",
  249. ib_get_sm_attr_str(attr_id), cl_ntoh16(attr_id),
  250. cl_ntoh32(attr_mod), cl_ntoh64(tid), cl_ntoh64(m_key_calc));
  251. ib_smp_init_new(osm_madw_get_smp_ptr(p_madw), IB_MAD_METHOD_SET,
  252. tid, attr_id, attr_mod, p_path->hop_count,
  253. m_key_calc, p_path->path,
  254. IB_LID_PERMISSIVE, IB_LID_PERMISSIVE);
  255. p_madw->mad_addr.dest_lid = IB_LID_PERMISSIVE;
  256. p_madw->mad_addr.addr_type.smi.source_lid = IB_LID_PERMISSIVE;
  257. p_madw->resp_expected = TRUE;
  258. p_madw->timeout = timeout;
  259. p_madw->fail_msg = err_msg;
  260. /*
  261. Fill in the mad wrapper context for the recipient.
  262. In this case, the only thing the recipient needs is the
  263. guid value.
  264. */
  265. if (p_context)
  266. p_madw->context = *p_context;
  267. memcpy(osm_madw_get_smp_ptr(p_madw)->data, p_payload, payload_size);
  268. Exit:
  269. OSM_LOG_EXIT(sm->p_log);
  270. return p_madw;
  271. }
  272. void osm_send_req_mad(IN osm_sm_t * sm, IN osm_madw_t *p_madw)
  273. {
  274. CL_ASSERT(p_madw);
  275. CL_ASSERT(sm);
  276. osm_vl15_post(sm->p_vl15, p_madw);
  277. }
  278. /**********************************************************************
  279. The plock MAY or MAY NOT be held before calling this function.
  280. **********************************************************************/
  281. ib_api_status_t osm_req_set(IN osm_sm_t * sm, IN const osm_dr_path_t * p_path,
  282. IN const uint8_t * p_payload,
  283. IN size_t payload_size,
  284. IN ib_net16_t attr_id, IN ib_net32_t attr_mod,
  285. IN boolean_t find_mkey, IN ib_net64_t m_key,
  286. IN uint32_t timeout,
  287. IN cl_disp_msgid_t err_msg,
  288. IN const osm_madw_context_t * p_context)
  289. {
  290. osm_madw_t *p_madw;
  291. ib_api_status_t status = IB_SUCCESS;
  292. p_madw = osm_prepare_req_set(sm, p_path, p_payload, payload_size, attr_id,
  293. attr_mod, find_mkey, m_key, timeout, err_msg, p_context);
  294. if (p_madw == NULL)
  295. status = IB_INSUFFICIENT_RESOURCES;
  296. else
  297. osm_send_req_mad(sm, p_madw);
  298. return status;
  299. }
  300. int osm_send_trap144(osm_sm_t * sm, ib_net16_t local)
  301. {
  302. osm_madw_t *madw;
  303. ib_smp_t *smp;
  304. ib_mad_notice_attr_t *ntc;
  305. osm_port_t *port, *smport;
  306. ib_port_info_t *pi;
  307. port = osm_get_port_by_guid(sm->p_subn, sm->p_subn->sm_port_guid);
  308. if (!port) {
  309. OSM_LOG(sm->p_log, OSM_LOG_ERROR,
  310. "ERR 1104: cannot find SM port by guid 0x%" PRIx64 "\n",
  311. cl_ntoh64(sm->p_subn->sm_port_guid));
  312. return -1;
  313. }
  314. pi = &port->p_physp->port_info;
  315. /* don't bother with sending trap when SMA supports this */
  316. if (!local &&
  317. pi->capability_mask&(IB_PORT_CAP_HAS_TRAP|IB_PORT_CAP_HAS_CAP_NTC))
  318. return 0;
  319. smport = osm_get_port_by_guid(sm->p_subn, sm->master_sm_guid);
  320. if (!smport) {
  321. OSM_LOG(sm->p_log, OSM_LOG_ERROR,
  322. "ERR 1106: cannot find master SM port by guid 0x%" PRIx64 "\n",
  323. cl_ntoh64(sm->master_sm_guid));
  324. return -1;
  325. }
  326. madw = osm_mad_pool_get(sm->p_mad_pool,
  327. osm_sm_mad_ctrl_get_bind_handle(&sm->mad_ctrl),
  328. MAD_BLOCK_SIZE, NULL);
  329. if (madw == NULL) {
  330. OSM_LOG(sm->p_log, OSM_LOG_ERROR,
  331. "ERR 1105: Unable to acquire MAD\n");
  332. return -1;
  333. }
  334. madw->mad_addr.dest_lid = smport->p_physp->port_info.base_lid;
  335. madw->mad_addr.addr_type.smi.source_lid = pi->base_lid;
  336. madw->resp_expected = TRUE;
  337. madw->fail_msg = CL_DISP_MSGID_NONE;
  338. smp = osm_madw_get_smp_ptr(madw);
  339. memset(smp, 0, sizeof(*smp));
  340. smp->base_ver = 1;
  341. smp->mgmt_class = IB_MCLASS_SUBN_LID;
  342. smp->class_ver = 1;
  343. smp->method = IB_MAD_METHOD_TRAP;
  344. smp->trans_id = cl_hton64((uint64_t) cl_atomic_inc(&sm->sm_trans_id)
  345. & (uint64_t)(0xFFFFFFFF));
  346. if (smp->trans_id == 0)
  347. smp->trans_id = cl_hton64((uint64_t) cl_atomic_inc(&sm->sm_trans_id)
  348. & (uint64_t)(0xFFFFFFFF));
  349. smp->attr_id = IB_MAD_ATTR_NOTICE;
  350. ntc = (ib_mad_notice_attr_t *) smp->data;
  351. ntc->generic_type = 0x80 | IB_NOTICE_TYPE_INFO;
  352. ib_notice_set_prod_type_ho(ntc, osm_node_get_type(port->p_node));
  353. ntc->g_or_v.generic.trap_num = cl_hton16(SM_LOCAL_CHANGES_TRAP); /* 144 */
  354. ntc->issuer_lid = pi->base_lid;
  355. ntc->data_details.ntc_144.lid = pi->base_lid;
  356. ntc->data_details.ntc_144.local_changes = local ?
  357. TRAP_144_MASK_OTHER_LOCAL_CHANGES : 0;
  358. ntc->data_details.ntc_144.new_cap_mask = pi->capability_mask;
  359. ntc->data_details.ntc_144.change_flgs = local;
  360. OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
  361. "Sending Trap 144, TID 0x%" PRIx64 " to SM lid %u\n",
  362. cl_ntoh64(smp->trans_id), cl_ntoh16(madw->mad_addr.dest_lid));
  363. osm_vl15_post(sm->p_vl15, madw);
  364. return 0;
  365. }