[377] in linux-net channel archive
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);
};