Linux E1000网卡驱动分析
linux上网etho解决网卡驱动的问题

linux上网etho解决网卡驱动的问题注意:本文是在linux系统完全安装的条件下进行的。
有的朋友安装linux是定制安装,因此可能会出现某些必要的软件包没有的情况。
这就需要自己解决了。
不难的呵呵一查看网卡是否安装1 ifconfig -a 如果没有ethX 就很可能是网卡没有安装,至少可以断定网卡没有自动加载。
如果这时输入ifconfig eth0 xxx.xxx.xx.xx 系统会提示没有eth0 该设备。
2 可以用 dmesg | grep ethx 来查看系统能不能检查到该模块。
如果能会返回ATL2: eth0 NIC Link is up <100M full duplex>否则没反应3 用lsmod 查看开机时是否有加载如果有的,会有atl2 或eg3之类的4,查看网卡驱动安装的目录#uname -r 查看内核版本#cd lib/modules/'uname -r'/kernel/drives/net 网卡驱动安装在该目录下#ls显示相关的驱动,如果没有就要手动安装了二,安装驱动1 查看你的驱动类型。
我切换到2003系统查看网卡型号。
2 网上下载驱动。
我下载的地址如下:/downloads/downloadsView.aspx?Langid=3&PNid=4&PFid =4&Level=5&Conn=4&DownTypeID=3&GetDown=false&Dow nloads=true#RTL8110S-32/RTL8169S-32/RTL8110SB(L)/RTL8169SB(L)<br>RTL8110SC(L)/RTL8169SC(L)3 通过U盘拷贝到linux中。
1)#modprobe usb-storage 必须的命令好像这样才能读出U 盘2) # mount /dev/sdb? /mnt (?为几可以用fdisk -l查看一下,我的是sda)注意:有的U盘可能linux无法读出。
Linux下查看网卡驱动和版本信息

Linux下查看网卡驱动和版本信息查看网卡生产厂商和信号查看基本信息:lspci查看详细信息:lspci -vvv # 3个小写的v查看网卡信息:lspci | grep Ethernet查看网卡驱动查看网卡驱动信息:lspci -vvv # 找到网卡设备的详细信息,包括网卡驱动# lsmod 列出加载的所有驱动,包括网卡驱动查看网卡驱动版本查看模块信息:modifo<module name> # 其中包含version信息或# ethtool-i <device name>RHEL 6.3中的网卡驱动版本:# modinfo igbfilename: /lib/modules/2.6.32-279.el6.x86_64/kernel/drivers/net/igb/igb.ko version: 3.2.10-klicense: GPLdescription: Intel(R) Gigabit Ethernet Network Driver# modinfo e1000efilename: /lib/modules/2.6.32-279.el6.x86_64/kernel/drivers/net/e1000e/e1000e.ko version: 1.9.5-klicense: GPLdescription: Intel(R) PRO/1000 Network Driverauthor: Intel Corporation,<linux.nics@># modinfo e1000filename: /lib/modules/2.6.32-279.el6.x86_64/kernel/drivers/net/e1000/e1000.ko version: 8.0.35-NAPIlicense: GPLdescription: Intel(R) PRO/1000 Network Driver# modinfo ixgbefilename: /lib/modules/2.6.32-279.el6.x86_64/kernel/drivers/net/ixgbe/ixgbe.ko version: 3.6.7-klicense: GPLdescription: Intel(R) 10 Gigabit PCI Express NetworkDriver# modinfo r8169filename: /lib/modules/2.6.32-279.el6.x86_64/kernel/drivers/net/r8169.ko version: 2.3LK-NAPIlicense: GPLdescription: RealTek RTL-8169 Gigabit Ethernet driver查看网络接口队列数查看网卡接口的中断信息:#cat /proc/interrupts | grep eth0或# ethtool-S eth0查看网卡驱动源码的版本号解压Intel网卡驱动源码,打开解压缩目录下的*.spec文件查看驱动的版本。
Linux网卡驱动架构分析

