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

📄 ccid3.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	packet = dccp_rx_hist_find_data_packet(&hcrx->ccid3hcrx_hist);	if (unlikely(packet == NULL)) {		DCCP_WARN("%s(%p), no data packet in history!\n",			  dccp_role(sk), sk);		return;	}	hcrx->ccid3hcrx_tstamp_last_feedback = now;	hcrx->ccid3hcrx_ccval_last_counter   = packet->dccphrx_ccval;	hcrx->ccid3hcrx_bytes_recv	     = 0;	/* Elapsed time information [RFC 4340, 13.2] in units of 10 * usecs */	delta = ktime_us_delta(now, packet->dccphrx_tstamp);	DCCP_BUG_ON(delta < 0);	hcrx->ccid3hcrx_elapsed_time = delta / 10;	if (hcrx->ccid3hcrx_p == 0)		hcrx->ccid3hcrx_pinv = ~0U;	/* see RFC 4342, 8.5 */	else if (hcrx->ccid3hcrx_p > 1000000) {		DCCP_WARN("p (%u) > 100%%\n", hcrx->ccid3hcrx_p);		hcrx->ccid3hcrx_pinv = 1;	/* use 100% in this case */	} else		hcrx->ccid3hcrx_pinv = 1000000 / hcrx->ccid3hcrx_p;	dp->dccps_hc_rx_insert_options = 1;	dccp_send_ack(sk);}static int ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb){	const struct ccid3_hc_rx_sock *hcrx;	__be32 x_recv, pinv;	if (!(sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN))		return 0;	hcrx = ccid3_hc_rx_sk(sk);	DCCP_SKB_CB(skb)->dccpd_ccval = hcrx->ccid3hcrx_ccval_last_counter;	if (dccp_packet_without_ack(skb))		return 0;	x_recv = htonl(hcrx->ccid3hcrx_x_recv);	pinv   = htonl(hcrx->ccid3hcrx_pinv);	if ((hcrx->ccid3hcrx_elapsed_time != 0 &&	     dccp_insert_option_elapsed_time(sk, skb,					     hcrx->ccid3hcrx_elapsed_time)) ||	    dccp_insert_option_timestamp(sk, skb) ||	    dccp_insert_option(sk, skb, TFRC_OPT_LOSS_EVENT_RATE,			       &pinv, sizeof(pinv)) ||	    dccp_insert_option(sk, skb, TFRC_OPT_RECEIVE_RATE,			       &x_recv, sizeof(x_recv)))		return -1;	return 0;}static int ccid3_hc_rx_detect_loss(struct sock *sk,				    struct dccp_rx_hist_entry *packet){	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);	struct dccp_rx_hist_entry *rx_hist =				dccp_rx_hist_head(&hcrx->ccid3hcrx_hist);	u64 seqno = packet->dccphrx_seqno;	u64 tmp_seqno;	int loss = 0;	u8 ccval;	tmp_seqno = hcrx->ccid3hcrx_seqno_nonloss;	if (!rx_hist ||	   follows48(packet->dccphrx_seqno, hcrx->ccid3hcrx_seqno_nonloss)) {		hcrx->ccid3hcrx_seqno_nonloss = seqno;		hcrx->ccid3hcrx_ccval_nonloss = packet->dccphrx_ccval;		goto detect_out;	}	while (dccp_delta_seqno(hcrx->ccid3hcrx_seqno_nonloss, seqno)	   > TFRC_RECV_NUM_LATE_LOSS) {		loss = 1;		dccp_li_update_li(sk,				  &hcrx->ccid3hcrx_li_hist,				  &hcrx->ccid3hcrx_hist,				  hcrx->ccid3hcrx_tstamp_last_feedback,				  hcrx->ccid3hcrx_s,				  hcrx->ccid3hcrx_bytes_recv,				  hcrx->ccid3hcrx_x_recv,				  hcrx->ccid3hcrx_seqno_nonloss,				  hcrx->ccid3hcrx_ccval_nonloss);		tmp_seqno = hcrx->ccid3hcrx_seqno_nonloss;		dccp_inc_seqno(&tmp_seqno);		hcrx->ccid3hcrx_seqno_nonloss = tmp_seqno;		dccp_inc_seqno(&tmp_seqno);		while (dccp_rx_hist_find_entry(&hcrx->ccid3hcrx_hist,		   tmp_seqno, &ccval)) {			hcrx->ccid3hcrx_seqno_nonloss = tmp_seqno;			hcrx->ccid3hcrx_ccval_nonloss = ccval;			dccp_inc_seqno(&tmp_seqno);		}	}	/* FIXME - this code could be simplified with above while */	/* but works at moment */	if (follows48(packet->dccphrx_seqno, hcrx->ccid3hcrx_seqno_nonloss)) {		hcrx->ccid3hcrx_seqno_nonloss = seqno;		hcrx->ccid3hcrx_ccval_nonloss = packet->dccphrx_ccval;	}detect_out:	dccp_rx_hist_add_packet(ccid3_rx_hist, &hcrx->ccid3hcrx_hist,		   &hcrx->ccid3hcrx_li_hist, packet,		   hcrx->ccid3hcrx_seqno_nonloss);	return 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;	u32 p_prev, r_sample, rtt_prev;	int loss, payload_size;	ktime_t now;	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;		r_sample = dccp_timestamp() - opt_recv->dccpor_timestamp_echo;		rtt_prev = hcrx->ccid3hcrx_rtt;		r_sample = dccp_sample_rtt(sk, 10 * r_sample);		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 (rtt_prev != hcrx->ccid3hcrx_rtt)			ccid3_pr_debug("%s(%p), New RTT=%uus, elapsed time=%u\n",				       dccp_role(sk), 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, opt_recv->dccpor_ndp,					skb, GFP_ATOMIC);	if (unlikely(packet == NULL)) {		DCCP_WARN("%s(%p), Not enough mem to add rx packet "			  "to history, consider it lost!\n", dccp_role(sk), sk);		return;	}	loss = ccid3_hc_rx_detect_loss(sk, packet);	if (DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK)		return;	payload_size = skb->len - dccp_hdr(skb)->dccph_doff * 4;	ccid3_hc_rx_update_s(hcrx, payload_size);	switch (hcrx->ccid3hcrx_state) {	case TFRC_RSTATE_NO_DATA:		ccid3_pr_debug("%s(%p, state=%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 += payload_size;		if (loss)			break;		now = ktime_get_real();		if ((ktime_us_delta(now, hcrx->ccid3hcrx_tstamp_last_ack) -		     (s64)hcrx->ccid3hcrx_rtt) >= 0) {			hcrx->ccid3hcrx_tstamp_last_ack = now;			ccid3_hc_rx_send_feedback(sk);		}		return;	case TFRC_RSTATE_TERM:		DCCP_BUG("%s(%p) - Illegal state TERM", dccp_role(sk), sk);		return;	}	/* Dealing with packet loss */	ccid3_pr_debug("%s(%p, state=%s), data loss! Reacting...\n",		       dccp_role(sk), sk, dccp_state_name(sk->sk_state));	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;	} else		DCCP_BUG("empty loss history");	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 ccid3_hc_rx_sock *hcrx = ccid_priv(ccid);	ccid3_pr_debug("entry\n");	hcrx->ccid3hcrx_state = TFRC_RSTATE_NO_DATA;	INIT_LIST_HEAD(&hcrx->ccid3hcrx_hist);	INIT_LIST_HEAD(&hcrx->ccid3hcrx_li_hist);	hcrx->ccid3hcrx_tstamp_last_feedback =		hcrx->ccid3hcrx_tstamp_last_ack = ktime_get_real();	return 0;}static void ccid3_hc_rx_exit(struct sock *sk){	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);	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(&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;	/* Listen socks doesn't have a private CCID block */	if (sk->sk_state == DCCP_LISTEN)		return;	hcrx = ccid3_hc_rx_sk(sk);	info->tcpi_ca_state = hcrx->ccid3hcrx_state;	info->tcpi_options  |= TCPI_OPT_TIMESTAMPS;	info->tcpi_rcv_rtt  = hcrx->ccid3hcrx_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;	const void *val;	/* Listen socks doesn't have a private CCID block */	if (sk->sk_state == DCCP_LISTEN)		return -EINVAL;	hcrx = ccid3_hc_rx_sk(sk);	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 struct ccid_operations ccid3 = {	.ccid_id		   = DCCPC_CCID3,	.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_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,};#ifdef CONFIG_IP_DCCP_CCID3_DEBUGmodule_param(ccid3_debug, bool, 0444);MODULE_PARM_DESC(ccid3_debug, "Enable debug messages");#endifstatic __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;	rc = ccid_register(&ccid3);	if (rc != 0)		goto out_free_tx;out:	return rc;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;	}}module_exit(ccid3_module_exit);MODULE_AUTHOR("Ian McDonald <ian.mcdonald@jandi.co.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 + -