Beispiel #1
0
void rxd_ep_check_unexp_tag_list(struct rxd_ep *ep, struct rxd_trecv_entry *trecv_entry)
{
	struct dlist_entry *match;
	struct rxd_rx_entry *rx_entry;
	struct rxd_pkt_data_start *pkt_start;

	FI_DBG(&rxd_prov, FI_LOG_EP_CTRL, "ep->num_unexp_msg: %d\n", ep->num_unexp_msg);
	FI_DBG(&rxd_prov, FI_LOG_EP_CTRL, "ep->num_unexp_pkt: %d\n", ep->num_unexp_pkt);
	match = dlist_find_first_match(&ep->unexp_tag_list, &rxd_match_unexp_tag,
				       (void *) trecv_entry);
	if (match) {
		dlist_remove(match);
		dlist_remove(&trecv_entry->entry);
		ep->num_unexp_msg--;

		rx_entry = container_of(match, struct rxd_rx_entry, unexp_entry);
		rx_entry->trecv = trecv_entry;
		FI_DBG(&rxd_prov, FI_LOG_EP_CTRL, "progressing unexp tagged recv [%p]\n",
			rx_entry->msg_id);

		pkt_start = (struct rxd_pkt_data_start *) rx_entry->unexp_buf->buf;
		rxd_ep_handle_data_msg(ep, rx_entry->peer_info, rx_entry, rx_entry->trecv->iov,
				     rx_entry->trecv->msg.iov_count, &pkt_start->ctrl,
				     pkt_start->data, rx_entry->unexp_buf);
		rxd_ep_repost_buff(rx_entry->unexp_buf);
	}
}
Beispiel #2
0
static void rxd_handle_connect_ack(struct rxd_ep *ep, struct ofi_ctrl_hdr *ctrl,
				   struct rxd_rx_buf *rx_buf)
{
	struct rxd_peer *peer;
	struct dlist_entry *match;
	struct rxd_tx_entry *tx_entry;

	FI_INFO(&rxd_prov, FI_LOG_EP_CTRL,
		"connect ack- msg_id: %" PRIu64 ", segno: %d\n",
		ctrl->msg_id, ctrl->seg_no);

	match = dlist_find_first_match(&ep->tx_entry_list,
					rxd_conn_msg_match, ctrl);
	if (!match) {
		FI_INFO(&rxd_prov, FI_LOG_EP_CTRL, "no matching connect\n");
		goto out;
	}

	tx_entry = container_of(match, struct rxd_tx_entry, entry);
	peer = rxd_ep_getpeer_info(ep, tx_entry->peer);
	peer->state = CMAP_CONNECTED;
	peer->conn_data = ctrl->conn_id;

	dlist_remove(match);
	rxd_tx_entry_done(ep, tx_entry);
out:
	rxd_ep_repost_buff(rx_buf);
}
Beispiel #3
0
int rxd_handle_ack(struct rxd_ep *ep, struct ofi_ctrl_hdr *ctrl,
		    struct rxd_rx_buf *rx_buf)
{
	int ret = 0;
	uint64_t idx;
	struct rxd_tx_entry *tx_entry;
	struct dlist_entry *item;
	struct rxd_pkt_meta *pkt;

	rxd_ep_lock_if_required(ep);
	FI_DBG(&rxd_prov, FI_LOG_EP_CTRL, "got ack: msg: %p - %d\n",
		ctrl->msg_id, ctrl->seg_no);

	idx = ctrl->msg_id & RXD_TX_IDX_BITS;
	tx_entry = &ep->tx_entry_fs->buf[idx];
	if (tx_entry->msg_id != ctrl->msg_id)
		goto out;

	item = dlist_find_first_match(&tx_entry->pkt_list, rxd_tx_pkt_match, ctrl);
	if (!item)
		goto out;

