Пример #1
0
ib_api_status_t
osmv_txn_init_rmpp_sender(IN osm_bind_handle_t h_bind,
			  IN osmv_txn_ctx_t * p_txn, IN osm_madw_t * p_madw)
{
	ib_api_status_t st;

	CL_ASSERT(p_txn);

	/* Double-Sided RMPP Direction Switch */
	osmv_txn_remove_timeout_ev(h_bind, osmv_txn_get_key(p_txn));

	p_txn->rmpp_txfr.rmpp_state = OSMV_TXN_RMPP_SENDER;
	p_txn->rmpp_txfr.p_rmpp_send_ctx = malloc(sizeof(osmv_rmpp_send_ctx_t));

	if (!p_txn->rmpp_txfr.p_rmpp_send_ctx) {
		return IB_INSUFFICIENT_MEMORY;
	}

	memset(p_txn->rmpp_txfr.p_rmpp_send_ctx, 0,
	       sizeof(osmv_rmpp_send_ctx_t));

	st = osmv_rmpp_send_ctx_init(p_txn->rmpp_txfr.p_rmpp_send_ctx,
				     (void *)p_madw->p_mad,
				     p_madw->mad_size, p_txn->p_log);
	return st;
}
Пример #2
0
ib_api_status_t
osmv_txn_init_rmpp_receiver(IN osm_bind_handle_t h_bind,
			    IN osmv_txn_ctx_t * p_txn,
			    IN boolean_t is_init_by_peer)
{
	ib_api_status_t st;
	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
	uint64_t key = osmv_txn_get_key(p_txn);

	CL_ASSERT(p_txn);

	/* Double-Sided RMPP Direction Switch */
	osmv_txn_remove_timeout_ev(h_bind, key);

	/* Set the Transaction Timeout value */
	st = osmv_txn_set_timeout_ev(h_bind, key,
				     p_bo->p_vendor->ttime_timeout);
	if (IB_SUCCESS != st) {

		return st;
	}

	p_txn->rmpp_txfr.rmpp_state = OSMV_TXN_RMPP_RECEIVER;
	p_txn->rmpp_txfr.is_rmpp_init_by_peer = is_init_by_peer;

	p_txn->rmpp_txfr.p_rmpp_recv_ctx = malloc(sizeof(osmv_rmpp_recv_ctx_t));

	if (!p_txn->rmpp_txfr.p_rmpp_recv_ctx) {

		osmv_txn_remove_timeout_ev(h_bind, key);
		return IB_INSUFFICIENT_MEMORY;
	}

	memset(p_txn->rmpp_txfr.p_rmpp_recv_ctx, 0,
	       sizeof(osmv_rmpp_recv_ctx_t));

	st = osmv_rmpp_recv_ctx_init(p_txn->rmpp_txfr.p_rmpp_recv_ctx,
				     p_txn->p_log);

	return st;
}
Пример #3
0
void
osmv_txn_done(IN osm_bind_handle_t h_bind,
	      IN uint64_t key, IN boolean_t is_in_cb)
{
	osmv_txn_ctx_t *p_ctx;
	osmv_bind_obj_t *const p_bo = (osmv_bind_obj_t *) h_bind;

	OSM_LOG_ENTER(p_bo->p_vendor->p_log);

	CL_ASSERT(h_bind);

	/* Cancel the (single) timeout possibly outstanding for this txn
	 * Don't do this if you are in the callback context, for 2 reasons:
	 * (1) The event wheel will remove the context itself.
	 * (2) If we try to, there is a deadlock in the event wheel
	 */
	if (FALSE == is_in_cb) {
		osmv_txn_remove_timeout_ev(h_bind, key);
	}

	/* Remove from DB */
	if (IB_NOT_FOUND ==
	    __osmv_txnmgr_remove_txn(&p_bo->txn_mgr, key, &p_ctx)) {
		return;
	}

	/* Destroy the transaction's RMPP contexts
	 * (can be more than one in the case of double sided transfer)
	 */

	if (p_ctx->rmpp_txfr.p_rmpp_send_ctx) {
		osmv_rmpp_send_ctx_done(p_ctx->rmpp_txfr.p_rmpp_send_ctx);
	}

	if (p_ctx->rmpp_txfr.p_rmpp_recv_ctx) {
		osmv_rmpp_recv_ctx_done(p_ctx->rmpp_txfr.p_rmpp_recv_ctx);
	}

	free(p_ctx);

	OSM_LOG_EXIT(p_bo->p_vendor->p_log);
}
static void
__osmv_dispatch_rmpp_snd(IN osm_bind_handle_t h_bind,
			 IN const ib_mad_t * p_mad,
			 IN osmv_txn_ctx_t * p_txn,
			 IN const osm_mad_addr_t * p_mad_addr)
{
	osmv_rmpp_send_ctx_t *p_send_ctx = osmv_txn_get_rmpp_send_ctx(p_txn);

	uint32_t old_wl = p_send_ctx->window_last;
	uint32_t total_segs = osmv_rmpp_send_ctx_get_num_segs(p_send_ctx);
	uint32_t seg_num = cl_ntoh32(((ib_rmpp_mad_t *) p_mad)->seg_num);
	uint32_t new_wl = cl_ntoh32(((ib_rmpp_mad_t *) p_mad)->paylen_newwin);
	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;

	OSM_LOG_ENTER(p_bo->p_vendor->p_log);

	if (TRUE == osmv_rmpp_is_abort_stop(p_mad)) {

		osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
			"__osmv_dispatch_rmpp_snd: ERR 6502: "
			"The remote side sent an ABORT/STOP indication.\n");
		osmv_rmpp_snd_error(p_send_ctx, IB_REMOTE_ERROR);
		goto dispatch_rmpp_snd_done;
	}

	if (FALSE == osmv_rmpp_is_ack(p_mad)) {

		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
			"Not supposed to receive DATA packets --> dropping the MAD\n");
		goto dispatch_rmpp_snd_done;
	}

	/* Continue processing the ACK */
	if (seg_num > old_wl) {

		osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
			"__osmv_dispatch_rmpp_snd: ERR 6503: "
			"ACK received for a non-sent segment %d\n", seg_num);

		osmv_rmpp_send_nak(h_bind, p_mad, p_mad_addr,
				   IB_RMPP_TYPE_ABORT, IB_RMPP_STATUS_S2B);

		osmv_rmpp_snd_error(p_send_ctx, IB_REMOTE_ERROR);
		goto dispatch_rmpp_snd_done;
	}

	osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
		"__osmv_dispatch_rmpp_snd: "
		"New WL = %u Old WL = %u Total Segs = %u\n",
		new_wl, old_wl, total_segs);

	if (new_wl < old_wl) {
		osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
			"__osmv_dispatch_rmpp_snd: ERR 6508: "
			"The receiver requests a smaller WL (%d) than before (%d)\n",
			new_wl, old_wl);

		osmv_rmpp_send_nak(h_bind, p_mad, p_mad_addr,
				   IB_RMPP_TYPE_ABORT, IB_RMPP_STATUS_W2S);

		osmv_rmpp_snd_error(p_send_ctx, IB_REMOTE_ERROR);
		goto dispatch_rmpp_snd_done;
	}

	/* Update the sender's window, and optionally wake up the sender thread
	 * Note! A single ACK can acknowledge a whole range of segments: [WF..SEG_NUM]
	 */
	osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
		"ACK for seg_num #%d accepted.\n", seg_num);

	if (seg_num == old_wl) {

		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
			"The send window [%d:%d] is totally acknowledged.\n",
			p_send_ctx->window_first, old_wl);

		p_send_ctx->window_first = seg_num + 1;
		p_send_ctx->window_last =
		    (new_wl < total_segs) ? new_wl : total_segs;

		/* Remove the response timeout event for the window */
		osmv_txn_remove_timeout_ev(h_bind, osmv_txn_get_key(p_txn));

		/* Wake up the sending thread */
		cl_event_signal(&p_send_ctx->event);
	}

dispatch_rmpp_snd_done:
	OSM_LOG_EXIT(p_bo->p_vendor->p_log);
}