static void fillMAD_Get_LFTRecord(UInt8 *umad, SInt64 len, UInt16 smLid, UInt16 destLid, UInt64 trId) { UInt64 mask; struct _LinearForwardingTableRecord lft; memset(umad, 0, len); umad_set_addr(umad, smLid, MAD_QP1, MAD_DEFAULT_SL, IB_DEFAULT_QP1_QKEY); /* Ignore GRH */ mad_set_field (umad_get_mad(umad), 0, IB_MAD_METHOD_F, IB_MAD_METHOD_GET_TABLE); mad_set_field (umad_get_mad(umad), 0, IB_MAD_CLASSVER_F, MAD_HEADER_CLASS_VERSION_SA); mad_set_field (umad_get_mad(umad), 0, IB_MAD_MGMTCLASS_F, IB_SA_CLASS); mad_set_field (umad_get_mad(umad), 0, IB_MAD_BASEVER_F, 1); mad_set_field64(umad_get_mad(umad), 0, IB_MAD_TRID_F, trId); mad_set_field (umad_get_mad(umad), 0, IB_MAD_ATTRID_F, IB_SA_ATTR_LFTRECORD); if (destLid > 0) { memset(&lft, 0, sizeof(lft)); lft.lid = hton16(destLid); mask = 0x1; /* lid */ memcpy((UInt8 *)umad_get_mad(umad) + IB_SA_DATA_OFFS, &lft, sizeof(lft)); } mad_set_field64(umad_get_mad(umad), 0, IB_SA_COMPMASK_F, mask); }
static void fillMAD_Delete_MCMemberRecord(UInt8 *umad, SInt64 len, UInt16 smLid, UInt64 guid, UInt64 trId, UInt8 *mgid, UInt8 *portGid) { UInt64 mask = 0; struct _MCMemberRecord mr; memset(umad, 0, len); umad_set_addr(umad, smLid, MAD_QP1, MAD_DEFAULT_SL, IB_DEFAULT_QP1_QKEY); /* Ignore GRH */ mad_set_field (umad_get_mad(umad), 0, IB_MAD_METHOD_F, IB_MAD_METHOD_DELETE); mad_set_field (umad_get_mad(umad), 0, IB_MAD_CLASSVER_F, MAD_HEADER_CLASS_VERSION_SA); mad_set_field (umad_get_mad(umad), 0, IB_MAD_MGMTCLASS_F, IB_SA_CLASS); mad_set_field (umad_get_mad(umad), 0, IB_MAD_BASEVER_F, 1); mad_set_field64(umad_get_mad(umad), 0, IB_MAD_TRID_F, trId); mad_set_field (umad_get_mad(umad), 0, IB_MAD_ATTRID_F, IB_SA_ATTR_MCRECORD); memset(&mr, 0, sizeof(mr)); memcpy(mr.mgid, mgid, 16); mask |= (1 << 0); memcpy(mr.portGid, portGid, 16); mask |= (1 << 1); mr.scope_joinState = 0x1; /* Scope remains unset */ mask |= (1 << 16); mask |= (1 << 17); memcpy((UInt8 *)umad_get_mad(umad) + IB_SA_DATA_OFFS, &mr, sizeof(mr)); mad_set_field64(umad_get_mad(umad), 0, IB_SA_COMPMASK_F, mask); }
static void fillMAD_Get_MCMemberRecord(UInt8 *umad, SInt64 len, UInt16 smLid, UInt64 guid, UInt64 trId) { memset(umad, 0, len); umad_set_addr(umad, smLid, MAD_QP1, MAD_DEFAULT_SL, IB_DEFAULT_QP1_QKEY); /* Ignore GRH */ mad_set_field (umad_get_mad(umad), 0, IB_MAD_METHOD_F, IB_MAD_METHOD_GET_TABLE); mad_set_field (umad_get_mad(umad), 0, IB_MAD_CLASSVER_F, MAD_HEADER_CLASS_VERSION_SA); mad_set_field (umad_get_mad(umad), 0, IB_MAD_MGMTCLASS_F, IB_SA_CLASS); mad_set_field (umad_get_mad(umad), 0, IB_MAD_BASEVER_F, 1); mad_set_field64(umad_get_mad(umad), 0, IB_MAD_TRID_F, trId); mad_set_field (umad_get_mad(umad), 0, IB_MAD_ATTRID_F, IB_SA_ATTR_MCRECORD); }
/* Returns 0 (invalid base version) on error */ static uint8_t get_base_version_from_ni(int fd, uint32_t aid, int pkey_index) { uint8_t rc; void *umad_p = NULL; struct umad_smp *send_mad; size_t length; umad_p = umad_alloc(1, sizeof(*send_mad) + umad_size()); if (!umad_p) { OUTPUT_ERROR ("can't alloc umad for OPA check; send_size %ld\n", sizeof(*send_mad)); return 0; } memset(umad_p, 0, sizeof(*send_mad) + umad_size()); umad_set_grh(umad_p, 0); send_mad = umad_get_mad(umad_p); send_mad->base_version = UMAD_BASE_VERSION; send_mad->mgmt_class = UMAD_CLASS_SUBN_DIRECTED_ROUTE; send_mad->class_version = 0x01; send_mad->method = UMAD_METHOD_GET; send_mad->tid = htonl(0xDEADBEEF); send_mad->attr_id = htons(UMAD_SM_ATTR_NODE_INFO); send_mad->dr_slid = 0xffff; send_mad->dr_dlid = 0xffff; umad_set_pkey(umad_p, pkey_index); umad_set_addr(umad_p, 0xffff, 0, 0, 0); rc = 0; if (umad_send(fd, aid, umad_p, sizeof(*send_mad), 100, 1) < 0) goto free_mad; length = sizeof(*send_mad); if (umad_recv(fd, umad_p, (int *)&length, 100) < 0) goto free_mad; if (length < sizeof(*send_mad)) goto free_mad; if (umad_status(umad_p) != 0) goto free_mad; rc = ((NODE_INFO *)(send_mad->data))->BaseVersion; free_mad: free(umad_p); return rc; }
static void fillMAD_Set_MCMemberRecord(UInt8 *umad, SInt64 len, UInt16 smLid, UInt64 guid, UInt64 trId, UInt8 *mgid, UInt8 *portGid) { UInt64 mask = 0; struct _MCMemberRecord mr; memset(umad, 0, len); umad_set_addr(umad, smLid, MAD_QP1, MAD_DEFAULT_SL, IB_DEFAULT_QP1_QKEY); /* Ignore GRH */ mad_set_field (umad_get_mad(umad), 0, IB_MAD_METHOD_F, IB_MAD_METHOD_SET); mad_set_field (umad_get_mad(umad), 0, IB_MAD_CLASSVER_F, MAD_HEADER_CLASS_VERSION_SA); mad_set_field (umad_get_mad(umad), 0, IB_MAD_MGMTCLASS_F, IB_SA_CLASS); mad_set_field (umad_get_mad(umad), 0, IB_MAD_BASEVER_F, 1); mad_set_field64(umad_get_mad(umad), 0, IB_MAD_TRID_F, trId); mad_set_field (umad_get_mad(umad), 0, IB_MAD_ATTRID_F, IB_SA_ATTR_MCRECORD); memset(&mr, 0, sizeof(mr)); memcpy(mr.mgid, mgid, 16); mask |= (1 << 0); memcpy(mr.portGid, portGid, 16); mask |= (1 << 1); mr.qkey = hton32(0x1); mask |= (1 << 2); mr.pkey = hton16(0xffff); mask |= (1 << 7); /* SL */ mask |= (1 << 12); /* FlowLabel */ mask |= (1 << 13); /* Traffic class */ mask |= (1 << 6); mr.scope_joinState = (0x5 << 4) | 0x1; mask |= (1 << 15); mask |= (1 << 16); memcpy((UInt8 *)umad_get_mad(umad) + IB_SA_DATA_OFFS, &mr, sizeof(mr)); mad_set_field64(umad_get_mad(umad), 0, IB_SA_COMPMASK_F, mask); }
static void fillMAD_Get_PathRecord(UInt8 *umad, SInt64 len, UInt16 smLid, UInt64 guid, UInt64 trId) { UInt8 dgid[16]; memset(umad, 0, len); umad_set_addr(umad, smLid, MAD_QP1, MAD_DEFAULT_SL, IB_DEFAULT_QP1_QKEY); /* Ignore GRH */ mad_set_field (umad_get_mad(umad), 0, IB_MAD_METHOD_F, IB_MAD_METHOD_GET); mad_set_field (umad_get_mad(umad), 0, IB_MAD_CLASSVER_F, MAD_HEADER_CLASS_VERSION_SA); mad_set_field (umad_get_mad(umad), 0, IB_MAD_MGMTCLASS_F, IB_SA_CLASS); mad_set_field (umad_get_mad(umad), 0, IB_MAD_BASEVER_F, 1); mad_set_field64(umad_get_mad(umad), 0, IB_MAD_TRID_F, trId); mad_set_field (umad_get_mad(umad), 0, IB_MAD_ATTRID_F, IB_SA_ATTR_PATHRECORD); mad_set_field64(umad_get_mad(umad), 0, IB_SA_COMPMASK_F, 0x4); mad_set_field64(dgid, 0, IB_GID_PREFIX_F, IB_DEFAULT_SUBN_PREFIX); mad_set_field64(dgid, 0, IB_GID_GUID_F , guid); /* 128 bit data */ mad_encode_field((UInt8 *)umad_get_mad(umad) + IB_SA_DATA_OFFS, IB_SA_PR_DGID_F, dgid); }
/****************************************************************************** * join_multicast_group ******************************************************************************/ int join_multicast_group(subn_adm_method method,struct mcast_parameters *params) { int portid = -1; int agentid = -1; void *umad_buff = NULL; void *mad = NULL; int length = MAD_SIZE; int test_result = 0; // mlid will be assigned to the new LID after the join if (umad_init() < 0) { fprintf(stderr, "failed to init the UMAD library\n"); goto cleanup; } /* use casting to loose the "const char0 *" */ portid = umad_open_port((char*)params->ib_devname,params->ib_port); if (portid < 0) { fprintf(stderr,"failed to open UMAD port %d\n",params->ib_port); goto cleanup; } agentid = umad_register(portid,MANAGMENT_CLASS_SUBN_ADM, 2, 0, 0); if (agentid < 0) { fprintf(stderr,"failed to register UMAD agent for MADs\n"); goto cleanup; } umad_buff = umad_alloc(1, umad_size() + MAD_SIZE); if (!umad_buff) { fprintf(stderr, "failed to allocate MAD buffer\n"); goto cleanup; } mad = umad_get_mad(umad_buff); prepare_mcast_mad(method,params,(struct sa_mad_packet_t *)mad); if (umad_set_addr(umad_buff,params->sm_lid,1,params->sm_sl,QP1_WELL_KNOWN_Q_KEY) < 0) { fprintf(stderr, "failed to set the destination address of the SMP\n"); goto cleanup; } if (umad_send(portid,agentid,umad_buff,MAD_SIZE,100,5) < 0) { fprintf(stderr, "failed to send MAD\n"); goto cleanup; } if (umad_recv(portid,umad_buff,&length,5000) < 0) { fprintf(stderr, "failed to receive MAD response\n"); goto cleanup; } if (check_mad_status((struct sa_mad_packet_t*)mad)) { fprintf(stderr, "failed to get mlid from MAD\n"); goto cleanup; } // "Join multicast group" message was sent if (method == SUBN_ADM_METHOD_SET) { get_mlid_from_mad((struct sa_mad_packet_t*)mad,¶ms->mlid); params->mcast_state |= MCAST_IS_JOINED; // "Leave multicast group" message was sent } else { params->mcast_state &= ~MCAST_IS_JOINED; } cleanup: if (umad_buff) umad_free(umad_buff); if (portid >= 0) { if (agentid >= 0) { if (umad_unregister(portid, agentid)) { fprintf(stderr, "failed to deregister UMAD agent for MADs\n"); test_result = 1; } } if (umad_close_port(portid)) { fprintf(stderr, "failed to close UMAD portid\n"); test_result = 1; } } return test_result; }
/** ========================================================================= */ FSTATUS oib_send_mad2(struct oib_port *port, uint8_t *send_mad, size_t send_size, struct oib_mad_addr *addr, int timeout_ms, int retries) { FSTATUS status = FSUCCESS; void *umad_p = NULL; int response; uint8_t mclass, class_ver; int aid; int correctedTimeout; struct umad_hdr *mad_hdr = (struct umad_hdr *)send_mad; uint16_t ib_lid; int pkey_idx; size_t padded_size; if (!port || !send_mad || !send_size || !addr) return FINVALID_PARAMETER; ib_lid = addr->lid & 0xffff; // Make sure we are registered for this class/version... mclass = mad_hdr->mgmt_class; class_ver = mad_hdr->class_version; response = (mad_hdr->method & 0x80) || (mad_hdr->method == UMAD_METHOD_TRAP_REPRESS) || (mclass == UMAD_CLASS_BM && ntohl(mad_hdr->attr_mod) & BM_ATTRIB_MOD_RESPONSE); aid = port->umad_agents[class_ver][mclass]; DBGPRINT (" Management Class 0x%x method 0x%x attrId 0x%x attrM 0x%x\n",mclass, mad_hdr->method, ntohs(mad_hdr->attr_id), ntohl(mad_hdr->attr_mod)); DBGPRINT (" base_version 0x%x class_version 0x%x\n",mad_hdr->base_version, mad_hdr->class_version); if (aid == OIB_INVALID_AGENTID) { // automatically register for "send" only int err = 0; struct oib_class_args mgmt_class[2]; memset(mgmt_class, 0, sizeof(mgmt_class)); mgmt_class[0].base_version = mad_hdr->base_version; mgmt_class[0].mgmt_class = mad_hdr->mgmt_class; mgmt_class[0].class_version = mad_hdr->class_version; mgmt_class[0].is_responding_client = 0; mgmt_class[0].is_trap_client = 0; mgmt_class[0].is_report_client = 0; mgmt_class[0].kernel_rmpp = 1; mgmt_class[0].use_methods = 0; DBGPRINT ("auto registering class 0x%02x; version 0x%x for send only\n", mclass, class_ver); if ((err = oib_bind_classes(port, mgmt_class)) != 0) { OUTPUT_ERROR ("Failed to auto register for class 0x%02x: %s\n", mclass, strerror(err)); status = FERROR; goto done; } aid = port->umad_agents[class_ver][mclass]; } // Initialize the user mad. // umad has limititation that outgoing packets must be > 36 bytes. padded_size = ( MAX(send_size,36) + 7) & ~0x7; DBGPRINT ("dlid %d qpn %d qkey %x sl %d\n", ib_lid, addr->qpn, addr->qkey, addr->sl); umad_p = umad_alloc(1, padded_size + umad_size()); if (!umad_p) { OUTPUT_ERROR ("can't alloc umad send_size %ld\n", padded_size); status = FINSUFFICIENT_MEMORY; goto done; } memset(umad_p, 0, padded_size + umad_size()); memcpy (umad_get_mad(umad_p), send_mad, send_size); /* Copy mad to umad */ umad_set_grh(umad_p, 0); pkey_idx = oib_find_pkey(port, addr->pkey); if (pkey_idx < 0) { DBGPRINT("P_Key 0x%x not found in pkey table\n", addr->pkey); if (addr->pkey == 0xffff) { pkey_idx = oib_find_pkey(port, 0x7fff); if (pkey_idx < 0) { OUTPUT_ERROR("Failed to find 0x7fff pkey defaulting to index 1\n"); pkey_idx = 1; } else { DBGPRINT("... using 0x7fff found at index %d\n", pkey_idx); } } else { // Previously, this code would try to find the limited management pkey // if it could not find the requested pkey, and use that pkey instead. // This would often "work" because all nodes should have the limited // management pkey, but b/c it was a limited member, this would result // in potential timeouts - especially where the full management pkey was // required. // Changed this code fail immediately without retrying a new pkey. OUTPUT_ERROR("Failed to find requested pkey:0x%x, class 0x%x aid:0x%x \n", addr->pkey, mclass, ntohs(mad_hdr->attr_id)); status = FPROTECTION; goto done; } } umad_set_pkey(umad_p, pkey_idx); umad_set_addr(umad_p, ib_lid?ib_lid:0xffff, addr->qpn, addr->sl, addr->qkey); if (dbg_file) { DBGPRINT(">>> sending: len %ld pktsz %zu\n", send_size, umad_size() + padded_size); umad_dump(umad_p); oib_dump_mad(dbg_file, umad_get_mad(umad_p), send_size, "send mad\n"); } correctedTimeout = (timeout_ms == OIB_SEND_TIMEOUT_DEFAULT) ? OIB_UTILS_DEF_TIMEOUT_MS : timeout_ms; if (umad_send(port->umad_fd, aid, umad_p, padded_size, (response ? 0 : correctedTimeout), retries) < 0) { OUTPUT_ERROR("send failed; %s, agent id %u MClass 0x%x method 0x%x attrId 0x%x attrM 0x%x\n", strerror(errno), aid, mclass, mad_hdr->method, ntohs(mad_hdr->attr_id), ntohl(mad_hdr->attr_mod)); status = FNOT_DONE; goto done; } done: // Free umad if allocated. if (umad_p != NULL) { umad_free(umad_p); } return status; }