	pkt = container_of(item, struct rxd_pkt_meta, entry);
	switch (pkt->type) {

	case RXD_PKT_STRT:
	case RXD_PKT_DATA:
		ret = rxd_tx_entry_progress(ep, tx_entry, ctrl);
		break;

	case RXD_PKT_LAST:
		rxd_ep_free_acked_pkts(ep, tx_entry, ctrl->seg_no);
		FI_DBG(&rxd_prov, FI_LOG_EP_CTRL, "reporting TX completion : %p\n", tx_entry);
		if (tx_entry->op_type != RXD_TX_READ_REQ) {
			rxd_cq_report_tx_comp(ep->tx_cq, tx_entry);
			rxd_tx_entry_done(ep, tx_entry);
		}
		break;
	default:
		FI_WARN(&rxd_prov, FI_LOG_EP_CTRL, "invalid pkt type\n");
		break;
	}
out:
	rxd_ep_repost_buff(rx_buf);
	rxd_ep_unlock_if_required(ep);
	return ret;
}
Beispiel #4
0
void rxd_handle_recv_comp(struct rxd_ep *ep, struct fi_cq_msg_entry *comp)
{
	struct ofi_ctrl_hdr *ctrl;
	struct rxd_rx_buf *rx_buf;
	struct rxd_peer *peer;

	FI_DBG(&rxd_prov, FI_LOG_EP_CTRL, "got recv completion\n");

	assert(rxd_reposted_bufs);
	rxd_reposted_bufs--;

	rx_buf = container_of(comp->op_context, struct rxd_rx_buf, context);
	ctrl = (struct ofi_ctrl_hdr *) rx_buf->buf;
	peer = rxd_ep_getpeer_info(ep, ctrl->conn_id);

	if (ctrl->version != OFI_CTRL_VERSION) {
		FI_WARN(&rxd_prov, FI_LOG_EP_CTRL, "ctrl version mismatch\n");
		return;
	}

	switch (ctrl->type) {
	case ofi_ctrl_connreq:
		rxd_handle_conn_req(ep, ctrl, comp, rx_buf);
		break;
	case ofi_ctrl_ack:
		rxd_handle_ack(ep, ctrl, rx_buf);
		break;
	case ofi_ctrl_discard:
		rxd_handle_discard(ep, ctrl, rx_buf);
		break;
	case ofi_ctrl_connresp:
		rxd_handle_connect_ack(ep, ctrl, rx_buf);
		break;
	case ofi_ctrl_start_data:
		rxd_handle_start_data(ep, peer, ctrl, comp, rx_buf);
		break;
	case ofi_ctrl_data:
		rxd_handle_data(ep, peer, ctrl, comp, rx_buf);
		break;
	default:
		rxd_ep_repost_buff(rx_buf);
		FI_WARN(&rxd_prov, FI_LOG_EP_CTRL,
			"invalid ctrl type \n", ctrl->type);
	}

	rxd_check_waiting_rx(ep);
}
Beispiel #5
0
void rxd_handle_discard(struct rxd_ep *ep, struct ofi_ctrl_hdr *ctrl,
			struct rxd_rx_buf *rx_buf)
{
	uint64_t idx;
	struct rxd_tx_entry *tx_entry;

	rxd_ep_lock_if_required(ep);
	FI_DBG(&rxd_prov, FI_LOG_EP_CTRL, "got Reject: msg: %p - %d\n",
		ctrl->msg_id, ctrl->seg_no);

	idx = ctrl->msg_id & RXD_TX_IDX_BITS;
	tx_entry = &ep->tx_entry_fs->buf[idx];
	if (tx_entry->msg_id != ctrl->msg_id)
		goto out;

	rxd_tx_entry_discard(ep, tx_entry);
out:
	rxd_ep_repost_buff(rx_buf);
	rxd_ep_unlock_if_required(ep);
}
Beispiel #6
0
/*
 * Discarded transfers were discarded by the receiving side, so we abort
 * transferring the rest of the data.  However, the completion is still
 * reported to the sender as successful.  This ensures that short and long
 * messages are treated the same, since short messages would be entirely
 * buffered at the receiver, with no notification that the application later
 * discarded the message.
 */
static void rxd_handle_discard(struct rxd_ep *ep, struct ofi_ctrl_hdr *ctrl,
			       struct rxd_rx_buf *rx_buf)
{
	struct rxd_tx_entry *tx_entry;
	uint64_t idx;

	FI_DBG(&rxd_prov, FI_LOG_EP_CTRL,
	       "discard- msg_id: %" PRIu64 ", segno: %d\n",
	       ctrl->msg_id, ctrl->seg_no);

	idx = ctrl->msg_id & RXD_TX_IDX_BITS;
	tx_entry = &ep->tx_entry_fs->buf[idx];
	if (tx_entry->msg_id == ctrl->msg_id) {
		rxd_cq_report_tx_comp(rxd_ep_tx_cq(ep), tx_entry);
		rxd_cntr_report_tx_comp(ep, tx_entry);
		rxd_tx_entry_done(ep, tx_entry);
	}

