~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/net/loopback.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * INET         An implementation of the TCP/IP protocol suite for the LINUX
  3  *              operating system.  INET is implemented using the  BSD Socket
  4  *              interface as the means of communication with the user level.
  5  *
  6  *              Pseudo-driver for the loopback interface.
  7  *
  8  * Version:     @(#)loopback.c  1.0.4b  08/16/93
  9  *
 10  * Authors:     Ross Biro, <bir7@leland.Stanford.Edu>
 11  *              Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
 12  *              Donald Becker, <becker@cesdis.gsfc.nasa.gov>
 13  *
 14  *              Alan Cox        :       Fixed oddments for NET3.014
 15  *              Alan Cox        :       Rejig for NET3.029 snap #3
 16  *              Alan Cox        :       Fixed NET3.029 bugs and sped up
 17  *              Larry McVoy     :       Tiny tweak to double performance
 18  *              Alan Cox        :       Backed out LMV's tweak - the linux mm
 19  *                                      can't take it...
 20  *              Michael Griffith:       Don't bother computing the checksums
 21  *                                      on packets received on the loopback
 22  *                                      interface.
 23  *              Alexey Kuznetsov:       Potential hang under some extreme
 24  *                                      cases removed.
 25  *
 26  *              This program is free software; you can redistribute it and/or
 27  *              modify it under the terms of the GNU General Public License
 28  *              as published by the Free Software Foundation; either version
 29  *              2 of the License, or (at your option) any later version.
 30  */
 31 #include <linux/kernel.h>
 32 #include <linux/sched.h>
 33 #include <linux/interrupt.h>
 34 #include <linux/fs.h>
 35 #include <linux/types.h>
 36 #include <linux/string.h>
 37 #include <linux/socket.h>
 38 #include <linux/errno.h>
 39 #include <linux/fcntl.h>
 40 #include <linux/in.h>
 41 #include <linux/init.h>
 42 
 43 #include <asm/system.h>
 44 #include <asm/uaccess.h>
 45 #include <asm/io.h>
 46 
 47 #include <linux/inet.h>
 48 #include <linux/netdevice.h>
 49 #include <linux/etherdevice.h>
 50 #include <linux/skbuff.h>
 51 #include <net/sock.h>
 52 #include <linux/if_ether.h>     /* For the statistics structure. */
 53 #include <linux/if_arp.h>       /* For ARPHRD_ETHER */
 54 
 55 #define LOOPBACK_OVERHEAD (128 + MAX_HEADER + 16 + 16)
 56 
 57 /*
 58  * The higher levels take care of making this non-reentrant (it's
 59  * called with bh's disabled).
 60  */
 61 static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)
 62 {
 63         struct net_device_stats *stats = (struct net_device_stats *)dev->priv;
 64 
 65         /*
 66          *      Optimise so buffers with skb->free=1 are not copied but
 67          *      instead are lobbed from tx queue to rx queue 
 68          */
 69 
 70         if(atomic_read(&skb->users) != 1)
 71         {
 72                 struct sk_buff *skb2=skb;
 73                 skb=skb_clone(skb, GFP_ATOMIC);         /* Clone the buffer */
 74                 if(skb==NULL) {
 75                         kfree_skb(skb2);
 76                         return 0;
 77                 }
 78                 kfree_skb(skb2);
 79         }
 80         else
 81                 skb_orphan(skb);
 82 
 83         skb->protocol=eth_type_trans(skb,dev);
 84         skb->dev=dev;
 85 #ifndef LOOPBACK_MUST_CHECKSUM
 86         skb->ip_summed = CHECKSUM_UNNECESSARY;
 87 #endif
 88         netif_rx(skb);
 89 
 90         stats->rx_bytes+=skb->len;
 91         stats->tx_bytes+=skb->len;
 92         stats->rx_packets++;
 93         stats->tx_packets++;
 94 
 95         return(0);
 96 }
 97 
 98 static struct net_device_stats *get_stats(struct net_device *dev)
 99 {
100         return (struct net_device_stats *)dev->priv;
101 }
102 
103 /* Initialize the rest of the LOOPBACK device. */
104 int __init loopback_init(struct net_device *dev)
105 {
106         dev->mtu                = PAGE_SIZE - LOOPBACK_OVERHEAD;
107         dev->hard_start_xmit    = loopback_xmit;
108         dev->hard_header        = eth_header;
109         dev->hard_header_cache  = eth_header_cache;
110         dev->header_cache_update= eth_header_cache_update;
111         dev->hard_header_len    = ETH_HLEN;             /* 14                   */
112         dev->addr_len           = ETH_ALEN;             /* 6                    */
113         dev->tx_queue_len       = 0;
114         dev->type               = ARPHRD_LOOPBACK;      /* 0x0001               */
115         dev->rebuild_header     = eth_rebuild_header;
116         dev->flags              = IFF_LOOPBACK;
117         dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL);
118         if (dev->priv == NULL)
119                         return -ENOMEM;
120         memset(dev->priv, 0, sizeof(struct net_device_stats));
121         dev->get_stats = get_stats;
122 
123         if (num_physpages >= ((128*1024*1024)>>PAGE_SHIFT))
124                 dev->mtu = 4096*4 - LOOPBACK_OVERHEAD;
125 
126         /*
127          *      Fill in the generic fields of the device structure. 
128          */
129    
130         dev_init_buffers(dev);
131   
132         return(0);
133 };
134 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.