目的:创建一个最简单的虚拟网卡
网卡驱动程序框架:
app: socket
--------------------------------------------------
---------------
--------------- 若干层网络协议--纯软件
---------------
---------------
nodo_start_xmit|| /\
\/ || netif_rx sk_buff
---------------
硬件相关的驱动程序(要提供ndo_start_xmit, 有数据时要用netif_rx上报)
--------------------------------------------------
硬件
写网卡驱动程序步骤:
1. 分配一个net_device结构体
2. 设置:
2.1 在结构体net_device_ops中定义发包函数:nodo_start_xmit
2.2 收到数据时(在中断处理函数里)用netif_rx上报数据
2.3 其他设置
3. 注册: register_netdev
代码如下
-
/*
-
* 参考drivers\net\dm9000.c
-
*/
-
#include <linux/module.h>
-
#include <linux/ioport.h>
-
#include <linux/netdevice.h>
-
#include <linux/etherdevice.h>
-
#include <linux/init.h>
-
#include <linux/interrupt.h>
-
#include <linux/skbuff.h>
-
#include <linux/spinlock.h>
-
#include <linux/crc32.h>
-
#include <linux/mii.h>
-
#include <linux/ethtool.h>
-
#include <linux/dm9000.h>
-
#include <linux/delay.h>
-
#include <linux/platform_device.h>
-
#include <linux/irq.h>
-
#include <linux/slab.h>
-
-
#include <asm/delay.h>
-
#include <asm/irq.h>
-
#include <asm/io.h>
-
-
static struct net_device *vnet_dev;
-
-
static struct net_device_ops vnet_dev_ops =
-
{
-
/* 2.1 在结构体net_device_ops中定义发包函数:nodo_start_xmit */
-
};
-
-
static int vnet_init(void)
-
{
-
/* 1. 分配一个net_device */
-
vnet_dev = alloc_netdev(0, "vnet%d", ether_setup); // alloc_etherdev;
-
-
/* 2. 设置: */
-
-
/* 2.2 其他信息 */
-
-
-
/* 3. 硬件相关的: request_irq, 在中断函数里得到数据后用netif_rx上报 */
-
-
/* 4. 注册net_device */
-
vnet_dev->netdev_ops = &vnet_dev_ops;//必须添加,否则会注册失败
-
register_netdev(vnet_dev);
-
-
-
return 0;
-
}
-
-
static void vnet_exit(void)
-
{
-
unregister_netdev(vnet_dev);
-
free_netdev(vnet_dev);
-
}
-
-
module_init(vnet_init);
-
module_exit(vnet_exit);
-
-
MODULE_LICENSE("GPL");
注意:vnet_dev_ops结构体必须添加,否则在开发板insmod驱动时会出现如下错误
-
Unable to handle kernel NULL pointer dereference at virtual address 00000000
-
pgd = cfac8000
-
[00000000] *pgd=5fb21831, *pte=00000000, *ppte=00000000
-
Internal error: Oops: 17 [#1] ARM
-
Modules linked in: vnet(O+)
-
CPU: 0 Tainted: G O (3.8.3 #82)
-
PC is at register_netdevice+0x74/0x390
-
LR is at 0x74656e76
-
pc : [<c02bbe34>] lr : [<74656e76>] psr: 60000013
-
sp : cfb6de48 ip : 00000000 fp : 00000001
-
r10: bf000024 r9 : cfb10760 r8 : bf0000b0
-
r7 : 00000000 r6 : 00000000 r5 : c04d8308 r4 : cfae5800
-
r3 : 00000030 r2 : 80000000 r1 : cfb6de25 r0 : 00000000
-
Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user
-
Control: 00c5387d Table: 5fac8008 DAC: 00000015
-
Process insmod (pid: 970, stack limit = 0xcfb6c1b0)
-
Stack: (0xcfb6de48 to 0xcfb6e000)
-
de40: cfae5a18 c04d8af8 cfb6c000 cfae5800 cfb6c000 c04de000
-
de60: 00000000 bf0000b0 cfb10760 bf000024 00000001 c02bc164 cfb6c000 bf000054
-
de80: 00000001 00000000 00000002 c0008658 00000018 00000017 00000017 bf000024
-
dea0: 00000000 c04dd144 bf0000b0 bf0000f8 00000018 cfac09c0 bf0000bc bf0000bc
-
dec0: cfb6c000 cfb6df50 00400100 bf0000b0 cfb10760 bf0000f8 00000001 c0059c84
-
dee0: bf0000bc 00007fff c0057e14 c008dcec d0862000 0000001c 00000020 00000018
-
df00: bf0001e4 c035a248 00000000 00000000 00000000 00000000 00000000 00000000
-
df20: 00000000 c008e9e0 000000d2 cfb6df50 0001776b 000eb040 000e1d93 c000eb28
-
df40: cfb6c000 00000000 00000000 c005a3a8 d0862000 0001776b d08740f8 d0873fc0
-
df60: d0879668 000001fc 000002fc 00000000 00000000 00000000 0000001e 0000001f
-
df80: 00000009 00000000 00000006 00000000 cfb6c000 000007cc beb07cc4 00000069
-
dfa0: 00000080 c000e980 000007cc beb07cc4 000eb040 0001776b 000e1d93 00000000
-
dfc0: 000007cc beb07cc4 00000069 00000080 beb07cc8 00000000 beb07cc8 00000000
-
dfe0: 00000001 beb07954 00021ea4 b6e59154 60000010 000eb040 00000000 00000000
-
[<c02bbe34>] (register_netdevice+0x74/0x390) from [<c02bc164>] (register_netdev+0x14/0x24)
-
[<c02bc164>] (register_netdev+0x14/0x24) from [<bf000054>] (vnet_init+0x30/0x48 [vnet])
-
[<bf000054>] (vnet_init+0x30/0x48 [vnet]) from [<c0008658>] (do_one_initcall+0x34/0x178)
-
[<c0008658>] (do_one_initcall+0x34/0x178) from [<c0059c84>] (load_module+0xb94/0x116c)
-
[<c0059c84>] (load_module+0xb94/0x116c) from [<c005a3a8>] (sys_init_module+0xc0/0xf4)
-
[<c005a3a8>] (sys_init_module+0xc0/0xf4) from [<c000e980>] (ret_fast_syscall+0x0/0x30)
-
Code: ebfffef3 e2506000 ba000008 e594c0d8 (e59c3000)
-
---[ end trace fb9590d42235a944 ]---
-
Segmentation fault
具体原理可以参考http://blog.chinaunix.net/uid-28970775-id-3941741.html
测试方法:
1. 加载驱动
2. 配置虚拟网卡的ip:ifconfig vnet0 3.3.3.3
3. 查看:ifconfig,看到新网卡vnet0
4. ping 3.3.3.3,发现可以ping通,说明ip实际是纯软件的概念,在ping本地ip时饶过了底层的网卡驱动,
因此说明网卡驱动只需要提供发包和收包的功能,并不需要了解那些上层协议
5. ping 3.3.3.4,开发板死机,由于驱动没有提供发包和收包的函数
阅读(1627) | 评论(0) | 转发(0) |