	rxd_ep_repost_buff(rx_buf);
}
Beispiel #7
0
int rxd_handle_nack(struct rxd_ep *ep, struct ofi_ctrl_hdr *ctrl,
		     struct rxd_rx_buf *rx_buf)
{
	int ret = 0;
	uint64_t idx;
	struct rxd_tx_entry *tx_entry;

	rxd_ep_lock_if_required(ep);
	FI_DBG(&rxd_prov, FI_LOG_EP_CTRL, "got NACK: msg: %p - %d\n",
		ctrl->msg_id, ctrl->seg_no);

	idx = ctrl->msg_id & RXD_TX_IDX_BITS;
	tx_entry = &ep->tx_entry_fs->buf[idx];
	if (tx_entry->msg_id != ctrl->msg_id)
		goto out;

	ret = rxd_tx_entry_progress(ep, tx_entry, ctrl);
out:
	rxd_ep_repost_buff(rx_buf);
	rxd_ep_unlock_if_required(ep);
	return ret;
}
Beispiel #8
0
int rxd_handle_conn_req(struct rxd_ep *ep, struct ofi_ctrl_hdr *ctrl,
			 struct fi_cq_msg_entry *comp,
			 struct rxd_rx_buf *rx_buf)
{
	int ret;
	void *addr;
	size_t addrlen;
	uint64_t peer;
	struct rxd_pkt_data *pkt_data;
	struct rxd_peer *peer_info;

	rxd_ep_lock_if_required(ep);

	pkt_data = (struct rxd_pkt_data *) ctrl;
	addr = pkt_data->data;
	addrlen = ctrl->seg_size;

	ret = rxd_av_dg_reverse_lookup(ep->av, ctrl->rx_key, addr, addrlen, &peer);
	if (ret == -FI_ENODATA) {
		ret = rxd_av_insert_dg_av(ep->av, addr);
		assert(ret == 1);

		ret = rxd_av_dg_reverse_lookup(ep->av, ctrl->rx_key, addr, addrlen, &peer);
		assert(ret == 0);
	}

	peer_info = rxd_ep_getpeer_info(ep, peer);
	if (!peer_info->addr_published) {
		peer_info->addr_published = 1;
		peer_info->conn_initiated = 1;
		peer_info->conn_data = ctrl->conn_id;
		peer_info->exp_msg_id++;
	}

	rxd_ep_reply_ack(ep, ctrl, ofi_ctrl_connresp, 0, ctrl->conn_id, peer, peer);
	rxd_ep_repost_buff(rx_buf);
	rxd_ep_unlock_if_required(ep);
	return ret;
}
Beispiel #9
0
static void rxd_handle_conn_req(struct rxd_ep *ep, struct ofi_ctrl_hdr *ctrl,
				struct fi_cq_msg_entry *comp,
				struct rxd_rx_buf *rx_buf)
{
	struct rxd_pkt_data *pkt_data;
	struct rxd_peer *peer_info;
	fi_addr_t dg_fiaddr;
	void *addr;
	int ret;

	FI_INFO(&rxd_prov, FI_LOG_EP_DATA,
	       "conn req - rx_key: %" PRIu64 "\n", ctrl->rx_key);

	pkt_data = (struct rxd_pkt_data *) ctrl;
	addr = pkt_data->data;
	if (ctrl->seg_size > RXD_MAX_DGRAM_ADDR) {
		FI_WARN(&rxd_prov, FI_LOG_EP_DATA, "addr too large\n");
		goto repost;
	}

	ret = rxd_av_insert_dg_addr(rxd_ep_av(ep), ctrl->rx_key, addr, &dg_fiaddr);
	if (ret) {
		FI_WARN(&rxd_prov, FI_LOG_EP_DATA, "failed to insert peer address\n");
		goto repost;
	}

	peer_info = rxd_ep_getpeer_info(ep, dg_fiaddr);
	if (peer_info->state != CMAP_CONNECTED) {
		peer_info->state = CMAP_CONNECTED;
		peer_info->conn_data = ctrl->conn_id;
		peer_info->exp_msg_id++;
	}

	rxd_ep_reply_ack(ep, ctrl, ofi_ctrl_connresp, 0, ctrl->conn_id,
			 dg_fiaddr, dg_fiaddr);
repost:
	rxd_ep_repost_buff(rx_buf);
}
Beispiel #10
0
void rxd_handle_connect_ack(struct rxd_ep *ep, struct ofi_ctrl_hdr *ctrl,
			     struct rxd_rx_buf *rx_buf)
{
	struct rxd_peer *peer;
	struct dlist_entry *match;
	struct rxd_tx_entry *tx_entry;

