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

📄 ccid3.c

📁 LINUX 2.6.17.4的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
			switch (step) {			case 0:				tstamp	  = entry->dccphrx_tstamp;				win_count = entry->dccphrx_ccval;				step = 1;				break;			case 1:				interval = win_count - entry->dccphrx_ccval;				if (interval < 0)					interval += TFRC_WIN_COUNT_LIMIT;				if (interval > 4)					goto found;				break;			}		}	}	if (unlikely(step == 0)) {		LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, packet history "			       "contains no data packets!\n",			       __FUNCTION__, dccp_role(sk), sk);		return ~0;	}	if (unlikely(interval == 0)) {		LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, Could not find a "			       "win_count interval > 0. Defaulting to 1\n",			       __FUNCTION__, dccp_role(sk), sk);		interval = 1;	}found:	rtt = timeval_delta(&tstamp, &tail->dccphrx_tstamp) * 4 / interval;	ccid3_pr_debug("%s, sk=%p, approximated RTT to %uus\n",		       dccp_role(sk), sk, rtt);	if (rtt == 0)		rtt = 1;	dccp_timestamp(sk, &tstamp);	delta = timeval_delta(&tstamp, &hcrx->ccid3hcrx_tstamp_last_feedback);	x_recv = usecs_div(hcrx->ccid3hcrx_bytes_recv, delta);	tmp1 = (u64)x_recv * (u64)rtt;	do_div(tmp1,10000000);	tmp2 = (u32)tmp1;	fval = (hcrx->ccid3hcrx_s * 100000) / tmp2;	/* do not alter order above or you will get overflow on 32 bit */	p = tfrc_calc_x_reverse_lookup(fval);	ccid3_pr_debug("%s, sk=%p, receive rate=%u bytes/s, implied "		       "loss rate=%u\n", dccp_role(sk), sk, x_recv, p);	if (p == 0)		return ~0;	else		return 1000000 / p; }static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss){	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);	if (seq_loss != DCCP_MAX_SEQNO + 1 &&	    list_empty(&hcrx->ccid3hcrx_li_hist)) {		struct dccp_li_hist_entry *li_tail;		li_tail = dccp_li_hist_interval_new(ccid3_li_hist,						    &hcrx->ccid3hcrx_li_hist,						    seq_loss, win_loss);		if (li_tail == NULL)			return;		li_tail->dccplih_interval = ccid3_hc_rx_calc_first_li(sk);	} else		    LIMIT_NETDEBUG(KERN_WARNING "%s: FIXME: find end of "				   "interval\n", __FUNCTION__);}static void ccid3_hc_rx_detect_loss(struct sock *sk){	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);	u8 win_loss;	const u64 seq_loss = dccp_rx_hist_detect_loss(&hcrx->ccid3hcrx_hist,						      &hcrx->ccid3hcrx_li_hist,						      &win_loss);	ccid3_hc_rx_update_li(sk, seq_loss, win_loss);}static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb){	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);	const struct dccp_options_received *opt_recv;	struct dccp_rx_hist_entry *packet;	struct timeval now;	u8 win_count;	u32 p_prev, r_sample, t_elapsed;	int ins;	BUG_ON(hcrx == NULL ||	       !(hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA ||		 hcrx->ccid3hcrx_state == TFRC_RSTATE_DATA));	opt_recv = &dccp_sk(sk)->dccps_options_received;	switch (DCCP_SKB_CB(skb)->dccpd_type) {	case DCCP_PKT_ACK:		if (hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA)			return;	case DCCP_PKT_DATAACK:		if (opt_recv->dccpor_timestamp_echo == 0)			break;		p_prev = hcrx->ccid3hcrx_rtt;		dccp_timestamp(sk, &now);		timeval_sub_usecs(&now, opt_recv->dccpor_timestamp_echo * 10);		r_sample = timeval_usecs(&now);		t_elapsed = opt_recv->dccpor_elapsed_time * 10;		if (unlikely(r_sample <= t_elapsed))			LIMIT_NETDEBUG(KERN_WARNING "%s: r_sample=%uus, "				       "t_elapsed=%uus\n",				       __FUNCTION__, r_sample, t_elapsed);		else			r_sample -= t_elapsed;		if (hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA)			hcrx->ccid3hcrx_rtt = r_sample;		else			hcrx->ccid3hcrx_rtt = (hcrx->ccid3hcrx_rtt * 9) / 10 +					      r_sample / 10;		if (p_prev != hcrx->ccid3hcrx_rtt)			ccid3_pr_debug("%s, New RTT=%luus, elapsed time=%u\n",				       dccp_role(sk), hcrx->ccid3hcrx_rtt,				       opt_recv->dccpor_elapsed_time);		break;	case DCCP_PKT_DATA:		break;	default: /* We're not interested in other packet types, move along */		return;	}	packet = dccp_rx_hist_entry_new(ccid3_rx_hist, sk, opt_recv->dccpor_ndp,					skb, SLAB_ATOMIC);	if (unlikely(packet == NULL)) {		LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, Not enough mem to "				"add rx packet to history, consider it lost!\n",			       __FUNCTION__, dccp_role(sk), sk);		return;	}	win_count = packet->dccphrx_ccval;	ins = dccp_rx_hist_add_packet(ccid3_rx_hist, &hcrx->ccid3hcrx_hist,				      &hcrx->ccid3hcrx_li_hist, packet);	if (DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK)		return;	switch (hcrx->ccid3hcrx_state) {	case TFRC_RSTATE_NO_DATA:		ccid3_pr_debug("%s, sk=%p(%s), skb=%p, sending initial "			       "feedback\n",			       dccp_role(sk), sk,			       dccp_state_name(sk->sk_state), skb);		ccid3_hc_rx_send_feedback(sk);		ccid3_hc_rx_set_state(sk, TFRC_RSTATE_DATA);		return;	case TFRC_RSTATE_DATA:		hcrx->ccid3hcrx_bytes_recv += skb->len -					      dccp_hdr(skb)->dccph_doff * 4;		if (ins != 0)			break;		dccp_timestamp(sk, &now);		if (timeval_delta(&now, &hcrx->ccid3hcrx_tstamp_last_ack) >=		    hcrx->ccid3hcrx_rtt) {			hcrx->ccid3hcrx_tstamp_last_ack = now;			ccid3_hc_rx_send_feedback(sk);		}		return;	default:		printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n",		       __FUNCTION__, dccp_role(sk), sk, hcrx->ccid3hcrx_state);		dump_stack();		return;	}	/* Dealing with packet loss */	ccid3_pr_debug("%s, sk=%p(%s), data loss! Reacting...\n",		       dccp_role(sk), sk, dccp_state_name(sk->sk_state));	ccid3_hc_rx_detect_loss(sk);	p_prev = hcrx->ccid3hcrx_p;		/* Calculate loss event rate */	if (!list_empty(&hcrx->ccid3hcrx_li_hist)) {		u32 i_mean = dccp_li_hist_calc_i_mean(&hcrx->ccid3hcrx_li_hist);		/* Scaling up by 1000000 as fixed decimal */		if (i_mean != 0)			hcrx->ccid3hcrx_p = 1000000 / i_mean;	}	if (hcrx->ccid3hcrx_p > p_prev) {		ccid3_hc_rx_send_feedback(sk);		return;	}}static int ccid3_hc_rx_init(struct ccid *ccid, struct sock *sk){	struct dccp_sock *dp = dccp_sk(sk);	struct ccid3_hc_rx_sock *hcrx = ccid_priv(ccid);	ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);	if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE &&	    dp->dccps_packet_size <= TFRC_MAX_PACKET_SIZE)		hcrx->ccid3hcrx_s = dp->dccps_packet_size;	else		hcrx->ccid3hcrx_s = TFRC_STD_PACKET_SIZE;	hcrx->ccid3hcrx_state = TFRC_RSTATE_NO_DATA;	INIT_LIST_HEAD(&hcrx->ccid3hcrx_hist);	INIT_LIST_HEAD(&hcrx->ccid3hcrx_li_hist);	dccp_timestamp(sk, &hcrx->ccid3hcrx_tstamp_last_ack);	hcrx->ccid3hcrx_tstamp_last_feedback = hcrx->ccid3hcrx_tstamp_last_ack;	hcrx->ccid3hcrx_rtt = 5000; /* XXX 5ms for now... */	return 0;}static void ccid3_hc_rx_exit(struct sock *sk){	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);	BUG_ON(hcrx == NULL);	ccid3_hc_rx_set_state(sk, TFRC_RSTATE_TERM);	/* Empty packet history */	dccp_rx_hist_purge(ccid3_rx_hist, &hcrx->ccid3hcrx_hist);	/* Empty loss interval history */	dccp_li_hist_purge(ccid3_li_hist, &hcrx->ccid3hcrx_li_hist);}static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info){	const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);	/* Listen socks doesn't have a private CCID block */	if (sk->sk_state == DCCP_LISTEN)		return;	BUG_ON(hcrx == NULL);	info->tcpi_ca_state	= hcrx->ccid3hcrx_state;	info->tcpi_options	|= TCPI_OPT_TIMESTAMPS;	info->tcpi_rcv_rtt	= hcrx->ccid3hcrx_rtt;}static void ccid3_hc_tx_get_info(struct sock *sk, struct tcp_info *info){	const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);	/* Listen socks doesn't have a private CCID block */	if (sk->sk_state == DCCP_LISTEN)		return;	BUG_ON(hctx == NULL);	info->tcpi_rto = hctx->ccid3hctx_t_rto;	info->tcpi_rtt = hctx->ccid3hctx_rtt;}static int ccid3_hc_rx_getsockopt(struct sock *sk, const int optname, int len,				  u32 __user *optval, int __user *optlen){	const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);	const void *val;		/* Listen socks doesn't have a private CCID block */	if (sk->sk_state == DCCP_LISTEN)		return -EINVAL;	switch (optname) {	case DCCP_SOCKOPT_CCID_RX_INFO:		if (len < sizeof(hcrx->ccid3hcrx_tfrc))			return -EINVAL;		len = sizeof(hcrx->ccid3hcrx_tfrc);		val = &hcrx->ccid3hcrx_tfrc;		break;	default:		return -ENOPROTOOPT;	}	if (put_user(len, optlen) || copy_to_user(optval, val, len))		return -EFAULT;	return 0;}static int ccid3_hc_tx_getsockopt(struct sock *sk, const int optname, int len,				  u32 __user *optval, int __user *optlen){	const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);	const void *val;		/* Listen socks doesn't have a private CCID block */	if (sk->sk_state == DCCP_LISTEN)		return -EINVAL;	switch (optname) {	case DCCP_SOCKOPT_CCID_TX_INFO:		if (len < sizeof(hctx->ccid3hctx_tfrc))			return -EINVAL;		len = sizeof(hctx->ccid3hctx_tfrc);		val = &hctx->ccid3hctx_tfrc;		break;	default:		return -ENOPROTOOPT;	}	if (put_user(len, optlen) || copy_to_user(optval, val, len))		return -EFAULT;	return 0;}static struct ccid_operations ccid3 = {	.ccid_id		   = 3,	.ccid_name		   = "ccid3",	.ccid_owner		   = THIS_MODULE,	.ccid_hc_tx_obj_size	   = sizeof(struct ccid3_hc_tx_sock),	.ccid_hc_tx_init	   = ccid3_hc_tx_init,	.ccid_hc_tx_exit	   = ccid3_hc_tx_exit,	.ccid_hc_tx_send_packet	   = ccid3_hc_tx_send_packet,	.ccid_hc_tx_packet_sent	   = ccid3_hc_tx_packet_sent,	.ccid_hc_tx_packet_recv	   = ccid3_hc_tx_packet_recv,	.ccid_hc_tx_insert_options = ccid3_hc_tx_insert_options,	.ccid_hc_tx_parse_options  = ccid3_hc_tx_parse_options,	.ccid_hc_rx_obj_size	   = sizeof(struct ccid3_hc_rx_sock),	.ccid_hc_rx_init	   = ccid3_hc_rx_init,	.ccid_hc_rx_exit	   = ccid3_hc_rx_exit,	.ccid_hc_rx_insert_options = ccid3_hc_rx_insert_options,	.ccid_hc_rx_packet_recv	   = ccid3_hc_rx_packet_recv,	.ccid_hc_rx_get_info	   = ccid3_hc_rx_get_info,	.ccid_hc_tx_get_info	   = ccid3_hc_tx_get_info,	.ccid_hc_rx_getsockopt	   = ccid3_hc_rx_getsockopt,	.ccid_hc_tx_getsockopt	   = ccid3_hc_tx_getsockopt,}; module_param(ccid3_debug, int, 0444);MODULE_PARM_DESC(ccid3_debug, "Enable debug messages");static __init int ccid3_module_init(void){	int rc = -ENOBUFS;	ccid3_rx_hist = dccp_rx_hist_new("ccid3");	if (ccid3_rx_hist == NULL)		goto out;	ccid3_tx_hist = dccp_tx_hist_new("ccid3");	if (ccid3_tx_hist == NULL)		goto out_free_rx;	ccid3_li_hist = dccp_li_hist_new("ccid3");	if (ccid3_li_hist == NULL)		goto out_free_tx;	rc = ccid_register(&ccid3);	if (rc != 0) 		goto out_free_loss_interval_history;out:	return rc;out_free_loss_interval_history:	dccp_li_hist_delete(ccid3_li_hist);	ccid3_li_hist = NULL;out_free_tx:	dccp_tx_hist_delete(ccid3_tx_hist);	ccid3_tx_hist = NULL;out_free_rx:	dccp_rx_hist_delete(ccid3_rx_hist);	ccid3_rx_hist = NULL;	goto out;}module_init(ccid3_module_init);static __exit void ccid3_module_exit(void){	ccid_unregister(&ccid3);	if (ccid3_tx_hist != NULL) {		dccp_tx_hist_delete(ccid3_tx_hist);		ccid3_tx_hist = NULL;	}	if (ccid3_rx_hist != NULL) {		dccp_rx_hist_delete(ccid3_rx_hist);		ccid3_rx_hist = NULL;	}	if (ccid3_li_hist != NULL) {		dccp_li_hist_delete(ccid3_li_hist);		ccid3_li_hist = NULL;	}}module_exit(ccid3_module_exit);MODULE_AUTHOR("Ian McDonald <iam4@cs.waikato.ac.nz>, "	      "Arnaldo Carvalho de Melo <acme@ghostprotocols.net>");MODULE_DESCRIPTION("DCCP TFRC CCID3 CCID");MODULE_LICENSE("GPL");MODULE_ALIAS("net-dccp-ccid-3");

⌨️ 快捷键说明

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