Linux内核——遍历 net_device 结构

本文介绍了在Linux内核版本2.6.32及以后版本中遍历net_device结构的方法,包括多种遍历宏定义及其使用场景。这些方法有助于更好地理解和操作Linux网络设备。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

linux内核版本 : 2.6.32<=(这个更早的也许就已经这样了,具体是从哪个版本开始的,我没有考证,需要在今后,发现后及时补充。)

extern struct net *init_net;	/* 存放net_device的全局变量 */
extern rwlock_t                         dev_base_lock;          /* Device list lock */

/*这些是我们遍历 net_device 结构的循环 */

#define for_each_netdev(net, d)         \
                list_for_each_entry(d, &(net)->dev_base_head, dev_list)
#define for_each_netdev_reverse(net, d) \
                list_for_each_entry_reverse(d, &(net)->dev_base_head, dev_list)
#define for_each_netdev_rcu(net, d)             \
                list_for_each_entry_rcu(d, &(net)->dev_base_head, dev_list)
#define for_each_netdev_safe(net, d, n) \
                list_for_each_entry_safe(d, n, &(net)->dev_base_head, dev_list)
#define for_each_netdev_continue(net, d)                \
                list_for_each_entry_continue(d, &(net)->dev_base_head, dev_list)
#define for_each_netdev_continue_rcu(net, d)            \
        list_for_each_entry_continue_rcu(d, &(net)->dev_base_head, dev_list)
#define for_each_netdev_in_bond_rcu(bond, slave)        \
                for_each_netdev_rcu(&init_net, slave)   \
                         if (netdev_master_upper_dev_get_rcu(slave) == bond)
#define net_device_entry(lh)    list_entry(lh, struct net_device, dev_list)


《深入理解Linux网络技术内幕》中介绍的是这样子的:

480 extern struct net_device                *dev_base;              /* All devices */
481 extern rwlock_t                         dev_base_lock;          /* Device list lock */

遍历方式:
struct net_device * dev = dev_base;
while(dev) {
	dev = dev->next;
}





### PCIe端口设备注册 在PCIe环境中,设备注册是一个重要的初始化步骤,它涉及到操作系统和硬件之间的交互。对于Intel DPDK环境下的PCIe设备注册,具体流程如下: #### 设备枚举与探测 当系统启动时,BIOS/UEFI会遍历所有的PCIe总线,并记录下所有连接到这些总线上的设备信息。随后,在Linux内核加载过程中,pci子系统将继续完成未被固件处理的剩余部分工作。 #### 驱动程序绑定 为了使特定的应用层软件(如DPDK)能够控制某个具体的PCIe网卡或其他类型的适配器,必须先让相应的驱动模块接管该物理设备。这通常意味着卸载默认由内核管理的标准网络接口驱动,并安装专有的用户空间驱动——例如rte_pmd_ixgbe库负责英特尔系列以太网控制器的支持[^1]。 ```c // 卸载原生驱动并替换为igb_uio/uio_pci_generic modprobe uio rmmod ixgbe insmod ./build/kmod/igb_uio.ko ``` #### 用户态驱动初始化 一旦完成了上述准备工作之后,就可以调用`rte_eal_init()`函数来解析命令行参数以及设置必要的运行期配置项;紧接着通过调用`rte_eth_dev_configure()`, `rte_eth_rx_queue_setup()`, 和 `rte_eth_tx_queue_setup()`等一系列API来进行更细致化的调整操作,比如指定队列数目、缓冲区大小等属性值。 ```c int main(int argc, char **argv) { int ret; // 初始化EAL (Environment Abstraction Layer) ret = rte_eal_init(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n"); struct rte_mempool *mbuf_pool; /* 创建内存池用于存储数据包 */ mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", NUM_MBUFS * nb_ports, MBUF_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, SOCKET_ID_ANY); ... } ``` #### 注册回调函数 某些情况下可能还需要定义额外的服务例程以便更好地响应来自底层硬件的通知事件。此时可以借助于`rte_intr_callback_register()` API 来关联自定义逻辑至中断源上。 ```c static void lcore_main(void) { uint8_t portid; unsigned lcore_id; RTE_LCORE_FOREACH(lcore_id) { if (lcore_id != rte_lcore_id()) continue; for (portid = 0; portid < nb_ports; ++portid) { // 设置接收描述符环形数组中的每一个元素都指向预先分配好的mempool对象实例 rxq_conf->rx_free_thresh = RX_FREE_THRESH; txconf.tx_rs_thresh = TX_RS_THRESH; // 启用RSS哈希算法支持 dev_info.flow_type_rss_offloads &= ~ETH_RSS_OFFLOAD_MASK; dev_info.default_rxportconf.rss_hf |= ETH_RSS_IP | ETH_RSS_UDP | ETH_RSS_TCP | ETH_RSS_SCTP; // 如果启用了多队列模式,则需要单独针对每个RX/TX通道分别执行setup动作 if (nb_rx_queues > 1 || nb_tx_queues > 1){ for(queue=0 ; queue<nb_rx_queues ;queue++){ rte_eth_rx_queue_setup(portid , queue , ... ); } for(queue=0 ; queue<nb_tx_queues ;queue++){ rte_eth_tx_queue_setup(portid , queue , ... ); } } // 开始轮询模式收发报文循环... while (!force_quit){ process_packets(); } } } } /* 中断服务例程(ISR),每当有新的分组到达时触发*/ void pkt_burst_handler(__attribute__((unused)) struct rte_interrupt_action *action) { printf("Packet burst received on lcore %u.\n", rte_lcore_id()); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

唯独不开心

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值