Linux⽹卡驱动架构分析⼀、⽹卡驱动架构 由上到下层次依次为:应⽤程序→系统调⽤接⼝→协议⽆关接⼝→⽹络协议栈→设备⽆关接⼝→设备驱动。
⼆、重要数据结构 1、Linux内核中每⼀个⽹卡由⼀个net_device结构来描述。
2、⽹卡操作函数集:net_device_ops,这个数据结构是上⾯net_device的⼀个成员。
3、⽹络数据包:sk_buff。
三、⽹卡驱动代码分析 所⽤⽂件为cs89x0.c,主要分析三个部分:⽹卡初始化、发送数据、接收数据。
㈠⽹卡初始化 ⽹卡驱动初始化主要在函数init_module中完成,部分代码如下:int __init init_module(void){ struct net_device *dev = alloc_etherdev(sizeof(struct net_local)); struct net_local *lp; int ret = 0; ... dev->irq = irq; dev->base_addr = io; ... ret = cs89x0_probe1(dev, io, 1); ...} cs89x0_probe1函数部分代码如下:static int __init cs89x0_probe1(struct net_device *dev, int ioaddr, int modular){ struct net_local *lp = netdev_priv(dev); static unsigned version_printed; int i; int tmp; unsigned rev_type = 0; int eeprom_buff[CHKSUM_LEN]; int retval; ... writeword(ioaddr, ADD_PORT, PP_ChipID); tmp = readword(ioaddr, DATA_PORT); //对硬件的初始化 ... for (i = 0; i < ETH_ALEN/2; i++) //初始化MAC地址 { dev->dev_addr[i*2] = eeprom_buff[i]; dev->dev_addr[i*2+1] = eeprom_buff[i] >> 8; } ... dev->netdev_ops = &net_ops; //初始化netdev_ops ... retval = register_netdev(dev); //注册⽹卡驱动} 由代码可以看出 1、定义并分配net_device结构,使⽤alloc_etherdev函数。
E1000零拷贝网卡驱动

开发背景
网络入侵检测、病毒监控、防火墙、网络实时 控制等应用需要实时高速获取和分析网络数据 包,转发包 高速网络的带宽增长迅速:
–
1Gb以太网- 10Gb以太网
现有的计算机操作系统限制导致收包能力跟不 上网卡本身的处理能力。
目标用户群
Linux网络流量监控软件开发人员 IDS软件开发人员 防火墙、路由器、NAT等的开发人员 需要建立自己IP栈的开发人员 包转发功能 需要高速采集网络包的开发人员
典型应用网络拓扑
典型应用
XX公司局域网监控系统产品 XX公司汇聚层Internet控制系统解决方案 XX公司VOIP监控与封堵干扰系统 XX公司网桥产品
谢谢!
DMA网卡驱动的关键技术
将大容量的用户内存空间映射到网卡DMA空 间。 修改网卡驱动接口,直接使用用户空间缓冲。 增加系统调用,唤醒应用程序接收和处理数据 包。 使用模块技术,不需要重新编译核心。
DMA网卡驱动的特点
可以同时支持多张网卡,同时兼容本来的驱动 网卡DMA通道直接使用用户进程缓冲区,不 经过IP协议栈处理 应用不需要调用以前的系统调用,节约syscall 时间 提供无包时阻塞功能,避免死循环 提供长度、包类型的过滤功能
基于直接DMA内存访问 的 高速网卡驱动
MSN:liangvy@ MAIL:liangvy@
产品名称:DMA 网卡驱动
功能:高性能发送/接收网卡以太网包。 支持平台:linux 2.4 支持硬件:Intel 8254X e1000千兆系列[收发] 卡等
DMA网卡驱动的发包处理过程
分配用户内存,填写包体 设置包标志为发送 调用发送函数,放入发送队列 减少拷贝次数,提高性能
Linux下网络驱动程序分析

收稿日期:2001208202(修改稿) 作者简介:郭学理(1946-),男,河南遂平人,教授,主要研究方向:计算机网络、分布并行处理; 潘松(1978-),男,湖南常德人,硕士研究生,主要研究方向:计算机网络通信; 韦智(1977-),男,广西柳州人,硕士研究生,主要研究方向:计算机网络通信.文章编号:1001-9081(2001)11-0023-02Linux 下网络驱动程序分析郭学理,潘 松,韦 智(武汉大学软件工程国家重点实验室,湖北武汉430072)摘 要:讨论了Linux 网络驱动程序的基本原理以及它的基本实现过程,并对它的两种驱动方式———模块驱动和内核启动驱动进行了比较。
关键词:Linux ;内核;网络驱动程序;模块驱动;内核驱动中图分类号:TP393;TP316.89 文献标识码:AANALYSIS OF LINUX BASED ON NETWORK DRIVERG UO Xue 2li ,PAN S ong ,WEI Zhi(State K ey Laboratory o f So ftware Engineering ,Wuhan Univer sity ,Wuhan Hubei 430072,China )Abstract :In this article ,we first discuss the basic principles and the basic implementation procedure of netw ork driver ,and then present a detailed comparion of its tw o driven m odes ,the m odule -driven m ode and the kernel -driven m ode.K ey w ords :Linux ;kernel ;netw ork driver ;m odule -driven ;kernel -driven Linux 是基于PC 机且与Unix 兼容的一种操作系统,它是由世界上许多优秀的程序员共同开发设计实现的一种免费发行软件。
linux查看网卡驱动信息

linux查看⽹卡驱动信息⽅法⼀:1:ethtool -i ethx如:linux:/mnt # ethtool -i eth1driver: e1000eversion: 1.0.2-k2firmware-version: 1.9-0bus-info: 0000:0b:00.0linux:/mnt # ethtool -i eth16driver: igbversion: 2.1.0-k2firmware-version: 1.4-1bus-info: 0000:0a:00.0linux:/mnt #2:使⽤ modinfo igb 查看驱动信息linux:~ # modinfo igbfilename: /lib/modules/2.6.32.12-0.7-default/kernel/drivers/net/igb/igb.koversion: 5.2.5license: GPLdescription: Intel(R) Gigabit Ethernet Network Driverauthor: Intel Corporation, <e1000-devel@>srcversion: 0E80ABCD0117D822FE8B271alias: pci:v00008086d000010D6sv*sd*bc*sc*i*alias: pci:v00008086d000010A9sv*sd*bc*sc*i*alias: pci:v00008086d000010A7sv*sd*bc*sc*i*alias: pci:v00008086d000010E8sv*sd*bc*sc*i*alias: pci:v00008086d00001526sv*sd*bc*sc*i*alias: pci:v00008086d0000150Dsv*sd*bc*sc*i*alias: pci:v00008086d000010E7sv*sd*bc*sc*i*alias: pci:v00008086d000010E6sv*sd*bc*sc*i*alias: pci:v00008086d00001518sv*sd*bc*sc*i*alias: pci:v00008086d0000150Asv*sd*bc*sc*i*alias: pci:v00008086d000010C9sv*sd*bc*sc*i*alias: pci:v00008086d00000440sv*sd*bc*sc*i*alias: pci:v00008086d0000043Csv*sd*bc*sc*i*alias: pci:v00008086d0000043Asv*sd*bc*sc*i*alias: pci:v00008086d00000438sv*sd*bc*sc*i*alias: pci:v00008086d00001516sv*sd*bc*sc*i*alias: pci:v00008086d00001511sv*sd*bc*sc*i*alias: pci:v00008086d00001510sv*sd*bc*sc*i*alias: pci:v00008086d00001527sv*sd*bc*sc*i*alias: pci:v00008086d0000150Fsv*sd*bc*sc*i*alias: pci:v00008086d0000150Esv*sd*bc*sc*i*alias: pci:v00008086d00001524sv*sd*bc*sc*i*alias: pci:v00008086d00001523sv*sd*bc*sc*i*alias: pci:v00008086d00001522sv*sd*bc*sc*i*alias: pci:v00008086d00001521sv*sd*bc*sc*i*alias: pci:v00008086d00001539sv*sd*bc*sc*i*alias: pci:v00008086d0000157Csv*sd*bc*sc*i*alias: pci:v00008086d0000157Bsv*sd*bc*sc*i*alias: pci:v00008086d00001538sv*sd*bc*sc*i*alias: pci:v00008086d00001537sv*sd*bc*sc*i*alias: pci:v00008086d00001536sv*sd*bc*sc*i*alias: pci:v00008086d00001533sv*sd*bc*sc*i*alias: pci:v00008086d00001F45sv*sd*bc*sc*i*alias: pci:v00008086d00001F41sv*sd*bc*sc*i*alias: pci:v00008086d00001F40sv*sd*bc*sc*i*depends: hwmon,dcasupported: externalvermagic: 2.6.32.12-0.7-default SMP mod_unload modversionsparm: InterruptThrottleRate:Maximum interrupts per second, per vector, (max 100000), default 3=adaptive (array of int) parm: IntMode:Change Interrupt Mode (0=Legacy, 1=MSI, 2=MSI-X), default 2 (array of int)parm: Node:set the starting node to allocate memory on, default -1 (array of int)parm: LLIPort:Low Latency Interrupt TCP Port (0-65535), default 0=off (array of int)parm: LLIPush:Low Latency Interrupt on TCP Push flag (0,1), default 0=off (array of int)parm: LLISize:Low Latency Interrupt on Packet Size (0-1500), default 0=off (array of int)parm: RSS:Number of Receive-Side Scaling Descriptor Queues (0-8), default 1, 0=number of cpus (array of int)parm: VMDQ:Number of Virtual Machine Device Queues: 0-1 = disable, 2-8 enable, default 0 (array of int)parm: max_vfs:Number of Virtual Functions: 0 = disable, 1-7 enable, default 0 (array of int)parm: MDD:Malicious Driver Detection (0/1), default 1 = enabled. Only available when max_vfs is greater than 0 (array of int) parm: QueuePairs:Enable Tx/Rx queue pairs for interrupt handling (0,1), default 1=on (array of int)parm: EEE:Enable/disable on parts that support the feature (array of int)parm: DMAC:Disable or set latency for DMA Coalescing ((0=off, 1000-10000(msec), 250, 500 (usec)) (array of int)parm: LRO:Large Receive Offload (0,1), default 0=off (array of int)parm: enable_debug:Set to 1 to enable debug tracing into the syslog (uint)parm: debug:Debug level (0=none, ..., 16=all) (int)linux:~ #⽅法⼆:1:dmesg | grep ethx如:linux:~ # dmesg | grep eth17[ 30.351872] igb 0000:0a:00.1: eth17: (PCIe:2.5Gb/s:Width x4) 00:0b:ab:52:fb:b3[ 30.351952] igb 0000:0a:00.1: eth17: PBA No: ffffff-0ff[429171.548763] device eth17 entered promiscuous mode[429173.116530] igb: eth17 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: RX [429173.118867] ADDRCONF(NETDEV_UP): eth17: link is not ready[429173.121176] ADDRCONF(NETDEV_CHANGE): eth17: link becomes ready [429183.236266] eth17: no IPv6 routers present[1641503.272376] igb 0000:0a:00.1: eth17: (PCIe:2.5Gb/s:Width x4) 00:0b:ab:52:fb:b3 [1641503.272460] igb 0000:0a:00.1: eth17: PBA No: ffffff-0ff[1641598.356110] device eth17 entered promiscuous mode[1641598.369229] igb: eth17 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: RX [1641598.372636] ADDRCONF(NETDEV_UP): eth17: link is not ready [1641598.374978] ADDRCONF(NETDEV_CHANGE): eth17: link becomes ready [1641608.564181] eth17: no IPv6 routers present[1701779.787471] igb 0000:0a:00.1: eth17: (PCIe:2.5GT/s:Width x4)[1701779.787473] igb 0000:0a:00.1: eth17: MAC: 00:0b:ab:52:fb:b3[1701779.787555] igb 0000:0a:00.1: eth17: PBA No: FFFFFF-0FF[1702124.805650] device eth17 entered promiscuous mode[1702141.839131] ADDRCONF(NETDEV_UP): eth17: link is not ready [1702144.057474] igb: eth17 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: None [1702144.059425] ADDRCONF(NETDEV_CHANGE): eth17: link becomes ready [1702154.705520] eth17: no IPv6 routers present[1712008.630151] igb 0000:0a:00.1: eth17: (PCIe:2.5GT/s:Width x4)[1712008.630153] igb 0000:0a:00.1: eth17: MAC: 00:0b:ab:52:fb:b3[1712008.630235] igb 0000:0a:00.1: eth17: PBA No: FFFFFF-0FF[1712100.136186] device eth17 entered promiscuous mode[1712101.873823] ADDRCONF(NETDEV_UP): eth17: link is not ready [1712104.159209] igb: eth17 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: None [1712104.161548] ADDRCONF(NETDEV_CHANGE): eth17: link becomes ready [1712114.854722] eth17: no IPv6 routers presentlinux:~ #2:使⽤ modinfo igb 查看驱动信息(结果同⽅法⼀中的)。
netmap-performance

[<ffffffff81a3f6ae>] x86_64_start_kernel+0xfd/0x101
handlers:
[<ffffffffa08441c0>] e1000_msix_other [e1000e]
Disabling IRQ #48
从上述信息,分析出,可能和 DMA 有关,查看内核编译选项: # cat .config | grep INTEL_IOMMU CONFIG_INTEL_IOMMU=y
[<ffffffff81659a6a>] common_interrupt+0x6a/0x6a
<EOI> [<ffffffff814fb70b>] ? cpuidle_enter_state+0x5b/0xe0
[<ffffffff814fb707>] ? cpuidle_enter_state+0x57/0xe0
[ 3.568464] {1}[Hardware Error]: slot: 0
[ 3.569046] {1}[Hardware Error]: secondary_bus: 0x00
[ 3.569652] {1}[Hardware Error]: vendor_id: 0x8086, device_id: 0x10d3
S1200BT.86B.02.00.0035.030220120927 03/02/2012
ffff8807053f5e84 ffff88081e803e28 ffffffff81653b0a ffff88081e803e58
ffffffff810dba9d 0000000000013080 ffff8807053f5e00 0000000000000030
21_SUSELinux网卡配置实例解析

#此时看网卡会闪灯旳
[root@sugon ~]# ethtool -p eth1
就是eth1,按ctrl+c结束测试。
#此时看网卡会闪灯旳
……
其他以此类推即可,假如网卡没有指示灯旳,只能经过一块一块网上分 别插上网线后,使用 ethtool命令查看当然网卡旳连接状态,详细查看 措施,参阅第五条。
#生成ifcfg-eth0:0文件后,修改ifcfg-eth0:0内容如下:注意IP不能与 ifcfg-eth0配置文件中旳IP地址相同,不能有网关信息,最佳不要有 MAC地址信息。
在系统中查看网卡是否被辨认
[root@sugon ~]# lspci |grep Ethernet #此命令能够查 出网卡是否被辨认及型号
02:00.0 Ethernet controller: Intel Corporation 82574L Gigabit Network Connection 03:00.0 Ethernet controller: Intel Corporation 82574L Gigabit Network Connection
#使用lspci不加参数能够查看目前系统旳全部硬件设备
查看网卡目前旳驱动程序版本
[root@sugon ~]# ethtool -i eth0
driver: e1000e
#Intel 82574l相应驱动模块为e1000e
firmware-version: 1.8-0 bus-info: 0000:03:00.0
网卡绑定环节1
下列以将eth0与eth1按mode=6模式进行绑定旳例子; 修改eth0与eth1配置文件内容如下(假如需要绑定更多网卡,则即更多 旳网卡配置文件按下面两块网卡旳配置文件格式进行修改即可): [root@sugon~]# cd /etc/sysconfig/network –scripts
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Linux-千兆网卡驱动实现机制浅析作者: Minit, 出处:博客,责任编辑: 罗丽艳,2009-03-29 00:001.引言本分析主要针对e1000网卡,驱动源码为7.3.20-k2。
本文的目的不是为了讲述如何编写驱动程序,主要是分析网卡驱动内部的实现机制。
通过此分析,希望可以理解驱动程序中的各个部分的关系,对网卡发送和接收数据包有直观的了解,同时也希望对设计网卡驱动程序有帮助。
由于网卡驱动程序与硬件和操作系统都有很紧密的联系,故要把某些问题完全弄清楚,需要很多的经验与相关知识,介于自身的水平有限,且自身经验较少,故肯定存在很多问题,希望本文的读者发现了问题不吝与作者联系。
2.网卡驱动的体系结构网卡作为一个PCI设备,其必须遵守相应的PCI规范,即必须为网卡定义相应的标识号,每个PCI外设由一个总线编号、一个设备编号及一个功能编号来标识。
网卡驱动程序则需要定义相应的pci_device_id结构来表示其支持的PCI外设的标识,通过在驱动程序的pci_device_id中查找设备标识号,将驱动程序与设备联系起来。
网卡作为PCI设备,其包括两类空间,一种是配置空间,CPU不能直接访问,访问这个空间,需要借助BIOS功能;另一种是普通的控制寄存器空间,这部分经过映射后,CPU可以直接访问控制。
在硬件加电初始化时,BIOS统一检查所有的PCI设备,并为每个设备分配一个物理地址,该地址通过BIOS获得并写到设备的配置空间内,驱动程序就可以将网卡的普通控制寄存器映射到一段内存空间内,CPU通过访问映射后的虚拟地址来操控网卡的寄存器。
当操作系统初始化时,其为每个PCI设备分配一个pci_dev结构,并将前面分配的物理地址写到pci_dev的resource字段中。
在网卡驱动程序中则可以通过读取pci_dev中的resource字段获得网卡的寄存器配置空间地址,其由函数pci_resource_start()和pci_resource_end()获得该空间的起始位置,通过ioremap()将该段位置映射到主存中,以便CPU访问控制网卡的I/O和内存空间。
如重启网卡设备,则是通过向映射后的网卡的相应寄存器写入命令实现,其通过映射后的首地址及相应的寄存器偏移量找到该寄存器的位置,然后通过函数writeb()写该寄存器。
有关相关寄存器对应的偏移量,一般是通过网卡的相关的datasheet获得。
如果要获取网卡的MAC地址,则一般通过函数readb()读取首地址开始的前六位内容即可得到。
通过pci_read_config_和pci_write_config_系列函数可以读写网卡的配置空间,如开启网卡设备就是将网卡配置空间的command域置1,从而设备就可以将寄存器映射到内存。
如通过函数pci_read_config_byte(pci_devpdev,PCI_INTERRUPT_LINE,&irq)获得设备所分配的中断号并保存在irq中。
pci_read_config_和pci_write_config_系列函数实际上是调用pci_bus_read_config_和pci_bus_write_config_系列函数实现的,这些函数实际操作网卡对应的PCI总线结构。
有关PCI寄存器的配置空间可参考《Linux Device Driver 3rd》或《PCI Bus Demystified》。
网卡作为一个规范的PCI设备,其对应的结构体pci_dev代表了网卡设备,体现了作为PCI设备所应有的规范。
网卡的网络传输性质,实际是通过另一结构体net_device来体现的,该结构体的初始化由网卡驱动程序实现。
内核中对网卡的操作,其实质就是对net_device结构的操作,pci_dev和net_device都表示网卡设备,只是体现的角度不一样。
net_device是对特定适配器的抽象,其为上层协议提供了统一的接口,网卡驱动则基于特定适配器实现了这一抽象。
PCI设备的驱动程序由pci_driver结构体表示,故网卡驱动应该是该结构体的一个实例,在该结构体中应该要定义实现与网卡相关的参数以及相应的操作。
网卡驱动实际操作的特定适配器,是由与硬件相关的adapter所表示的结构体,adapter体现了大部分与硬件相关的属性,网卡驱动除了直接对pci_dev结构操作外,其他对网卡设备的操作基本是对adapter结构体的操作。
adapter体现了net_device与pci_dev的关联,也实现了网络设备的适配器无关性。
与网卡设备pci_dev的通信是通过adapter来实现的,而这个实现则是网卡驱动所要完成的任务。
下面图2-1描述了三个重要数据结构间的关系,pci_dev结构体现了网卡的配置空间和I/O与内存区域,net_device结构则向内核提供了操作网卡的抽象接口,其参数值可按照功能分为5个部分。
e1000_adapter结构除了体现相应的硬件无关性外,还管理了发送与接收数据包的相应缓冲空间,网卡的物理地址空间映射后的虚拟地址也在此结构中保存。
e1000_adapter结构中的e1000_hw结构主要保存网卡的硬件参数,其值就是通过读取pci_dev的内容获取而来的。
以上的数据结构在网卡工作时起着最核心的作用,同时也是编写驱动程序必须操作的结构体。
图2-1 网卡驱动程序的主要数据结构3. 网卡设备的注册与初始化网卡设备的注册与初始化是在其相关的驱动程序的e1000_probe()函数中实现的,有关设备如何与该驱动相关联,以及如何调用到e1000_probe()的,在此不作介绍。
在函数e1000_probe()中首先调用函数pci_enable_device()启用设备,然后声明了DMA空间,接着调用函数alloc_etherdev()生成结构体net_device,该结构体就表示了网卡设备,对net_device的参数进行了初始化后,调用register_netdev()注册该设备。
以上仅是对设备的注册,设备的初始化主要包括对两个结构体的赋值,一个是net_device,另一个则是e1000_adapter。
对e1000_adapter的初始化包括对其中的e1000_hw结构的初始化,其调用函数e1000_sw_init()实现。
在对e1000_hw的初始化过程中使用了ioremap()实现了网卡硬件地址与内存虚拟地址之间的映射。
对网卡设备进行撤销则调用函数free_netdev()实现。
有关网卡设备注册与初始化的更详细的过程可以参考《Understanding Linux Network Internals》。
4. 网卡设备的启动与关闭网卡设备启动时首先调用函数e1000_open(),在该函数中调用e1000_request_irq()申请中断号及其相应的中断处理程序e1000_intr(),其实际是调用request_irq()函数来实现的。
在函数e1000_open()中调用e1000_setup_all_tx_resources()根据发送队列数建立发送缓冲区,每个缓冲区的建立由函数e1000_setup_tx_resources()实现,在e1000_setup_tx_resources()中,主要是对描述发送缓冲区的结构体e1000_tx_ring的初始化,其将DMA缓冲区与网卡所映射的虚拟地址空间联系起来,使用函数pci_alloc_consistent()实现一致性映射。
而虚拟地址空间与网卡的物理地址相对应,故而这三种空间就对应了起来,DMA也就可以在此基础上实现了,当数据包内容被映射到DMA缓冲区后,其将完全由设备操控。
DMA的缓冲区的初始化在驱动程序的e1000_probe()函数中实现。
e1000_open()函数会调用e1000_up()对网卡的一些相关的软硬件参数与空间进行配置,如硬件寄存器的读写,数据包接收与发送空间的处理函数的初始化等。
发送缓冲空间的初始化结构及相互间的关系如图4-1所示。
接收缓冲区的初始化与上述类似,由e1000_setup_all_rx_resources()调用e1000_setup_rx_resources()对结构体e1000_rx_ring进行初始化。
接收缓冲空间的结构如图4-2所示。
图4-1 发送缓冲区的结构图图4-2 接收缓冲区的结构图网卡的关闭由函数e1000_close()实现,其会首先关闭中断,然后释放中断号,并且会释放网卡申请的相应的空间。
5. 发送与接收数据包数据包的发送:图5-1 发送数据包的结构图及相互关系根据发送队列数num_tx_queues建立相应的发送缓冲区结构e1000_tx_ring,在该结构中有描述该区域的指向e1000_tx_desc 结构的desc,该缓冲区指向的dma总线地址,用于接收硬件传送来的用e1000_buffer结构描述的缓冲块数组buffer_info[],另外的几个参数则主要用于描述这些缓冲块,其中count表示缓冲块的个数,next_to_use和next_to_clean主要描述缓冲块的使用状态,如已经接收接收了数据的位置及准备接收的位置,当有新的数据包要发送时,首先由上层协议调用e1000_xmit_frame(),在该函数中接着调用e1000_tx_queue()根据相应的参数找到缓冲块存放,缓冲块的初始化则由函数e1000_tx_map()实现。
buffer_info指向的环形缓冲块区域主要用来接收总线地址映射来的数据包,所有的缓冲块用next_to_match连接成一个环,每个缓冲块用结构体e1000_buffer表示,在该结构中,skb存放数据包的内容,dma表示该数据包所在的总线地址。
此处使用函数pci_map_single()进行流式映射,的映射方向为PCI_DMA_TODEVICE,控制总线会把虚拟地址空间所指内容映射到总线地址,然后将该内容由网卡传送出去。
发送数据包的相关结构图及相互关系如图5-1所示。
e1000_tx_ring结构中的desc所指向的buffer_addr记录了每次发送的缓冲块所映射的总线地址,即buffer_addr记录的是总线地址。
而desc本是一个虚拟地址,该虚拟地址是通过pci_alloc_consistent()映射的发送缓冲区的地址,其与DMA缓冲区中的一段总线地址相对应,该总线地址由e1000_tx_ring结构中的dma成员保存,这种映射关系在对开启网卡时就实现了,其与在发送数据包时映射的总线地址有区别,后者是在发送时动态进行的。
数据包的接收图5-2 接收数据包的结构图及相互关系根据接收队列数num_rx_queues建立相应的接收缓冲区结构e1000_rx_ring,在该结构中有描述该区域的指向e1000_rx_desc结构的desc,该缓冲区指向的dma总线地址,用于接收硬件传送来的用e1000_buffer结构描述的缓冲块数组buffer_info[],另外的几个参数则主要用于描述这些缓冲块,其中count表示缓冲块的个数,next_to_use和next_to_clean主要描述缓冲块的使用状态,如已经接收接收了数据的位置及准备接收的位置,当有新的数据包要到来时,则根据这两个参数找到相应的区域存放。