	rxd_ep_lock_if_required(ep);
	match = dlist_find_first_match(&ep->tx_entry_list, rxd_conn_msg_match, ctrl);
	if (!match)
		goto out;

	tx_entry = container_of(match, struct rxd_tx_entry, entry);
	peer = rxd_ep_getpeer_info(ep, tx_entry->peer);
	peer->addr_published = 1;
	peer->conn_data = ctrl->conn_id;

	dlist_remove(match);
	rxd_tx_entry_done(ep, tx_entry);
out:
	rxd_ep_repost_buff(rx_buf);
	rxd_ep_unlock_if_required(ep);
}
Beispiel #11
0
static void rxd_handle_ack(struct rxd_ep *ep, struct ofi_ctrl_hdr *ctrl,
			   struct rxd_rx_buf *rx_buf)
{
	struct rxd_tx_entry *tx_entry;
	uint64_t idx;

	FI_DBG(&rxd_prov, FI_LOG_EP_CTRL,
	       "ack- msg_id: %" PRIu64 ", segno: %d, segsz: %d, buf: %p\n",
	       ctrl->msg_id, ctrl->seg_no, ctrl->seg_size, rx_buf);

	idx = ctrl->msg_id & RXD_TX_IDX_BITS;
	tx_entry = &ep->tx_entry_fs->buf[idx];
	if (tx_entry->msg_id != ctrl->msg_id)
		goto out;

	rxd_ep_free_acked_pkts(ep, tx_entry, ctrl->seg_no);
	if ((tx_entry->bytes_sent == tx_entry->op_hdr.size) &&
	    dlist_empty(&tx_entry->pkt_list)) {
		FI_DBG(&rxd_prov, FI_LOG_EP_CTRL,
			"reporting TX completion : %p\n", tx_entry);
		if (tx_entry->op_type != RXD_TX_READ_REQ) {
			rxd_cq_report_tx_comp(rxd_ep_tx_cq(ep), tx_entry);
			rxd_cntr_report_tx_comp(ep, tx_entry);
			rxd_tx_entry_free(ep, tx_entry);
		}
	} else {
		tx_entry->rx_key = ctrl->rx_key;
		/* do not allow reduce window size (on duplicate acks) */
		tx_entry->window = MAX(tx_entry->window, ctrl->seg_no + ctrl->seg_size);
		FI_DBG(&rxd_prov, FI_LOG_EP_CTRL,
		       "ack- msg_id: %" PRIu64 ", window: %d\n",
		       ctrl->msg_id, tx_entry->window);
	}
out:
	rxd_ep_repost_buff(rx_buf);
}
Beispiel #12
0
void rxd_handle_data(struct rxd_ep *ep, struct rxd_peer *peer,
		      struct ofi_ctrl_hdr *ctrl, struct fi_cq_msg_entry *comp,
		      struct rxd_rx_buf *rx_buf)
{
	int ret;
	struct rxd_rx_entry *rx_entry;
	struct rxd_tx_entry *tx_entry;
	struct rxd_pkt_data *pkt_data = (struct rxd_pkt_data *) ctrl;
	uint16_t win_sz;
	uint64_t curr_stamp;

	rxd_ep_lock_if_required(ep);
	rx_entry = &ep->rx_entry_fs->buf[ctrl->rx_key];

