数据包计数器:网络设备驱动开发

一个用于统计接收数据包数量和大小的Linux内核驱动

项目简介

本项目实现了一个简单的虚拟网络设备驱动,专门用于统计通过该设备的数据包数量和大小。这个驱动不实际传输数据,而是专注于数据包的监控和统计功能,是学习Linux网络设备驱动开发的绝佳示例。

通过这个项目,你将学习到如何创建网络设备接口、处理数据包接收、维护统计信息以及通过sysfs接口暴露内核数据。

驱动功能特性

软件架构

用户空间 SysFS接口 网络栈 数据包计数器驱动 虚拟硬件

核心数据结构

struct pktcnt_priv {
    struct net_device *dev;
    unsigned long packet_count;
    unsigned long total_bytes;
    struct device *device;
};
            

这个结构体保存了我们的网络设备实例和统计信息:

关键函数实现

数据包接收处理

static int pktcnt_rx(struct sk_buff *skb, struct net_device *dev, 
                    struct packet_type *pt, struct net_device *orig_dev)
{
    struct pktcnt_priv *priv = netdev_priv(dev);
    
    // 更新统计信息
    priv->packet_count++;
    priv->total_bytes += skb->len;
    
    // 释放SKB(因为我们只是统计,不实际处理)
    kfree_skb(skb);
    
    return NET_RX_SUCCESS;
}
            

设备初始化

static int pktcnt_init(struct net_device *dev)
{
    struct pktcnt_priv *priv = netdev_priv(dev);
    
    // 初始化私有数据
    priv->dev = dev;
    priv->packet_count = 0;
    priv->total_bytes = 0;
    
    // 设置设备参数
    ether_setup(dev);
    dev->netdev_ops = &pktcnt_netdev_ops;
    
    // 随机MAC地址
    eth_hw_addr_random(dev);
    
    return 0;
}
            

SysFS接口实现

通过SysFS,我们可以轻松地从用户空间访问驱动统计信息:

static ssize_t packet_count_show(struct device *d,
                                struct device_attribute *attr, char *buf)
{
    struct pktcnt_priv *priv = netdev_priv(to_net_dev(d));
    return sprintf(buf, "%lu\n", priv->packet_count);
}

static ssize_t total_bytes_show(struct device *d,
                               struct device_attribute *attr, char *buf)
{
    struct pktcnt_priv *priv = netdev_priv(to_net_dev(d));
    return sprintf(buf, "%lu\n", priv->total_bytes);
}

// 定义设备属性
static DEVICE_ATTR_RO(packet_count);
static DEVICE_ATTR_RO(total_bytes);
            

设备操作函数表

函数指针 功能描述
ndo_init 设备初始化
ndo_uninit 设备卸载清理
ndo_open 打开设备
ndo_stop 关闭设备
ndo_start_xmit 数据包发送处理

编译和加载

Makefile示例

obj-m += pktcnt.o

all:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
            

加载驱动

# 编译模块
make

# 加载模块
sudo insmod pktcnt.ko

# 查看系统日志
dmesg | tail

# 查看网络接口
ip link show
            

测试和使用

驱动加载后,可以通过以下方式测试和使用:

  1. 使用ip link show查看新创建的网络接口
  2. 使用ifconfig pktcnt0 up激活接口
  3. 向该接口发送测试数据包:ping -I pktcnt0 127.0.0.1
  4. 查看统计信息:cat /sys/class/net/pktcnt0/packet_count
  5. 查看总字节数:cat /sys/class/net/pktcnt0/total_bytes

提示: 由于这是一个虚拟设备,发送到该设备的数据包不会真正传输到网络,但会被驱动统计。

应用场景

网络监控 流量分析 教学示例 调试工具 性能测试

扩展思路

进阶挑战: 尝试修改驱动,使其能够统计特定协议(如TCP、UDP或ICMP)的数据包数量和大小。