zoukankan      html  css  js  c++  java
  • IMX257虚拟网卡vnet驱动程序

    20150419 IMX257虚拟网卡vnet驱动程序

    2015-04-19 Lover雪儿

    一、一个简单的虚拟网卡驱动

     1 static struct net_device *vnet_dev; //定义一个网络设备结构体
     2 
     3 
     4 static const struct net_device_ops virt_netdev_ops = {
     5     .ndo_start_xmit        = NULL,
     6 };
     7 
     8 
     9 static int virt_net_init(void){
    10     
    11     /* 1.分配一个net_device结构体 */
    12     vnet_dev = alloc_netdev(0,"vnet%d",ether_setup); //私有数据为0,
    13     /* 2.设置 */
    14     vnet_dev->netdev_ops = &virt_netdev_ops;
    15     /* 3.注册 */
    16     //register_netdevice(vnet_dev);    //会报锁的错误
    17     register_netdev(vnet_dev);   //rtnl_lock();
    18     return 0;
    19 }
    20 
    21 static void virt_net_exit(void){
    22     if(vnet_dev){
    23         unregister_netdev(vnet_dev);
    24         free_netdev(vnet_dev);
    25     }
    26 }
    27 
    28 module_init(virt_net_init);
    29 module_exit(virt_net_exit);
    30 MODULE_AUTHOR("Lover雪儿");
    31 MODULE_LICENSE("GPL");

     如上面程序所示,定义分配一个net_device结构体,注册结构体,这样就实现了一个简单的虚拟网卡驱动。

    实现效果:

    如图所示,在/sys/class/net/目录下多生成了一个vnet0的文件夹

    附驱动程序virt_net1.c

     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 
    18 #include <asm/system.h>
    19 #include <asm/io.h>
    20 #include <asm/irq.h>
    21 
    22 static struct net_device *vnet_dev; //定义一个网络设备结构体
    23 
    24 
    25 static const struct net_device_ops virt_netdev_ops = {
    26     .ndo_start_xmit        = NULL,
    27 };
    28 
    29 
    30 static int virt_net_init(void){
    31     
    32     /* 1.分配一个net_device结构体 */
    33     vnet_dev = alloc_netdev(0,"vnet%d",ether_setup); //私有数据为0,
    34     /* 2.设置 */
    35     vnet_dev->netdev_ops = &virt_netdev_ops;
    36     /* 3.注册 */
    37     //register_netdevice(vnet_dev);    //会报锁的错误
    38     register_netdev(vnet_dev);   //rtnl_lock();
    39     return 0;
    40 }
    41 
    42 static void virt_net_exit(void){
    43     if(vnet_dev){
    44         unregister_netdev(vnet_dev);
    45         free_netdev(vnet_dev);
    46     }
    47 }
    48 
    49 module_init(virt_net_init);
    50 module_exit(virt_net_exit);
    51 MODULE_AUTHOR("Lover雪儿");
    52 MODULE_LICENSE("GPL");
    53 
    54 
    55 /*
    56 
    57 /////////////////////////////////////////////////////////////////////
    58 网卡驱动程序框架:
    59 app:  socket
    60 --------------------------------------------------------------------
    61         -----------------
    62         ----------------- 若干层网络协议--纯软件
    63         -----------------
    64 hard_start_xmit() 用于发送数据包            ↑↑↑
    65     ↓↓↓              sk_buff                netif_rx()用于上报数据包
    66 调用硬件相关的驱动程序(要提供har_start_xmit,有数据时用netif_rx上报)
    67 --------------------------------------------------------------------
    68               硬件
    69 //////////////////////////////////////////////////////////////////////
    70               
    71 网卡驱动编写:
    72 1.分配一个net_device结构体
    73 2.设置
    74 2.1 发包函数:hard_start_xmit
    75 2.2 收到到数据时,(在中断处理函数中)用netif_rx上报数据
    76 2.3 其他设置
    77 3.注册 register_netdevice              
    78     
    79 
    80 一、测试1th
    81 insmod virt_net.ko
    82 ifconfig vnet0 3.3.3.3
    83 ping 3.3.3.3
    84 ping 3.3.3.4  看效果 
    85 
    86 
    87 */
    virt_net1.c

    二、增加ping功能

    下面是我画的一个网卡驱动程序框架。

    所以此处我们增加一个发送数据包的函数 hard_start_xmit用于转发数据包。

    1.在net_device结构体下定义hard_start_xmit。

    vnet_dev->hard_start_xmit = vir_net_send_packet;

    2.实现vir_net_send_packet函数

    此处我们的代码只是增加一些打印语句,以便确定当我们ping的时候,是否会调用该函数。

     1 //转发发送数据包
     2 static int virt_net_send_packet(struct sk_buff *skb, struct net_device *dev){
     3     static int cnt = 0;
     4     printk("vir_net_send_packet cnt = %d
    ",++cnt);
     5     return 0;
     6 }
     7 
     8 static const struct net_device_ops virt_netdev_ops = {
     9     .ndo_start_xmit        = virt_net_send_packet,
    10 };
    11 //接着在入口函数中增加net_device_ops
    12 
    13 vnet_dev->netdev_ops = &virt_netdev_ops;

     实现效果:

    ping 测试:

    附驱动程序virt_net2.c

     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 
    18 #include <asm/system.h>
    19 #include <asm/io.h>
    20 #include <asm/irq.h>
    21 
    22 static struct net_device *vnet_dev; //定义一个网络设备结构体
    23 
    24 //转发发送数据包
    25 static int virt_net_send_packet(struct sk_buff *skb, struct net_device *dev){
    26     static int cnt = 0;
    27     printk("vir_net_send_packet cnt = %d
    ",++cnt);
    28     return 0;
    29 }
    30 
    31 static const struct net_device_ops virt_netdev_ops = {
    32     .ndo_start_xmit        = virt_net_send_packet,
    33 };
    34 
    35 
    36 static int virt_net_init(void){
    37     
    38     /* 1.分配一个net_device结构体 */
    39     vnet_dev = alloc_netdev(0,"vnet%d",ether_setup); //私有数据为0,
    40     /* 2.设置 */
    41     vnet_dev->netdev_ops = &virt_netdev_ops;
    42     /* 3.注册 */
    43     //register_netdevice(vnet_dev);    //会报锁的错误
    44     register_netdev(vnet_dev);   //rtnl_lock();
    45     return 0;
    46 }
    47 
    48 static void virt_net_exit(void){
    49     if(vnet_dev){
    50         unregister_netdev(vnet_dev);
    51         free_netdev(vnet_dev);
    52     }
    53 }
    54 
    55 module_init(virt_net_init);
    56 module_exit(virt_net_exit);
    57 MODULE_AUTHOR("Lover雪儿");
    58 MODULE_LICENSE("GPL");
    59 
    60 
    61 /*
    62 
    63 /////////////////////////////////////////////////////////////////////
    64 网卡驱动程序框架:
    65 app:  socket
    66 --------------------------------------------------------------------
    67         -----------------
    68         ----------------- 若干层网络协议--纯软件
    69         -----------------
    70 hard_start_xmit() 用于发送数据包            ↑↑↑
    71     ↓↓↓              sk_buff                netif_rx()用于上报数据包
    72 调用硬件相关的驱动程序(要提供har_start_xmit,有数据时用netif_rx上报)
    73 --------------------------------------------------------------------
    74               硬件
    75 //////////////////////////////////////////////////////////////////////
    76               
    77 网卡驱动编写:
    78 1.分配一个net_device结构体
    79 2.设置
    80 2.1 发包函数:hard_start_xmit
    81 2.2 收到到数据时,(在中断处理函数中)用netif_rx上报数据
    82 2.3 其他设置
    83 3.注册 register_netdevice              
    84     
    85 
    86 一、测试1th
    87 insmod virt_net.ko
    88 ifconfig vnet0 3.3.3.3
    89 ping 3.3.3.3
    90 ping 3.3.3.4  看效果 
    91 
    92 */
    virt_net2.c

    三、增加数据包的统计,设置MAC地址

    有关于数据包的统计信息定义在net_device结构体的stats结构体下,主要是定义了收发数据包的个数,字节数,时间等。此处,我们就增加一个统计发送数据包的个数,以及字节数。

    stats结构体如下:

    发送数据包的统计
    struct net_device_stats
    {
        unsigned long rx_packets; / * total packets received * /
        unsigned long tx_packets; / * total packets transmitted * /
        unsigned long rx_bytes; / * total bytes received * /
        unsigned long tx_bytes; / * total bytes transmitted * /
        unsigned long rx_errors; / * bad packets received * /
        unsigned long tx_errors; / * packet transmit probls * /
        unsigned long rx_dropped; / * no space in linux buffers * /
        unsigned long tx_dropped; / * no space available in linux * /
        unsigned long multicast; / * multicast packets received * /
        unsigned long collisions;
    
        / * detailed rx_errors: * /
        unsigned long rx_length_errors;
        unsigned long rx_over_errors; / * receiver ring buff overflow * /
        unsigned long rx_crc_errors; / * recved pkt with crc error * /
        unsigned long rx_frame_errors; / * recv'd frame alignment error * /
        unsigned long rx_fifo_errors; / * recv'r fifo overrun * /
        unsigned long rx_missed_errors; / * receiver missed packet * /
     
        / * detailed tx_errors * /
        unsigned long tx_aborted_errors;
        unsigned long tx_carrier_errors;
        unsigned long tx_fifo_errors;
        unsigned long tx_heartbeat_errors;
        unsigned long tx_window_errors;
     
        / * for cslip etc * /
        unsigned long rx_compressed;
        unsigned long tx_compressed;
    };

    接下来就是在virt_net_send_packet实现数据包的自加。

     1 static int virt_net_send_packet(struct sk_buff *skb, struct net_device *dev)
     2 {
     3     static int cnt = 0;
     4     printk("virt_net_send_packet cnt = %d
    ", ++cnt);
     5 
     6     /* 更新统计信息 */
     7     dev->stats.tx_packets++;
     8     dev->stats.tx_bytes += skb->len;
     9     
    10     return 0;
    11 }

    设置mac地址

     1 static int virt_net_init(void)
     2 {
     3     /* 1. 分配一个net_device结构体 */
     4     vnet_dev = alloc_netdev(0, "vnet%d", ether_setup);;  /* alloc_etherdev */
     5 
     6     /* 2. 设置 */
     7     vnet_dev->netdev_ops    = &virt_netdev_ops;
     8 
     9     /* 设置MAC地址 */
    10     vnet_dev->dev_addr[0] = 0x08;
    11     vnet_dev->dev_addr[1] = 0x89;
    12     vnet_dev->dev_addr[2] = 0x89;
    13     vnet_dev->dev_addr[3] = 0x89;
    14     vnet_dev->dev_addr[4] = 0x89;
    15     vnet_dev->dev_addr[5] = 0x11;
    16 
    17     /* 设置下面两项才能ping通 */
    18     //vnet_dev->flags           |= IFF_NOARP;
    19     //vnet_dev->features        |= NETIF_F_NO_CSUM;    
    20 
    21     /* 3. 注册 */
    22     //register_netdevice(vnet_dev);
    23     register_netdev(vnet_dev);
    24     
    25     return 0;
    26 }

     实现效果:

    附驱动程序virt_net3.c

      1 #include <linux/module.h>
      2 #include <linux/errno.h>
      3 #include <linux/netdevice.h>
      4 #include <linux/etherdevice.h>
      5 #include <linux/kernel.h>
      6 #include <linux/types.h>
      7 #include <linux/fcntl.h>
      8 #include <linux/interrupt.h>
      9 #include <linux/ioport.h>
     10 #include <linux/in.h>
     11 #include <linux/skbuff.h>
     12 #include <linux/slab.h>
     13 #include <linux/spinlock.h>
     14 #include <linux/string.h>
     15 #include <linux/init.h>
     16 #include <linux/bitops.h>
     17 #include <linux/delay.h>
     18 #include <linux/ip.h>
     19 
     20 #include <asm/system.h>
     21 #include <asm/io.h>
     22 #include <asm/irq.h>
     23 
     24 static struct net_device *vnet_dev;
     25 
     26 
     27 static int virt_net_send_packet(struct sk_buff *skb, struct net_device *dev)
     28 {
     29     static int cnt = 0;
     30     printk("virt_net_send_packet cnt = %d
    ", ++cnt);
     31 
     32     /* 更新统计信息 */
     33     dev->stats.tx_packets++;
     34     dev->stats.tx_bytes += skb->len;
     35     
     36     return 0;
     37 }
     38 
     39 static const struct net_device_ops virt_netdev_ops = {
     40     .ndo_start_xmit        = virt_net_send_packet,
     41 };
     42 
     43 static int virt_net_init(void)
     44 {
     45     /* 1. 分配一个net_device结构体 */
     46     vnet_dev = alloc_netdev(0, "vnet%d", ether_setup);;  /* alloc_etherdev */
     47 
     48     /* 2. 设置 */
     49     vnet_dev->netdev_ops    = &virt_netdev_ops;
     50 
     51     /* 设置MAC地址 */
     52     vnet_dev->dev_addr[0] = 0x08;
     53     vnet_dev->dev_addr[1] = 0x89;
     54     vnet_dev->dev_addr[2] = 0x89;
     55     vnet_dev->dev_addr[3] = 0x89;
     56     vnet_dev->dev_addr[4] = 0x89;
     57     vnet_dev->dev_addr[5] = 0x11;
     58 
     59     /* 设置下面两项才能ping通 */
     60     //vnet_dev->flags           |= IFF_NOARP;
     61     //vnet_dev->features        |= NETIF_F_NO_CSUM;    
     62 
     63     /* 3. 注册 */
     64     //register_netdevice(vnet_dev);
     65     register_netdev(vnet_dev);
     66     
     67     return 0;
     68 }
     69 
     70 static void virt_net_exit(void)
     71 {
     72     unregister_netdev(vnet_dev);
     73     free_netdev(vnet_dev);
     74 }
     75 
     76 module_init(virt_net_init);
     77 module_exit(virt_net_exit);
     78 MODULE_AUTHOR("Lover雪儿");
     79 MODULE_LICENSE("GPL");
     80 
     81 
     82 /*
     83 
     84 /////////////////////////////////////////////////////////////////////
     85 网卡驱动程序框架:
     86 app:  socket
     87 --------------------------------------------------------------------
     88         -----------------
     89         ----------------- 若干层网络协议--纯软件
     90         -----------------
     91 hard_start_xmit() 用于发送数据包            ↑↑↑
     92     ↓↓↓              sk_buff                netif_rx()用于上报数据包
     93 调用硬件相关的驱动程序(要提供har_start_xmit,有数据时用netif_rx上报)
     94 --------------------------------------------------------------------
     95               硬件
     96 //////////////////////////////////////////////////////////////////////
     97               
     98 网卡驱动编写:
     99 1.分配一个net_device结构体
    100 2.设置
    101 2.1 发包函数:hard_start_xmit
    102 2.2 收到到数据时,(在中断处理函数中)用netif_rx上报数据
    103 2.3 其他设置
    104 3.注册 register_netdevice              
    105     
    106 
    107 一、测试1th
    108 insmod virt_net.ko
    109 ifconfig vnet0 3.3.3.3
    110 ping 3.3.3.3
    111 ping 3.3.3.4  看效果 
    112 
    113 */
    virt_net3.c

    四、模拟回环网卡程序,实现数据包的收发过程

    前面我们已经实现了转发数据包的功能,此处我们增加一个接受数据包的功能。

    如程序中所示,主要就是交换数据包中的源目的MAC头信息,源目的IP信息等功能。

     1 static void emulator_rx_packet(struct sk_buff *skb, struct net_device *dev)
     2 {
     3     /* 参考LDD3 */
     4     unsigned char *type;
     5     struct iphdr *ih;
     6     __be32 *saddr, *daddr, tmp;
     7     unsigned char    tmp_dev_addr[ETH_ALEN];
     8     struct ethhdr *ethhdr;
     9     
    10     struct sk_buff *rx_skb;
    11         
    12     // 从硬件读出/保存数据
    13     /* 对调"源/目的"的mac地址 */
    14     ethhdr = (struct ethhdr *)skb->data;
    15     memcpy(tmp_dev_addr, ethhdr->h_dest, ETH_ALEN);
    16     memcpy(ethhdr->h_dest, ethhdr->h_source, ETH_ALEN);
    17     memcpy(ethhdr->h_source, tmp_dev_addr, ETH_ALEN);
    18 
    19     /* 对调"源/目的"的ip地址 */    
    20     ih = (struct iphdr *)(skb->data + sizeof(struct ethhdr));
    21     saddr = &ih->saddr;
    22     daddr = &ih->daddr;
    23 
    24     tmp = *saddr;
    25     *saddr = *daddr;
    26     *daddr = tmp;
    27     
    28     //((u8 *)saddr)[2] ^= 1; /* change the third octet (class C) */
    29     //((u8 *)daddr)[2] ^= 1;
    30     type = skb->data + sizeof(struct ethhdr) + sizeof(struct iphdr);
    31     //printk("tx package type = %02x
    ", *type);
    32     // 修改类型, 原来0x8表示ping
    33     *type = 0; /* 0表示reply */
    34     
    35     ih->check = 0;           /* and rebuild the checksum (ip needs it) */
    36     ih->check = ip_fast_csum((unsigned char *)ih,ih->ihl);
    37     
    38     // 构造一个sk_buff
    39     rx_skb = dev_alloc_skb(skb->len + 2);
    40     skb_reserve(rx_skb, 2); /* align IP on 16B boundary */    
    41     memcpy(skb_put(rx_skb, skb->len), skb->data, skb->len);
    42 
    43     /* Write metadata, and then pass to the receive level */
    44     rx_skb->dev = dev;
    45     rx_skb->protocol = eth_type_trans(rx_skb, dev);
    46     rx_skb->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it */
    47     dev->stats.rx_packets++;
    48     dev->stats.rx_bytes += skb->len;
    49 
    50     // 提交sk_buff
    51     netif_rx(rx_skb);
    52 }

     接着在发送数据包函数中:

     1 static int virt_net_send_packet(struct sk_buff *skb, struct net_device *dev)
     2 {
     3     static int cnt = 0;
     4     //printk("virt_net_send_packet cnt = %d
    ", ++cnt);
     5 
     6     /* 对于真实的网卡, 把skb里的数据通过网卡发送出去 */
     7     netif_stop_queue(dev); /* 停止该网卡的队列 */
     8     /* ...... */           /* 把skb的数据写入网卡 */
     9 
    10     /* 构造一个假的sk_buff,上报 */
    11     emulator_rx_packet(skb, dev);
    12 
    13     dev_kfree_skb (skb);   /* 释放skb */
    14     netif_wake_queue(dev); /* 数据全部发送出去后,唤醒网卡的队列 */
    15 
    16     /* 更新统计信息 */
    17     dev->stats.tx_packets++;
    18     dev->stats.tx_bytes += skb->len;
    19     
    20     return 0;
    21 }

    实现效果:

    附驱动程序virt_net4.c

      1 #include <linux/module.h>
      2 #include <linux/errno.h>
      3 #include <linux/netdevice.h>
      4 #include <linux/etherdevice.h>
      5 #include <linux/kernel.h>
      6 #include <linux/types.h>
      7 #include <linux/fcntl.h>
      8 #include <linux/interrupt.h>
      9 #include <linux/ioport.h>
     10 #include <linux/in.h>
     11 #include <linux/skbuff.h>
     12 #include <linux/slab.h>
     13 #include <linux/spinlock.h>
     14 #include <linux/string.h>
     15 #include <linux/init.h>
     16 #include <linux/bitops.h>
     17 #include <linux/delay.h>
     18 #include <linux/ip.h>
     19 
     20 #include <asm/system.h>
     21 #include <asm/io.h>
     22 #include <asm/irq.h>
     23 
     24 static struct net_device *vnet_dev;
     25 
     26 static void emulator_rx_packet(struct sk_buff *skb, struct net_device *dev)
     27 {
     28     /* 参考LDD3 */
     29     unsigned char *type;
     30     struct iphdr *ih;
     31     __be32 *saddr, *daddr, tmp;
     32     unsigned char    tmp_dev_addr[ETH_ALEN];
     33     struct ethhdr *ethhdr;
     34     
     35     struct sk_buff *rx_skb;
     36         
     37     // 从硬件读出/保存数据
     38     /* 对调"源/目的"的mac地址 */
     39     ethhdr = (struct ethhdr *)skb->data;
     40     memcpy(tmp_dev_addr, ethhdr->h_dest, ETH_ALEN);
     41     memcpy(ethhdr->h_dest, ethhdr->h_source, ETH_ALEN);
     42     memcpy(ethhdr->h_source, tmp_dev_addr, ETH_ALEN);
     43 
     44     /* 对调"源/目的"的ip地址 */    
     45     ih = (struct iphdr *)(skb->data + sizeof(struct ethhdr));
     46     saddr = &ih->saddr;
     47     daddr = &ih->daddr;
     48 
     49     tmp = *saddr;
     50     *saddr = *daddr;
     51     *daddr = tmp;
     52     
     53     //((u8 *)saddr)[2] ^= 1; /* change the third octet (class C) */
     54     //((u8 *)daddr)[2] ^= 1;
     55     type = skb->data + sizeof(struct ethhdr) + sizeof(struct iphdr);
     56     //printk("tx package type = %02x
    ", *type);
     57     // 修改类型, 原来0x8表示ping
     58     *type = 0; /* 0表示reply */
     59     
     60     ih->check = 0;           /* and rebuild the checksum (ip needs it) */
     61     ih->check = ip_fast_csum((unsigned char *)ih,ih->ihl);
     62     
     63     // 构造一个sk_buff
     64     rx_skb = dev_alloc_skb(skb->len + 2);
     65     skb_reserve(rx_skb, 2); /* align IP on 16B boundary */    
     66     memcpy(skb_put(rx_skb, skb->len), skb->data, skb->len);
     67 
     68     /* Write metadata, and then pass to the receive level */
     69     rx_skb->dev = dev;
     70     rx_skb->protocol = eth_type_trans(rx_skb, dev);
     71     rx_skb->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it */
     72     dev->stats.rx_packets++;
     73     dev->stats.rx_bytes += skb->len;
     74 
     75     // 提交sk_buff
     76     netif_rx(rx_skb);
     77 }
     78 
     79 static int virt_net_send_packet(struct sk_buff *skb, struct net_device *dev)
     80 {
     81     static int cnt = 0;
     82     //printk("virt_net_send_packet cnt = %d
    ", ++cnt);
     83 
     84     /* 对于真实的网卡, 把skb里的数据通过网卡发送出去 */
     85     netif_stop_queue(dev); /* 停止该网卡的队列 */
     86     /* ...... */           /* 把skb的数据写入网卡 */
     87 
     88     /* 构造一个假的sk_buff,上报 */
     89     emulator_rx_packet(skb, dev);
     90 
     91     dev_kfree_skb (skb);   /* 释放skb */
     92     netif_wake_queue(dev); /* 数据全部发送出去后,唤醒网卡的队列 */
     93 
     94     /* 更新统计信息 */
     95     dev->stats.tx_packets++;
     96     dev->stats.tx_bytes += skb->len;
     97     
     98     return 0;
     99 }
    100 
    101 static const struct net_device_ops virt_netdev_ops = {
    102     .ndo_start_xmit        = virt_net_send_packet,
    103 };
    104 
    105 static int virt_net_init(void)
    106 {
    107     /* 1. 分配一个net_device结构体 */
    108     vnet_dev = alloc_netdev(0, "vnet%d", ether_setup);;  /* alloc_etherdev */
    109 
    110     /* 2. 设置 */
    111     vnet_dev->netdev_ops    = &virt_netdev_ops;
    112 
    113     /* 设置MAC地址 */
    114     vnet_dev->dev_addr[0] = 0x08;
    115     vnet_dev->dev_addr[1] = 0x89;
    116     vnet_dev->dev_addr[2] = 0x89;
    117     vnet_dev->dev_addr[3] = 0x89;
    118     vnet_dev->dev_addr[4] = 0x89;
    119     vnet_dev->dev_addr[5] = 0x11;
    120 
    121     /* 设置下面两项才能ping通 */
    122     vnet_dev->flags           |= IFF_NOARP;
    123     vnet_dev->features        |= NETIF_F_NO_CSUM;    
    124 
    125     /* 3. 注册 */
    126     //register_netdevice(vnet_dev);
    127     register_netdev(vnet_dev);
    128     
    129     return 0;
    130 }
    131 
    132 static void virt_net_exit(void)
    133 {
    134     unregister_netdev(vnet_dev);
    135     free_netdev(vnet_dev);
    136 }
    137 
    138 module_init(virt_net_init);
    139 module_exit(virt_net_exit);
    140 MODULE_AUTHOR("Lover雪儿");
    141 MODULE_LICENSE("GPL");
    142 
    143 
    144 /*
    145 
    146 /////////////////////////////////////////////////////////////////////
    147 网卡驱动程序框架:
    148 app:  socket
    149 --------------------------------------------------------------------
    150         -----------------
    151         ----------------- 若干层网络协议--纯软件
    152         -----------------
    153 hard_start_xmit() 用于发送数据包            ↑↑↑
    154     ↓↓↓              sk_buff                netif_rx()用于上报数据包
    155 调用硬件相关的驱动程序(要提供har_start_xmit,有数据时用netif_rx上报)
    156 --------------------------------------------------------------------
    157               硬件
    158 //////////////////////////////////////////////////////////////////////
    159               
    160 网卡驱动编写:
    161 1.分配一个net_device结构体
    162 2.设置
    163 2.1 发包函数:hard_start_xmit
    164 2.2 收到到数据时,(在中断处理函数中)用netif_rx上报数据
    165 2.3 其他设置
    166 3.注册 register_netdevice              
    167     
    168 
    169 一、测试1th
    170 insmod virt_net.ko
    171 ifconfig vnet0 3.3.3.3
    172 ping 3.3.3.3
    173 ping 3.3.3.4  看效果 
    174 
    175     
    176 */
    virt_net4.c
  • 相关阅读:
    SQL Server, Timeout expired.all pooled connections were in use and max pool size was reached
    javascript 事件调用顺序
    Best Practices for Speeding Up Your Web Site
    C语言程序设计 使用VC6绿色版
    破解SQL Prompt 3.9的几步操作
    Master page Path (MasterPage 路径)
    几个小型数据库的比较
    CSS+DIV 完美实现垂直居中的方法
    由Response.Redirect引发的"Thread was being aborted. "异常的处理方法
    Adsutil.vbs 在脚本攻击中的妙用
  • 原文地址:https://www.cnblogs.com/lihaiyan/p/4439337.html
Copyright © 2011-2022 走看看