如何在网卡驱动内核模块中获取真实网卡的所有VLAN接口信息?
内核态获取VLAN接口信息及父网卡关联VLAN列表
核心结构体与VLAN设备判断
VLAN接口的私有信息并非存放在netdevice.h的结构体中,而是定义在<linux/if_vlan.h>的struct vlan_dev_priv里:
struct vlan_dev_priv { struct net_device *real_dev; // 指向父网卡的net_device指针 unsigned short vlan_id; // VLAN ID unsigned int flags; // VLAN配置标志(如VLAN_FLAG_REORDER_HDR) struct hlist_node hlist; // 挂在父网卡vlan_info链表的节点 struct net_device *vlan_dev; // 指向自身的net_device指针 // ... 其他成员 };
判断一个struct net_device是否为VLAN设备,直接用vlan_dev_check()宏(来自<linux/if_vlan.h>),它会检查设备的priv_flags是否包含IFF_802_1Q_VLAN标志位。
从VLAN接口提取详细信息
如果驱动已持有VLAN接口的struct net_device指针,可按以下步骤获取信息:
- 引入头文件
#include <linux/if_vlan.h> - 验证设备类型
- 提取私有数据并访问成员
示例代码:
struct net_device *vlan_dev = ...; // 目标VLAN设备指针 if (vlan_dev_check(vlan_dev)) { struct vlan_dev_priv *vlan_priv = vlan_dev_priv(vlan_dev); pr_info("VLAN ID: %d, 父网卡: %s\n", vlan_priv->vlan_id, vlan_priv->real_dev->name); // 可进一步读取VLAN配置,比如是否启用报文头重排序 if (vlan_priv->flags & VLAN_FLAG_REORDER_HDR) { pr_info("该VLAN启用报文头重排序\n"); } }
遍历父网卡的所有关联VLAN接口
要获取某真实网卡(如port-1)对应的所有VLAN接口,可利用父设备struct net_device中的vlan_info链表头,该链表维护了所有挂载在该父设备上的VLAN私有数据:
示例代码:
struct net_device *real_dev = ...; // 父网卡的net_device指针 struct hlist_node *pos; struct vlan_dev_priv *vlan_priv; // 网络设备可能动态变更,必须用RCU保护遍历过程 rcu_read_lock(); hlist_for_each_entry_rcu(vlan_priv, pos, &real_dev->vlan_info, hlist) { struct net_device *vlan_dev = vlan_priv->vlan_dev; pr_info("找到关联VLAN接口: %s, VLAN ID: %d\n", vlan_dev->name, vlan_priv->vlan_id); } rcu_read_unlock();
关键注意事项
- 编译驱动时需确保内核配置开启
CONFIG_VLAN_8021Q,否则相关结构体和宏会无法使用 - 所有访问网络设备结构体的操作必须遵循RCU规则,避免并发销毁导致的空指针或内存错误
- 若仅需用户态查询,可直接执行
ip link show或查看/proc/net/vlan/config文件获取VLAN关联关系
内容的提问来源于stack exchange,提问作者Inu1997
相关产品推荐
相关产品推荐

