ccid2.c

来自「linux 内核源代码」· C语言 代码 · 共 836 行 · 第 1/2 页

C
836
字号
{	struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);	/* slow start */	if (hctx->ccid2hctx_cwnd < hctx->ccid2hctx_ssthresh) {		hctx->ccid2hctx_acks = 0;		/* We can increase cwnd at most maxincr [ack_ratio/2] */		if (*maxincr) {			/* increase every 2 acks */			hctx->ccid2hctx_ssacks++;			if (hctx->ccid2hctx_ssacks == 2) {				ccid2_change_cwnd(hctx, hctx->ccid2hctx_cwnd+1);				hctx->ccid2hctx_ssacks = 0;				*maxincr = *maxincr - 1;			}		} else {			/* increased cwnd enough for this single ack */			hctx->ccid2hctx_ssacks = 0;		}	} else {		hctx->ccid2hctx_ssacks = 0;		hctx->ccid2hctx_acks++;		if (hctx->ccid2hctx_acks >= hctx->ccid2hctx_cwnd) {			ccid2_change_cwnd(hctx, hctx->ccid2hctx_cwnd + 1);			hctx->ccid2hctx_acks = 0;		}	}	/* update RTO */	if (hctx->ccid2hctx_srtt == -1 ||	    time_after(jiffies, hctx->ccid2hctx_lastrtt + hctx->ccid2hctx_srtt)) {		unsigned long r = (long)jiffies - (long)seqp->ccid2s_sent;		int s;		/* first measurement */		if (hctx->ccid2hctx_srtt == -1) {			ccid2_pr_debug("R: %lu Time=%lu seq=%llu\n",				       r, jiffies,				       (unsigned long long)seqp->ccid2s_seq);			ccid2_change_srtt(hctx, r);			hctx->ccid2hctx_rttvar = r >> 1;		} else {			/* RTTVAR */			long tmp = hctx->ccid2hctx_srtt - r;			long srtt;			if (tmp < 0)				tmp *= -1;			tmp >>= 2;			hctx->ccid2hctx_rttvar *= 3;			hctx->ccid2hctx_rttvar >>= 2;			hctx->ccid2hctx_rttvar += tmp;			/* SRTT */			srtt = hctx->ccid2hctx_srtt;			srtt *= 7;			srtt >>= 3;			tmp = r >> 3;			srtt += tmp;			ccid2_change_srtt(hctx, srtt);		}		s = hctx->ccid2hctx_rttvar << 2;		/* clock granularity is 1 when based on jiffies */		if (!s)			s = 1;		hctx->ccid2hctx_rto = hctx->ccid2hctx_srtt + s;		/* must be at least a second */		s = hctx->ccid2hctx_rto / HZ;		/* DCCP doesn't require this [but I like it cuz my code sux] */#if 1		if (s < 1)			hctx->ccid2hctx_rto = HZ;#endif		/* max 60 seconds */		if (s > 60)			hctx->ccid2hctx_rto = HZ * 60;		hctx->ccid2hctx_lastrtt = jiffies;		ccid2_pr_debug("srtt: %ld rttvar: %ld rto: %ld (HZ=%d) R=%lu\n",			       hctx->ccid2hctx_srtt, hctx->ccid2hctx_rttvar,			       hctx->ccid2hctx_rto, HZ, r);		hctx->ccid2hctx_sent = 0;	}	/* we got a new ack, so re-start RTO timer */	ccid2_hc_tx_kill_rto_timer(sk);	ccid2_start_rto_timer(sk);}static void ccid2_hc_tx_dec_pipe(struct sock *sk){	struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);	ccid2_change_pipe(hctx, hctx->ccid2hctx_pipe-1);	BUG_ON(hctx->ccid2hctx_pipe < 0);	if (hctx->ccid2hctx_pipe == 0)		ccid2_hc_tx_kill_rto_timer(sk);}static void ccid2_congestion_event(struct ccid2_hc_tx_sock *hctx,				   struct ccid2_seq *seqp){	if (time_before(seqp->ccid2s_sent, hctx->ccid2hctx_last_cong)) {		ccid2_pr_debug("Multiple losses in an RTT---treating as one\n");		return;	}	hctx->ccid2hctx_last_cong = jiffies;	ccid2_change_cwnd(hctx, hctx->ccid2hctx_cwnd >> 1);	hctx->ccid2hctx_ssthresh = hctx->ccid2hctx_cwnd;	if (hctx->ccid2hctx_ssthresh < 2)		hctx->ccid2hctx_ssthresh = 2;}static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb){	struct dccp_sock *dp = dccp_sk(sk);	struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);	u64 ackno, seqno;	struct ccid2_seq *seqp;	unsigned char *vector;	unsigned char veclen;	int offset = 0;	int done = 0;	unsigned int maxincr = 0;	ccid2_hc_tx_check_sanity(hctx);	/* check reverse path congestion */	seqno = DCCP_SKB_CB(skb)->dccpd_seq;	/* XXX this whole "algorithm" is broken.  Need to fix it to keep track	 * of the seqnos of the dupacks so that rpseq and rpdupack are correct	 * -sorbo.	 */	/* need to bootstrap */	if (hctx->ccid2hctx_rpdupack == -1) {		hctx->ccid2hctx_rpdupack = 0;		hctx->ccid2hctx_rpseq = seqno;	} else {		/* check if packet is consecutive */		if (dccp_delta_seqno(hctx->ccid2hctx_rpseq, seqno) == 1)			hctx->ccid2hctx_rpseq = seqno;		/* it's a later packet */		else if (after48(seqno, hctx->ccid2hctx_rpseq)) {			hctx->ccid2hctx_rpdupack++;			/* check if we got enough dupacks */			if (hctx->ccid2hctx_rpdupack >=			    hctx->ccid2hctx_numdupack) {				hctx->ccid2hctx_rpdupack = -1; /* XXX lame */				hctx->ccid2hctx_rpseq = 0;				ccid2_change_l_ack_ratio(sk, dp->dccps_l_ack_ratio << 1);			}		}	}	/* check forward path congestion */	/* still didn't send out new data packets */	if (hctx->ccid2hctx_seqh == hctx->ccid2hctx_seqt)		return;	switch (DCCP_SKB_CB(skb)->dccpd_type) {	case DCCP_PKT_ACK:	case DCCP_PKT_DATAACK:		break;	default:		return;	}	ackno = DCCP_SKB_CB(skb)->dccpd_ack_seq;	if (after48(ackno, hctx->ccid2hctx_high_ack))		hctx->ccid2hctx_high_ack = ackno;	seqp = hctx->ccid2hctx_seqt;	while (before48(seqp->ccid2s_seq, ackno)) {		seqp = seqp->ccid2s_next;		if (seqp == hctx->ccid2hctx_seqh) {			seqp = hctx->ccid2hctx_seqh->ccid2s_prev;			break;		}	}	/* If in slow-start, cwnd can increase at most Ack Ratio / 2 packets for	 * this single ack.  I round up.	 * -sorbo.	 */	maxincr = dp->dccps_l_ack_ratio >> 1;	maxincr++;	/* go through all ack vectors */	while ((offset = ccid2_ackvector(sk, skb, offset,					 &vector, &veclen)) != -1) {		/* go through this ack vector */		while (veclen--) {			const u8 rl = *vector & DCCP_ACKVEC_LEN_MASK;			u64 ackno_end_rl;			dccp_set_seqno(&ackno_end_rl, ackno - rl);			ccid2_pr_debug("ackvec start:%llu end:%llu\n",				       (unsigned long long)ackno,				       (unsigned long long)ackno_end_rl);			/* if the seqno we are analyzing is larger than the			 * current ackno, then move towards the tail of our			 * seqnos.			 */			while (after48(seqp->ccid2s_seq, ackno)) {				if (seqp == hctx->ccid2hctx_seqt) {					done = 1;					break;				}				seqp = seqp->ccid2s_prev;			}			if (done)				break;			/* check all seqnos in the range of the vector			 * run length			 */			while (between48(seqp->ccid2s_seq,ackno_end_rl,ackno)) {				const u8 state = *vector &						 DCCP_ACKVEC_STATE_MASK;				/* new packet received or marked */				if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED &&				    !seqp->ccid2s_acked) {					if (state ==					    DCCP_ACKVEC_STATE_ECN_MARKED) {						ccid2_congestion_event(hctx,								       seqp);					} else						ccid2_new_ack(sk, seqp,							      &maxincr);					seqp->ccid2s_acked = 1;					ccid2_pr_debug("Got ack for %llu\n",						       (unsigned long long)seqp->ccid2s_seq);					ccid2_hc_tx_dec_pipe(sk);				}				if (seqp == hctx->ccid2hctx_seqt) {					done = 1;					break;				}				seqp = seqp->ccid2s_next;			}			if (done)				break;			dccp_set_seqno(&ackno, ackno_end_rl - 1);			vector++;		}		if (done)			break;	}	/* The state about what is acked should be correct now	 * Check for NUMDUPACK	 */	seqp = hctx->ccid2hctx_seqt;	while (before48(seqp->ccid2s_seq, hctx->ccid2hctx_high_ack)) {		seqp = seqp->ccid2s_next;		if (seqp == hctx->ccid2hctx_seqh) {			seqp = hctx->ccid2hctx_seqh->ccid2s_prev;			break;		}	}	done = 0;	while (1) {		if (seqp->ccid2s_acked) {			done++;			if (done == hctx->ccid2hctx_numdupack)				break;		}		if (seqp == hctx->ccid2hctx_seqt)			break;		seqp = seqp->ccid2s_prev;	}	/* If there are at least 3 acknowledgements, anything unacknowledged	 * below the last sequence number is considered lost	 */	if (done == hctx->ccid2hctx_numdupack) {		struct ccid2_seq *last_acked = seqp;		/* check for lost packets */		while (1) {			if (!seqp->ccid2s_acked) {				ccid2_pr_debug("Packet lost: %llu\n",					       (unsigned long long)seqp->ccid2s_seq);				/* XXX need to traverse from tail -> head in				 * order to detect multiple congestion events in				 * one ack vector.				 */				ccid2_congestion_event(hctx, seqp);				ccid2_hc_tx_dec_pipe(sk);			}			if (seqp == hctx->ccid2hctx_seqt)				break;			seqp = seqp->ccid2s_prev;		}		hctx->ccid2hctx_seqt = last_acked;	}	/* trim acked packets in tail */	while (hctx->ccid2hctx_seqt != hctx->ccid2hctx_seqh) {		if (!hctx->ccid2hctx_seqt->ccid2s_acked)			break;		hctx->ccid2hctx_seqt = hctx->ccid2hctx_seqt->ccid2s_next;	}	ccid2_hc_tx_check_sanity(hctx);}static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk){	struct ccid2_hc_tx_sock *hctx = ccid_priv(ccid);	ccid2_change_cwnd(hctx, 1);	/* Initialize ssthresh to infinity.  This means that we will exit the	 * initial slow-start after the first packet loss.  This is what we	 * want.	 */	hctx->ccid2hctx_ssthresh  = ~0;	hctx->ccid2hctx_numdupack = 3;	/* XXX init ~ to window size... */	if (ccid2_hc_tx_alloc_seq(hctx))		return -ENOMEM;	hctx->ccid2hctx_rto	 = 3 * HZ;	ccid2_change_srtt(hctx, -1);	hctx->ccid2hctx_rttvar	 = -1;	hctx->ccid2hctx_rpdupack = -1;	hctx->ccid2hctx_last_cong = jiffies;	hctx->ccid2hctx_rtotimer.function = &ccid2_hc_tx_rto_expire;	hctx->ccid2hctx_rtotimer.data	  = (unsigned long)sk;	init_timer(&hctx->ccid2hctx_rtotimer);	ccid2_hc_tx_check_sanity(hctx);	return 0;}static void ccid2_hc_tx_exit(struct sock *sk){	struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);	int i;	ccid2_hc_tx_kill_rto_timer(sk);	for (i = 0; i < hctx->ccid2hctx_seqbufc; i++)		kfree(hctx->ccid2hctx_seqbuf[i]);	hctx->ccid2hctx_seqbufc = 0;}static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb){	const struct dccp_sock *dp = dccp_sk(sk);	struct ccid2_hc_rx_sock *hcrx = ccid2_hc_rx_sk(sk);	switch (DCCP_SKB_CB(skb)->dccpd_type) {	case DCCP_PKT_DATA:	case DCCP_PKT_DATAACK:		hcrx->ccid2hcrx_data++;		if (hcrx->ccid2hcrx_data >= dp->dccps_r_ack_ratio) {			dccp_send_ack(sk);			hcrx->ccid2hcrx_data = 0;		}		break;	}}static struct ccid_operations ccid2 = {	.ccid_id		= DCCPC_CCID2,	.ccid_name		= "ccid2",	.ccid_owner		= THIS_MODULE,	.ccid_hc_tx_obj_size	= sizeof(struct ccid2_hc_tx_sock),	.ccid_hc_tx_init	= ccid2_hc_tx_init,	.ccid_hc_tx_exit	= ccid2_hc_tx_exit,	.ccid_hc_tx_send_packet	= ccid2_hc_tx_send_packet,	.ccid_hc_tx_packet_sent	= ccid2_hc_tx_packet_sent,	.ccid_hc_tx_packet_recv	= ccid2_hc_tx_packet_recv,	.ccid_hc_rx_obj_size	= sizeof(struct ccid2_hc_rx_sock),	.ccid_hc_rx_packet_recv	= ccid2_hc_rx_packet_recv,};#ifdef CONFIG_IP_DCCP_CCID2_DEBUGmodule_param(ccid2_debug, bool, 0444);MODULE_PARM_DESC(ccid2_debug, "Enable debug messages");#endifstatic __init int ccid2_module_init(void){	return ccid_register(&ccid2);}module_init(ccid2_module_init);static __exit void ccid2_module_exit(void){	ccid_unregister(&ccid2);}module_exit(ccid2_module_exit);MODULE_AUTHOR("Andrea Bittau <a.bittau@cs.ucl.ac.uk>");MODULE_DESCRIPTION("DCCP TCP-Like (CCID2) CCID");MODULE_LICENSE("GPL");MODULE_ALIAS("net-dccp-ccid-2");

⌨️ 快捷键说明

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