⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 transport.c

📁 在linux环境下的流控制传输协议(sctp)的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	}	if (dst) {		transport->pathmtu = dst_mtu(dst);		/* Initialize sk->sk_rcv_saddr, if the transport is the		 * association's active path for getsockname().		 */		if (asoc && (transport == asoc->peer.active_path))			opt->pf->af->to_sk_saddr(&transport->saddr,						 asoc->base.sk);	} else		transport->pathmtu = SCTP_DEFAULT_MAXSEGMENT;}/* Hold a reference to a transport.  */void sctp_transport_hold(struct sctp_transport *transport){	atomic_inc(&transport->refcnt);}/* Release a reference to a transport and clean up * if there are no more references. */void sctp_transport_put(struct sctp_transport *transport){	if (atomic_dec_and_test(&transport->refcnt))		sctp_transport_destroy(transport);}/* Update transport's RTO based on the newly calculated RTT. */void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt){	/* Check for valid transport.  */	SCTP_ASSERT(tp, "NULL transport", return);	/* We should not be doing any RTO updates unless rto_pending is set.  */	SCTP_ASSERT(tp->rto_pending, "rto_pending not set", return);	if (tp->rttvar || tp->srtt) {		/* 6.3.1 C3) When a new RTT measurement R' is made, set		 * RTTVAR <- (1 - RTO.Beta) * RTTVAR + RTO.Beta * |SRTT - R'|		 * SRTT <- (1 - RTO.Alpha) * SRTT + RTO.Alpha * R'		 */		/* Note:  The above algorithm has been rewritten to		 * express rto_beta and rto_alpha as inverse powers		 * of two.		 * For example, assuming the default value of RTO.Alpha of		 * 1/8, rto_alpha would be expressed as 3.		 */		tp->rttvar = tp->rttvar - (tp->rttvar >> sctp_rto_beta)			+ ((abs(tp->srtt - rtt)) >> sctp_rto_beta);		tp->srtt = tp->srtt - (tp->srtt >> sctp_rto_alpha)			+ (rtt >> sctp_rto_alpha);	} else {		/* 6.3.1 C2) When the first RTT measurement R is made, set		 * SRTT <- R, RTTVAR <- R/2.		 */		tp->srtt = rtt;		tp->rttvar = rtt >> 1;	}	/* 6.3.1 G1) Whenever RTTVAR is computed, if RTTVAR = 0, then	 * adjust RTTVAR <- G, where G is the CLOCK GRANULARITY.	 */	if (tp->rttvar == 0)		tp->rttvar = SCTP_CLOCK_GRANULARITY;	/* 6.3.1 C3) After the computation, update RTO <- SRTT + 4 * RTTVAR. */	tp->rto = tp->srtt + (tp->rttvar << 2);	/* 6.3.1 C6) Whenever RTO is computed, if it is less than RTO.Min	 * seconds then it is rounded up to RTO.Min seconds.	 */	if (tp->rto < tp->asoc->rto_min)		tp->rto = tp->asoc->rto_min;	/* 6.3.1 C7) A maximum value may be placed on RTO provided it is	 * at least RTO.max seconds.	 */	if (tp->rto > tp->asoc->rto_max)		tp->rto = tp->asoc->rto_max;	tp->rtt = rtt;	tp->last_rto = tp->rto;	/* Reset rto_pending so that a new RTT measurement is started when a	 * new data chunk is sent.	 */	tp->rto_pending = 0;	SCTP_DEBUG_PRINTK("%s: transport: %p, rtt: %d, srtt: %d "			  "rttvar: %d, rto: %ld\n", __FUNCTION__,			  tp, rtt, tp->srtt, tp->rttvar, tp->rto);}/* This routine updates the transport's cwnd and partial_bytes_acked * parameters based on the bytes acked in the received SACK. */void sctp_transport_raise_cwnd(struct sctp_transport *transport,			       __u32 sack_ctsn, __u32 bytes_acked){	__u32 cwnd, ssthresh, flight_size, pba, pmtu;	cwnd = transport->cwnd;	flight_size = transport->flight_size;	/* The appropriate cwnd increase algorithm is performed if, and only	 * if the cumulative TSN has advanced and the congestion window is	 * being fully utilized.	 */	if ((transport->asoc->ctsn_ack_point >= sack_ctsn) ||	    (flight_size < cwnd))		return;	ssthresh = transport->ssthresh;	pba = transport->partial_bytes_acked;	pmtu = transport->asoc->pathmtu;	if (cwnd <= ssthresh) {		/* RFC 2960 7.2.1, sctpimpguide-05 2.14.2 When cwnd is less		 * than or equal to ssthresh an SCTP endpoint MUST use the		 * slow start algorithm to increase cwnd only if the current		 * congestion window is being fully utilized and an incoming		 * SACK advances the Cumulative TSN Ack Point. Only when these		 * two conditions are met can the cwnd be increased otherwise		 * the cwnd MUST not be increased. If these conditions are met		 * then cwnd MUST be increased by at most the lesser of		 * 1) the total size of the previously outstanding DATA		 * chunk(s) acknowledged, and 2) the destination's path MTU.		 */		if (bytes_acked > pmtu)			cwnd += pmtu;		else			cwnd += bytes_acked;		SCTP_DEBUG_PRINTK("%s: SLOW START: transport: %p, "				  "bytes_acked: %d, cwnd: %d, ssthresh: %d, "				  "flight_size: %d, pba: %d\n",				  __FUNCTION__,				  transport, bytes_acked, cwnd,				  ssthresh, flight_size, pba);	} else {		/* RFC 2960 7.2.2 Whenever cwnd is greater than ssthresh,		 * upon each SACK arrival that advances the Cumulative TSN Ack		 * Point, increase partial_bytes_acked by the total number of		 * bytes of all new chunks acknowledged in that SACK including		 * chunks acknowledged by the new Cumulative TSN Ack and by		 * Gap Ack Blocks.		 *		 * When partial_bytes_acked is equal to or greater than cwnd		 * and before the arrival of the SACK the sender had cwnd or		 * more bytes of data outstanding (i.e., before arrival of the		 * SACK, flightsize was greater than or equal to cwnd),		 * increase cwnd by MTU, and reset partial_bytes_acked to		 * (partial_bytes_acked - cwnd).		 */		pba += bytes_acked;		if (pba >= cwnd) {			cwnd += pmtu;			pba = ((cwnd < pba) ? (pba - cwnd) : 0);		}		SCTP_DEBUG_PRINTK("%s: CONGESTION AVOIDANCE: "				  "transport: %p, bytes_acked: %d, cwnd: %d, "				  "ssthresh: %d, flight_size: %d, pba: %d\n",				  __FUNCTION__,				  transport, bytes_acked, cwnd,				  ssthresh, flight_size, pba);	}	transport->cwnd = cwnd;	transport->partial_bytes_acked = pba;}/* This routine is used to lower the transport's cwnd when congestion is * detected. */void sctp_transport_lower_cwnd(struct sctp_transport *transport,			       sctp_lower_cwnd_t reason){	switch (reason) {	case SCTP_LOWER_CWND_T3_RTX:		/* RFC 2960 Section 7.2.3, sctpimpguide		 * When the T3-rtx timer expires on an address, SCTP should		 * perform slow start by:		 *      ssthresh = max(cwnd/2, 4*MTU)		 *      cwnd = 1*MTU		 *      partial_bytes_acked = 0		 */		transport->ssthresh = max(transport->cwnd/2,					  4*transport->asoc->pathmtu);		transport->cwnd = transport->asoc->pathmtu;		break;	case SCTP_LOWER_CWND_FAST_RTX:		/* RFC 2960 7.2.4 Adjust the ssthresh and cwnd of the		 * destination address(es) to which the missing DATA chunks		 * were last sent, according to the formula described in		 * Section 7.2.3.		 *		 * RFC 2960 7.2.3, sctpimpguide Upon detection of packet		 * losses from SACK (see Section 7.2.4), An endpoint		 * should do the following:		 *      ssthresh = max(cwnd/2, 4*MTU)		 *      cwnd = ssthresh		 *      partial_bytes_acked = 0		 */		transport->ssthresh = max(transport->cwnd/2,					  4*transport->asoc->pathmtu);		transport->cwnd = transport->ssthresh;		break;	case SCTP_LOWER_CWND_ECNE:		/* RFC 2481 Section 6.1.2.		 * If the sender receives an ECN-Echo ACK packet		 * then the sender knows that congestion was encountered in the		 * network on the path from the sender to the receiver. The		 * indication of congestion should be treated just as a		 * congestion loss in non-ECN Capable TCP. That is, the TCP		 * source halves the congestion window "cwnd" and reduces the		 * slow start threshold "ssthresh".		 * A critical condition is that TCP does not react to		 * congestion indications more than once every window of		 * data (or more loosely more than once every round-trip time).		 */		if ((jiffies - transport->last_time_ecne_reduced) >		    transport->rtt) {			transport->ssthresh = max(transport->cwnd/2,						  4*transport->asoc->pathmtu);			transport->cwnd = transport->ssthresh;			transport->last_time_ecne_reduced = jiffies;		}		break;	case SCTP_LOWER_CWND_INACTIVE:		/* RFC 2960 Section 7.2.1, sctpimpguide		 * When the endpoint does not transmit data on a given		 * transport address, the cwnd of the transport address		 * should be adjusted to max(cwnd/2, 4*MTU) per RTO.		 * NOTE: Although the draft recommends that this check needs		 * to be done every RTO interval, we do it every hearbeat		 * interval.		 */		if ((jiffies - transport->last_time_used) > transport->rto)			transport->cwnd = max(transport->cwnd/2,						 4*transport->asoc->pathmtu);		break;	}	transport->partial_bytes_acked = 0;	SCTP_DEBUG_PRINTK("%s: transport: %p reason: %d cwnd: "			  "%d ssthresh: %d\n", __FUNCTION__,			  transport, reason,			  transport->cwnd, transport->ssthresh);}/* What is the next timeout value for this transport? */unsigned long sctp_transport_timeout(struct sctp_transport *t){	unsigned long timeout;	timeout = t->rto + sctp_jitter(t->rto);	if (t->state != SCTP_UNCONFIRMED)		timeout += t->hbinterval;	timeout += jiffies;	return timeout;}/* Reset transport variables to their initial values */void sctp_transport_reset(struct sctp_transport *t){	struct sctp_association *asoc = t->asoc;	/* RFC 2960 (bis), Section 5.2.4	 * All the congestion control parameters (e.g., cwnd, ssthresh)	 * related to this peer MUST be reset to their initial values	 * (see Section 6.2.1)	 */	t->cwnd = min(4*asoc->pathmtu, max_t(__u32, 2*asoc->pathmtu, 4380));	t->ssthresh = asoc->peer.i.a_rwnd;	t->last_rto = t->rto = asoc->rto_initial;	t->rtt = 0;	t->srtt = 0;	t->rttvar = 0;	/* Reset these additional varibles so that we have a clean	 * slate.	 */	t->partial_bytes_acked = 0;	t->flight_size = 0;	t->error_count = 0;	t->rto_pending = 0;	/* Initialize the state information for SFR-CACC */	t->cacc.changeover_active = 0;	t->cacc.cycling_changeover = 0;	t->cacc.next_tsn_at_change = 0;	t->cacc.cacc_saw_newack = 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -