一个用于统计接收数据包数量和大小的Linux内核驱动
本项目实现了一个简单的虚拟网络设备驱动,专门用于统计通过该设备的数据包数量和大小。这个驱动不实际传输数据,而是专注于数据包的监控和统计功能,是学习Linux网络设备驱动开发的绝佳示例。
通过这个项目,你将学习到如何创建网络设备接口、处理数据包接收、维护统计信息以及通过sysfs接口暴露内核数据。
struct pktcnt_priv { struct net_device *dev; unsigned long packet_count; unsigned long total_bytes; struct device *device; };
这个结构体保存了我们的网络设备实例和统计信息:
dev
: 指向关联的网络设备结构体packet_count
: 接收到的数据包计数器total_bytes
: 接收到的总字节数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,我们可以轻松地从用户空间访问驱动统计信息:
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 |
数据包发送处理 |
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
驱动加载后,可以通过以下方式测试和使用:
ip link show
查看新创建的网络接口ifconfig pktcnt0 up
激活接口ping -I pktcnt0 127.0.0.1
cat /sys/class/net/pktcnt0/packet_count
cat /sys/class/net/pktcnt0/total_bytes
提示: 由于这是一个虚拟设备,发送到该设备的数据包不会真正传输到网络,但会被驱动统计。
进阶挑战: 尝试修改驱动,使其能够统计特定协议(如TCP、UDP或ICMP)的数据包数量和大小。