一、一个简单的虚拟网卡驱动
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 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include 9 #include 10 #include 11 #include 12 #include 13 #include 14 #include 15 #include 16 #include 17 18 #include 19 #include 20 #include 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 */ 二、增加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 = %dn',++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 2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include 9 #include 10 #include 11 #include 12 #include 13 #include 14 #include 15 #include 16 #include 17 18 #include 19 #include 20 #include 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 = %dn',++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 */ 三、增加数据包的统计,设置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; }; 


上一篇:iMX257引脚配置函数/内存读写函数
下一篇:S3C2440 nor_flash驱动程序
推荐阅读最新更新时间:2026-03-23 10:46
- 热门资源推荐
- 热门放大器推荐
- LDK120M12R 1.2V低压降稳压器典型应用(可调版)电路
- EVB-UTC2000-DFP、EVK-UTC2000 评估套件基于 UTC2000 USB 3.0/2.0 Type-A,即插即用 Type-C DFP
- LTC3219 演示板、250mA 通用九通道 LED 驱动器
- DC919A-D,LTC2204 CMOS 输出演示板,直流输入,40Msps 16 位 ADC,DC
- AD8618ARZ-REEL 二阶低通滤波器运算放大器的典型应用电路
- 使用 NXP Semiconductors 的 PCA9511A 的参考设计
- LT3091MPDE 恒流恒压实验室电源的典型应用
- ADR392B 4.096 Vout 微功率、低噪声精密电压基准的典型应用
- LT3470HDDB 5V 降压转换器的典型应用电路
- 使用 Diodes Incorporated 的 AZ7042ZTR-E1 的参考设计



现场总线技术及其应用 (阳宪惠)
虚拟网卡驱动
单片机定义
现代雷达系统的信号设计
BFR340T






京公网安备 11010802033920号