[3939] in linux-net channel archive

home help back first fref pref prev next nref lref last post

TCP/buffering changes

daemon@ATHENA.MIT.EDU (Alan Cox)
Sat Aug 3 20:11:08 1996

Date: 	Sun, 4 Aug 96 00:32 BST
From: alan@lxorguk.ukuu.org.uk (Alan Cox)
To: linux-kernel@vger.rutgers.edu, linux-net@vger.rutgers.edu,
        torvalds@cs.helsinki.fi

*
*	Ok Linus this looks like the working diff. 
*
*	1.	sock_wmalloc/rmalloc allow an allocation to succeed if no
*		memory is allocated. Its up to the protocol to handle limits
*		gracefully beyond this. At worst we can slightly overcommit
*		socket resources beyond those requested.
*
*	2.	TCP sleep for memory is fixed
*
*	3.	Pedro's eth_copy_csum fix
*
*	4.	POSIX 1003.1g compliance oddities while Im fixing tcp
*		MSG_PEEK prevents errors being reported (so you can peek 
*		when there is an error to see whats next, without upsetting
*		the error state)
*		EINVAL and ECONNABORTED error return fixes.
*
*	5.	Fixed the sk->mss == 0 bug reports. sk->mss can be 0 if the
*		remote offers us a zero window and we send before the first
*		ack opening the window. We don't chop our mss to fit their
*		largest window until we see one offered now.
*	
*	Alan
*
*
diff --unified --new-file --recursive --exclude-from exclude linux.vanilla/net/core/sock.c linux/net/core/sock.c
--- linux.vanilla/net/core/sock.c	Sun Jul 28 13:33:17 1996
+++ linux/net/core/sock.c	Sat Aug  3 23:23:04 1996
@@ -348,7 +363,7 @@
 struct sk_buff *sock_wmalloc(struct sock *sk, unsigned long size, int force, int priority)
 {
 	if (sk) {
-		if (force || sk->wmem_alloc + size < sk->sndbuf) {
+		if (force || !sk->wmem_alloc || sk->wmem_alloc + size < sk->sndbuf) {
 			struct sk_buff * skb = alloc_skb(size, priority);
 			if (skb)
 				atomic_add(skb->truesize, &sk->wmem_alloc);
@@ -362,7 +377,7 @@
 struct sk_buff *sock_rmalloc(struct sock *sk, unsigned long size, int force, int priority)
 {
 	if (sk) {
-		if (force || sk->rmem_alloc + size < sk->rcvbuf) {
+		if (force || !sk->rmem_alloc || sk->rmem_alloc + size < sk->rcvbuf) {
 			struct sk_buff *skb = alloc_skb(size, priority);
 			if (skb)
 				atomic_add(skb->truesize, &sk->rmem_alloc);
diff --unified --new-file --recursive --exclude-from exclude linux.vanilla/net/ethernet/eth.c linux/net/ethernet/eth.c
--- linux.vanilla/net/ethernet/eth.c	Sun Jul 28 13:33:18 1996
+++ linux/net/ethernet/eth.c	Sat Aug  3 19:18:34 1996
@@ -273,7 +273,7 @@
 	int ip_length;
 
 	IS_SKB(dest);
-	eth=(struct ethhdr *)dest->data;
+	eth=(struct ethhdr *)src;
 	if(eth->h_proto!=htons(ETH_P_IP))
 	{
 		memcpy(dest->data,src,length);
diff --unified --new-file --recursive --exclude-from exclude linux.vanilla/net/ipv4/af_inet.c linux/net/ipv4/af_inet.c
--- linux.vanilla/net/ipv4/af_inet.c	Sun Jul 28 13:33:18 1996
+++ linux/net/ipv4/af_inet.c	Wed Jul 31 18:25:36 1996
@@ -814,7 +814,7 @@
 		
 	/* check this error. */
 	if (sk->state != TCP_CLOSE)
-		return(-EIO);
+		return(-EINVAL);
 	if(addr_len<sizeof(struct sockaddr_in))
 		return -EINVAL;
 		
@@ -1104,6 +1104,12 @@
 		destroy_sock(sk2);
 		newsock->data = NULL;
 		return err;
+	}
+	if (sk2->state == TCP_CLOSE)
+	{
+		destroy_sock(sk2);
+		newsock->data=NULL;
+		return -ECONNABORTED;
 	}
 	newsock->state = SS_CONNECTED;
 	return(0);
diff --unified --new-file --recursive --exclude-from exclude linux.vanilla/net/ipv4/tcp.c linux/net/ipv4/tcp.c
--- linux.vanilla/net/ipv4/tcp.c	Sun Jul 28 13:33:19 1996
+++ linux/net/ipv4/tcp.c	Sat Aug  3 23:16:42 1996
@@ -856,16 +856,24 @@
 	lock_sock(sk);
 }
 
+extern __inline int tcp_memory_free(struct sock *sk, int umem)
+{
+	if(!sk->wmem_alloc || sk->wmem_alloc+umem>=sk->sndbuf)
+		return 0;
+	return 1;
+}
+
 /*
  *	Wait for more memory for a socket
  */
-static void wait_for_tcp_memory(struct sock * sk)
+static void wait_for_tcp_memory(struct sock * sk, int umem)
 {
 	release_sock(sk);
 	cli();
-	if (sk->wmem_alloc*2 > sk->sndbuf &&
+	/* THIS LINE HAS TO BE CORRECT AND MATCH SOCK_WMALLOC OR KERBOOM */
+	if ( !tcp_memory_free(sk,umem) &&
 	    (sk->state == TCP_ESTABLISHED||sk->state == TCP_CLOSE_WAIT)
-		&& sk->err == 0)
+		&& sk->err == 0 /* && check shutdown ?? */)
 	{
 		sk->socket->flags &= ~SO_NOSPACE;
 		interruptible_sleep_on(sk->sleep);
@@ -964,16 +972,20 @@
 			 */
 #ifndef CONFIG_NO_PATH_MTU_DISCOVERY
 			/*
-			 *	FIXME:  I'm almost sure that this fragment is BUG,
-			 *		but it works... I do not know why 8) --ANK
-			 *
 			 *	Really, we should rebuild all the queues...
 			 *	It's difficult. Temporary hack is to send all
 			 *	queued segments with allowed fragmentation.
 			 */
 			{
+				/*
+				 *	new_mss may be zero. That indicates
+				 *	we don't have a window estimate for
+				 *	the remote box yet. 
+				 *		-- AC
+				 */
+				
 				int new_mss = min(sk->mtu, sk->max_window);
-				if (new_mss < sk->mss)
+				if (new_mss && new_mss < sk->mss)
 				{
 					tcp_send_partial(sk);
 					sk->mss = new_mss;
@@ -1095,7 +1107,7 @@
 					return -ERESTARTSYS;
 				}
 
-				wait_for_tcp_memory(sk);
+				wait_for_tcp_memory(sk, tmp);
 				continue;
 			}
 
@@ -1428,7 +1440,7 @@
 		if (copied)
 			break;
 
-		if (sk->err)
+		if (sk->err && !(flags&MSG_PEEK))
 		{
 			copied = sock_error(sk);
 			break;


home help back first fref pref prev next nref lref last post