	ret = rxd_check_data_pkt_order(ep, peer, ctrl, rx_entry);
	if (ret == RXD_PKT_ORDR_DUP) {
		FI_DBG(&rxd_prov, FI_LOG_EP_CTRL,
			"duplicate pkt: %d expected:%d, rx-key:%d, ctrl_msg_id: %p\n",
			ctrl->seg_no, rx_entry->exp_seg_no, ctrl->rx_key, ctrl->msg_id);

		win_sz = (rx_entry->msg_id == ctrl->msg_id &&
			  rx_entry->last_win_seg == ctrl->seg_no) ? rx_entry->window : 0;
		rxd_ep_reply_ack(ep, ctrl, ofi_ctrl_ack, win_sz,
			       ctrl->rx_key, peer->conn_data, ctrl->conn_id);

		goto repost;
	} else if (ret == RXD_PKT_ORDR_UNEXP) {
		if (!(comp->flags & RXD_UNEXP_ENTRY)) {
			curr_stamp = fi_gettime_us();
			if (rx_entry->nack_stamp == 0 ||
			    (curr_stamp > rx_entry->nack_stamp &&
			     curr_stamp - rx_entry->nack_stamp > RXD_RETRY_TIMEOUT)) {

				FI_DBG(&rxd_prov, FI_LOG_EP_CTRL,
				       "unexpected pkt, sending NACK: %d\n", ctrl->seg_no);

				rx_entry->nack_stamp = curr_stamp;
				rxd_ep_reply_nack(ep, ctrl, rx_entry->exp_seg_no,
						ctrl->rx_key, peer->conn_data,
						ctrl->conn_id);
			}
			rxd_ep_enqueue_pkt(ep, ctrl, comp);
		}
		goto out;
	}

	rx_entry->nack_stamp = 0;
	FI_DBG(&rxd_prov, FI_LOG_EP_CTRL, "expected pkt: %d\n", ctrl->seg_no);
	switch (rx_entry->op_hdr.op) {
	case ofi_op_msg:
		rxd_ep_handle_data_msg(ep, peer, rx_entry, rx_entry->recv->iov,
				     rx_entry->recv->msg.iov_count, ctrl,
				     pkt_data->data, rx_buf);
		break;

	case ofi_op_tagged:
		rxd_ep_handle_data_msg(ep, peer, rx_entry, rx_entry->trecv->iov,
				     rx_entry->trecv->msg.iov_count, ctrl,
				     pkt_data->data, rx_buf);
		break;

	case ofi_op_write:
		rxd_ep_handle_data_msg(ep, peer, rx_entry, rx_entry->write.iov,
				       rx_entry->op_hdr.iov_count, ctrl,
				       pkt_data->data, rx_buf);
		break;

	case ofi_op_read_rsp:
		tx_entry = rx_entry->read_rsp.tx_entry;
		rxd_ep_handle_data_msg(ep, peer, rx_entry, tx_entry->read_req.dst_iov,
				       tx_entry->read_req.msg.iov_count, ctrl,
				       pkt_data->data, rx_buf);
		break;

	case ofi_op_atomic:
	default:
		FI_WARN(&rxd_prov, FI_LOG_EP_CTRL, "invalid op type\n");
	}

repost:
	if (comp->flags & RXD_UNEXP_ENTRY) {
		rxd_release_unexp_entry(ep->rx_cq, comp);
		ep->num_unexp_pkt--;
	}

	rxd_ep_repost_buff(rx_buf);
out:
	rxd_ep_unlock_if_required(ep);
}
Beispiel #13
0
void rxd_handle_start_data(struct rxd_ep *ep, struct rxd_peer *peer,
			   struct ofi_ctrl_hdr *ctrl,
			   struct fi_cq_msg_entry *comp,
			   struct rxd_rx_buf *rx_buf)
{
	int ret;
	struct rxd_rx_entry *rx_entry;
	struct rxd_pkt_data_start *pkt_start;
	pkt_start = (struct rxd_pkt_data_start *) ctrl;

	rxd_ep_lock_if_required(ep);
	if (pkt_start->op.version != OFI_OP_VERSION) {
		FI_WARN(&rxd_prov, FI_LOG_EP_CTRL, "op version mismatch\n");
		goto repost;
	}

	ret = rxd_check_start_pkt_order(ep, peer, ctrl, comp);
	if (ret == RXD_PKT_ORDR_DUP) {
		FI_DBG(&rxd_prov, FI_LOG_EP_CTRL, "duplicate pkt: %d\n", ctrl->seg_no);
		rxd_handle_dup_datastart(ep, ctrl, rx_buf);
		goto repost;
	} else if (ret == RXD_PKT_ORDR_UNEXP) {
		FI_DBG(&rxd_prov, FI_LOG_EP_CTRL, "unexpected pkt: %d\n", ctrl->seg_no);
		rxd_ep_enqueue_pkt(ep, ctrl, comp);
		goto out;
	}

	rx_entry = rxd_get_rx_entry(ep);
	if (!rx_entry)
		goto repost;

