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

📄 ccid2.c

📁 LINUX 2.6.17.4的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  net/dccp/ccids/ccid2.c * *  Copyright (c) 2005, 2006 Andrea Bittau <a.bittau@cs.ucl.ac.uk> * *  Changes to meet Linux coding standards, and DCCP infrastructure fixes. * *  Copyright (c) 2006 Arnaldo Carvalho de Melo <acme@conectiva.com.br> * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *//* * This implementation should follow: draft-ietf-dccp-ccid2-10.txt * * BUGS: * - sequence number wrapping * - jiffies wrapping */#include <linux/config.h>#include "../ccid.h"#include "../dccp.h"#include "ccid2.h"static int ccid2_debug;#undef CCID2_DEBUG#ifdef CCID2_DEBUG#define ccid2_pr_debug(format, a...) \        do { if (ccid2_debug) \                printk(KERN_DEBUG "%s: " format, __FUNCTION__, ##a); \        } while (0)#else#define ccid2_pr_debug(format, a...)#endifstatic const int ccid2_seq_len = 128;#ifdef CCID2_DEBUGstatic void ccid2_hc_tx_check_sanity(const struct ccid2_hc_tx_sock *hctx){	int len = 0;	int pipe = 0;	struct ccid2_seq *seqp = hctx->ccid2hctx_seqh;	/* there is data in the chain */	if (seqp != hctx->ccid2hctx_seqt) {		seqp = seqp->ccid2s_prev;		len++;		if (!seqp->ccid2s_acked)			pipe++;		while (seqp != hctx->ccid2hctx_seqt) {			struct ccid2_seq *prev = seqp->ccid2s_prev;			len++;			if (!prev->ccid2s_acked)				pipe++;			/* packets are sent sequentially */			BUG_ON(seqp->ccid2s_seq <= prev->ccid2s_seq);			BUG_ON(seqp->ccid2s_sent < prev->ccid2s_sent);			BUG_ON(len > ccid2_seq_len);			seqp = prev;		}	}	BUG_ON(pipe != hctx->ccid2hctx_pipe);	ccid2_pr_debug("len of chain=%d\n", len);	do {		seqp = seqp->ccid2s_prev;		len++;		BUG_ON(len > ccid2_seq_len);	} while (seqp != hctx->ccid2hctx_seqh);	BUG_ON(len != ccid2_seq_len);	ccid2_pr_debug("total len=%d\n", len);}#else#define ccid2_hc_tx_check_sanity(hctx) do {} while (0)#endifstatic int ccid2_hc_tx_send_packet(struct sock *sk,				   struct sk_buff *skb, int len){	struct ccid2_hc_tx_sock *hctx;	switch (DCCP_SKB_CB(skb)->dccpd_type) {	case 0: /* XXX data packets from userland come through like this */	case DCCP_PKT_DATA:	case DCCP_PKT_DATAACK:		break;	/* No congestion control on other packets */	default:		return 0;	}        hctx = ccid2_hc_tx_sk(sk);	ccid2_pr_debug("pipe=%d cwnd=%d\n", hctx->ccid2hctx_pipe,		       hctx->ccid2hctx_cwnd);	if (hctx->ccid2hctx_pipe < hctx->ccid2hctx_cwnd) {		/* OK we can send... make sure previous packet was sent off */		if (!hctx->ccid2hctx_sendwait) {			hctx->ccid2hctx_sendwait = 1;			return 0;		}	}	return 100; /* XXX */}static void ccid2_change_l_ack_ratio(struct sock *sk, int val){	struct dccp_sock *dp = dccp_sk(sk);	/*	 * XXX I don't really agree with val != 2.  If cwnd is 1, ack ratio	 * should be 1... it shouldn't be allowed to become 2.	 * -sorbo.	 */	if (val != 2) {		const struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);		int max = hctx->ccid2hctx_cwnd / 2;		/* round up */		if (hctx->ccid2hctx_cwnd & 1)			max++;		if (val > max)			val = max;	}	ccid2_pr_debug("changing local ack ratio to %d\n", val);	WARN_ON(val <= 0);	dp->dccps_l_ack_ratio = val;}static void ccid2_change_cwnd(struct sock *sk, int val){	struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);	if (val == 0)		val = 1;	/* XXX do we need to change ack ratio? */	ccid2_pr_debug("change cwnd to %d\n", val);	BUG_ON(val < 1);	hctx->ccid2hctx_cwnd = val;}static void ccid2_start_rto_timer(struct sock *sk);static void ccid2_hc_tx_rto_expire(unsigned long data){	struct sock *sk = (struct sock *)data;	struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);	long s;	bh_lock_sock(sk);	if (sock_owned_by_user(sk)) {		sk_reset_timer(sk, &hctx->ccid2hctx_rtotimer,			       jiffies + HZ / 5);		goto out;	}	ccid2_pr_debug("RTO_EXPIRE\n");	ccid2_hc_tx_check_sanity(hctx);	/* back-off timer */	hctx->ccid2hctx_rto <<= 1;	s = hctx->ccid2hctx_rto / HZ;	if (s > 60)		hctx->ccid2hctx_rto = 60 * HZ;	ccid2_start_rto_timer(sk);	/* adjust pipe, cwnd etc */	hctx->ccid2hctx_pipe = 0;	hctx->ccid2hctx_ssthresh = hctx->ccid2hctx_cwnd >> 1;	if (hctx->ccid2hctx_ssthresh < 2)		hctx->ccid2hctx_ssthresh = 2;	ccid2_change_cwnd(sk, 1);	/* clear state about stuff we sent */	hctx->ccid2hctx_seqt	= hctx->ccid2hctx_seqh;	hctx->ccid2hctx_ssacks	= 0;	hctx->ccid2hctx_acks	= 0;	hctx->ccid2hctx_sent	= 0;	/* clear ack ratio state. */	hctx->ccid2hctx_arsent	 = 0;	hctx->ccid2hctx_ackloss  = 0;	hctx->ccid2hctx_rpseq	 = 0;	hctx->ccid2hctx_rpdupack = -1;	ccid2_change_l_ack_ratio(sk, 1);	ccid2_hc_tx_check_sanity(hctx);out:	bh_unlock_sock(sk);	sock_put(sk);}static void ccid2_start_rto_timer(struct sock *sk){	struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);	ccid2_pr_debug("setting RTO timeout=%ld\n", hctx->ccid2hctx_rto);	BUG_ON(timer_pending(&hctx->ccid2hctx_rtotimer));	sk_reset_timer(sk, &hctx->ccid2hctx_rtotimer,		       jiffies + hctx->ccid2hctx_rto);}static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, int len){	struct dccp_sock *dp = dccp_sk(sk);	struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);	u64 seq;	ccid2_hc_tx_check_sanity(hctx);	BUG_ON(!hctx->ccid2hctx_sendwait);	hctx->ccid2hctx_sendwait = 0;	hctx->ccid2hctx_pipe++;	BUG_ON(hctx->ccid2hctx_pipe < 0);	/* There is an issue.  What if another packet is sent between	 * packet_send() and packet_sent().  Then the sequence number would be	 * wrong.	 * -sorbo.	 */	seq = dp->dccps_gss;	hctx->ccid2hctx_seqh->ccid2s_seq   = seq;	hctx->ccid2hctx_seqh->ccid2s_acked = 0;	hctx->ccid2hctx_seqh->ccid2s_sent  = jiffies;	hctx->ccid2hctx_seqh = hctx->ccid2hctx_seqh->ccid2s_next;	ccid2_pr_debug("cwnd=%d pipe=%d\n", hctx->ccid2hctx_cwnd,		       hctx->ccid2hctx_pipe);	if (hctx->ccid2hctx_seqh == hctx->ccid2hctx_seqt) {		/* XXX allocate more space */		WARN_ON(1);	}	hctx->ccid2hctx_sent++;	/* Ack Ratio.  Need to maintain a concept of how many windows we sent */	hctx->ccid2hctx_arsent++;	/* We had an ack loss in this window... */	if (hctx->ccid2hctx_ackloss) {		if (hctx->ccid2hctx_arsent >= hctx->ccid2hctx_cwnd) {			hctx->ccid2hctx_arsent	= 0;			hctx->ccid2hctx_ackloss	= 0;		}	} else {		/* No acks lost up to now... */		/* decrease ack ratio if enough packets were sent */		if (dp->dccps_l_ack_ratio > 1) {			/* XXX don't calculate denominator each time */			int denom = dp->dccps_l_ack_ratio * dp->dccps_l_ack_ratio -				    dp->dccps_l_ack_ratio;			denom = hctx->ccid2hctx_cwnd * hctx->ccid2hctx_cwnd / denom;			if (hctx->ccid2hctx_arsent >= denom) {				ccid2_change_l_ack_ratio(sk, dp->dccps_l_ack_ratio - 1);				hctx->ccid2hctx_arsent = 0;			}		} else {			/* we can't increase ack ratio further [1] */			hctx->ccid2hctx_arsent = 0; /* or maybe set it to cwnd*/		}	}	/* setup RTO timer */	if (!timer_pending(&hctx->ccid2hctx_rtotimer))		ccid2_start_rto_timer(sk);#ifdef CCID2_DEBUG	ccid2_pr_debug("pipe=%d\n", hctx->ccid2hctx_pipe);	ccid2_pr_debug("Sent: seq=%llu\n", seq);	do {		struct ccid2_seq *seqp = hctx->ccid2hctx_seqt;		while (seqp != hctx->ccid2hctx_seqh) {			ccid2_pr_debug("out seq=%llu acked=%d time=%lu\n",			       	       seqp->ccid2s_seq, seqp->ccid2s_acked,				       seqp->ccid2s_sent);			seqp = seqp->ccid2s_next;		}	} while (0);	ccid2_pr_debug("=========\n");	ccid2_hc_tx_check_sanity(hctx);#endif}/* XXX Lame code duplication! * returns -1 if none was found. * else returns the next offset to use in the function call. */static int ccid2_ackvector(struct sock *sk, struct sk_buff *skb, int offset,			   unsigned char **vec, unsigned char *veclen){        const struct dccp_hdr *dh = dccp_hdr(skb);        unsigned char *options = (unsigned char *)dh + dccp_hdr_len(skb);        unsigned char *opt_ptr;        const unsigned char *opt_end = (unsigned char *)dh +                                        (dh->dccph_doff * 4);        unsigned char opt, len;        unsigned char *value;	BUG_ON(offset < 0);	options += offset;	opt_ptr = options;	if (opt_ptr >= opt_end)		return -1;	while (opt_ptr != opt_end) {                opt   = *opt_ptr++;                len   = 0;                value = NULL;                /* Check if this isn't a single byte option */                if (opt > DCCPO_MAX_RESERVED) {                        if (opt_ptr == opt_end)                                goto out_invalid_option;                        len = *opt_ptr++;                        if (len < 3)                                goto out_invalid_option;                        /*                         * Remove the type and len fields, leaving                         * just the value size                         */                        len     -= 2;                        value   = opt_ptr;                        opt_ptr += len;                        if (opt_ptr > opt_end)                                goto out_invalid_option;                }		switch (opt) {		case DCCPO_ACK_VECTOR_0:		case DCCPO_ACK_VECTOR_1:			*vec	= value;			*veclen = len;			return offset + (opt_ptr - options);		}	}	return -1;out_invalid_option:	BUG_ON(1); /* should never happen... options were previously parsed ! */	return -1;}static void ccid2_hc_tx_kill_rto_timer(struct sock *sk){	struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);	sk_stop_timer(sk, &hctx->ccid2hctx_rtotimer);	ccid2_pr_debug("deleted RTO timer\n");}static inline void ccid2_new_ack(struct sock *sk,			         struct ccid2_seq *seqp,				 unsigned int *maxincr){

⌨️ 快捷键说明

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