Linux
分类: LINUX
2014-12-04 10:24:12
数据链路层 MAC 是 Media Access Control 的缩写,即媒体访问控制子层协议。该协议位于 OSI 七层协议中数据链路层的下半部分,主要负责控制与连接物理层的物理介质。在发送数据的时候,MAC 协议可以事先判断是否可以发送数据,如果可以发送将给数据加上一些控制信息,最终将数据以及控制信息以规定的格式发送到物理层;在接收数据的时候,MAC 协议首先判断输入的信息并是否发生传输错误,如果没有错误,则去掉控制信息发送至 LLC 层。以太网 MAC 由 IEEE-802.3 以太网标准定义。
物理层 PHY 是物理接口收发器,它实现物理层。包括 MII/GMII(介质独立接口)子层、PCS(物理编码子层)、PMA(物理介质附加)子层、 PMD(物理介质相关)子层、MDI 子层。
MII 即媒体独立接口 , “媒体独立”表明在不对 MAC 硬件重新设计或替换的情况下,任何类型的 PHY 设备都可以正常工作。包括分别用于发送器和接收器的两条独立信道。每条信道都有自己的数据、时钟和控制信号。MII 数据接口总共需要 16 个信号,包括 TX_ER,TXD<3:0>,TX_EN,TX_CLK,COL,RXD<3:0>,RX_EX,RX_CLK,CRS,RX_DV 等。
RMII (Reduced Media Independant Interface ) 是简化的 MII 接口 ,在数据的收发上它比 MII 接口少了一倍的信号线,所以它一般要求是 50 兆的总线时钟 。RMII 一般用在多端口的交换机,它不是每个端口安排收、发两个时钟,而是所有的数据端口公用一个时钟用于所有端口的收发 ,这里就节省了不少的端口数目。RMII 的一个端口要求 7 个数据线 ,比 MII 少了一倍,所以交换机能够接入多一倍数据的端口。和 MII 一样,RMII 支持 10 兆和 100 兆的总线接口速度 。
GMII(Gigabit MII) 是千兆网的 MII 接口,这个也有相应的 RGMII 接口,表示简化了的 GMII 接口。GMII 采用 8 位接口数据,工作时钟 125MHz,因此传输速率可达 1000Mbps 。同时兼容 MII 所规定的 10/100 Mbps 工作方式。
MII 管理接口是个双信号接口,一个是时钟信号 MDC,另一个是数据信号 MDIO。通过管理接口,上层能监视和控制 PHY 的寄存器。PHY 里面的部分寄存器是 IEEE 定义的,这样 PHY 把自己的目前的状态反映到寄存器里面,MAC 通过管理接口不断的读取 PHY 的状态寄存器以得知目前 PHY 的状态,例如连接速度,双工的能力等。当然也可以通过管理接口设置 PHY 的寄存器达到控制的目的,例如流控的打开关闭,自协商模式还是强制模式等,这也是 ethtool 的工作原理。
MDIO/MDC,即 PHY 管理接口串行通信总线,该总线由 IEEE 通过以太网标准 IEEE 802.3 的若干条款加以定义。MDIO 是一种简单的双线串行接口,将管理器件 ( 如 MAC 控制器、微处理器 ) 与具备管理功能的收发器 ( 如多端口吉比特以太网收发器或 10GbE XAUI 收发器 ) 相连接,从而控制收发器并从收发器收集状态信息。可收集的信息包括链接状态、传输速度与选择、断电、低功率休眠状态、TX/RX 模式选择、自动协商控制、环回模式控制等。除了拥有 IEEE 要求的功能之外,收发器厂商还可添加更多的信息收集功能。
MDC 则是管理数据的时钟输入,最高速率可达 8.3MHz。MDIO 是管理数据的输入输出双向接口,数据是与 MDC 时钟同步的。MDIO 的工作流程为:
MDIO 接口在没有传输数据的空闲状态(IDLE)数据线 MDIO 处于高阻态。
MDIO 出现一个 2bit 的开始标识码 (01) 一个读 / 写操作开始。
MDIO 出现一个 2bit 数据来标识是读操作 (10) 还是写操作 (01)。
MDIO 出现一个 5bit 数据标识 PHY 的地址。
MDIO 出现一个 5bitPHY 寄存器地址。
MDIO 需要 2 个时钟的访问时间。
MDIO 串行读出 / 写入 16bit 的寄存器数据。
MDIO 恢复成 IDLE 状态,同时 MDIO 进入高阻状态。
注:以上内容部分摘选自互联网。
目前几乎所有的网卡驱动程序都有对 ethtool 的支持,其框架如图 2 所示,ethtool 框架包含内核空间和用户空间两部分:用户空间的部分负责将 ethtool 命令发送到内核,并接收命令的执行结果;内核空间的部分根据相应的命令字,通过 MDIO/MDC 读写 MII 寄存器,实现对网卡的管理,并把执行结果传回用户空间。由于 Linux 网络驱动程序是一个复杂而庞大的体系,这里只介绍驱动程序中对 MII 寄存器的定义,对 MDIO/MDC 的支持以及驱动程序中实现如何实现 ethtool 功能部分。
图 2.ethtool 在 Linux 中的实现框架
IEEE 802.3 规定的 MII 寄存器
关于 MII/GMII 接口 PHY 寄存器的定义在 802.3 的 22.2.4 Management functions. 章节中,如该章节中的 Table 22 – 6 和 Table 22 – 7(即本文的图 3 和图 4,均出自 )所示,
图 3. IEEE802.3 定义的 MII 管理寄存器集可以看到寄存器分为基本集和扩展集,基本集的定义因 GMII 和 MII 而不同,对于 MII, 基本集包括寄存器 0 控制寄存器和 1 状态寄存器,而对于 GMII;基本集包括寄存器 0、1 和 15。控制寄存器 0 和状态寄存器 1 的定义如图 3 所示:
图 4. IEEE802.3 定义的寄存器 0 控制寄存器和 1 状态寄存器点击(此处)折叠或打开
通过 MDC/MDIO 读写 MII 寄存器的具体实现
在本文的前面部分介绍过 MDC/MDIO 的工作流程,网卡驱动程序中的 MDIO 读写函数 mdio_read 和 mdio_write,也就是清单 3 中的函数指针的具体实现是在各个网卡的驱动程序文件中完成的,都遵从 IEEE802.3 MDIO 的帧格式。典型的帧格式是第 22 条款中定义的格式:
图 5.IEEE802.3 条款 22 定义的 MDIO 帧格式在驱动程序中实现 ethtool 功能
在 kernel/include/linux/ethtool.h 定义了结构体 ethtool_ops,这个结构体的所有成员都是函数指针类型,定义了 ethtool 可以实现的功能,该结构体成员变量较多,在这里就不列出代码清单;同时,在结构体 net_device 中也有成员变量 ethtool_ops 如清单 2 所示,
清单 2,kernel/include/linux/NetDevice.h, net_device 中成员变量 ethtool_opsstruct net_device { ... const struct ethtool_ops *ethtool_ops; ... }
网卡驱动程序需要初始化 ethtool_ops 并且实现其定义的函数功能,从而实现对 ethtool 的支持,以 Dm9000.c 为例。
清单 3,kernel/drivers/net/Dm9000.c,DM9000 驱动程序对 ethtool 的支持static const struct ethtool_ops dm9000_ethtool_ops = { .get_drvinfo = dm9000_get_drvinfo, .get_settings= dm9000_get_settings, .set_settings = dm9000_set_settings, .get_msglevel = dm9000_get_msglevel, .set_msglevel = dm9000_set_msglevel, .nway_reset= dm9000_nway_reset, .get_link = dm9000_get_link, .get_eeprom_len = dm9000_get_eeprom_len, .get_eeprom = dm9000_get_eeprom, .set_eeprom= dm9000_set_eeprom, .get_rx_csum= dm9000_get_rx_csum, .set_rx_csum= dm9000_set_rx_csum, .get_tx_csum= ethtool_op_get_tx_csum, .set_tx_csum= dm9000_set_tx_csum, }; ... ndev->ethtool_ops = &dm9000_ethtool_ops; ...
清单 3 中的各个函数在 DM9000 的驱动程序中均有实现,比如如果需要查看当前网络的连接情况,可以通过 dm9000_get_link 获得,函数的具体实现如清单 4:
清单 4,dm9000_get_linkstatic u32 dm9000_get_link(struct net_device *dev) { board_info_t *dm = to_dm9000_board(dev); u32 ret; if (dm->flags & DM9000_PLATF_EXT_PHY) ret = mii_link_ok(&dm->mii); else ret = dm9000_read_locked(dm, DM9000_NSR) & NSR_LINKST ? 1 : 0; return ret; } kernel/drivers/net/Mii.c int mii_link_ok (struct mii_if_info *mii) { /* first, a dummy read, needed to latch some MII phys */ mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR); if (mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR) & BMSR_LSTATUS) return 1; return 0; }
可以看到最终的实现还是通过 MDIO/MDC 读取 PHY 寄存器得到。
除了管理网卡的命令,ethtool 还有还有其它扩展的功能,ethtool 的框架十分有利于新功能的扩展,开发人员可以在这个框架里加入自己想要的功能来实现对除了网卡管理的其它功能,事实上,现在的 ethtool 已经提供了一些其它的功能,比如用来实现网卡 Firmware 的刷写和更新,对网络驱动程序日志的控制等,这些新功能对于调试程序,修正错误是十分有利的。
清单 5, 部分 ethtool 的扩展功能:firmware 更新和修改日志级别ethtool -f|--flash DEVNAME FILENAME ethtool -s|--change DEVNAME msglvl %d
上一节主要介绍了 ethtool 实现的基础和方法,本节将主要介绍 ethtool 的一些用法,主要集中在 ethtool 在配置和管理网卡方面的用法。
了解 ethtool 用法最好的方法是查看 ethtool 的帮助信息“ethtool -h” 或者 “man ethtool”,由于帮助信息很多,这里就不一一列出了,将会举例一些实际的应用例子代替。
实例 1,利用 ethtool 来查看网卡接口 eth4 的信息
清单 6,查看网卡的接口信息root@IMMV2-DEV4:~# ethtool eth4 Settings for eth4: Supported ports: [ TP ] Supported link modes: 10baseT/Half 10baseT/Full 100baseT/Half 100baseT/Full 1000baseT/Full Supports auto-negotiation: Yes Advertised link modes: 10baseT/Half 10baseT/Full 100baseT/Half 100baseT/Full 1000baseT/Full Advertised auto-negotiation: Yes Speed: 100Mb/s Duplex: Full Port: Twisted Pair PHYAD: 1 Transceiver: internal Auto-negotiation: on Supports Wake-on: g Wake-on: g Link detected: yes
实例 2,关闭网卡的自动协商并且查看修改结果。
清单 7,关闭网卡的自动协商并且查看修改结果root@IMMV2-DEV4:~# ethtool -s eth4 autoneg off root@IMMV2-DEV4:~# ethtool eth4 Settings for eth4: Supported ports: [ TP ] Supported link modes: 10baseT/Half 10baseT/Full 100baseT/Half 100baseT/Full 1000baseT/Full Supports auto-negotiation: Yes Advertised link modes: Not reported Advertised auto-negotiation: No Speed: 100Mb/s Duplex: Full Port: Twisted Pair PHYAD: 1 Transceiver: internal Auto-negotiation: off Supports Wake-on: g Wake-on: g Link detected: yes
实例 3,关闭网卡的自动协商并且修改网卡的速率为 10Mb/s
清单 8,关闭网卡的自动协商并修改网卡速率为 10Mb/sroot@IMMV2-DEV4:~# ethtool -s eth4 autoneg off speed 10 root@IMMV2-DEV4:~# ethtool eth4 Settings for eth4: Supported ports: [ TP ] Supported link modes: 10baseT/Half 10baseT/Full 100baseT/Half 100baseT/Full 1000baseT/Full Supports auto-negotiation: Yes Advertised link modes: Not reported Advertised auto-negotiation: No Speed: 10Mb/s Duplex: Full Port: Twisted Pair PHYAD: 1 Transceiver: internal Auto-negotiation: off Supports Wake-on: g Wake-on: g Link detected: yes
ethtool 的其它功能可以根据其帮助信息规定的语法来实现,这里就不一一列举。
ethtool 是一个 Linux 下功能强大的网络管理工具,本文首先介绍了这个工具的实现原理和方法,重点介绍了 IEEE802.3.22 中的 MII 管理寄存器和 MDIO/MDC 标准以及 Linux 网络驱动程序中对 ethtool 的支持,然后实例说明了利用这个工具管理网卡的方法,最后介绍了在 ethtool 框架上扩展 SideBand 管理的实例,可以作为广大开发人员的一个参考。