一文了解Linux内核网络设备驱动

本文详细解析了Linux内核中网络设备驱动的工作原理,包括数据包从被网卡接收直至进入socket接收队列的流程,以及网络设备的初始化、启动、中断处理和NAPI机制。此外,还介绍了如何通过ethtool和sysfs监控网卡状态,为理解Linux网络设备驱动的底层运作提供了全面的指导。
摘要由CSDN通过智能技术生成

1. 接收数据包过程概述

介绍数据包收包过程,有助于我们了解Linux内核网络设备在数据收包过程中的位置,下面从宏观的角度介绍数据包从被网卡接收到进入 socket 接收队列的整个过程:

  • 加载网卡驱动,初始化
  • 数据包从外部网络进入网卡
  • 网卡(通过DMA)将包拷贝到内核内存中的ring buffer
  • 产生硬件中断,通知系统收到了一个包
  • 驱动调用 NAPI ,如果轮询(poll)还没有开始,就开始轮询
  • ksoftirqd软中断调用 NAPI 的poll函数从ring buffer收包(poll 函数是网卡驱动在初始化阶段注册的;每个cpu上都运行着一个ksoftirqd进程,在系统启动期间就注册了)
  • ring buffer里面对应的内存区域解除映射(unmapped)
  • 如果 packet steering 功能打开,或者网卡有多队列,网卡收到的数据包会被分发到多个cpu
  • 数据包从队列进入协议层
  • 协议层处理数据包
  • 数据包从协议层进入相应 socket 的接收队列

2. 网络设备初始化

下面以常见的Intel I350 网卡的驱动 ibg 为例介绍它的工作过程:

2.1 初始化

驱动会使用module_init向内核注册一个初始化函数,当驱动被加载时,内核会调用这个函数。在drivers/net/ethernet/intel/igb/igb_main.c中初始化函数(igb_init_module):

/**
 *  igb_init_module - Driver Registration Routine
 *
 *  igb_init_module is the first routine called when the driver is
 *  loaded. All it does is register with the PCI subsystem.
 **/
static int __init igb_init_module(void)
{
  int ret;
  pr_info("%s - version %s\n", igb_driver_string, igb_driver_version);
  pr_info("%s\n", igb_copyright);

  /* ... */

  ret = pci_register_driver(&igb_driver);
  return ret;
}

module_init(igb_init_module);

linux 4.20.11内核如下:

/**
 *  igb_init_module - Driver Registration Routine
 *
 *  igb_init_module is the first routine called when the driver is
 *  loaded. All it does is register with the PCI subsystem.
 **/
static int __init igb_init_module(void)
{
	int ret;

	pr_info("%s - version %s\n",
	       igb_driver_string, igb_driver_version);
	pr_info("%s\n", igb_copyright);

#ifdef CONFIG_IGB_DCA
	dca_register_notify(&dca_notifier);
#endif
	ret = pci_register_driver(&igb_driver);
	return ret;
}

module_init(igb_init_module);

初始化的大部分工作在pci_register_driver中完成。

2.2 PCI初始化

Intel I350 网卡是 PCI express 设备。PCI 设备通过PCI Configuration Space 里面的寄存器识别自己。

PCI express 总线是一种完全不同于过去PCI总线的一种全新总线规范,与PCI总线共享并行架构相比,PCI
Express总线是一种点对点串行连接的设备连接方式,点对点意味着每一个PCI
Express设备都拥有自己独立的数据连接,各个设备之间并发的数据传输互不影响,而对于过去PCI那种共享总线方式,PCI总线上只能有一个设备进行通信,一旦PCI总线上挂接的设备增多,每个设备的实际传输速率就会下降,性能得不到保证。PCI
Express以点对点的方式处理通信,每个设备在要求传输数据的时候各自建立自己的传输通道,对于其他设备这个通道是封闭的,这样的操作保证了通道的专有性,避免其他设备的干扰。

当设备驱动编译时,MODULE_DEVICE_TABLE 宏(定义在 include/module.h) 会导出一个 PCI 设备 ID 列表(a table of PCI device IDs),驱动据此识别它可以控制的设备,内核也会依据这个列表对不同设备加载相应驱动。

static DEFINE_PCI_DEVICE_TABLE(igb_pci_tbl) = {
  { PCI_VDEVICE(INTEL, E1000_DEV_ID_I354_BACKPLANE_1GBPS) },
  { PCI_VDEVICE(INTEL, E1000_DEV_ID_I354_SGMII) },
  { PCI_VDEVICE(INTEL, E1000_DEV_ID_I354_BACKPLANE_2_5GBPS) },
  { PCI_VDEVICE(INTEL, E1000_DEV_ID_I211_COPPER), board_82575 },
  { PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_COPPER), board_82575 },
  { PCI_VDEVICE(INTEL, 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值