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

📄 ccid3.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	/* prepare to send now (add options etc.) */	dp->dccps_hc_tx_insert_options = 1;	DCCP_SKB_CB(skb)->dccpd_ccval = hctx->ccid3hctx_last_win_count;	hctx->ccid3hctx_idle = 0;	/* set the nominal send time for the next following packet */	hctx->ccid3hctx_t_nom = ktime_add_us(hctx->ccid3hctx_t_nom,					     hctx->ccid3hctx_t_ipi);	return 0;}static void ccid3_hc_tx_packet_sent(struct sock *sk, int more,				    unsigned int len){	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);	struct dccp_tx_hist_entry *packet;	ccid3_hc_tx_update_s(hctx, len);	packet = dccp_tx_hist_entry_new(ccid3_tx_hist, GFP_ATOMIC);	if (unlikely(packet == NULL)) {		DCCP_CRIT("packet history - out of memory!");		return;	}	dccp_tx_hist_add_entry(&hctx->ccid3hctx_hist, packet);	packet->dccphtx_tstamp = ktime_get_real();	packet->dccphtx_seqno  = dccp_sk(sk)->dccps_gss;	packet->dccphtx_rtt    = hctx->ccid3hctx_rtt;	packet->dccphtx_sent   = 1;}static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb){	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);	struct ccid3_options_received *opt_recv;	struct dccp_tx_hist_entry *packet;	ktime_t now;	unsigned long t_nfb;	u32 pinv, r_sample;	/* we are only interested in ACKs */	if (!(DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK ||	      DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_DATAACK))		return;	opt_recv = &hctx->ccid3hctx_options_received;	switch (hctx->ccid3hctx_state) {	case TFRC_SSTATE_NO_FBACK:	case TFRC_SSTATE_FBACK:		/* get packet from history to look up t_recvdata */		packet = dccp_tx_hist_find_entry(&hctx->ccid3hctx_hist,					      DCCP_SKB_CB(skb)->dccpd_ack_seq);		if (unlikely(packet == NULL)) {			DCCP_WARN("%s(%p), seqno %llu(%s) doesn't exist "				  "in history!\n",  dccp_role(sk), sk,			    (unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq,				dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type));			return;		}		/* Update receive rate in units of 64 * bytes/second */		hctx->ccid3hctx_x_recv = opt_recv->ccid3or_receive_rate;		hctx->ccid3hctx_x_recv <<= 6;		/* Update loss event rate */		pinv = opt_recv->ccid3or_loss_event_rate;		if (pinv == ~0U || pinv == 0)	       /* see RFC 4342, 8.5   */			hctx->ccid3hctx_p = 0;		else				       /* can not exceed 100% */			hctx->ccid3hctx_p = 1000000 / pinv;		now = ktime_get_real();		/*		 * Calculate new round trip sample as per [RFC 3448, 4.3] by		 *	R_sample  =  (now - t_recvdata) - t_elapsed		 */		r_sample = dccp_sample_rtt(sk, ktime_us_delta(now, packet->dccphtx_tstamp));		/*		 * Update RTT estimate by		 * If (No feedback recv)		 *    R = R_sample;		 * Else		 *    R = q * R + (1 - q) * R_sample;		 *		 * q is a constant, RFC 3448 recomments 0.9		 */		if (hctx->ccid3hctx_state == TFRC_SSTATE_NO_FBACK) {			/*			 * Larger Initial Windows [RFC 4342, sec. 5]			 */			hctx->ccid3hctx_rtt  = r_sample;			hctx->ccid3hctx_x    = rfc3390_initial_rate(sk);			hctx->ccid3hctx_t_ld = now;			ccid3_update_send_interval(hctx);			ccid3_pr_debug("%s(%p), s=%u, MSS=%u, "				       "R_sample=%uus, X=%u\n", dccp_role(sk),				       sk, hctx->ccid3hctx_s,				       dccp_sk(sk)->dccps_mss_cache, r_sample,				       (unsigned)(hctx->ccid3hctx_x >> 6));			ccid3_hc_tx_set_state(sk, TFRC_SSTATE_FBACK);		} else {			hctx->ccid3hctx_rtt = (9 * hctx->ccid3hctx_rtt +						   r_sample) / 10;			/* Update sending rate (step 4 of [RFC 3448, 4.3]) */			if (hctx->ccid3hctx_p > 0)				hctx->ccid3hctx_x_calc =					tfrc_calc_x(hctx->ccid3hctx_s,						    hctx->ccid3hctx_rtt,						    hctx->ccid3hctx_p);			ccid3_hc_tx_update_x(sk, &now);			ccid3_pr_debug("%s(%p), RTT=%uus (sample=%uus), s=%u, "				       "p=%u, X_calc=%u, X_recv=%u, X=%u\n",				       dccp_role(sk),				       sk, hctx->ccid3hctx_rtt, r_sample,				       hctx->ccid3hctx_s, hctx->ccid3hctx_p,				       hctx->ccid3hctx_x_calc,				       (unsigned)(hctx->ccid3hctx_x_recv >> 6),				       (unsigned)(hctx->ccid3hctx_x >> 6));		}		/* unschedule no feedback timer */		sk_stop_timer(sk, &hctx->ccid3hctx_no_feedback_timer);		/* remove all packets older than the one acked from history */		dccp_tx_hist_purge_older(ccid3_tx_hist,					 &hctx->ccid3hctx_hist, packet);		/*		 * As we have calculated new ipi, delta, t_nom it is possible		 * that we now can send a packet, so wake up dccp_wait_for_ccid		 */		sk->sk_write_space(sk);		/*		 * Update timeout interval for the nofeedback timer.		 * We use a configuration option to increase the lower bound.		 * This can help avoid triggering the nofeedback timer too		 * often ('spinning') on LANs with small RTTs.		 */		hctx->ccid3hctx_t_rto = max_t(u32, 4 * hctx->ccid3hctx_rtt,						   CONFIG_IP_DCCP_CCID3_RTO *						   (USEC_PER_SEC/1000));		/*		 * Schedule no feedback timer to expire in		 * max(t_RTO, 2 * s/X)  =  max(t_RTO, 2 * t_ipi)		 */		t_nfb = max(hctx->ccid3hctx_t_rto, 2 * hctx->ccid3hctx_t_ipi);		ccid3_pr_debug("%s(%p), Scheduled no feedback timer to "			       "expire in %lu jiffies (%luus)\n",			       dccp_role(sk),			       sk, usecs_to_jiffies(t_nfb), t_nfb);		sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,				   jiffies + usecs_to_jiffies(t_nfb));		/* set idle flag */		hctx->ccid3hctx_idle = 1;		break;	case TFRC_SSTATE_NO_SENT:	/* fall through */	case TFRC_SSTATE_TERM:		/* ignore feedback when closing */		break;	}}static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,				     unsigned char len, u16 idx,				     unsigned char *value){	int rc = 0;	const struct dccp_sock *dp = dccp_sk(sk);	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);	struct ccid3_options_received *opt_recv;	__be32 opt_val;	opt_recv = &hctx->ccid3hctx_options_received;	if (opt_recv->ccid3or_seqno != dp->dccps_gsr) {		opt_recv->ccid3or_seqno		     = dp->dccps_gsr;		opt_recv->ccid3or_loss_event_rate    = ~0;		opt_recv->ccid3or_loss_intervals_idx = 0;		opt_recv->ccid3or_loss_intervals_len = 0;		opt_recv->ccid3or_receive_rate	     = 0;	}	switch (option) {	case TFRC_OPT_LOSS_EVENT_RATE:		if (unlikely(len != 4)) {			DCCP_WARN("%s(%p), invalid len %d "				  "for TFRC_OPT_LOSS_EVENT_RATE\n",				  dccp_role(sk), sk, len);			rc = -EINVAL;		} else {			opt_val = get_unaligned((__be32 *)value);			opt_recv->ccid3or_loss_event_rate = ntohl(opt_val);			ccid3_pr_debug("%s(%p), LOSS_EVENT_RATE=%u\n",				       dccp_role(sk), sk,				       opt_recv->ccid3or_loss_event_rate);		}		break;	case TFRC_OPT_LOSS_INTERVALS:		opt_recv->ccid3or_loss_intervals_idx = idx;		opt_recv->ccid3or_loss_intervals_len = len;		ccid3_pr_debug("%s(%p), LOSS_INTERVALS=(%u, %u)\n",			       dccp_role(sk), sk,			       opt_recv->ccid3or_loss_intervals_idx,			       opt_recv->ccid3or_loss_intervals_len);		break;	case TFRC_OPT_RECEIVE_RATE:		if (unlikely(len != 4)) {			DCCP_WARN("%s(%p), invalid len %d "				  "for TFRC_OPT_RECEIVE_RATE\n",				  dccp_role(sk), sk, len);			rc = -EINVAL;		} else {			opt_val = get_unaligned((__be32 *)value);			opt_recv->ccid3or_receive_rate = ntohl(opt_val);			ccid3_pr_debug("%s(%p), RECEIVE_RATE=%u\n",				       dccp_role(sk), sk,				       opt_recv->ccid3or_receive_rate);		}		break;	}	return rc;}static int ccid3_hc_tx_init(struct ccid *ccid, struct sock *sk){	struct ccid3_hc_tx_sock *hctx = ccid_priv(ccid);	hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT;	INIT_LIST_HEAD(&hctx->ccid3hctx_hist);	hctx->ccid3hctx_no_feedback_timer.function =				ccid3_hc_tx_no_feedback_timer;	hctx->ccid3hctx_no_feedback_timer.data     = (unsigned long)sk;	init_timer(&hctx->ccid3hctx_no_feedback_timer);	return 0;}static void ccid3_hc_tx_exit(struct sock *sk){	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);	ccid3_hc_tx_set_state(sk, TFRC_SSTATE_TERM);	sk_stop_timer(sk, &hctx->ccid3hctx_no_feedback_timer);	/* Empty packet history */	dccp_tx_hist_purge(ccid3_tx_hist, &hctx->ccid3hctx_hist);}static void ccid3_hc_tx_get_info(struct sock *sk, struct tcp_info *info){	struct ccid3_hc_tx_sock *hctx;	/* Listen socks doesn't have a private CCID block */	if (sk->sk_state == DCCP_LISTEN)		return;	hctx = ccid3_hc_tx_sk(sk);	info->tcpi_rto = hctx->ccid3hctx_t_rto;	info->tcpi_rtt = hctx->ccid3hctx_rtt;}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;	const void *val;	/* Listen socks doesn't have a private CCID block */	if (sk->sk_state == DCCP_LISTEN)		return -EINVAL;	hctx = ccid3_hc_tx_sk(sk);	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;}/* *	Receiver Half-Connection Routines */#ifdef CONFIG_IP_DCCP_CCID3_DEBUGstatic const char *ccid3_rx_state_name(enum ccid3_hc_rx_states state){	static char *ccid3_rx_state_names[] = {	[TFRC_RSTATE_NO_DATA] = "NO_DATA",	[TFRC_RSTATE_DATA]    = "DATA",	[TFRC_RSTATE_TERM]    = "TERM",	};	return ccid3_rx_state_names[state];}#endifstatic void ccid3_hc_rx_set_state(struct sock *sk,				  enum ccid3_hc_rx_states state){	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);	enum ccid3_hc_rx_states oldstate = hcrx->ccid3hcrx_state;	ccid3_pr_debug("%s(%p) %-8.8s -> %s\n",		       dccp_role(sk), sk, ccid3_rx_state_name(oldstate),		       ccid3_rx_state_name(state));	WARN_ON(state == oldstate);	hcrx->ccid3hcrx_state = state;}static inline void ccid3_hc_rx_update_s(struct ccid3_hc_rx_sock *hcrx, int len){	if (unlikely(len == 0))	/* don't update on empty packets (e.g. ACKs) */		ccid3_pr_debug("Packet payload length is 0 - not updating\n");	else		hcrx->ccid3hcrx_s = hcrx->ccid3hcrx_s == 0 ? len :				    (9 * hcrx->ccid3hcrx_s + len) / 10;}static void ccid3_hc_rx_send_feedback(struct sock *sk){	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);	struct dccp_sock *dp = dccp_sk(sk);	struct dccp_rx_hist_entry *packet;	ktime_t now;	suseconds_t delta;	ccid3_pr_debug("%s(%p) - entry \n", dccp_role(sk), sk);	now = ktime_get_real();	switch (hcrx->ccid3hcrx_state) {	case TFRC_RSTATE_NO_DATA:		hcrx->ccid3hcrx_x_recv = 0;		break;	case TFRC_RSTATE_DATA:		delta = ktime_us_delta(now,				       hcrx->ccid3hcrx_tstamp_last_feedback);		DCCP_BUG_ON(delta < 0);		hcrx->ccid3hcrx_x_recv =			scaled_div32(hcrx->ccid3hcrx_bytes_recv, delta);		break;	case TFRC_RSTATE_TERM:		DCCP_BUG("%s(%p) - Illegal state TERM", dccp_role(sk), sk);		return;	}

⌨️ 快捷键说明

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