[377] in linux-net channel archive

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

Fix for net3 snapshot #5 and loopback deaths

daemon@ATHENA.MIT.EDU (Alan Cox)
Fri May 26 15:59:35 1995

Date: Fri, 26 May 95 17:58 BST
From: iialan@iifeak.swan.ac.uk (Alan Cox)
To: linux-net3@www.linux.org.uk


This cures the problem with named and broadcast servers, as well as other
loopback non TCP. I also fixed appletalk (change net/include/atalk.h to
define ATALK_BCAST as 255 not 0). I'm just posting the loopback patch for now,
I'll do another snapshot on tuesday.

PS: This isnt on ftp.linux.org.uk. I have to resolve a massive overload on
the poor box (an 8Mb Sun3) which isnt taking kindly to 30 ftp's at a time.

Alan


--- loopback.c.old	Fri May 26 10:25:15 1995
+++ loopback.c	Fri May 26 10:30:48 1995
@@ -41,67 +41,82 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
+#include "sock.h"
 
 
-static int
-loopback_xmit(struct sk_buff *skb, struct device *dev)
+static int loopback_xmit(struct sk_buff *skb, struct device *dev)
 {
-  struct enet_statistics *stats = (struct enet_statistics *)dev->priv;
-  unsigned long flags;
-  int unlock=1;
+	struct enet_statistics *stats = (struct enet_statistics *)dev->priv;
+	unsigned long flags;
+	int unlock=1;
   
-  if (skb == NULL || dev == NULL) return(0);
+	if (skb == NULL || dev == NULL) 
+		return(0);
 
-  save_flags(flags);
-  cli();
-  if (dev->tbusy != 0) {
+	save_flags(flags);
+	cli();
+	if (dev->tbusy != 0) 
+	{
+		restore_flags(flags);
+		stats->tx_errors++;
+		return(1);
+	}
+	dev->tbusy = 1;
 	restore_flags(flags);
-	stats->tx_errors++;
-	return(1);
-  }
-  dev->tbusy = 1;
-  restore_flags(flags);
   
-  /* Optimise so buffers with skb->free=1 are not copied but
-     instead are lobbed from tx queue to rx queue */
-
-  if(skb->free==0)
-  {
-  	struct sk_buff *skb2=skb;
-  	skb=skb_clone(skb, GFP_ATOMIC);		/* Clone the buffer */
-  	if(skb==NULL)
-  		return 1;
-  	dev_kfree_skb(skb2, FREE_READ);
-  	unlock=0;
-  }
-
-  skb->protocol=eth_type_trans(skb,dev);
-  skb->dev=dev;
-  save_flags(flags);
-  cli();
-  netif_rx(skb);
-  if(unlock)
-  	skb_device_unlock(skb);
-  restore_flags(flags);
+	/*
+	 *	Optimise so buffers with skb->free=1 are not copied but
+	 *	instead are lobbed from tx queue to rx queue 
+	 */
+
+	if(skb->free==0)
+	{
+	  	struct sk_buff *skb2=skb;
+	  	skb=skb_clone(skb, GFP_ATOMIC);		/* Clone the buffer */
+	  	if(skb==NULL)
+	  		return 1;
+	  	dev_kfree_skb(skb2, FREE_READ);
+  		unlock=0;
+	}
+	else if(skb->sk)
+	{
+	  	/*
+	  	 *	Packet sent but looped back around. Cease to charge
+	  	 *	the socket for the frame.
+	  	 */
+		save_flags(flags);
+	  	cli();
+	  	skb->sk->wmem_alloc-=skb->mem_len;
+	  	skb->sk->write_space(skb->sk);
+	  	restore_flags(flags);
+	}
+
+	skb->protocol=eth_type_trans(skb,dev);
+	skb->dev=dev;
+	save_flags(flags);
+	cli();
+	netif_rx(skb);
+	if(unlock)
+	  	skb_device_unlock(skb);
+	restore_flags(flags);
   
-  stats->tx_packets++;
+	stats->tx_packets++;
 
-  dev->tbusy = 0;
+	dev->tbusy = 0;
 
-  if (!intr_count && (bh_active & bh_mask)) 
-  {
-	start_bh_atomic();
-	do_bottom_half();
-	end_bh_atomic();
-  }
+	if (!intr_count && (bh_active & bh_mask)) 
+	{
+		start_bh_atomic();
+		do_bottom_half();
+		end_bh_atomic();
+	}
 
-  return(0);
+	return(0);
 }
 
