前面讲到,register_netdev首先为网络设备接口分配一个名称,然后将dev插入到一个叫做dev_base的网络设备全局链表中。由此我们不难想到,通过访问dev_base,就可以遍历到系统中的所有网络设备,而每一个网络设备接口都有一个net_device结构来表示。该结构中有一个成员函数指针:
struct net_device_stats* (*get_stats)(struct net_device *dev);
它返回一个struct net_device_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 problems */
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;
};
OK,有了这些基础知识,我们就可以写一个网络流量统计的内核模块了,这是一个最简单的程序,它每次被插入到内核中时,会在日志文件中打出当前系统上的所有网络设备接口的传输的和收到的字节数和包数。我们可以把它进一步改造,输出到/proc文件系统,再通过用户空间的一个程序计算单位时间的流量,就成为一个真正的网络流量统计程序了。
下面是代码:
/* netbase.c
* helinqiang@hotmail.com
* 2006-03-14
*/
#include <linux/init.h>
#include <linux/netdevice.h>
MODULE_AUTHOR("Linqiang He, Hangzhou China");
MODULE_LICENSE("Dual BSD/GPL");
static int __init netbase_init_module(void)
{
struct net_device *dev = dev_base;
struct net_device_stats *stats;
while( dev != NULL ){
printk(KERN_INFO "dev name: %s/n", dev->name);
stats = dev->get_stats(dev);
printk(KERN_INFO "/ttransmitted bytes: %lu/n", stats->tx_bytes);
printk(KERN_INFO "/treceived bytes: %lu/n", stats->rx_bytes);
printk(KERN_INFO "/ttransmitted packets: %lu/n", stats->tx_packets);
printk(KERN_INFO "/treceived packets: %lu/n", stats->rx_packets);
dev = dev->next;
}
return 0;
}
static void __exit netbase_exit_module(void)
{
}
module_init(netbase_init_module);
module_exit(netbase_exit_module);
下面是在我的电脑上的某一时刻的输出结果:
Mar 14 21:22:34 localhost kernel: dev name: lo
Mar 14 21:22:34 localhost kernel: transmitted bytes: 4660
Mar 14 21:22:34 localhost kernel: received bytes: 4660
Mar 14 21:22:34 localhost kernel: transmitted packets: 61
Mar 14 21:22:34 localhost kernel: received packets: 61
Mar 14 21:22:34 localhost kernel: dev name: sit0
Mar 14 21:22:34 localhost kernel: transmitted bytes: 0
Mar 14 21:22:34 localhost kernel: received bytes: 0
Mar 14 21:22:34 localhost kernel: transmitted packets: 0
Mar 14 21:22:34 localhost kernel: received packets: 0
Mar 14 21:22:34 localhost kernel: dev name: eth0
Mar 14 21:22:34 localhost kernel: transmitted bytes: 437071
Mar 14 21:22:34 localhost kernel: received bytes: 4046403
Mar 14 21:22:34 localhost kernel: transmitted packets: 2607
Mar 14 21:22:34 localhost kernel: received packets: 17773
struct net_device_stats* (*get_stats)(struct net_device *dev);
它返回一个struct net_device_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 problems */
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;
};
OK,有了这些基础知识,我们就可以写一个网络流量统计的内核模块了,这是一个最简单的程序,它每次被插入到内核中时,会在日志文件中打出当前系统上的所有网络设备接口的传输的和收到的字节数和包数。我们可以把它进一步改造,输出到/proc文件系统,再通过用户空间的一个程序计算单位时间的流量,就成为一个真正的网络流量统计程序了。
下面是代码:
/* netbase.c
* helinqiang@hotmail.com
* 2006-03-14
*/
#include <linux/init.h>
#include <linux/netdevice.h>
MODULE_AUTHOR("Linqiang He, Hangzhou China");
MODULE_LICENSE("Dual BSD/GPL");
static int __init netbase_init_module(void)
{
struct net_device *dev = dev_base;
struct net_device_stats *stats;
while( dev != NULL ){
printk(KERN_INFO "dev name: %s/n", dev->name);
stats = dev->get_stats(dev);
printk(KERN_INFO "/ttransmitted bytes: %lu/n", stats->tx_bytes);
printk(KERN_INFO "/treceived bytes: %lu/n", stats->rx_bytes);
printk(KERN_INFO "/ttransmitted packets: %lu/n", stats->tx_packets);
printk(KERN_INFO "/treceived packets: %lu/n", stats->rx_packets);
dev = dev->next;
}
return 0;
}
static void __exit netbase_exit_module(void)
{
}
module_init(netbase_init_module);
module_exit(netbase_exit_module);
下面是在我的电脑上的某一时刻的输出结果:
Mar 14 21:22:34 localhost kernel: dev name: lo
Mar 14 21:22:34 localhost kernel: transmitted bytes: 4660
Mar 14 21:22:34 localhost kernel: received bytes: 4660
Mar 14 21:22:34 localhost kernel: transmitted packets: 61
Mar 14 21:22:34 localhost kernel: received packets: 61
Mar 14 21:22:34 localhost kernel: dev name: sit0
Mar 14 21:22:34 localhost kernel: transmitted bytes: 0
Mar 14 21:22:34 localhost kernel: received bytes: 0
Mar 14 21:22:34 localhost kernel: transmitted packets: 0
Mar 14 21:22:34 localhost kernel: received packets: 0
Mar 14 21:22:34 localhost kernel: dev name: eth0
Mar 14 21:22:34 localhost kernel: transmitted bytes: 437071
Mar 14 21:22:34 localhost kernel: received bytes: 4046403
Mar 14 21:22:34 localhost kernel: transmitted packets: 2607
Mar 14 21:22:34 localhost kernel: received packets: 17773