drivers/net/loopback.c
changeset 0 aa628870c1d3
child 2 d1f6d8b6f81c
equal deleted inserted replaced
-1:000000000000 0:aa628870c1d3
       
     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
       
    11  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
       
    12  *		Donald Becker, <becker@scyld.com>
       
    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/jiffies.h>
       
    33 #include <linux/module.h>
       
    34 #include <linux/interrupt.h>
       
    35 #include <linux/fs.h>
       
    36 #include <linux/types.h>
       
    37 #include <linux/string.h>
       
    38 #include <linux/socket.h>
       
    39 #include <linux/errno.h>
       
    40 #include <linux/fcntl.h>
       
    41 #include <linux/in.h>
       
    42 #include <linux/init.h>
       
    43 
       
    44 #include <asm/system.h>
       
    45 #include <asm/uaccess.h>
       
    46 #include <asm/io.h>
       
    47 
       
    48 #include <linux/inet.h>
       
    49 #include <linux/netdevice.h>
       
    50 #include <linux/etherdevice.h>
       
    51 #include <linux/skbuff.h>
       
    52 #include <linux/ethtool.h>
       
    53 #include <net/sock.h>
       
    54 #include <net/checksum.h>
       
    55 #include <linux/if_ether.h>	/* For the statistics structure. */
       
    56 #include <linux/if_arp.h>	/* For ARPHRD_ETHER */
       
    57 #include <linux/ip.h>
       
    58 #include <linux/tcp.h>
       
    59 #include <linux/percpu.h>
       
    60 #include <net/net_namespace.h>
       
    61 
       
    62 struct pcpu_lstats {
       
    63 	unsigned long packets;
       
    64 	unsigned long bytes;
       
    65 };
       
    66 
       
    67 /*
       
    68  * The higher levels take care of making this non-reentrant (it's
       
    69  * called with bh's disabled).
       
    70  */
       
    71 static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)
       
    72 {
       
    73 	struct pcpu_lstats *pcpu_lstats, *lb_stats;
       
    74 
       
    75 	skb_orphan(skb);
       
    76 
       
    77 	skb->protocol = eth_type_trans(skb,dev);
       
    78 
       
    79 	dev->last_rx = jiffies;
       
    80 
       
    81 	/* it's OK to use per_cpu_ptr() because BHs are off */
       
    82 	pcpu_lstats = dev->ml_priv;
       
    83 	lb_stats = per_cpu_ptr(pcpu_lstats, smp_processor_id());
       
    84 	lb_stats->bytes += skb->len;
       
    85 	lb_stats->packets++;
       
    86 
       
    87 	netif_rx(skb);
       
    88 
       
    89 	return 0;
       
    90 }
       
    91 
       
    92 static struct net_device_stats *get_stats(struct net_device *dev)
       
    93 {
       
    94 	const struct pcpu_lstats *pcpu_lstats;
       
    95 	struct net_device_stats *stats = &dev->stats;
       
    96 	unsigned long bytes = 0;
       
    97 	unsigned long packets = 0;
       
    98 	int i;
       
    99 
       
   100 	pcpu_lstats = dev->ml_priv;
       
   101 	for_each_possible_cpu(i) {
       
   102 		const struct pcpu_lstats *lb_stats;
       
   103 
       
   104 		lb_stats = per_cpu_ptr(pcpu_lstats, i);
       
   105 		bytes   += lb_stats->bytes;
       
   106 		packets += lb_stats->packets;
       
   107 	}
       
   108 	stats->rx_packets = packets;
       
   109 	stats->tx_packets = packets;
       
   110 	stats->rx_bytes = bytes;
       
   111 	stats->tx_bytes = bytes;
       
   112 	return stats;
       
   113 }
       
   114 
       
   115 static u32 always_on(struct net_device *dev)
       
   116 {
       
   117 	return 1;
       
   118 }
       
   119 
       
   120 static const struct ethtool_ops loopback_ethtool_ops = {
       
   121 	.get_link		= always_on,
       
   122 	.set_tso		= ethtool_op_set_tso,
       
   123 	.get_tx_csum		= always_on,
       
   124 	.get_sg			= always_on,
       
   125 	.get_rx_csum		= always_on,
       
   126 };
       
   127 
       
   128 static int loopback_dev_init(struct net_device *dev)
       
   129 {
       
   130 	struct pcpu_lstats *lstats;
       
   131 
       
   132 	lstats = alloc_percpu(struct pcpu_lstats);
       
   133 	if (!lstats)
       
   134 		return -ENOMEM;
       
   135 
       
   136 	dev->ml_priv = lstats;
       
   137 	return 0;
       
   138 }
       
   139 
       
   140 static void loopback_dev_free(struct net_device *dev)
       
   141 {
       
   142 	struct pcpu_lstats *lstats = dev->ml_priv;
       
   143 
       
   144 	free_percpu(lstats);
       
   145 	free_netdev(dev);
       
   146 }
       
   147 
       
   148 /*
       
   149  * The loopback device is special. There is only one instance
       
   150  * per network namespace.
       
   151  */
       
   152 static void loopback_setup(struct net_device *dev)
       
   153 {
       
   154 	dev->get_stats		= &get_stats;
       
   155 	dev->mtu		= (16 * 1024) + 20 + 20 + 12;
       
   156 	dev->hard_start_xmit	= loopback_xmit;
       
   157 	dev->hard_header_len	= ETH_HLEN;	/* 14	*/
       
   158 	dev->addr_len		= ETH_ALEN;	/* 6	*/
       
   159 	dev->tx_queue_len	= 0;
       
   160 	dev->type		= ARPHRD_LOOPBACK;	/* 0x0001*/
       
   161 	dev->flags		= IFF_LOOPBACK;
       
   162 	dev->features 		= NETIF_F_SG | NETIF_F_FRAGLIST
       
   163 		| NETIF_F_TSO
       
   164 		| NETIF_F_NO_CSUM
       
   165 		| NETIF_F_HIGHDMA
       
   166 		| NETIF_F_LLTX
       
   167 		| NETIF_F_NETNS_LOCAL;
       
   168 	dev->ethtool_ops	= &loopback_ethtool_ops;
       
   169 	dev->header_ops		= &eth_header_ops;
       
   170 	dev->init = loopback_dev_init;
       
   171 	dev->destructor = loopback_dev_free;
       
   172 }
       
   173 
       
   174 /* Setup and register the loopback device. */
       
   175 static __net_init int loopback_net_init(struct net *net)
       
   176 {
       
   177 	struct net_device *dev;
       
   178 	int err;
       
   179 
       
   180 	err = -ENOMEM;
       
   181 	dev = alloc_netdev(0, "lo", loopback_setup);
       
   182 	if (!dev)
       
   183 		goto out;
       
   184 
       
   185 	dev_net_set(dev, net);
       
   186 	err = register_netdev(dev);
       
   187 	if (err)
       
   188 		goto out_free_netdev;
       
   189 
       
   190 	net->loopback_dev = dev;
       
   191 	return 0;
       
   192 
       
   193 
       
   194 out_free_netdev:
       
   195 	free_netdev(dev);
       
   196 out:
       
   197 	if (net == &init_net)
       
   198 		panic("loopback: Failed to register netdevice: %d\n", err);
       
   199 	return err;
       
   200 }
       
   201 
       
   202 static __net_exit void loopback_net_exit(struct net *net)
       
   203 {
       
   204 	struct net_device *dev = net->loopback_dev;
       
   205 
       
   206 	unregister_netdev(dev);
       
   207 }
       
   208 
       
   209 static struct pernet_operations __net_initdata loopback_net_ops = {
       
   210        .init = loopback_net_init,
       
   211        .exit = loopback_net_exit,
       
   212 };
       
   213 
       
   214 static int __init loopback_init(void)
       
   215 {
       
   216 	return register_pernet_device(&loopback_net_ops);
       
   217 }
       
   218 
       
   219 /* Loopback is special. It should be initialized before any other network
       
   220  * device and network subsystem.
       
   221  */
       
   222 fs_initcall(loopback_init);