Chinaunix首页 | 论坛 | 博客
  • 博客访问: 98117
  • 博文数量: 38
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 384
  • 用 户 组: 普通用户
  • 注册时间: 2014-04-06 16:52
文章分类

全部博文(38)

文章存档

2014年(38)

我的朋友

分类: 嵌入式

2014-05-13 15:09:41

目的:创建一个最简单的虚拟网卡

网卡驱动程序框架:
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


代码如下

点击(此处)折叠或打开

  1. /*
  2.  * 参考drivers\net\dm9000.c
  3.  */
  4. #include <linux/module.h>
  5. #include <linux/ioport.h>
  6. #include <linux/netdevice.h>
  7. #include <linux/etherdevice.h>
  8. #include <linux/init.h>
  9. #include <linux/interrupt.h>
  10. #include <linux/skbuff.h>
  11. #include <linux/spinlock.h>
  12. #include <linux/crc32.h>
  13. #include <linux/mii.h>
  14. #include <linux/ethtool.h>
  15. #include <linux/dm9000.h>
  16. #include <linux/delay.h>
  17. #include <linux/platform_device.h>
  18. #include <linux/irq.h>
  19. #include <linux/slab.h>

  20. #include <asm/delay.h>
  21. #include <asm/irq.h>
  22. #include <asm/io.h>

  23. static struct net_device *vnet_dev;

  24. static struct net_device_ops vnet_dev_ops =
  25. {
  26.     /* 2.1 在结构体net_device_ops中定义发包函数:nodo_start_xmit */
  27. };

  28. static int vnet_init(void)
  29. {
  30.     /* 1. 分配一个net_device */
  31.     vnet_dev = alloc_netdev(0, "vnet%d", ether_setup); // alloc_etherdev;

  32.     /* 2. 设置: */

  33.     /* 2.2 其他信息 */


  34.     /* 3. 硬件相关的: request_irq, 在中断函数里得到数据后用netif_rx上报 */

  35.     /* 4. 注册net_device */
  36.     vnet_dev->netdev_ops = &vnet_dev_ops;//必须添加,否则会注册失败
  37.     register_netdev(vnet_dev);

  38.     
  39.     return 0;
  40. }

  41. static void vnet_exit(void)
  42. {
  43.     unregister_netdev(vnet_dev);
  44.     free_netdev(vnet_dev);
  45. }

  46. module_init(vnet_init);
  47. module_exit(vnet_exit);

  48. MODULE_LICENSE("GPL");
注意:vnet_dev_ops结构体必须添加,否则在开发板insmod驱动时会出现如下错误

点击(此处)折叠或打开

  1. Unable to handle kernel NULL pointer dereference at virtual address 00000000
  2. pgd = cfac8000
  3. [00000000] *pgd=5fb21831, *pte=00000000, *ppte=00000000
  4. Internal error: Oops: 17 [#1] ARM
  5. Modules linked in: vnet(O+)
  6. CPU: 0 Tainted: G O (3.8.3 #82)
  7. PC is at register_netdevice+0x74/0x390
  8. LR is at 0x74656e76
  9. pc : [<c02bbe34>] lr : [<74656e76>] psr: 60000013
  10. sp : cfb6de48 ip : 00000000 fp : 00000001
  11. r10: bf000024 r9 : cfb10760 r8 : bf0000b0
  12. r7 : 00000000 r6 : 00000000 r5 : c04d8308 r4 : cfae5800
  13. r3 : 00000030 r2 : 80000000 r1 : cfb6de25 r0 : 00000000
  14. Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user
  15. Control: 00c5387d Table: 5fac8008 DAC: 00000015
  16. Process insmod (pid: 970, stack limit = 0xcfb6c1b0)
  17. Stack: (0xcfb6de48 to 0xcfb6e000)
  18. de40: cfae5a18 c04d8af8 cfb6c000 cfae5800 cfb6c000 c04de000
  19. de60: 00000000 bf0000b0 cfb10760 bf000024 00000001 c02bc164 cfb6c000 bf000054
  20. de80: 00000001 00000000 00000002 c0008658 00000018 00000017 00000017 bf000024
  21. dea0: 00000000 c04dd144 bf0000b0 bf0000f8 00000018 cfac09c0 bf0000bc bf0000bc
  22. dec0: cfb6c000 cfb6df50 00400100 bf0000b0 cfb10760 bf0000f8 00000001 c0059c84
  23. dee0: bf0000bc 00007fff c0057e14 c008dcec d0862000 0000001c 00000020 00000018
  24. df00: bf0001e4 c035a248 00000000 00000000 00000000 00000000 00000000 00000000
  25. df20: 00000000 c008e9e0 000000d2 cfb6df50 0001776b 000eb040 000e1d93 c000eb28
  26. df40: cfb6c000 00000000 00000000 c005a3a8 d0862000 0001776b d08740f8 d0873fc0
  27. df60: d0879668 000001fc 000002fc 00000000 00000000 00000000 0000001e 0000001f
  28. df80: 00000009 00000000 00000006 00000000 cfb6c000 000007cc beb07cc4 00000069
  29. dfa0: 00000080 c000e980 000007cc beb07cc4 000eb040 0001776b 000e1d93 00000000
  30. dfc0: 000007cc beb07cc4 00000069 00000080 beb07cc8 00000000 beb07cc8 00000000
  31. dfe0: 00000001 beb07954 00021ea4 b6e59154 60000010 000eb040 00000000 00000000
  32. [<c02bbe34>] (register_netdevice+0x74/0x390) from [<c02bc164>] (register_netdev+0x14/0x24)
  33. [<c02bc164>] (register_netdev+0x14/0x24) from [<bf000054>] (vnet_init+0x30/0x48 [vnet])
  34. [<bf000054>] (vnet_init+0x30/0x48 [vnet]) from [<c0008658>] (do_one_initcall+0x34/0x178)
  35. [<c0008658>] (do_one_initcall+0x34/0x178) from [<c0059c84>] (load_module+0xb94/0x116c)
  36. [<c0059c84>] (load_module+0xb94/0x116c) from [<c005a3a8>] (sys_init_module+0xc0/0xf4)
  37. [<c005a3a8>] (sys_init_module+0xc0/0xf4) from [<c000e980>] (ret_fast_syscall+0x0/0x30)
  38. Code: ebfffef3 e2506000 ba000008 e594c0d8 (e59c3000)
  39. ---[ end trace fb9590d42235a944 ]---
  40. 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) |
给主人留下些什么吧!~~