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

📄 ccid3.c

📁 linux2.6.16版本
💻 C
📖 第 1 页 / 共 3 页
字号:
	case TFRC_SSTATE_FBACK:		if (len > 0) {			hctx->ccid3hctx_t_nom = now;			ccid3_calc_new_t_ipi(hctx);			ccid3_calc_new_delta(hctx);			timeval_add_usecs(&hctx->ccid3hctx_t_nom,					  hctx->ccid3hctx_t_ipi);		}		break;	default:		printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n",		       __FUNCTION__, dccp_role(sk), sk, hctx->ccid3hctx_state);		dump_stack();		break;	}}static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb){	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;	struct dccp_tx_hist_entry *packet;	struct timeval now;	unsigned long next_tmout; 	u32 t_elapsed;	u32 pinv;	u32 x_recv;	u32 r_sample;	BUG_ON(hctx == NULL || hctx->ccid3hctx_state == TFRC_SSTATE_TERM);	/* 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;	t_elapsed = dp->dccps_options_received.dccpor_elapsed_time * 10;	x_recv = opt_recv->ccid3or_receive_rate;	pinv = opt_recv->ccid3or_loss_event_rate;	switch (hctx->ccid3hctx_state) {	case TFRC_SSTATE_NO_SENT:		/* FIXME: what to do here? */		return;	case TFRC_SSTATE_NO_FBACK:	case TFRC_SSTATE_FBACK:		/* Calculate new round trip sample by		 * R_sample = (now - t_recvdata) - t_delay */		/* get t_recvdata from history */		packet = dccp_tx_hist_find_entry(&hctx->ccid3hctx_hist,						 DCCP_SKB_CB(skb)->dccpd_ack_seq);		if (unlikely(packet == NULL)) {			LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, seqno "				       "%llu(%s) does't exist in history!\n",				       __FUNCTION__, 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 RTT */		dccp_timestamp(sk, &now);		r_sample = timeval_delta(&now, &packet->dccphtx_tstamp);		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;		/* 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) {			ccid3_hc_tx_set_state(sk, TFRC_SSTATE_FBACK);			hctx->ccid3hctx_rtt = r_sample;		} else			hctx->ccid3hctx_rtt = (hctx->ccid3hctx_rtt * 9) / 10 +					      r_sample / 10;		ccid3_pr_debug("%s, sk=%p, New RTT estimate=%uus, "			       "r_sample=%us\n", dccp_role(sk), sk,			       hctx->ccid3hctx_rtt, r_sample);		/* Update timeout interval */		hctx->ccid3hctx_t_rto = max_t(u32, 4 * hctx->ccid3hctx_rtt,					      USEC_PER_SEC);		/* Update receive rate */		hctx->ccid3hctx_x_recv = x_recv;/* X_recv in bytes per sec */		/* Update loss event rate */		if (pinv == ~0 || pinv == 0)			hctx->ccid3hctx_p = 0;		else {			hctx->ccid3hctx_p = 1000000 / pinv;			if (hctx->ccid3hctx_p < TFRC_SMALLEST_P) {				hctx->ccid3hctx_p = TFRC_SMALLEST_P;				ccid3_pr_debug("%s, sk=%p, Smallest p used!\n",					       dccp_role(sk), sk);			}		}		/* unschedule no feedback timer */		sk_stop_timer(sk, &hctx->ccid3hctx_no_feedback_timer);		/* Update sending rate */		ccid3_hc_tx_update_x(sk);		/* Update next send time */		timeval_sub_usecs(&hctx->ccid3hctx_t_nom,				  hctx->ccid3hctx_t_ipi);		ccid3_calc_new_t_ipi(hctx);		timeval_add_usecs(&hctx->ccid3hctx_t_nom,				  hctx->ccid3hctx_t_ipi);		ccid3_calc_new_delta(hctx);		/* 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_ccids.		 */		sk->sk_write_space(sk);		/*		 * Schedule no feedback timer to expire in		 * max(4 * R, 2 * s / X)		 */		next_tmout = max(hctx->ccid3hctx_t_rto,				 2 * usecs_div(hctx->ccid3hctx_s,					       hctx->ccid3hctx_x));					ccid3_pr_debug("%s, sk=%p, Scheduled no feedback timer to "			       "expire in %lu jiffies (%luus)\n",			       dccp_role(sk), sk,			       usecs_to_jiffies(next_tmout), next_tmout); 		sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, 			       jiffies + max_t(u32, 1, usecs_to_jiffies(next_tmout)));		/* set idle flag */		hctx->ccid3hctx_idle = 1;   		break;	default:		printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n",		       __FUNCTION__, dccp_role(sk), sk, hctx->ccid3hctx_state);		dump_stack();		break;	}}static void ccid3_hc_tx_insert_options(struct sock *sk, struct sk_buff *skb){	const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);	BUG_ON(hctx == NULL);	if (!(sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN))		return;	 DCCP_SKB_CB(skb)->dccpd_ccval = hctx->ccid3hctx_last_win_count;}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;	BUG_ON(hctx == NULL);	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)) {			LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, invalid "				       "len for TFRC_OPT_LOSS_EVENT_RATE\n",				       __FUNCTION__, dccp_role(sk), sk);			rc = -EINVAL;		} else {			opt_recv->ccid3or_loss_event_rate = ntohl(*(u32 *)value);			ccid3_pr_debug("%s, sk=%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, sk=%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)) {			LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, invalid "				       "len for TFRC_OPT_RECEIVE_RATE\n",				       __FUNCTION__, dccp_role(sk), sk);			rc = -EINVAL;		} else {			opt_recv->ccid3or_receive_rate = ntohl(*(u32 *)value);			ccid3_pr_debug("%s, sk=%p, RECEIVE_RATE=%u\n",				       dccp_role(sk), sk,				       opt_recv->ccid3or_receive_rate);		}		break;	}	return rc;}static int ccid3_hc_tx_init(struct sock *sk){	struct dccp_sock *dp = dccp_sk(sk);	struct ccid3_hc_tx_sock *hctx;	dp->dccps_hc_tx_ccid_private = kmalloc(sizeof(*hctx), gfp_any());	if (dp->dccps_hc_tx_ccid_private == NULL)		return -ENOMEM;	hctx = ccid3_hc_tx_sk(sk);	memset(hctx, 0, sizeof(*hctx));	if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE &&	    dp->dccps_packet_size <= TFRC_MAX_PACKET_SIZE)		hctx->ccid3hctx_s = dp->dccps_packet_size;	else		hctx->ccid3hctx_s = TFRC_STD_PACKET_SIZE;	/* Set transmission rate to 1 packet per second */	hctx->ccid3hctx_x     = hctx->ccid3hctx_s;	hctx->ccid3hctx_t_rto = USEC_PER_SEC;	hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT;	INIT_LIST_HEAD(&hctx->ccid3hctx_hist);	init_timer(&hctx->ccid3hctx_no_feedback_timer);	return 0;}static void ccid3_hc_tx_exit(struct sock *sk){	struct dccp_sock *dp = dccp_sk(sk);	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);	BUG_ON(hctx == NULL);	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);	kfree(dp->dccps_hc_tx_ccid_private);	dp->dccps_hc_tx_ccid_private = NULL;}/* * RX Half Connection methods *//* TFRC receiver states */enum ccid3_hc_rx_states {       	TFRC_RSTATE_NO_DATA = 1,	TFRC_RSTATE_DATA,	TFRC_RSTATE_TERM    = 127,};#ifdef 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 inline 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 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;	struct timeval now;	ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);	dccp_timestamp(sk, &now);	switch (hcrx->ccid3hcrx_state) {	case TFRC_RSTATE_NO_DATA:		hcrx->ccid3hcrx_x_recv = 0;		break;	case TFRC_RSTATE_DATA: {		const u32 delta = timeval_delta(&now,					&hcrx->ccid3hcrx_tstamp_last_feedback);		hcrx->ccid3hcrx_x_recv = usecs_div(hcrx->ccid3hcrx_bytes_recv,						   delta);	}		break;	default:		printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n",		       __FUNCTION__, dccp_role(sk), sk, hcrx->ccid3hcrx_state);		dump_stack();		return;	}	packet = dccp_rx_hist_find_data_packet(&hcrx->ccid3hcrx_hist);	if (unlikely(packet == NULL)) {		LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, no data packet "			       "in history!\n",			       __FUNCTION__, dccp_role(sk), sk);		return;	}	hcrx->ccid3hcrx_tstamp_last_feedback = now;	hcrx->ccid3hcrx_last_counter	     = packet->dccphrx_ccval;	hcrx->ccid3hcrx_seqno_last_counter   = packet->dccphrx_seqno;	hcrx->ccid3hcrx_bytes_recv	     = 0;	/* Convert to multiples of 10us */	hcrx->ccid3hcrx_elapsed_time =			timeval_delta(&now, &packet->dccphrx_tstamp) / 10;	if (hcrx->ccid3hcrx_p == 0)		hcrx->ccid3hcrx_pinv = ~0;	else		hcrx->ccid3hcrx_pinv = 1000000 / hcrx->ccid3hcrx_p;	dp->dccps_hc_rx_insert_options = 1;	dccp_send_ack(sk);}static void ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb){	const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);	u32 x_recv, pinv;	BUG_ON(hcrx == NULL);	if (!(sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN))		return;	DCCP_SKB_CB(skb)->dccpd_ccval = hcrx->ccid3hcrx_last_counter;	if (dccp_packet_without_ack(skb))		return;			if (hcrx->ccid3hcrx_elapsed_time != 0)		dccp_insert_option_elapsed_time(sk, skb,						hcrx->ccid3hcrx_elapsed_time);	dccp_insert_option_timestamp(sk, skb);	x_recv = htonl(hcrx->ccid3hcrx_x_recv);	pinv   = htonl(hcrx->ccid3hcrx_pinv);	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));}/* calculate first loss interval * * returns estimated loss interval in usecs */static u32 ccid3_hc_rx_calc_first_li(struct sock *sk){	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);	struct dccp_rx_hist_entry *entry, *next, *tail = NULL;	u32 rtt, delta, x_recv, fval, p, tmp2;	struct timeval tstamp = { 0, };	int interval = 0;	int win_count = 0;	int step = 0;	u64 tmp1;	list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist,				 dccphrx_node) {		if (dccp_rx_hist_entry_data_packet(entry)) {			tail = entry;			switch (step) {			case 0:				tstamp	  = entry->dccphrx_tstamp;				win_count = entry->dccphrx_ccval;				step = 1;				break;			case 1:				interval = win_count - entry->dccphrx_ccval;

⌨️ 快捷键说明

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