| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| uint64_t mad_trid(void) |
| { |
| static uint64_t trid; |
| uint64_t next; |
| |
| if (!trid) { |
| srandom((int)time(NULL) * getpid()); |
| trid = random(); |
| } |
| next = ++trid; |
| next = GET_IB_USERLAND_TID(next); |
| return next; |
| } |
| |
| int mad_get_timeout(const struct ibmad_port *srcport, int override_ms) |
| { |
| return (override_ms ? override_ms : |
| srcport->timeout ? srcport->timeout : madrpc_timeout); |
| } |
| |
| int mad_get_retries(const struct ibmad_port *srcport) |
| { |
| return (srcport->retries ? srcport->retries : madrpc_retries); |
| } |
| |
| void *mad_encode(void *buf, ib_rpc_t * rpc, ib_dr_path_t * drpath, void *data) |
| { |
| int is_resp = rpc->method & IB_MAD_RESPONSE; |
| int mgtclass; |
| |
| |
| mad_set_field(buf, 0, IB_MAD_METHOD_F, rpc->method); |
| mad_set_field(buf, 0, IB_MAD_RESPONSE_F, is_resp ? 1 : 0); |
| mgtclass = rpc->mgtclass & 0xff; |
| if (mgtclass == IB_SA_CLASS || mgtclass == IB_CC_CLASS) |
| mad_set_field(buf, 0, IB_MAD_CLASSVER_F, 2); |
| else |
| mad_set_field(buf, 0, IB_MAD_CLASSVER_F, 1); |
| mad_set_field(buf, 0, IB_MAD_MGMTCLASS_F, rpc->mgtclass & 0xff); |
| mad_set_field(buf, 0, IB_MAD_BASEVER_F, 1); |
| |
| |
| if ((rpc->mgtclass & 0xff) == IB_SMI_DIRECT_CLASS) { |
| if (!drpath) { |
| IBWARN("encoding dr mad without drpath (null)"); |
| errno = EINVAL; |
| return NULL; |
| } |
| if (drpath->cnt >= IB_SUBNET_PATH_HOPS_MAX) { |
| IBWARN("dr path with hop count %d", drpath->cnt); |
| errno = EINVAL; |
| return NULL; |
| } |
| mad_set_field(buf, 0, IB_DRSMP_HOPCNT_F, drpath->cnt); |
| mad_set_field(buf, 0, IB_DRSMP_HOPPTR_F, |
| is_resp ? drpath->cnt + 1 : 0x0); |
| mad_set_field(buf, 0, IB_DRSMP_STATUS_F, rpc->rstatus); |
| mad_set_field(buf, 0, IB_DRSMP_DIRECTION_F, is_resp ? 1 : 0); |
| } else |
| mad_set_field(buf, 0, IB_MAD_STATUS_F, rpc->rstatus); |
| |
| |
| if (!rpc->trid) |
| rpc->trid = mad_trid(); |
| |
| mad_set_field64(buf, 0, IB_MAD_TRID_F, rpc->trid); |
| mad_set_field(buf, 0, IB_MAD_ATTRID_F, rpc->attr.id); |
| mad_set_field(buf, 0, IB_MAD_ATTRMOD_F, rpc->attr.mod); |
| |
| |
| mad_set_field64(buf, 0, IB_MAD_MKEY_F, rpc->mkey); |
| |
| if ((rpc->mgtclass & 0xff) == IB_SMI_DIRECT_CLASS) { |
| |
| mad_set_field(buf, 0, IB_DRSMP_DRDLID_F, |
| drpath->drdlid ? drpath->drdlid : 0xffff); |
| mad_set_field(buf, 0, IB_DRSMP_DRSLID_F, |
| drpath->drslid ? drpath->drslid : 0xffff); |
| |
| |
| if (is_resp) |
| mad_set_array(buf, 0, IB_DRSMP_RPATH_F, drpath->p); |
| else |
| mad_set_array(buf, 0, IB_DRSMP_PATH_F, drpath->p); |
| } |
| |
| if ((rpc->mgtclass & 0xff) == IB_SA_CLASS) |
| mad_set_field64(buf, 0, IB_SA_COMPMASK_F, rpc->mask); |
| |
| if ((rpc->mgtclass & 0xff) == IB_CC_CLASS) { |
| ib_rpc_cc_t *rpccc = (ib_rpc_cc_t *)rpc; |
| mad_set_field64(buf, 0, IB_CC_CCKEY_F, rpccc->cckey); |
| } |
| |
| if (data) |
| memcpy((char *)buf + rpc->dataoffs, data, rpc->datasz); |
| |
| |
| if (mad_is_vendor_range2(rpc->mgtclass & 0xff)) |
| mad_set_field(buf, 0, IB_VEND2_OUI_F, rpc->oui); |
| |
| return (uint8_t *) buf + IB_MAD_SIZE; |
| } |
| |
| int mad_build_pkt(void *umad, ib_rpc_t * rpc, ib_portid_t * dport, |
| ib_rmpp_hdr_t * rmpp, void *data) |
| { |
| uint8_t *p, *mad; |
| int lid_routed = (rpc->mgtclass & 0xff) != IB_SMI_DIRECT_CLASS; |
| int is_smi = ((rpc->mgtclass & 0xff) == IB_SMI_CLASS || |
| (rpc->mgtclass & 0xff) == IB_SMI_DIRECT_CLASS); |
| struct ib_mad_addr addr; |
| |
| if (!is_smi) |
| umad_set_addr(umad, dport->lid, dport->qp, dport->sl, |
| dport->qkey); |
| else if (lid_routed) |
| umad_set_addr(umad, dport->lid, dport->qp, 0, 0); |
| else if ((dport->drpath.drslid != 0xffff) && (dport->lid > 0)) |
| umad_set_addr(umad, dport->lid, 0, 0, 0); |
| else |
| umad_set_addr(umad, 0xffff, 0, 0, 0); |
| |
| if (dport->grh_present && !is_smi) { |
| addr.grh_present = 1; |
| memcpy(addr.gid, dport->gid, 16); |
| addr.hop_limit = 0xff; |
| addr.traffic_class = 0; |
| addr.flow_label = 0; |
| umad_set_grh(umad, &addr); |
| } else |
| umad_set_grh(umad, NULL); |
| umad_set_pkey(umad, is_smi ? 0 : dport->pkey_idx); |
| |
| mad = umad_get_mad(umad); |
| p = mad_encode(mad, rpc, lid_routed ? NULL : &dport->drpath, data); |
| if (!p) |
| return -1; |
| |
| if (!is_smi && rmpp) { |
| mad_set_field(mad, 0, IB_SA_RMPP_VERS_F, 1); |
| mad_set_field(mad, 0, IB_SA_RMPP_TYPE_F, rmpp->type); |
| mad_set_field(mad, 0, IB_SA_RMPP_RESP_F, 0x3f); |
| mad_set_field(mad, 0, IB_SA_RMPP_FLAGS_F, rmpp->flags); |
| mad_set_field(mad, 0, IB_SA_RMPP_STATUS_F, rmpp->status); |
| mad_set_field(mad, 0, IB_SA_RMPP_D1_F, rmpp->d1.u); |
| mad_set_field(mad, 0, IB_SA_RMPP_D2_F, rmpp->d2.u); |
| } |
| |
| return ((int)(p - mad)); |
| } |