-static struct enet_statistics *
-get_stats(struct device *dev)
+static struct enet_statistics *get_stats(struct device *dev)
 {
-    return (struct enet_statistics *)dev->priv;
+	return (struct enet_statistics *)dev->priv;
 }
 
 static int loopback_open(struct device *dev)
@@ -111,47 +126,38 @@
 }
 
 /* Initialize the rest of the LOOPBACK device. */
-int
-loopback_init(struct device *dev)
+int loopback_init(struct device *dev)
 {
-  int i;
+	int i;
 
-  dev->mtu		= 2000;			/* MTU			*/
-  dev->tbusy		= 0;
-  dev->hard_start_xmit	= loopback_xmit;
-  dev->open		= NULL;
-#if 1
-  dev->hard_header	= eth_header;
-  dev->hard_header_len	= ETH_HLEN;		/* 14			*/
-  dev->addr_len		= ETH_ALEN;		/* 6			*/
-  dev->type		= ARPHRD_ETHER;		/* 0x0001		*/
-  dev->rebuild_header	= eth_rebuild_header;
-  dev->open		= loopback_open;
-#else
-  dev->hard_header_length = 0;
-  dev->addr_len		= 0;
-  dev->type		= 0;			/* loopback_type (0)	*/
-  dev->hard_header	= NULL;
-  dev->type_trans	= NULL;
-  dev->rebuild_header	= NULL;
-#endif
-
-  /* New-style flags. */
-  dev->flags		= IFF_LOOPBACK|IFF_BROADCAST;
-  dev->family		= AF_INET;
+	dev->mtu		= 2000;			/* MTU			*/
+	dev->tbusy		= 0;
+	dev->hard_start_xmit	= loopback_xmit;
+	dev->open		= NULL;
+	dev->hard_header	= eth_header;
+	dev->hard_header_len	= ETH_HLEN;		/* 14			*/
+	dev->addr_len		= ETH_ALEN;		/* 6			*/
+	dev->type		= ARPHRD_ETHER;		/* 0x0001		*/
+	dev->rebuild_header	= eth_rebuild_header;
+	dev->open		= loopback_open;
+	dev->flags		= IFF_LOOPBACK|IFF_BROADCAST;
+	dev->family		= AF_INET;
 #ifdef CONFIG_INET    
-  dev->pa_addr		= in_aton("127.0.0.1");
-  dev->pa_brdaddr	= in_aton("127.255.255.255");
-  dev->pa_mask		= in_aton("255.0.0.0");
-  dev->pa_alen		= sizeof(unsigned long);
+	dev->pa_addr		= in_aton("127.0.0.1");
+	dev->pa_brdaddr	= in_aton("127.255.255.255");
+	dev->pa_mask		= in_aton("255.0.0.0");
+	dev->pa_alen		= sizeof(unsigned long);
 #endif  
-  dev->priv = kmalloc(sizeof(struct enet_statistics), GFP_KERNEL);
-  memset(dev->priv, 0, sizeof(struct enet_statistics));
-  dev->get_stats = get_stats;
-
-  /* Fill in the generic fields of the device structure. */
-  for (i = 0; i < DEV_NUMBUFFS; i++)
-	skb_queue_head_init(&dev->buffs[i]);
+	dev->priv = kmalloc(sizeof(struct enet_statistics), GFP_KERNEL);
+	memset(dev->priv, 0, sizeof(struct enet_statistics));
+	dev->get_stats = get_stats;
+
+	/*
+	 *	Fill in the generic fields of the device structure. 
+	 */
+   
+	for (i = 0; i < DEV_NUMBUFFS; i++)
+		skb_queue_head_init(&dev->buffs[i]);
   
-  return(0);
+	return(0);
 };

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