一、一个简单的虚拟网卡驱动
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
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;
};