in gloo/transport/ibverbs/pair.cc [405:489]
void Pair::handleCompletion(struct ibv_wc* wc) {
if (wc->opcode == IBV_WC_RECV_RDMA_WITH_IMM) {
// Incoming RDMA write completed.
// Slot is encoded in immediate data on receive work completion.
// It is set in the Pair::send function.
auto slot = wc->imm_data;
GLOO_ENFORCE_EQ(
wc->status,
IBV_WC_SUCCESS,
"Recv for slot ",
slot,
": ",
ibv_wc_status_str(wc->status));
GLOO_ENFORCE(recvCompletionHandlers_[slot] != nullptr);
recvCompletionHandlers_[slot]->handleCompletion(wc);
// Backfill receive work requests.
postReceive();
} else if (wc->opcode == IBV_WC_RDMA_WRITE) {
// Outbound RDMA write completed.
// Slot is encoded in wr_id fields on send work request. Unlike
// the receive work completions, the immediate data field on send
// work requests are not pass to the respective work completion.
auto slot = wc->wr_id;
GLOO_ENFORCE_EQ(
wc->status,
IBV_WC_SUCCESS,
"Send for slot ",
slot,
": ",
ibv_wc_status_str(wc->status));
GLOO_ENFORCE(sendCompletionHandlers_[slot] != nullptr);
sendCompletionHandlers_[slot]->handleCompletion(wc);
} else if (wc->opcode == IBV_WC_RECV) {
// Memory region recv completed.
//
// Only used by the remote side of the pair to pass ibv_mr's.
// They are written to in FIFO order, so we can pick up
// and use the first MemoryRegion instance in the list of
// mapped receive regions.
//
// The buffer trying to write to this slot might be waiting for
// the other side of this pair to send its memory region.
// Lock access, and notify anybody waiting afterwards.
//
// Slot is encoded in immediate data on receive work completion.
// It is set in the Pair::sendMemoryRegion function.
auto slot = wc->imm_data;
GLOO_ENFORCE_EQ(
wc->status,
IBV_WC_SUCCESS,
"Memory region recv for slot ",
slot,
": ",
ibv_wc_status_str(wc->status));
// Move ibv_mr from memory region 'inbox' to final slot.
const auto& mr = mappedRecvRegions_[recvPosted_ % kMaxBuffers];
peerMemoryRegions_[slot] = mr->mr();
// Notify any buffer waiting for the details of its remote peer.
cv_.notify_all();
// Backfill receive work requests.
postReceive();
} else if (wc->opcode == IBV_WC_SEND) {
// Memory region send completed.
auto slot = wc->wr_id;
GLOO_ENFORCE_EQ(
wc->status,
IBV_WC_SUCCESS,
"Memory region send for slot ",
slot,
": ",
ibv_wc_status_str(wc->status));
GLOO_ENFORCE_GT(mappedSendRegions_.size(), 0);
GLOO_ENFORCE_EQ(mappedSendRegions_.count(slot), 1);
mappedSendRegions_.erase(slot);
} else {
GLOO_ENFORCE(false, "Unexpected completion with opcode: ", wc->opcode);
}
}