• 虚拟网卡驱动


    网卡驱动程序框架:

    app:  socket

    --------------------------------------------------

                     ---------------

                     --------------- 若干层网络协议--纯软件            ---------------

                     --------------- hard_start_xmit||  /  

                                      /  ||  netif_rx   sk_buff   

                    ---------------           硬件相关的驱动程序(要提供hard_start_xmit, 有数据时要用netif_rx上报) 

                    --------------------------------------------------

                   硬件                      怎么写网卡驱动程序?

    1. 分配一个net_device结构体

    2. 设置: 2.1 发包函数: hard_start_xmit

    2.2 收到数据时(在中断处理函数里)用netif_rx上报数据

    2.3 其他设置

    3. 注册: register_netdevice

    测试1th/2th:

    1. insmod virt_net.ko

    2. ifconfig vnet0 3.3.3.3    ifconfig // 查看

    3. ping 3.3.3.3  // 成功      ping 3.3.3.4  // 死机

      1 #include <linux/errno.h>
      2 #include <linux/netdevice.h>
      3 #include <linux/etherdevice.h>
      4 #include <linux/kernel.h>
      5 #include <linux/types.h>
      6 #include <linux/fcntl.h>
      7 #include <linux/interrupt.h>
      8 #include <linux/ioport.h>
      9 #include <linux/in.h>
     10 #include <linux/skbuff.h>
     11 #include <linux/slab.h>
     12 #include <linux/spinlock.h>
     13 #include <linux/string.h>
     14 #include <linux/init.h>
     15 #include <linux/bitops.h>
     16 #include <linux/delay.h>
     17 #include <linux/ip.h>
     18 
     19 #include <asm/system.h>
     20 #include <asm/io.h>
     21 #include <asm/irq.h>
     22 
     23 
     24 static struct net_device *vnet_dev;
     25 
     26 
     27 static void emulator_rx_packet(struct sk_buff *skb, struct net_device *dev)
     28 {
     29     /* 参考LDD3 */
     30     unsigned char *type;
     31     struct iphdr *ih;
     32     __be32 *saddr, *daddr, tmp;
     33     unsigned char    tmp_dev_addr[ETH_ALEN];
     34     struct ethhdr *ethhdr;
     35     
     36     struct sk_buff *rx_skb;
     37         
     38     // 从硬件读出/保存数据
     39     /* 对调"源/目的"的mac地址 */
     40     ethhdr = (struct ethhdr *)skb->data;
     41     memcpy(tmp_dev_addr, ethhdr->h_dest, ETH_ALEN);
     42     memcpy(ethhdr->h_dest, ethhdr->h_source, ETH_ALEN);
     43     memcpy(ethhdr->h_source, tmp_dev_addr, ETH_ALEN);
     44 
     45     /* 对调"源/目的"的ip地址 */    
     46     ih = (struct iphdr *)(skb->data + sizeof(struct ethhdr));
     47     saddr = &ih->saddr;
     48     daddr = &ih->daddr;
     49 
     50     tmp = *saddr;
     51     *saddr = *daddr;
     52     *daddr = tmp;
     53     
     54     //((u8 *)saddr)[2] ^= 1; /* change the third octet (class C) */
     55     //((u8 *)daddr)[2] ^= 1;
     56     type = skb->data + sizeof(struct ethhdr) + sizeof(struct iphdr);
     57     //printk("tx package type = %02x
    ", *type);
     58     // 修改类型, 原来0x8表示ping
     59     *type = 0; /* 0表示reply */
     60     
     61     ih->check = 0;           /* and rebuild the checksum (ip needs it) */
     62     ih->check = ip_fast_csum((unsigned char *)ih,ih->ihl);
     63     
     64     // 构造一个sk_buff
     65     rx_skb = dev_alloc_skb(skb->len + 2);
     66     skb_reserve(rx_skb, 2); /* align IP on 16B boundary */    
     67     memcpy(skb_put(rx_skb, skb->len), skb->data, skb->len);
     68 
     69     /* Write metadata, and then pass to the receive level */
     70     rx_skb->dev = dev;
     71     rx_skb->protocol = eth_type_trans(rx_skb, dev);
     72     rx_skb->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it */
     73     dev->stats.rx_packets++;
     74     dev->stats.rx_bytes += skb->len;
     75 
     76     // 提交sk_buff
     77     netif_rx(rx_skb);
     78 }
     79 
     80 static    int vir_net_send_packet (struct sk_buff *skb,
     81                             struct net_device *dev)
     82 {
     83     static int cnt = 0;
     84     printk("vir_net_send_packet cnt = %d 
    ",++cnt);
     85     /* 对于真是的网卡,把skb里的数据通过网卡发送出去 */
     86     netif_stop_queue(dev);    /* 停止网卡的队列 */
     87     /*............*/        /* 把skb数据写入网卡 */
     88 
     89     /* 构造一个假的sk_buff,上报 */
     90     emulator_rx_packet(skb, dev);
     91 
     92     dev_kfree_skb (skb);     /*释放skb*/    
     93     netif_wake_queue(dev);     /*数据发送完,唤醒网卡*/
     94 
     95     /* 更新统计信息 */    
     96     dev->stats.tx_packets++;
     97     dev->stats.tx_bytes += skb->len;
     98     
     99     return 0;
    100 }
    101 
    102 static int vir_net_init(void)
    103 {
    104     /* 分配一个net_device结构体 */
    105     vnet_dev = alloc_netdev(0, "vnet%d", ether_setup);
    106 
    107     /* 设置 */
    108     vnet_dev->hard_start_xmit = vir_net_send_packet;
    109     /* 设置mac地址 */
    110 
    111     vnet_dev->dev_addr[0] = vnet_dev->perm_addr[0] = 1 >> 24;
    112     vnet_dev->dev_addr[1] = vnet_dev->perm_addr[1] = 1 >> 16;
    113     vnet_dev->dev_addr[2] = vnet_dev->perm_addr[2] = 1 >> 8;
    114     vnet_dev->dev_addr[3] = vnet_dev->perm_addr[3] = 1;
    115     vnet_dev->dev_addr[4] = vnet_dev->perm_addr[4] = 1 >> 8;
    116     vnet_dev->dev_addr[5] = vnet_dev->perm_addr[5] = 1;
    117 
    118    /* 设置下面两项才能ping通 */
    119     vnet_dev->flags           |= IFF_NOARP;
    120     vnet_dev->features        |= NETIF_F_NO_CSUM;    
    121 
    122 
    123     /* 注册 */
    124     register_netdev(vnet_dev);
    125     
    126     return 0;
    127 }
    128 
    129 static void vir_net_exit(void)
    130 {
    131     unregister_netdev(vnet_dev);
    132     free_netdev(vnet_dev);
    133     
    134 }
    135 module_init(vir_net_init);
    136 module_exit(vir_net_exit);
    137 MODULE_LICENSE("GPL");

    测试DM9000C驱动程序:

    1. 把dm9dev9000c.c放到内核的drivers/net目录下

    2. 修改drivers/net/Makefile 把 obj-$(CONFIG_DM9000) += dm9000.o 改为 obj-$(CONFIG_DM9000) += dm9dev9000c.o

    3. make uImage    使用新内核启动

    4. 使用NFS启动 或 ifconfig eth0 192.168.1.17 ping 192.168.1.1  

  • 相关阅读:
    职场“十不要”,让你少奋斗30年
    360与QQ在用户界面上的明显BUG
    urlMappings在asp.net2.0,asp.net4.0中的差异
    NHibernate主键生成方式
    MDaemon 常用视频教程
    sqlserver 差异备份与还原示例
    没有不死的爱情, 只有平淡的亲情——如何维系我们的婚姻
    25 个在 Web 中嵌入图表的免费资源
    atoi,atol,strtod,strtol,strtoul实现类型转换
    人生之精华,胜读十年书
  • 原文地址:https://www.cnblogs.com/CZM-/p/5292835.html
Copyright © 2020-2023  润新知