	rx_entry->peer_info = peer;
	rx_entry->op_hdr = pkt_start->op;
	rx_entry->exp_seg_no = 0;
	rx_entry->msg_id = ctrl->msg_id;
	rx_entry->done = 0;
	rx_entry->peer = ctrl->conn_id;
	rx_entry->source = (ep->caps & FI_DIRECTED_RECV) ?
		rxd_av_get_fi_addr(ep->av, ctrl->conn_id) : FI_ADDR_UNSPEC;
	rx_entry->window = 1;
	rx_entry->last_win_seg = 1;

	FI_DBG(&rxd_prov, FI_LOG_EP_CTRL, "Assign rx_entry :%d for  %p\n",
	       rx_entry->key, rx_entry->msg_id);

	ep->credits--;
	ret = rxd_process_start_data(ep, rx_entry, peer, ctrl, comp, rx_buf);
	if (ret == -FI_ENOMEM)
		rxd_rx_entry_release(ep, rx_entry);
	else if (ret == -FI_ENOENT) {
		peer->exp_msg_id++;

		/* reply ack, with win_sz = 0 */
		FI_DBG(&rxd_prov, FI_LOG_EP_CTRL, "Sending wait-ACK [%p] - %d\n",
			ctrl->msg_id, ctrl->seg_no);
		goto out;
	} else {
		peer->exp_msg_id++;
	}

repost:
	if (comp->flags & RXD_UNEXP_ENTRY) {
		rxd_release_unexp_entry(ep->rx_cq, comp);
		ep->num_unexp_pkt--;
	}
	rxd_ep_repost_buff(rx_buf);
out:
	rxd_ep_unlock_if_required(ep);
	return;
}
Beispiel #14
0
static void rxd_handle_start_data(struct rxd_ep *ep, struct rxd_peer *peer,
				  struct ofi_ctrl_hdr *ctrl,
				  struct fi_cq_msg_entry *comp,
				  struct rxd_rx_buf *rx_buf)
{
	struct rxd_rx_entry *rx_entry;
	struct rxd_pkt_data_start *pkt_start;
	int ret;

	FI_DBG(&rxd_prov, FI_LOG_EP_CTRL,
	       "start data- msg_id: %" PRIu64 ", segno: %d, buf: %p\n",
	       ctrl->msg_id, ctrl->seg_no, rx_buf);

	pkt_start = (struct rxd_pkt_data_start *) ctrl;
	if (pkt_start->op.version != OFI_OP_VERSION) {
		FI_WARN(&rxd_prov, FI_LOG_EP_CTRL, "op version mismatch\n");
		goto repost;
	}

	ret = rxd_check_start_pkt_order(ep, peer, ctrl, comp);
	if (ret) {
		if (ret == -FI_EALREADY) {
			FI_DBG(&rxd_prov, FI_LOG_EP_CTRL, "duplicate pkt: %d\n",
				ctrl->seg_no);
			rxd_handle_dup_datastart(ep, ctrl, rx_buf);
			goto repost;
		} else {
			FI_DBG(&rxd_prov, FI_LOG_EP_CTRL, "unexpected pkt: %d\n",
				ctrl->seg_no);
			goto repost;
		}
	}

	rx_entry = rxd_rx_entry_alloc(ep);
	if (!rx_entry)
		goto repost;

	rx_entry->peer_info = peer;
	rx_entry->op_hdr = pkt_start->op;
	rx_entry->exp_seg_no = 0;
	rx_entry->msg_id = ctrl->msg_id;
	rx_entry->done = 0;
	rx_entry->peer = ctrl->conn_id;
	rx_entry->source = (ep->util_ep.caps & FI_DIRECTED_RECV) ?
		rxd_av_fi_addr(rxd_ep_av(ep), ctrl->conn_id) : FI_ADDR_UNSPEC;
	rx_entry->credits = 1;
	rx_entry->last_win_seg = 1;

	FI_DBG(&rxd_prov, FI_LOG_EP_CTRL, "Assign rx_entry :%d for  %p\n",
	       rx_entry->key, rx_entry->msg_id);

