loopback.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:4k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  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@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/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. #include <asm/system.h>
  43. #include <asm/uaccess.h>
  44. #include <asm/io.h>
  45. #include <linux/inet.h>
  46. #include <linux/netdevice.h>
  47. #include <linux/etherdevice.h>
  48. #include <linux/skbuff.h>
  49. #include <net/sock.h>
  50. #include <linux/if_ether.h> /* For the statistics structure. */
  51. #include <linux/if_arp.h> /* For ARPHRD_ETHER */
  52. #define LOOPBACK_OVERHEAD (128 + MAX_HEADER + 16 + 16)
  53. /*
  54.  * The higher levels take care of making this non-reentrant (it's
  55.  * called with bh's disabled).
  56.  */
  57. static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)
  58. {
  59. struct net_device_stats *stats = (struct net_device_stats *)dev->priv;
  60. /*
  61.  * Optimise so buffers with skb->free=1 are not copied but
  62.  * instead are lobbed from tx queue to rx queue 
  63.  */
  64. if(atomic_read(&skb->users) != 1)
  65. {
  66.    struct sk_buff *skb2=skb;
  67.    skb=skb_clone(skb, GFP_ATOMIC); /* Clone the buffer */
  68.    if(skb==NULL) {
  69. kfree_skb(skb2);
  70. return 0;
  71. }
  72.    kfree_skb(skb2);
  73. }
  74. else
  75. skb_orphan(skb);
  76. skb->protocol=eth_type_trans(skb,dev);
  77. skb->dev=dev;
  78. #ifndef LOOPBACK_MUST_CHECKSUM
  79. skb->ip_summed = CHECKSUM_UNNECESSARY;
  80. #endif
  81. dev->last_rx = jiffies;
  82. stats->rx_bytes+=skb->len;
  83. stats->tx_bytes+=skb->len;
  84. stats->rx_packets++;
  85. stats->tx_packets++;
  86. netif_rx(skb);
  87. return(0);
  88. }
  89. static struct net_device_stats *get_stats(struct net_device *dev)
  90. {
  91. return (struct net_device_stats *)dev->priv;
  92. }
  93. /* Initialize the rest of the LOOPBACK device. */
  94. int __init loopback_init(struct net_device *dev)
  95. {
  96. dev->mtu = (16 * 1024) + 20 + 20 + 12;
  97. dev->hard_start_xmit = loopback_xmit;
  98. dev->hard_header = eth_header;
  99. dev->hard_header_cache = eth_header_cache;
  100. dev->header_cache_update= eth_header_cache_update;
  101. dev->hard_header_len = ETH_HLEN; /* 14 */
  102. dev->addr_len = ETH_ALEN; /* 6 */
  103. dev->tx_queue_len = 0;
  104. dev->type = ARPHRD_LOOPBACK; /* 0x0001 */
  105. dev->rebuild_header = eth_rebuild_header;
  106. dev->flags = IFF_LOOPBACK;
  107. dev->features = NETIF_F_SG|NETIF_F_FRAGLIST|NETIF_F_NO_CSUM|NETIF_F_HIGHDMA;
  108. dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL);
  109. if (dev->priv == NULL)
  110. return -ENOMEM;
  111. memset(dev->priv, 0, sizeof(struct net_device_stats));
  112. dev->get_stats = get_stats;
  113. /*
  114.  * Fill in the generic fields of the device structure. 
  115.  */
  116.    
  117. return(0);
  118. };