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/* 38 * Abstract: 39 * Implementation of osm_req_t. 40 * This object represents the generic attribute requester. 41 * This object is part of the opensm family of objects. 42 */ 43 44#if HAVE_CONFIG_H 45# include <config.h> 46#endif /* HAVE_CONFIG_H */ 47 48#include <string.h> 49#include <iba/ib_types.h> 50#include <complib/cl_debug.h> 51#include <opensm/osm_file_ids.h> 52#define FILE_ID OSM_FILE_REQ_C 53#include <opensm/osm_madw.h> 54#include <opensm/osm_attrib_req.h> 55#include <opensm/osm_log.h> 56#include <opensm/osm_helper.h> 57#include <opensm/osm_mad_pool.h> 58#include <opensm/osm_vl15intf.h> 59#include <opensm/osm_msgdef.h> 60#include <opensm/osm_opensm.h> 61#include <opensm/osm_db_pack.h> 62 63/********************************************************************** 64 The plock must be held before calling this function. 65**********************************************************************/ 66static ib_net64_t req_determine_mkey(IN osm_sm_t * sm, 67 IN const osm_dr_path_t * p_path) 68{ 69 osm_node_t *p_node; 70 osm_port_t *p_sm_port; 71 osm_physp_t *p_physp; 72 ib_net64_t dest_port_guid = 0, m_key; 73 uint8_t hop; 74 75 OSM_LOG_ENTER(sm->p_log); 76 77 p_physp = NULL; 78 79 p_sm_port = osm_get_port_by_guid(sm->p_subn, sm->p_subn->sm_port_guid); 80 81 /* hop_count == 0: destination port guid is SM */ 82 if (p_path->hop_count == 0) { 83 dest_port_guid = sm->p_subn->sm_port_guid; 84 goto Remote_Guid; 85 } 86 87 if (p_sm_port) { 88 p_node = p_sm_port->p_node; 89 if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH) 90 p_physp = osm_node_get_physp_ptr(p_node, p_path->path[1]); 91 else 92 p_physp = p_sm_port->p_physp; 93 } 94 95 /* hop_count == 1: outgoing physp is SM physp */ 96 for (hop = 2; p_physp && hop <= p_path->hop_count; hop++) { 97 p_physp = p_physp->p_remote_physp; 98 if (!p_physp) 99 break; 100 p_node = p_physp->p_node; 101 p_physp = osm_node_get_physp_ptr(p_node, p_path->path[hop]); 102 } 103 104 /* At this point, p_physp points at the outgoing physp on the 105 last hop, or NULL if we don't know it. 106 */ 107 if (!p_physp) { 108 OSM_LOG(sm->p_log, OSM_LOG_ERROR, 109 "ERR 1107: Outgoing physp is null on non-hop_0!\n"); 110 osm_dump_dr_path_v2(sm->p_log, p_path, FILE_ID, OSM_LOG_ERROR); 111 dest_port_guid = 0; 112 goto Remote_Guid; 113 } 114 115 if (p_physp->p_remote_physp) { 116 dest_port_guid = p_physp->p_remote_physp->port_guid; 117 goto Remote_Guid; 118 } 119 120 OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Target port guid unknown, " 121 "using persistent DB\n"); 122 if (!osm_db_neighbor_get(sm->p_subn->p_neighbor, 123 cl_ntoh64(p_physp->port_guid), 124 p_physp->port_num, 125 &dest_port_guid, NULL)) { 126 dest_port_guid = cl_hton64(dest_port_guid); 127 } 128 129Remote_Guid: 130 if (dest_port_guid) { 131 if (!osm_db_guid2mkey_get(sm->p_subn->p_g2m, 132 cl_ntoh64(dest_port_guid), &m_key)) { 133 m_key = cl_hton64(m_key); 134 OSM_LOG(sm->p_log, OSM_LOG_DEBUG, 135 "Found mkey for guid 0x%" 136 PRIx64 "\n", cl_ntoh64(dest_port_guid)); 137 } else { 138 OSM_LOG(sm->p_log, OSM_LOG_DEBUG, 139 "Target port mkey unknown, using default\n"); 140 m_key = sm->p_subn->opt.m_key; 141 } 142 } else { 143 OSM_LOG(sm->p_log, OSM_LOG_DEBUG, 144 "Target port guid unknown, using default\n"); 145 m_key = sm->p_subn->opt.m_key; 146 } 147 148 OSM_LOG_EXIT(sm->p_log); 149 150 return m_key; 151} 152 153/********************************************************************** 154 The plock must be held before calling this function. 155**********************************************************************/ 156ib_api_status_t osm_req_get(IN osm_sm_t * sm, IN const osm_dr_path_t * p_path, 157 IN ib_net16_t attr_id, IN ib_net32_t attr_mod, 158 IN boolean_t find_mkey, ib_net64_t m_key, 159 IN cl_disp_msgid_t err_msg, 160 IN const osm_madw_context_t * p_context) 161{ 162 osm_madw_t *p_madw; 163 ib_api_status_t status = IB_SUCCESS; 164 ib_net64_t m_key_calc; 165 ib_net64_t tid; 166 167 CL_ASSERT(sm); 168 169 OSM_LOG_ENTER(sm->p_log); 170 171 CL_ASSERT(p_path); 172 CL_ASSERT(attr_id); 173 174 /* do nothing if we are exiting ... */ 175 if (osm_exit_flag) 176 goto Exit; 177 178 /* p_context may be NULL. */ 179 180 p_madw = osm_mad_pool_get(sm->p_mad_pool, sm->mad_ctrl.h_bind, 181 MAD_BLOCK_SIZE, NULL); 182 if (p_madw == NULL) { 183 OSM_LOG(sm->p_log, OSM_LOG_ERROR, 184 "ERR 1101: Unable to acquire MAD\n"); 185 status = IB_INSUFFICIENT_RESOURCES; 186 goto Exit; 187 } 188 189 tid = cl_hton64((uint64_t) cl_atomic_inc(&sm->sm_trans_id) 190 & (uint64_t)(0xFFFFFFFF)); 191 if (tid == 0) 192 tid = cl_hton64((uint64_t) cl_atomic_inc(&sm->sm_trans_id) 193 & (uint64_t)(0xFFFFFFFF)); 194 195 if (sm->p_subn->opt.m_key_lookup == TRUE) { 196 if (find_mkey == TRUE) 197 m_key_calc = req_determine_mkey(sm, p_path); 198 else 199 m_key_calc = m_key; 200 } else 201 m_key_calc = sm->p_subn->opt.m_key; 202 203 OSM_LOG(sm->p_log, OSM_LOG_DEBUG, 204 "Getting %s (0x%X), modifier 0x%X, TID 0x%" PRIx64 205 ", MKey 0x%016" PRIx64 "\n", 206 ib_get_sm_attr_str(attr_id), cl_ntoh16(attr_id), 207 cl_ntoh32(attr_mod), cl_ntoh64(tid), cl_ntoh64(m_key_calc)); 208 209 ib_smp_init_new(osm_madw_get_smp_ptr(p_madw), IB_MAD_METHOD_GET, 210 tid, attr_id, attr_mod, p_path->hop_count, 211 m_key_calc, p_path->path, 212 IB_LID_PERMISSIVE, IB_LID_PERMISSIVE); 213 214 p_madw->mad_addr.dest_lid = IB_LID_PERMISSIVE; 215 p_madw->mad_addr.addr_type.smi.source_lid = IB_LID_PERMISSIVE; 216 p_madw->resp_expected = TRUE; 217 p_madw->fail_msg = err_msg; 218 219 /* 220 Fill in the mad wrapper context for the recipient. 221 In this case, the only thing the recipient needs is the 222 guid value. 223 */ 224 225 if (p_context) 226 p_madw->context = *p_context; 227 228 osm_vl15_post(sm->p_vl15, p_madw); 229 230Exit: 231 OSM_LOG_EXIT(sm->p_log); 232 return status; 233} 234 235/********************************************************************** 236 The plock must be held before calling this function. 237**********************************************************************/ 238osm_madw_t *osm_prepare_req_set(IN osm_sm_t * sm, IN const osm_dr_path_t * p_path, 239 IN const uint8_t * p_payload, 240 IN size_t payload_size, 241 IN ib_net16_t attr_id, IN ib_net32_t attr_mod, 242 IN boolean_t find_mkey, IN ib_net64_t m_key, 243 IN cl_disp_msgid_t err_msg, 244 IN const osm_madw_context_t * p_context) 245{ 246 osm_madw_t *p_madw = NULL; 247 ib_net64_t m_key_calc; 248 ib_net64_t tid; 249 250 CL_ASSERT(sm); 251 252 OSM_LOG_ENTER(sm->p_log); 253 254 CL_ASSERT(p_path); 255 CL_ASSERT(attr_id); 256 CL_ASSERT(p_payload); 257 258 /* do nothing if we are exiting ... */ 259 if (osm_exit_flag) 260 goto Exit; 261 262 /* p_context may be NULL. */ 263 264 p_madw = osm_mad_pool_get(sm->p_mad_pool, sm->mad_ctrl.h_bind, 265 MAD_BLOCK_SIZE, NULL); 266 if (p_madw == NULL) { 267 OSM_LOG(sm->p_log, OSM_LOG_ERROR, 268 "ERR 1102: Unable to acquire MAD\n"); 269 goto Exit; 270 } 271 272 tid = cl_hton64((uint64_t) cl_atomic_inc(&sm->sm_trans_id) 273 & (uint64_t)(0xFFFFFFFF)); 274 if (tid == 0) 275 tid = cl_hton64((uint64_t) cl_atomic_inc(&sm->sm_trans_id) 276 & (uint64_t)(0xFFFFFFFF)); 277 278 if (sm->p_subn->opt.m_key_lookup == TRUE) { 279 if (find_mkey == TRUE) 280 m_key_calc = req_determine_mkey(sm, p_path); 281 else 282 m_key_calc = m_key; 283 } else 284 m_key_calc = sm->p_subn->opt.m_key; 285 286 OSM_LOG(sm->p_log, OSM_LOG_DEBUG, 287 "Setting %s (0x%X), modifier 0x%X, TID 0x%" PRIx64 288 ", MKey 0x%016" PRIx64 "\n", 289 ib_get_sm_attr_str(attr_id), cl_ntoh16(attr_id), 290 cl_ntoh32(attr_mod), cl_ntoh64(tid), cl_ntoh64(m_key_calc)); 291 292 ib_smp_init_new(osm_madw_get_smp_ptr(p_madw), IB_MAD_METHOD_SET, 293 tid, attr_id, attr_mod, p_path->hop_count, 294 m_key_calc, p_path->path, 295 IB_LID_PERMISSIVE, IB_LID_PERMISSIVE); 296 297 p_madw->mad_addr.dest_lid = IB_LID_PERMISSIVE; 298 p_madw->mad_addr.addr_type.smi.source_lid = IB_LID_PERMISSIVE; 299 p_madw->resp_expected = TRUE; 300 p_madw->fail_msg = err_msg; 301 302 /* 303 Fill in the mad wrapper context for the recipient. 304 In this case, the only thing the recipient needs is the 305 guid value. 306 */ 307 308 if (p_context) 309 p_madw->context = *p_context; 310 311 memcpy(osm_madw_get_smp_ptr(p_madw)->data, p_payload, payload_size); 312 313Exit: 314 OSM_LOG_EXIT(sm->p_log); 315 return p_madw; 316} 317 318void osm_send_req_mad(IN osm_sm_t * sm, IN osm_madw_t *p_madw) 319{ 320 CL_ASSERT(p_madw); 321 CL_ASSERT(sm); 322 323 osm_vl15_post(sm->p_vl15, p_madw); 324} 325 326/********************************************************************** 327 The plock MAY or MAY NOT be held before calling this function. 328**********************************************************************/ 329ib_api_status_t osm_req_set(IN osm_sm_t * sm, IN const osm_dr_path_t * p_path, 330 IN const uint8_t * p_payload, 331 IN size_t payload_size, 332 IN ib_net16_t attr_id, IN ib_net32_t attr_mod, 333 IN boolean_t find_mkey, IN ib_net64_t m_key, 334 IN cl_disp_msgid_t err_msg, 335 IN const osm_madw_context_t * p_context) 336{ 337 osm_madw_t *p_madw; 338 ib_api_status_t status = IB_SUCCESS; 339 340 p_madw = osm_prepare_req_set(sm, p_path, p_payload, payload_size, attr_id, 341 attr_mod, find_mkey, m_key, err_msg, p_context); 342 if (p_madw == NULL) 343 status = IB_INSUFFICIENT_RESOURCES; 344 else 345 osm_send_req_mad(sm, p_madw); 346 347 return status; 348} 349 350int osm_send_trap144(osm_sm_t * sm, ib_net16_t local) 351{ 352 osm_madw_t *madw; 353 ib_smp_t *smp; 354 ib_mad_notice_attr_t *ntc; 355 osm_port_t *port, *smport; 356 ib_port_info_t *pi; 357 358 port = osm_get_port_by_guid(sm->p_subn, sm->p_subn->sm_port_guid); 359 if (!port) { 360 OSM_LOG(sm->p_log, OSM_LOG_ERROR, 361 "ERR 1104: cannot find SM port by guid 0x%" PRIx64 "\n", 362 cl_ntoh64(sm->p_subn->sm_port_guid)); 363 return -1; 364 } 365 366 pi = &port->p_physp->port_info; 367 368 /* don't bother with sending trap when SMA supports this */ 369 if (!local && 370 pi->capability_mask&(IB_PORT_CAP_HAS_TRAP|IB_PORT_CAP_HAS_CAP_NTC)) 371 return 0; 372 373 smport = osm_get_port_by_guid(sm->p_subn, sm->master_sm_guid); 374 if (!smport) { 375 OSM_LOG(sm->p_log, OSM_LOG_ERROR, 376 "ERR 1106: cannot find master SM port by guid 0x%" PRIx64 "\n", 377 cl_ntoh64(sm->master_sm_guid)); 378 return -1; 379 } 380 381 madw = osm_mad_pool_get(sm->p_mad_pool, 382 osm_sm_mad_ctrl_get_bind_handle(&sm->mad_ctrl), 383 MAD_BLOCK_SIZE, NULL); 384 if (madw == NULL) { 385 OSM_LOG(sm->p_log, OSM_LOG_ERROR, 386 "ERR 1105: Unable to acquire MAD\n"); 387 return -1; 388 } 389 390 madw->mad_addr.dest_lid = smport->p_physp->port_info.base_lid; 391 madw->mad_addr.addr_type.smi.source_lid = pi->base_lid; 392 madw->resp_expected = TRUE; 393 madw->fail_msg = CL_DISP_MSGID_NONE; 394 395 smp = osm_madw_get_smp_ptr(madw); 396 memset(smp, 0, sizeof(*smp)); 397 398 smp->base_ver = 1; 399 smp->mgmt_class = IB_MCLASS_SUBN_LID; 400 smp->class_ver = 1; 401 smp->method = IB_MAD_METHOD_TRAP; 402 smp->trans_id = cl_hton64((uint64_t) cl_atomic_inc(&sm->sm_trans_id) 403 & (uint64_t)(0xFFFFFFFF)); 404 if (smp->trans_id == 0) 405 smp->trans_id = cl_hton64((uint64_t) cl_atomic_inc(&sm->sm_trans_id) 406 & (uint64_t)(0xFFFFFFFF)); 407 408 smp->attr_id = IB_MAD_ATTR_NOTICE; 409 410 ntc = (ib_mad_notice_attr_t *) smp->data; 411 412 ntc->generic_type = 0x80 | IB_NOTICE_TYPE_INFO; 413 ib_notice_set_prod_type_ho(ntc, osm_node_get_type(port->p_node)); 414 ntc->g_or_v.generic.trap_num = cl_hton16(SM_LOCAL_CHANGES_TRAP); /* 144 */ 415 ntc->issuer_lid = pi->base_lid; 416 ntc->data_details.ntc_144.lid = pi->base_lid; 417 ntc->data_details.ntc_144.local_changes = local ? 418 TRAP_144_MASK_OTHER_LOCAL_CHANGES : 0; 419 ntc->data_details.ntc_144.new_cap_mask = pi->capability_mask; 420 ntc->data_details.ntc_144.change_flgs = local; 421 422 OSM_LOG(sm->p_log, OSM_LOG_DEBUG, 423 "Sending Trap 144, TID 0x%" PRIx64 " to SM lid %u\n", 424 cl_ntoh64(smp->trans_id), cl_ntoh16(madw->mad_addr.dest_lid)); 425 426 osm_vl15_post(sm->p_vl15, madw); 427 428 return 0; 429} 430