	ep->credits--;
	ret = rxd_process_start_data(ep, rx_entry, peer, ctrl, comp, rx_buf);
	if (ret == -FI_ENOMEM)
		rxd_rx_entry_free(ep, rx_entry);
	else if (ret == -FI_ENOENT) {
		peer->exp_msg_id++;

		/* reply ack, with no window = 0 */
		FI_DBG(&rxd_prov, FI_LOG_EP_CTRL, "Sending wait-ACK [%p] - %d\n",
			ctrl->msg_id, ctrl->seg_no);
		goto out;
	} else {
		peer->exp_msg_id++;
	}

repost:
	rxd_ep_repost_buff(rx_buf);
out:
	assert(rxd_reposted_bufs);
	return;
}
Beispiel #15
0
static void rxd_handle_data(struct rxd_ep *ep, struct rxd_peer *peer,
			    struct ofi_ctrl_hdr *ctrl, struct fi_cq_msg_entry *comp,
			    struct rxd_rx_buf *rx_buf)
{
	struct rxd_rx_entry *rx_entry;
	struct rxd_tx_entry *tx_entry;
	struct rxd_pkt_data *pkt_data = (struct rxd_pkt_data *) ctrl;
	uint16_t credits;
	int ret;

	FI_DBG(&rxd_prov, FI_LOG_EP_CTRL,
	       "data pkt- msg_id: %" PRIu64 ", segno: %d, buf: %p\n",
	       ctrl->msg_id, ctrl->seg_no, rx_buf);

	rx_entry = &ep->rx_entry_fs->buf[ctrl->rx_key];

	ret = rxd_check_data_pkt_order(ep, peer, ctrl, rx_entry);
	if (ret) {
		if (ret == -FI_EALREADY) {
			FI_DBG(&rxd_prov, FI_LOG_EP_CTRL, "duplicate pkt: %d "
				"expected:%d, rx-key:%d, ctrl_msg_id: %p\n",
				ctrl->seg_no, rx_entry->exp_seg_no, ctrl->rx_key,
				ctrl->msg_id);

			credits = ((rx_entry->msg_id == ctrl->msg_id) &&
				  (rx_entry->last_win_seg == ctrl->seg_no)) ?
				  rx_entry->credits : 0;
			rxd_ep_reply_ack(ep, ctrl, ofi_ctrl_ack, credits,
				       ctrl->rx_key, peer->conn_data,
				       ctrl->conn_id);
			goto repost;
		} else {
			FI_DBG(&rxd_prov, FI_LOG_EP_CTRL, "invalid pkt: segno: %d "
			       "expected:%d, rx-key:%d, ctrl_msg_id: %ld, "
			       "rx_entry_msg_id: %ld\n",
			       ctrl->seg_no, rx_entry->exp_seg_no, ctrl->rx_key,
			       ctrl->msg_id, rx_entry->msg_id);
			FI_DBG(&rxd_prov, FI_LOG_EP_CTRL, "invalid pkt: "
			       "credits: %d, last win: %d\n",
			       rx_entry->credits, rx_entry->last_win_seg);
			credits = (rx_entry->msg_id == ctrl->msg_id) ?
				  rx_entry->last_win_seg - rx_entry->exp_seg_no : 0;
			rxd_ep_reply_ack(ep, ctrl, ofi_ctrl_ack, credits,
				       ctrl->rx_key, peer->conn_data,
				       ctrl->conn_id);
			goto repost;
		}
	}

	rx_entry->nack_stamp = 0;
	FI_DBG(&rxd_prov, FI_LOG_EP_CTRL, "expected pkt: %d\n", ctrl->seg_no);
	switch (rx_entry->op_hdr.op) {
	case ofi_op_msg:
		rxd_ep_handle_data_msg(ep, peer, rx_entry, rx_entry->recv->iov,
				     rx_entry->recv->msg.iov_count, ctrl,
				     pkt_data->data, rx_buf);
		break;
	case ofi_op_tagged:
		rxd_ep_handle_data_msg(ep, peer, rx_entry, rx_entry->trecv->iov,
				     rx_entry->trecv->msg.iov_count, ctrl,
				     pkt_data->data, rx_buf);
		break;
	case ofi_op_write:
		rxd_ep_handle_data_msg(ep, peer, rx_entry, rx_entry->write.iov,
				       rx_entry->op_hdr.iov_count, ctrl,
				       pkt_data->data, rx_buf);
		break;
	case ofi_op_read_rsp:
		tx_entry = rx_entry->read_rsp.tx_entry;
		rxd_ep_handle_data_msg(ep, peer, rx_entry, tx_entry->read_req.dst_iov,
				       tx_entry->read_req.msg.iov_count, ctrl,
				       pkt_data->data, rx_buf);
		break;
	case ofi_op_atomic:
	default:
		FI_WARN(&rxd_prov, FI_LOG_EP_CTRL, "invalid op type\n");
	}

repost:
	rxd_ep_repost_buff(rx_buf);
}