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\n",++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\n",++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\n", ++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\n", ++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\n", *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\n", ++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\n", *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\n", ++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

时间: 2024-09-30 06:20:39

IMX257虚拟网卡vnet驱动程序的相关文章

虚拟网卡TUN/TAP 驱动程序设计原理

昨天韦哥写了<Linux下Tun/Tap设备通信原理>一文,只提到了两个使用Tun的用户进程之间的通信路径,并没有说明Tun虚拟网卡驱动是如何实现的,而正好看到了这里的一篇讲解这方面的文章,果断转载了,感谢作者,原文在这里:虚拟网卡TUN/TAP 驱动程序设计原理 简介 虚拟网卡Tun/tap驱动是一个开源项目,支持很多的类UNIX平台,OpenVPN和Vtun都是基于它实现隧道包封装.本文将介绍tun/tap驱动的使用并分析虚拟网卡tun/tap驱动程序在linux环境下的设计思路. tun

单网卡绑定多个ip, 多个网卡绑定成一块虚拟网卡

Linux网卡配置与绑定 Redhat Linux的网络配置,基本上是通过修改几个配置文件来实现的,虽然也可以用ifconfig来设置IP,用route来配置默认网关,用hostname来配置主机名,但是重启后会丢失. 相关的配置文件 /ect/hosts 配置主机名和IP地址的对应 /etc/sysconfig/network 配置主机名和网关 /etc/sysconfig/network-scripts/ifcfg-eth0 eth0配置文件,eth1则文件名为ifcfg-eth1,以此类推

删除Windows中隐藏的物理网卡和网络虚拟化失败后的虚拟网卡

Windows环境下,在更换硬件服务器主板和网卡等硬件.恢复操作系统或者网络虚拟化失败后,可能会出现网卡方面的问题.例如,设备管理器中多了不应该存在的网卡:因命名冲突无法重命名当前网络连接:IP地址冲突却找不到那个与之冲突的网卡:网络虚拟化失败后出现无法删除的虚拟网卡等等.下面我们就来总结一下如何删除这些可见或不可见的Ghost一样的网卡. 一.识别各类网络设备和网络连接 由于网络虚拟化会在物理机上新增许多虚拟网络设备(包括虚拟网卡),情况会变得复杂,因而首先我们需要分清他们.当然如果没有进行网

解决win8/8.1 的“无法启动虚拟网卡适配器任务”

因业务需要,一直使用华赛的VPN(Secospace VPN Client),在Windows XP到Windows 7的32位和64位系统中都可以正常使用,但是升级到Windows 8(Windows 8.1)64位后,安装过程中没有出现驱动程序安装的提示,但是显示成功安装.安装后,新建连接,导入配置文件都正常,连接过程至第5步的时候提示"无法启动虚拟网卡适配任务",连接失败. 尝试使用兼容模式.以系统管理员身份运行等方法均无效:使用新疆冠新网站所述的方法也没有解决.无奈只能退回到W

CentOS下使用TUN/TAP虚拟网卡的基本教程

在计算机网络中,TUN与TAP是操作系统内核中的虚拟网络设备.不同于普通靠硬件网路板卡实现的设备,这些虚拟的网络设备全部用软件实现,并向运行于操作系统上的软件提供与硬件的网络设备完全相同的功能.TAP 等同于一个以太网设备,它操作第二层数据包如以太网数据帧.TUN模拟了网络层设备,操作第三层数据包比如IP数据封包.操作系统通过TUN/TAP设备向绑定该设备的用户空间的程序发送数据,反之,用户空间的程序也可以像操作硬件网络设备那样,通过TUN/TAP设备发送数据.在后种情况下,TUN/TAP设备向

有线网卡与无线网卡、物理网卡与虚拟网卡的区分

获取当前活跃状态的网卡MAC地址.物理地址 Wmic命令:Win32_NetworkAdapter和Win32_NetworkAdapterConfiguration. 其中cmd命令行执行: 1. Wmic Path Win32_NetworkAdapter get GUID,MACAddress,NetEnabled,PhysicalAdapter,Index 备注: GUID:连接唯一标识; MACAddress:网卡地址; NetEnabled: 是否启用了适配器,True为启用,Fal

半截水晶头线接激活本地虚拟网卡

可有可无的小方法~ 很多人在用虚拟机的时候,有时虚拟网卡不够用,又没有可用网线插来激活本地网卡时,这时可以自制一个水晶头加半截网线(或者从水晶头还 能用的废掉的网线上截取下来如下图)来激活本地网卡,多增加一个可用虚拟网卡(虽然第一次在当时无法解决(^-^)) 制作方法:截取或制作成水晶头后,将线皮剥掉至漏出铜线,将线序颜色排列成T-568B的线序(如下图) 以10/100兆太网网卡为例的DTE类型接口引脚定义为(对应上图从左到右): 1-TX+Tranceive  Data+  (发信号+)  

SylixOS USB虚拟网卡框架

1. USB子系统简介 1.1      USB简介 USB,是英文Universal Serial Bus(通用串行总线)的缩写,是一个外部总线标准,用于规范电脑与外部设备的连接和通讯.是应用在PC领域的接口技术.USB接口支持设备的即插即用和热插拔功能.USB是在1994年底由英特尔.康柏.IBM.Microsoft等多家公司联合提出的. 1.2      USB虚拟网卡框架 1.2.1   普通网卡与USB网卡框架对比 如图 11所示,普通网卡驱动与USB网卡驱动相比最大的区别是,USB网

Linux网络配置之虚拟网卡的配置(ubuntu)

关于图形界面的配置,我这里就不多介绍了,这个很简单.这里介绍的是如何通过修改配置文件来实现虚拟网卡. 首先介绍ubuntu(我这里使用的是ubuntu-16.04)下虚拟网卡的配置 1.先用ifconfig查看当前的网卡配置 ens33 Link encap:以太网 硬件地址 02:0c:29:c6:be:c7 inet6 地址: fe80::20c:29ef:fec6:bec7/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 跃点数: