免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2014 | 回复: 0
打印 上一主题 下一主题

通过char设备模仿以太网接口//char read==eth send;char write == eth receive [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-04-02 11:19 |只看该作者 |倒序浏览
本帖最后由 Roemer 于 2010-04-02 16:58 编辑

  1. /*************************************************************************

  2. Fake eth char convert
  3. **************************************************************************/

  4. #include <linux/kernel.h>
  5. #include <linux/etherdevice.h>
  6. #include <linux/netdevice.h>
  7. #include <linux/moduleparam.h>
  8. #include <linux/errno.h>
  9. #include <linux/fcntl.h>
  10. #include <linux/file.h>
  11. #include <linux/proc_fs.h>
  12. #include <linux/init.h>
  13. #include <linux/module.h>
  14. #include <linux/smp_lock.h>
  15. #include <linux/device.h>
  16. #include <linux/wait.h>
  17. #include <linux/kmod.h>
  18. #include <linux/cdev.h>



  19. /*  MAC地址  */

  20. static char vir_mac[]={0x00, 0xAA, 0xBB, 0xCC, 0xBB, 0xAA};
  21. char *vir_mac_p = NULL;
  22. int loop = 0;                       /* when loop=1, enable loopback mode,not write Yet :) */

  23. //VIRMAC
  24. module_param(vir_mac_p, charp, 0444);
  25. MODULE_PARM_DESC(vir_mac_p, "MAC");

  26. module_param(loop, int, 0);
  27. MODULE_PARM_DESC(loop, "loopback mode");



  28. #define ETH_BUFFER_LEN 1520
  29. #define FAKE_IRQ       18
  30. #define ETH_VIR_MAJOR  160


  31. struct s_buff
  32. {
  33.   unsigned char buffer[ETH_BUFFER_LEN];
  34.   unsigned int  length;
  35. };

  36. //buffer for Eth
  37. static struct s_buff tx_buff;
  38. static struct s_buff rx_buff;


  39. struct vireth_priv
  40. {

  41.   struct net_device * netdev;      /* net device parameter */
  42.   struct net_device_stats stats;   /* net statistics */
  43.   struct sk_buff *skb;             /* free send skb*/
  44.   struct proc_dir_entry *entry;   
  45.   wait_queue_head_t inq;           /* send waitQ, for eth char read */
  46.   struct semaphore sem;
  47.   
  48. };

  49. static struct vireth_priv * dev_vireth = NULL;





  50. #define  VIRETH_NAME        "vir_eth"        /* 网络设备的名字 */


  51. static int vireth_open(struct net_device *dev);
  52. static int vireth_release(struct net_device *dev);
  53. static void vireth_init(struct net_device *dev);
  54. static int vireth_xmit(struct sk_buff *skb, struct net_device *dev);
  55. static int vireth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
  56. static int transmit_int(int irq, void *dev_id);
  57. static int receive_int(int irq, void *dev_id);


  58. /************************* MII Proc interface **************************/
  59. static int MII_read_proc(char *page, char **start, off_t off,
  60.          int count, int *eof, void *data)
  61. {
  62.   #if 0
  63.      int length;
  64.      
  65.      if (down_interruptible(&dev_vireth->sem))
  66.      {
  67.         return -ERESTARTSYS;
  68.      }
  69.      //
  70.      while( 0 == tx_buff.length )
  71.      {
  72.          up(&dev_vireth->sem);
  73.          //sleep
  74.          if( wait_event_interruptible(dev_vireth->inq,(0 != tx_buff.length)) )
  75.          {
  76.            return -ERESTARTSYS;
  77.          }
  78.       
  79.          if (down_interruptible(&dev_vireth->sem))
  80.          {
  81.            return -ERESTARTSYS;
  82.          }
  83.      }   
  84.    
  85.      memcpy(page,tx_buff.buffer,tx_buff.length );
  86.      length = tx_buff.length;
  87.      tx_buff.length = 0;
  88.      
  89.      up(&dev_vireth->sem);
  90.      *eof = 1;
  91.      
  92.      transmit_int(FAKE_IRQ,dev_vireth);
  93.      //printk("#### %d##\n",length);
  94.    
  95.       return length;
  96.    #endif
  97.    ////////////
  98.    *eof = 1;
  99.    return 0;
  100. }

  101. static int MII_write_proc(struct file *file, const char *buffer,
  102.          unsigned long count, void *data)
  103. {
  104.   #if 0
  105.   
  106.     if(count > ETH_BUFFER_LEN)
  107.     {
  108.       printk("Error input len\n");
  109.       return -1;
  110.     }
  111.    
  112.     memcpy(rx_buff.buffer, buffer, count);
  113.     rx_buff.length = count;
  114.     receive_int(FAKE_IRQ,dev_vireth);
  115.    
  116.     return count;
  117.   
  118.   #endif
  119.   ///////////////
  120.   return 0;
  121. }   


  122. /************************* fake interrupt**************************/

  123. static int receive_int(int irq, void *dev_id)
  124. {
  125.   struct sk_buff *skb;
  126.   //struct vireth_priv *priv = netdev_priv(dev);

  127.   /*
  128.    * The packet has been retrieved from the transmission
  129.    * medium. Build an skb around it, so upper layers can handle it
  130.    */
  131.   skb = dev_alloc_skb(rx_buff.length + 4);
  132.   if (!skb)
  133.   {
  134.     if (printk_ratelimit())
  135.     { printk(KERN_NOTICE "snull rx: low on mem - packet dropped\n");}
  136.      dev_vireth->stats.rx_dropped++;
  137.        goto out;
  138.   }
  139.   skb_reserve(skb, 2); /* align IP on 16B boundary */  
  140.   
  141.   memcpy(skb_put(skb, rx_buff.length), rx_buff.buffer, rx_buff.length);
  142.   
  143.   /* Write metadata, and then pass to the receive level */
  144.   skb->protocol = eth_type_trans(skb, dev_vireth->netdev);
  145.   //skb->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it */
  146.   dev_vireth->stats.rx_packets++;
  147.   dev_vireth->stats.rx_bytes += rx_buff.length;
  148.   netif_rx(skb);

  149. out:
  150.   return 0;
  151. }


  152. //send finished
  153.   static int transmit_int(int irq, void *dev_id)
  154. {
  155.      dev_kfree_skb(dev_vireth->skb);
  156.      netif_wake_queue(dev_vireth->netdev);      
  157.      return 0;
  158. }



  159. /*************************Eth  interface **************************/
  160. static int vireth_open(struct net_device *dev)
  161. {   
  162.    /* 启动发送队列 */
  163.   netif_start_queue(dev);
  164.   return 0;
  165. }


  166. static int vireth_release(struct net_device *dev)
  167. {    /* 停止发送队列 */
  168.   netif_stop_queue(dev);  /* can't transmit any more */
  169.   return 0;
  170. }


  171. //copy from skb to buffer
  172. static int vireth_write_packet(struct sk_buff *skb, struct net_device *dev)
  173. {
  174.   //lock char read
  175.    if(down_interruptible(&dev_vireth->sem))
  176.    {
  177.      return 1;
  178.    }
  179.    //still have pack int TX buffer
  180.    if(tx_buff.length !=0 )
  181.    {
  182.      up(&dev_vireth->sem);
  183.      return 1;
  184.    }
  185.    memcpy(tx_buff.buffer, skb->data, skb->len);  
  186.    tx_buff.length = skb->len;

  187.    up(&dev_vireth->sem);
  188.    wake_up_interruptible(&dev_vireth->inq);
  189.      
  190.    return 0;
  191. }


  192. static int vireth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
  193. {
  194.   int rc = 0;

  195.   switch (cmd)
  196.   {
  197.     default:
  198.       rc = -ENOSYS;
  199.       break;
  200.   }

  201.   return rc;
  202. }

  203. //call by up layer
  204. static int vireth_xmit(struct sk_buff *skb, struct net_device *dev)
  205. {
  206.   struct vireth_priv * priv = (struct vireth_priv *)netdev_priv(dev);
  207.   int rc;

  208.   netif_stop_queue(dev);

  209.   if (vireth_write_packet(skb, dev))
  210.   {
  211.     priv->stats.tx_dropped++;
  212.     rc = 1;
  213.   }
  214.   else
  215.   {
  216.     priv->stats.tx_packets++;
  217.     priv->stats.tx_bytes += skb->len;
  218.         priv->skb = skb;
  219.     dev->trans_start = jiffies;         /* save the timestamp */

  220.     rc = 0;
  221.   }

  222.   return rc;
  223. }


  224. static struct net_device_stats *vireth_get_stats(struct net_device *dev)
  225. {
  226.    struct vireth_priv * priv = (struct vireth_priv *)netdev_priv(dev);

  227.    return &(priv->stats);
  228. }

  229. /* fake multicast ability */
  230. static void set_multicast_list(struct net_device *dev)
  231. {
  232.   return;
  233. }

  234. static int set_mac_address(struct net_device *dev, void* addr)
  235. {
  236.   struct sockaddr *address = addr;

  237.   if (!is_valid_ether_addr(address->sa_data))
  238.   {
  239.     return -EADDRNOTAVAIL;
  240.   }

  241.   memcpy(dev->dev_addr, address->sa_data, dev->addr_len);
  242.   printk("%s: Setting MAC address to %pM\n", dev->name,  dev->dev_addr);

  243.   return 0;
  244. }



  245. static const struct net_device_ops vireth_netdev_ops = {
  246.   .ndo_open               = vireth_open,
  247.   .ndo_stop               = vireth_release,
  248.   .ndo_do_ioctl           = vireth_ioctl,
  249.   .ndo_get_stats          = vireth_get_stats,
  250.   .ndo_start_xmit         = vireth_xmit,
  251.   .ndo_set_multicast_list = set_multicast_list,
  252.   .ndo_set_mac_address  = set_mac_address,
  253. };

  254. /************************char dev ************************/

  255. static struct cdev vireth_cdev;

  256. static int vireth_char_open(struct inode * inode, struct file * filp)
  257. {
  258.   return 0;
  259. }


  260. static int vireth_char_release(struct inode * inode, struct file * filp)
  261. {
  262.   return 0;
  263. }

  264. static int vireth_char_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg)
  265. {
  266.     switch(cmd)
  267.     {
  268.        default:
  269.            return -EINVAL;
  270.     }
  271.    
  272.     return 0;
  273. }

  274. //eth out put packet
  275. static ssize_t vireth_char_read(struct file * file, char __user * buf, size_t count, loff_t *ppos)
  276. {
  277.     int length;
  278.     unsigned long ret;
  279.      
  280.      if (down_interruptible(&dev_vireth->sem))
  281.      {
  282.         return -ERESTARTSYS;
  283.      }
  284.      //
  285.      while( 0 == tx_buff.length )
  286.      {
  287.          up(&dev_vireth->sem);
  288.          //sleep
  289.          if( wait_event_interruptible(dev_vireth->inq,(0 != tx_buff.length)) )
  290.          {
  291.            return -ERESTARTSYS;
  292.          }
  293.       
  294.          if (down_interruptible(&dev_vireth->sem))
  295.          {
  296.            return -ERESTARTSYS;
  297.          }
  298.      }   
  299.    
  300.      ret = copy_to_user(buf,tx_buff.buffer,tx_buff.length );
  301.      length = tx_buff.length;
  302.      tx_buff.length = 0;
  303.      
  304.      up(&dev_vireth->sem);   
  305.      
  306.      transmit_int(FAKE_IRQ,dev_vireth);
  307.      //printk("#### %d##\n",length);
  308.    
  309.      return length;
  310.   
  311. }

  312. static ssize_t vireth_char_write(struct file * file, const char __user * buf, size_t count,
  313.        loff_t *ppos)
  314. {
  315.     unsigned long ret;
  316.     if(count > ETH_BUFFER_LEN)
  317.     {
  318.        printk("Error input len\n");
  319.        return -1;
  320.     }
  321.    
  322.     ret = copy_from_user(rx_buff.buffer, buf, count);
  323.     rx_buff.length = count;
  324.     receive_int(FAKE_IRQ,dev_vireth);
  325.    
  326.     return count;
  327. }


  328. static struct file_operations vireth_char_fops = {
  329.   .llseek     = NULL,
  330.   .read       = vireth_char_read,
  331.   .write      = vireth_char_write,
  332.   .ioctl      = vireth_char_ioctl,
  333.   .open       = vireth_char_open,
  334.   .release    = vireth_char_release,
  335.   .fasync     = NULL,
  336. };


  337. static int __init vireth_char_init(void)
  338. {
  339.     int ret;
  340.     int devno = MKDEV(ETH_VIR_MAJOR,0);
  341.    
  342.     printk("Vireth version:%s %s\n",__DATE__,__TIME__);
  343.             
  344.     cdev_init(&vireth_cdev, &vireth_char_fops);
  345.     vireth_cdev.owner = THIS_MODULE;
  346.     ret = cdev_add(&vireth_cdev, devno, 1);
  347.     if(ret)
  348.     {        
  349.        return ret;  
  350.     }
  351.    
  352.     return 0;
  353. }

  354. static void __exit vireth_char_exit(void)
  355. {
  356.     cdev_del(&vireth_cdev);
  357. }

  358. /*************************eth  init **************************/

  359. static void vireth_init(struct net_device *dev)
  360. {
  361.   struct vireth_priv * priv = NULL;

  362.   ether_setup(dev);
  363.   dev->netdev_ops  = &vireth_netdev_ops;

  364.   dev->watchdog_timeo = 3*HZ;   
  365.   dev->irq = FAKE_IRQ;//no use
  366.   
  367.   memcpy(dev->dev_addr, vir_mac, ETH_ALEN);

  368.   priv = (struct vireth_priv *)netdev_priv(dev);
  369.   dev_vireth = priv;
  370.   
  371.   priv->netdev = dev;

  372. }

  373. inline char ascTochar(char s)
  374. {
  375.          if( ('0'<= s) && ( s<='9') )
  376.          {
  377.                    return (s-'0');
  378.          }
  379.          
  380.          else if( ('a'<= s) && (s<='f') )
  381.          {
  382.                    return (s-'a'+10);
  383.          }
  384.          else if( ('A'<= s) && (s<='F') )
  385.          {
  386.                    return (s-'A'+10);
  387.          }
  388.          else
  389.          {
  390.                   return 0;
  391.          }
  392.          
  393. }

  394. static int __init vireth_init_module(void)
  395. {
  396.   int rc = 0;
  397.   int i;
  398.   
  399.   struct net_device  *net_dev = NULL;
  400.   
  401.   printk("Input MAC:%s\n",vir_mac_p);
  402.   if(vir_mac_p)
  403.   {
  404.           for(i=0;i<6;i++)
  405.           {
  406.                    vir_mac[i] = ascTochar( *(vir_mac_p+i*2) )<<4;
  407.                    vir_mac[i] |=ascTochar( *(vir_mac_p+i*2+1) );
  408.           }
  409.   }
  410.   //
  411.   printk("active MAC: ");
  412.   for(i=0;i<6;i++)
  413.   {
  414.           printk("%02X:",vir_mac[i]);
  415.   }
  416.   printk("\n");
  417.   
  418.   /* alloc net dev */
  419.   net_dev = alloc_netdev(sizeof(struct vireth_priv), VIRETH_NAME, vireth_init);
  420.   if (!net_dev)
  421.   {
  422.     //log(KERN_ERR "no enough memory!\n");
  423.     rc = -1;
  424.     goto ERROR0;
  425.   }

  426.   /* got a name for eth*/
  427.   rc = dev_alloc_name(net_dev, VIRETH_NAME);
  428.   if (rc < 0)
  429.     {
  430.     //log(KERN_INFO "failed to alloc device name %s\n", VIRETH_NAME);
  431.     goto ERROR0;
  432.   }

  433.   rc = register_netdev(net_dev);
  434.   if (rc < 0)
  435.   {
  436.     goto ERROR0;
  437.   }
  438.   

  439.   dev_vireth->entry = create_proc_entry("VIR_ETH_MII_DATA", 0, NULL);
  440.   if (dev_vireth->entry == NULL)
  441.     {
  442.       return -ENOMEM;
  443.     }
  444.   dev_vireth->entry->read_proc = MII_read_proc;
  445.   dev_vireth->entry->write_proc = MII_write_proc;
  446.   dev_vireth->entry->data = NULL;
  447.   
  448.   init_waitqueue_head(&dev_vireth->inq);
  449.   init_MUTEX(&dev_vireth->sem);
  450.   
  451.   vireth_char_init();

  452.   return rc;

  453. ERROR0:
  454.   
  455.   free_netdev(net_dev);
  456.   return rc;
  457. }


  458. static void __exit vireth_cleanup_module(void)
  459. {
  460.     unregister_netdev(dev_vireth->netdev);
  461.     remove_proc_entry("VIR_ETH_MII_DATA", NULL);
  462.     free_netdev(dev_vireth->netdev);
  463.     vireth_char_exit();  
  464. }

  465. module_init(vireth_init_module);
  466. module_exit(vireth_cleanup_module);

  467. MODULE_AUTHOR("roemer");
  468. MODULE_DESCRIPTION("virtual ETH driver");
  469. MODULE_LICENSE("GPL");
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP