예제 #1
0
static void
dctcp_ack_received(struct cc_var *ccv, uint16_t type)
{
	struct dctcp *dctcp_data;
	int bytes_acked = 0;

	dctcp_data = ccv->cc_data;

	if (CCV(ccv, t_flags) & TF_ECN_PERMIT) {
		/*
		 * DCTCP doesn't treat receipt of ECN marked packet as a
		 * congestion event. Thus, DCTCP always executes the ACK
		 * processing out of congestion recovery.
		 */
		if (IN_CONGRECOVERY(CCV(ccv, t_flags))) {
			EXIT_CONGRECOVERY(CCV(ccv, t_flags));
			newreno_cc_algo.ack_received(ccv, type);
			ENTER_CONGRECOVERY(CCV(ccv, t_flags));
		} else
			newreno_cc_algo.ack_received(ccv, type);

		if (type == CC_DUPACK)
			bytes_acked = CCV(ccv, t_maxseg);

		if (type == CC_ACK)
			bytes_acked = ccv->bytes_this_ack;

		/* Update total bytes. */
		dctcp_data->bytes_total += bytes_acked;

		/* Update total marked bytes. */
		if (dctcp_data->ece_curr) {
			if (!dctcp_data->ece_prev
			    && bytes_acked > CCV(ccv, t_maxseg)) {
				dctcp_data->bytes_ecn +=
				    (bytes_acked - CCV(ccv, t_maxseg));
			} else
				dctcp_data->bytes_ecn += bytes_acked;
			dctcp_data->ece_prev = 1;
		} else {
			if (dctcp_data->ece_prev
			    && bytes_acked > CCV(ccv, t_maxseg))
				dctcp_data->bytes_ecn += CCV(ccv, t_maxseg);
			dctcp_data->ece_prev = 0;
		}
		dctcp_data->ece_curr = 0;

		/*
		 * Update the fraction of marked bytes at the end of
		 * current window size.
		 */
		if ((IN_FASTRECOVERY(CCV(ccv, t_flags)) &&
		    SEQ_GEQ(ccv->curack, CCV(ccv, snd_recover))) ||
		    (!IN_FASTRECOVERY(CCV(ccv, t_flags)) &&
		    SEQ_GT(ccv->curack, dctcp_data->save_sndnxt)))
			dctcp_update_alpha(ccv);
	} else
		newreno_cc_algo.ack_received(ccv, type);
}
예제 #2
0
/*
 * Perform any necessary tasks before we enter congestion recovery.
 */
static void
newreno_cong_signal(struct cc_var *ccv, uint32_t type)
{
	uint32_t cwin, ssthresh_on_loss;
	u_int mss;

	cwin = CCV(ccv, snd_cwnd);
	mss = CCV(ccv, t_maxseg);
	ssthresh_on_loss =
	    max((CCV(ccv, snd_max) - CCV(ccv, snd_una)) / 2 / mss, 2)
		* mss;

	/* Catch algos which mistakenly leak private signal types. */
	KASSERT((type & CC_SIGPRIVMASK) == 0,
	    ("%s: congestion signal type 0x%08x is private\n", __func__, type));

	cwin = max(cwin / 2 / mss, 2) * mss;

	switch (type) {
	case CC_NDUPACK:
		if (!IN_FASTRECOVERY(CCV(ccv, t_flags))) {
			if (!IN_CONGRECOVERY(CCV(ccv, t_flags))) {
				CCV(ccv, snd_ssthresh) = ssthresh_on_loss;
				CCV(ccv, snd_cwnd) = cwin;
			}
			ENTER_RECOVERY(CCV(ccv, t_flags));
		}
		break;
	case CC_ECN:
		if (!IN_CONGRECOVERY(CCV(ccv, t_flags))) {
			CCV(ccv, snd_ssthresh) = ssthresh_on_loss;
			CCV(ccv, snd_cwnd) = cwin;
			ENTER_CONGRECOVERY(CCV(ccv, t_flags));
		}
		break;
	case CC_RTO:
		CCV(ccv, snd_ssthresh) = ssthresh_on_loss;
		CCV(ccv, snd_cwnd) = mss;
		break;
	}
}
예제 #3
0
/*
 * Perform any necessary tasks before we enter congestion recovery.
 */
static void
dctcp_cong_signal(struct cc_var *ccv, uint32_t type)
{
	struct dctcp *dctcp_data;
	u_int win, mss;

	dctcp_data = ccv->cc_data;
	win = CCV(ccv, snd_cwnd);
	mss = CCV(ccv, t_maxseg);

	switch (type) {
	case CC_NDUPACK:
		if (!IN_FASTRECOVERY(CCV(ccv, t_flags))) {
			if (!IN_CONGRECOVERY(CCV(ccv, t_flags))) {
				CCV(ccv, snd_ssthresh) = mss *
				    max(win / 2 / mss, 2);
				dctcp_data->num_cong_events++;
			} else {
				/* cwnd has already updated as congestion
				 * recovery. Reverse cwnd value using
				 * snd_cwnd_prev and recalculate snd_ssthresh
				 */
				win = CCV(ccv, snd_cwnd_prev);
				CCV(ccv, snd_ssthresh) =
				    max(win / 2 / mss, 2) * mss;
			}
			ENTER_RECOVERY(CCV(ccv, t_flags));
		}
		break;
	case CC_ECN:
		/*
		 * Save current snd_cwnd when the host encounters both
		 * congestion recovery and fast recovery.
		 */
		CCV(ccv, snd_cwnd_prev) = win;
		if (!IN_CONGRECOVERY(CCV(ccv, t_flags))) {
			if (V_dctcp_slowstart &&
			    dctcp_data->num_cong_events++ == 0) {
				CCV(ccv, snd_ssthresh) =
				    mss * max(win / 2 / mss, 2);
				dctcp_data->alpha = MAX_ALPHA_VALUE;
				dctcp_data->bytes_ecn = 0;
				dctcp_data->bytes_total = 0;
				dctcp_data->save_sndnxt = CCV(ccv, snd_nxt);
			} else
				CCV(ccv, snd_ssthresh) = max((win - ((win *
				    dctcp_data->alpha) >> 11)) / mss, 2) * mss;
			CCV(ccv, snd_cwnd) = CCV(ccv, snd_ssthresh);
			ENTER_CONGRECOVERY(CCV(ccv, t_flags));
		}
		dctcp_data->ece_curr = 1;
		break;
	case CC_RTO:
		if (CCV(ccv, t_flags) & TF_ECN_PERMIT) {
			CCV(ccv, t_flags) |= TF_ECN_SND_CWR;
			dctcp_update_alpha(ccv);
			dctcp_data->save_sndnxt += CCV(ccv, t_maxseg);
			dctcp_data->num_cong_events++;
		}
		break;
	}
}