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

📄 tcp_send.c

📁 minix3的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
				tmp_pack->acc_next=					bf_cut(tcp_conn->tc_send_data, 					(unsigned)(seg_lo_data-queue_lo_data), 					(unsigned) (seg_hi_data-seg_lo_data));			}			seg_flags |= THF_ACK;		}after_data:		if (!(seg_flags & THF_ACK))		{			if (pack2write)				bf_afree(pack2write);			return NULL;		}		tcp_hdr->th_seq_nr= htonl(seg_seq);		tcp_hdr->th_ack_nr= htonl(tcp_conn->tc_RCV_NXT);		tcp_hdr->th_flags= seg_flags;		tcp_hdr->th_window= htons(tcp_conn->tc_RCV_HI -			tcp_conn->tc_RCV_NXT);		tcp_hdr->th_urgptr= htons(seg_up);		pack_size= bf_bufsize(pack2write);		ip_hdr->ih_length= htons(pack_size);		pack2write->acc_linkC++;		ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;		tcp_pack= bf_delhead(pack2write, ip_hdr_len);		tcp_hdr->th_chksum= ~tcp_pack_oneCsum(ip_hdr, tcp_pack);		bf_afree(tcp_pack);		new_dis= curr_time + 2*HZ*tcp_conn->tc_ttl;		if (new_dis > tcp_conn->tc_senddis)			tcp_conn->tc_senddis= new_dis;		return pack2write;	default:		DBLOCK(1, tcp_print_conn(tcp_conn); printf("\n"));		ip_panic(( "Illegal state" ));	}	assert(0);	return NULL;}/*tcp_release_retrans*/PUBLIC void tcp_release_retrans(tcp_conn, seg_ack, new_win)tcp_conn_t *tcp_conn;u32_t seg_ack;u16_t new_win;{	tcp_fd_t *tcp_fd;	size_t size, offset;	acc_t *pack;	clock_t retrans_time, curr_time, rtt, artt, drtt, srtt;	u32_t queue_lo, queue_hi;	u16_t mss, cthresh;	unsigned window;	DBLOCK(0x10, printf("tcp_release_retrans, conn[%d]: ack %lu, win %u\n",		tcp_conn-tcp_conn_table, (unsigned long)seg_ack, new_win););	assert(tcp_conn->tc_busy);	assert (tcp_GEmod4G(seg_ack, tcp_conn->tc_SND_UNA));	assert (tcp_LEmod4G(seg_ack, tcp_conn->tc_SND_NXT));	tcp_conn->tc_snd_dack= 0;	mss= tcp_conn->tc_mtu-IP_TCP_MIN_HDR_SIZE;	curr_time= get_time();	if (tcp_conn->tc_rt_seq != 0 && 		tcp_Gmod4G(seg_ack, tcp_conn->tc_rt_seq))	{		assert(curr_time >= tcp_conn->tc_rt_time);		retrans_time= curr_time-tcp_conn->tc_rt_time;		rtt= tcp_conn->tc_rtt;		tcp_conn->tc_rt_seq= 0;		if (rtt == TCP_RTT_GRAN*CLOCK_GRAN &&			retrans_time <= TCP_RTT_GRAN*CLOCK_GRAN)		{			/* Common in fast networks. Nothing to do. */		}		else		{			srtt= retrans_time * TCP_RTT_SCALE;			artt= tcp_conn->tc_artt;			artt= ((TCP_RTT_SMOOTH-1)*artt+srtt)/TCP_RTT_SMOOTH;			srtt -= artt;			if (srtt < 0)				srtt= -srtt;			drtt= tcp_conn->tc_drtt;			drtt= ((TCP_RTT_SMOOTH-1)*drtt+srtt)/TCP_RTT_SMOOTH;			rtt= (artt+TCP_DRTT_MULT*drtt-1)/TCP_RTT_SCALE+1;			if (rtt < TCP_RTT_GRAN*CLOCK_GRAN)			{				rtt= TCP_RTT_GRAN*CLOCK_GRAN;			}			else if (rtt > TCP_RTT_MAX)			{#if DEBUG				static int warned /* = 0 */;				if (!warned)				{					printf("tcp_release_retrans: warning retransmission time is limited to %d ms\n",						TCP_RTT_MAX*1000/HZ);					warned= 1;				}#endif				rtt= TCP_RTT_MAX;			}			DBLOCK(0x10, printf(	"tcp_release_retrans, conn[%d]: retrans_time= %ld ms, rtt = %ld ms\n",				tcp_conn-tcp_conn_table,				retrans_time*1000/HZ,				rtt*1000/HZ));			DBLOCK(0x10, printf(	"tcp_release_retrans: artt= %ld -> %ld, drtt= %ld -> %ld\n",				tcp_conn->tc_artt, artt,				tcp_conn->tc_drtt, drtt));			tcp_conn->tc_artt= artt;			tcp_conn->tc_drtt= drtt;			tcp_conn->tc_rtt= rtt;		}		if (tcp_conn->tc_mtu != tcp_conn->tc_max_mtu &&			curr_time > tcp_conn->tc_mtutim+TCP_PMTU_INCR_IV)		{			tcp_mtu_incr(tcp_conn);		}	}	/* Update the current window. */	window= tcp_conn->tc_snd_cwnd-tcp_conn->tc_SND_UNA;	assert(seg_ack != tcp_conn->tc_SND_UNA);	/* For every real ACK we try to increase the current window	 * with 1 mss.	 */	window += mss;	/* If the window becomes larger than the current threshold,	 * increment the threshold by a small amount and set the	 * window to the threshold.	 */	cthresh= tcp_conn->tc_snd_cthresh;	if (window > cthresh)	{		cthresh += tcp_conn->tc_snd_cinc;		tcp_conn->tc_snd_cthresh= cthresh;		window= cthresh;	}	/* If the window is larger than the window advertised by the	 * receiver, set the window size to the advertisement.	 */	if (window > new_win)		window= new_win;	tcp_conn->tc_snd_cwnd= seg_ack+window;	/* Release data queued for retransmissions. */	queue_lo= tcp_conn->tc_SND_UNA;	queue_hi= tcp_conn->tc_SND_NXT;	tcp_conn->tc_SND_UNA= seg_ack;	if (tcp_Lmod4G(tcp_conn->tc_SND_TRM, seg_ack))	{		tcp_conn->tc_SND_TRM= seg_ack;	}	assert(tcp_GEmod4G(tcp_conn->tc_snd_cwnd, seg_ack));	/* Advance ISS every 0.5GB to avoid problem with wrap around */	if (tcp_conn->tc_SND_UNA - tcp_conn->tc_ISS > 0x40000000)	{		tcp_conn->tc_ISS += 0x20000000;		DBLOCK(1, printf(			"tcp_release_retrans: updating ISS to 0x%lx\n",			(unsigned long)tcp_conn->tc_ISS););		if (tcp_Lmod4G(tcp_conn->tc_SND_UP, tcp_conn->tc_ISS))		{			tcp_conn->tc_SND_UP= tcp_conn->tc_ISS;			DBLOCK(1, printf(			"tcp_release_retrans: updating SND_UP to 0x%lx\n",				(unsigned long)tcp_conn->tc_SND_UP););		}	}	if (queue_lo == tcp_conn->tc_ISS)		queue_lo++;	if (tcp_conn->tc_flags & TCF_FIN_SENT)	{		if (seg_ack == queue_hi)			seg_ack--;		if (queue_lo == queue_hi)			queue_lo--;		queue_hi--;	}	offset= seg_ack - queue_lo;	size= queue_hi - seg_ack;	pack= tcp_conn->tc_send_data;	tcp_conn->tc_send_data= 0;	if (!size)	{		bf_afree(pack);	}	else	{		pack= bf_delhead(pack, offset);		tcp_conn->tc_send_data= pack;	}	if (tcp_Gmod4G(tcp_conn->tc_SND_TRM, tcp_conn->tc_snd_cwnd))		tcp_conn->tc_SND_TRM= tcp_conn->tc_snd_cwnd;	/* Copy in new data if an ioctl is pending or if a write request is	 * pending and either the write can be completed or at least one	 * mss buffer space is available.	 */	tcp_fd= tcp_conn->tc_fd;	if (tcp_fd)	{		if (tcp_fd->tf_flags & TFF_IOCTL_IP) 		{			tcp_fd_write(tcp_conn);		}		if ((tcp_fd->tf_flags & TFF_WRITE_IP) &&			(size+tcp_fd->tf_write_count <= TCP_MAX_SND_WND_SIZE ||			size <= TCP_MAX_SND_WND_SIZE-mss))		{			tcp_fd_write(tcp_conn);		}		if (tcp_fd->tf_flags & TFF_SEL_WRITE) 			tcp_rsel_write(tcp_conn);	}	else	{		if (tcp_conn->tc_SND_UNA == tcp_conn->tc_SND_NXT)		{			assert(tcp_conn->tc_state == TCS_CLOSING);			DBLOCK(0x10,			printf("all data sent in abondoned connection\n"));			tcp_close_connection(tcp_conn, ENOTCONN);			return;		}	}	if (!size && !tcp_conn->tc_send_data)	{		/* Reset window if a write is completed */		tcp_conn->tc_snd_cwnd= tcp_conn->tc_SND_UNA + mss;	}	DIFBLOCK(2, (tcp_conn->tc_snd_cwnd == tcp_conn->tc_SND_TRM),		printf("not sending: zero window\n"));	if (tcp_conn->tc_snd_cwnd != tcp_conn->tc_SND_TRM &&		tcp_conn->tc_SND_NXT != tcp_conn->tc_SND_TRM)	{		tcp_conn_write(tcp_conn, 1);	}}/*tcp_fast_retrans*/PUBLIC void tcp_fast_retrans(tcp_conn)tcp_conn_t *tcp_conn;{	u16_t mss, mss2;	/* Update threshold sequence number for retransmission calculation. */	if (tcp_Gmod4G(tcp_conn->tc_SND_TRM, tcp_conn->tc_rt_threshold))		tcp_conn->tc_rt_threshold= tcp_conn->tc_SND_TRM;	tcp_conn->tc_SND_TRM= tcp_conn->tc_SND_UNA;	mss= tcp_conn->tc_mtu-IP_TCP_MIN_HDR_SIZE;	mss2= 2*mss;	if (tcp_conn->tc_snd_cwnd == tcp_conn->tc_SND_UNA)		tcp_conn->tc_snd_cwnd++;	if (tcp_Gmod4G(tcp_conn->tc_snd_cwnd, tcp_conn->tc_SND_UNA + mss2))	{		tcp_conn->tc_snd_cwnd= tcp_conn->tc_SND_UNA + mss2;		if (tcp_Gmod4G(tcp_conn->tc_SND_TRM, tcp_conn->tc_snd_cwnd))			tcp_conn->tc_SND_TRM= tcp_conn->tc_snd_cwnd;		tcp_conn->tc_snd_cthresh /= 2;		if (tcp_conn->tc_snd_cthresh < mss2)			tcp_conn->tc_snd_cthresh= mss2;	}	tcp_conn_write(tcp_conn, 1);}#if 0PUBLIC void do_tcp_timeout(tcp_conn)tcp_conn_t *tcp_conn;{	tcp_send_timeout(tcp_conn-tcp_conn_table,		&tcp_conn->tc_transmit_timer);}#endif/*tcp_send_timeout*/PRIVATE void tcp_send_timeout(conn, timer)int conn;struct timer *timer;{	tcp_conn_t *tcp_conn;	u16_t mss, mss2;	u32_t snd_una, snd_nxt;	clock_t curr_time, rtt, stt, timeout;	acc_t *pkt;	int new_ttl, no_push;	DBLOCK(0x20, printf("tcp_send_timeout: conn[%d]\n", conn));	curr_time= get_time();	tcp_conn= &tcp_conn_table[conn];	assert(tcp_conn->tc_flags & TCF_INUSE);	assert(tcp_conn->tc_state != TCS_CLOSED);	assert(tcp_conn->tc_state != TCS_LISTEN);	snd_una= tcp_conn->tc_SND_UNA;	snd_nxt= tcp_conn->tc_SND_NXT;	no_push= (tcp_conn->tc_flags & TCF_NO_PUSH);	if (snd_nxt == snd_una || no_push)	{		/* Nothing more to send */		assert(tcp_conn->tc_SND_TRM == snd_una || no_push);		/* A new write sets the timer if tc_transmit_seq == SND_UNA */		tcp_conn->tc_transmit_seq= tcp_conn->tc_SND_UNA;		tcp_conn->tc_stt= 0;		tcp_conn->tc_0wnd_to= 0;		assert(!tcp_conn->tc_fd ||			!(tcp_conn->tc_fd->tf_flags & TFF_WRITE_IP) ||			(tcp_print_conn(tcp_conn), printf("\n"), 0));		if (snd_nxt != snd_una)		{			assert(no_push);			DBLOCK(1, printf("not setting keepalive timer\n"););			/* No point in setting the keepalive timer if we			 * still have to send more data.			 */			return;		}		assert(tcp_conn->tc_send_data == NULL);		DBLOCK(0x20, printf("keep alive timer\n"));		if (tcp_conn->tc_ka_snd != tcp_conn->tc_SND_NXT ||			tcp_conn->tc_ka_rcv != tcp_conn->tc_RCV_NXT)		{			tcp_conn->tc_ka_snd= tcp_conn->tc_SND_NXT;			tcp_conn->tc_ka_rcv= tcp_conn->tc_RCV_NXT;			DBLOCK(0x20, printf("tcp_send_timeout: conn[%d] setting keepalive timer (+%ld ms)\n",				tcp_conn-tcp_conn_table,				tcp_conn->tc_ka_time*1000/HZ));			clck_timer(&tcp_conn->tc_transmit_timer,				curr_time+tcp_conn->tc_ka_time,				tcp_send_timeout,				tcp_conn-tcp_conn_table);			return;		}		DBLOCK(0x10, printf(		"tcp_send_timeout, conn[%d]: triggering keep alive probe\n",			tcp_conn-tcp_conn_table));		tcp_conn->tc_ka_snd--;		if (!(tcp_conn->tc_flags & TCF_FIN_SENT))		{			pkt= bf_memreq(1);			*ptr2acc_data(pkt)= '\xff';	/* a random char */			tcp_conn->tc_send_data= pkt; pkt= NULL;		}		tcp_conn->tc_SND_UNA--;		if (tcp_conn->tc_SND_UNA == tcp_conn->tc_ISS)		{			/* We didn't send anything so far. Retrying the			 * SYN is too hard. Decrement ISS and hope			 * that the other side doesn't care.			 */			tcp_conn->tc_ISS--;		}		/* Set tc_transmit_seq and tc_stt to trigger packet */		tcp_conn->tc_transmit_seq= tcp_conn->tc_SND_UNA;		tcp_conn->tc_stt= curr_time;		/* Set tc_rt_seq for round trip measurements */		tcp_conn->tc_rt_time= curr_time;		tcp_conn->tc_rt_seq= tcp_conn->tc_SND_UNA;		/* Set PSH to make sure that data gets sent */		tcp_conn->tc_SND_PSH= tcp_conn->tc_SND_NXT;		assert(tcp_check_conn(tcp_conn));		/* Fall through */	}	rtt= tcp_conn->tc_rtt;	if (tcp_conn->tc_transmit_seq != tcp_conn->tc_SND_UNA)	{		/* Some data has been acknowledged since the last time the		 * timer was set, set the timer again. */		tcp_conn->tc_transmit_seq= tcp_conn->tc_SND_UNA;		tcp_conn->tc_stt= 0;		tcp_conn->tc_0wnd_to= 0;		DBLOCK(0x20, printf(	"tcp_send_timeout: conn[%d] setting timer to %ld ms (+%ld ms)\n",			tcp_conn-tcp_conn_table,			(curr_time+rtt)*1000/HZ, rtt*1000/HZ));		clck_timer(&tcp_conn->tc_transmit_timer,			curr_time+rtt, tcp_send_timeout,			tcp_conn-tcp_conn_table);		return;	}	stt= tcp_conn->tc_stt;	if (stt == 0)	{		/* Some packet arrived but did not acknowledge any data.		 * Apparently, the other side is still alive and has a		 * reason to transmit. We can asume a zero window.		 */		DBLOCK(0x10, printf("conn[%d] setting zero window timer\n",			tcp_conn-tcp_conn_table));		if (tcp_conn->tc_0wnd_to < TCP_0WND_MIN)			tcp_conn->tc_0wnd_to= TCP_0WND_MIN;		else if (tcp_conn->tc_0wnd_to < rtt)			tcp_conn->tc_0wnd_to= rtt;		else		{			tcp_conn->tc_0wnd_to *= 2;			if (tcp_conn->tc_0wnd_to > TCP_0WND_MAX)				tcp_conn->tc_0wnd_to= TCP_0WND_MAX;		}		tcp_conn->tc_stt= curr_time;		tcp_conn->tc_rt_seq= 0;		DBLOCK(0x10, printf(	"tcp_send_timeout: conn[%d] setting timer to %ld ms (+%ld ms)\n",			tcp_conn-tcp_conn_table,			(curr_time+tcp_conn->tc_0wnd_to)*1000/HZ,			tcp_conn->tc_0wnd_to*1000/HZ));		clck_timer(&tcp_conn->tc_transmit_timer,			curr_time+tcp_conn->tc_0wnd_to,			tcp_send_timeout, tcp_conn-tcp_conn_table);		return;	}	assert(stt <= curr_time);

⌨️ 快捷键说明

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