首頁 > 軟體

ethtool 在 Linux 中的實現框架和應用

2020-06-16 17:50:54

Linux 的一個顯著特點就是其強大的網路功能,Linux 幾乎支援所有的網路協定,並在這些協定基礎上提供了豐富的應用。對 Linux 網路管理的重要性不言而喻,這些管理依賴於網路工具,比如最常用的 ifconfig,route,ip,ethtool 等,其中 ethtool 提供了強大的網絡卡及網絡卡驅動管理能力,其具體的實現框架和網路驅動程式及網路硬體關係緊密,容易修改和擴充套件,能夠為 Linux 網路開發人員和管理人員提供對網絡卡硬體,驅動程式和網路協定棧的設定,檢視以及及偵錯等功能。

Linux 網絡卡驅動程式對 ethtool 的支援和實現

從典型的乙太網控制器說起

網絡卡工作在 OSI 網路體系的最後兩層,物理層和資料鏈路層,物理層定義了資料傳送與接收所需要的電與光信號、線路狀態、時鐘基準、資料編碼和電路等,並向資料鏈路層裝置提供標準介面。物理層的晶片稱之為 PHY。資料鏈路層則提供定址機構、資料框的構建、資料差錯檢查、傳送控制、向網路層提供標準的資料介面等功能。乙太網卡中資料鏈路層的晶片稱之為 MAC 控制器。很多網絡卡的這兩個部分是做到一起的。他們之間的關係是 PCI 匯流排接 MAC 匯流排,MAC 接 PHY,PHY 接網線(當然也不是直接接上的,還有一個變壓裝置)。

一般地,一個典型的乙太網控制器的基本結構如圖 1 所示:

圖 1. 一個典型的符合 IEEE802.3 標準的的乙太網控制器結構圖

資料鏈路層 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 進入高阻狀態。

註:以上內容部分摘選自網際網路。

Linux 裝置驅動程式中對 ethtool 的支援

目前幾乎所有的網絡卡驅動程式都有對 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,均出自 http://standards.ieee.org/getieee802/download/802.3-2008_section2.pdf)所示,

圖 3. IEEE802.3 定義的 MII 管理暫存器集

可以看到暫存器分為基本集和擴充套件集,基本集的定義因 GMII 和 MII 而不同,對於 MII, 基本集包括暫存器 0 控制暫存器和 1 狀態暫存器,而對於 GMII;基本集包括暫存器 0、1 和 15。控制暫存器 0 和狀態暫存器 1 的定義如圖 3 所示:

圖 4. IEEE802.3 定義的暫存器 0 控制暫存器和 1 狀態暫存器

圖 4. IEEE802.3 定義的暫存器 0 控制暫存器和 1 狀態暫存器

對暫存器 0 和暫存器 1 的讀寫可以實現對網絡卡的管理,清單 1 列出了部分 PHY 管理暫存器以及控制暫存器和狀態暫存器的各個 bit 的定義。

清單 1,/kernel/drivers/net/Mii.h, 定義 PHY 管理暫存器
 #define MII_BMCR            0x00        /* Basic mode control register */ 
 #define MII_BMSR            0x01        /* Basic mode status register  */ 
 #define MII_PHYSID1         0x02        /* PHYS ID 1                   */ 
 #define MII_PHYSID2         0x03        /* PHYS ID 2                   */ 
 #define MII_ADVERTISE       0x04        /* Advertisement control reg   */ 
 #define MII_LPA             0x05        /* Link partner ability reg    */ 
 #define MII_EXPANSION       0x06        /* Expansion register          */ 
 #define MII_CTRL1000        0x09        /* 1000BASE-T control          */ 
 ... 

 /* Basic mode control register. */ 
 #define BMCR_RESV               0x003f  /* Unused...                   */ 
 #define BMCR_SPEED1000 		 0x0040  /* MSB of Speed (1000)         */ 
 #define BMCR_CTST               0x0080  /* Collision test              */ 
 #define BMCR_FULLDPLX           0x0100  /* Full duplex                 */ 
 #define BMCR_ANRESTART          0x0200  /* Auto negotiation restart    */ 
 #define BMCR_ISOLATE            0x0400  /* Disconnect DP83840 from MII */ 
 #define BMCR_PDOWN              0x0800  /* Powerdown the DP83840       */ 
 #define BMCR_ANENABLE           0x1000  /* Enable auto negotiation     */ 
 #define BMCR_SPEED100           0x2000  /* Select 100Mbps              */ 
 #define BMCR_LOOPBACK           0x4000  /* TXD loopback bits           */ 
 #define BMCR_RESET              0x8000  /* Reset the DP83840           */ 

 /* Basic mode status register. */ 
 #define BMSR_ERCAP              0x0001  /* Ext-reg capability          */ 
 #define BMSR_JCD                0x0002  /* Jabber detected             */ 
 #define BMSR_LSTATUS            0x0004  /* Link status                 */ 
 #define BMSR_ANEGCAPABLE        0x0008  /* Able to do auto-negotiation */ 
 #define BMSR_RFAULT             0x0010  /* Remote fault detected       */ 
 #define BMSR_ANEGCOMPLETE       0x0020  /* Auto-negotiation complete   */ 
 #define BMSR_RESV               0x00c0  /* Unused...                   */ 
 #define BMSR_ESTATEN 		 0x0100 	 /* Extended Status in R15 */ 
 #define BMSR_100FULL2 		 0x0200 	 /* Can do 100BASE-T2 HDX */ 
 #define BMSR_100HALF2 		 0x0400 	 /* Can do 100BASE-T2 FDX */ 
 #define BMSR_10HALF             0x0800  /* Can do 10mbps, half-duplex  */ 
 #define BMSR_10FULL             0x1000  /* Can do 10mbps, full-duplex  */ 
 #define BMSR_100HALF            0x2000  /* Can do 100mbps, half-duplex */ 
 #define BMSR_100FULL            0x4000  /* Can do 100mbps, full-duplex */ 
 #define BMSR_100BASE4           0x8000  /* Can do 100mbps, 4k packets  */

通過 MDC/MDIO 讀寫 MII 暫存器的具體實現

在本文的前面部分介紹過 MDC/MDIO 的工作流程,網絡卡驅動程式中的 MDIO 讀寫函數 mdio_read 和 mdio_write???也就是清單 3 中的函數指標的具體實現是在各個網絡卡的驅動程式檔案中完成的,都遵從 IEEE802.3 MDIO 的幀格式。典型的幀格式是第 22 條款中定義的格式:

圖 5.IEEE802.3 條款 22 定義的 MDIO 幀格式

長度(bit)說明
ST 2bits 01b
OP 2bits 操作碼,寫為 01b,讀為 10b
PHYADR 5bits PHY ID
REGADR 5bits 暫存器地址
TA 2 bits 狀態轉換域,讀操作為 X0b, 寫操作為 10b
DATA 16 bits 資料

在驅動程式中實現 ethtool 功能

在 kernel/include/linux/ethtool.h 定義了結構體 ethtool_ops,這個結構體的所有成員都是函數指標型別,定義了 ethtool 可以實現的功能,該結構體成員變數較多,在這裡就不列出程式碼清單;同時,在結構體 net_device 中也有成員變數 ethtool_ops 如清單 2 所示,

清單 2,kernel/include/linux/NetDevice.h, net_device 中成員變數 ethtool_ops
 struct 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_link
 static 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 的幫助資訊“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/s
 root@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

根據 NIC 的一些特性,可以擴充套件 ethtool 來完成對網絡卡特殊功能的支援,一個典型的擴充套件應用就是增加 ethtool 對 SideBand 的支援功能,有關 SideBand 的介紹可以參考 IBM developerWorks 《淺談 NCSI 及其在 Linux 上的實現

》。圖 6 是一個通過新增自定義的 cmd 和對應的實現函數來完成 SideBand 的 select_channel,enable_channel 及 disable_channel 等功能的框圖。以 select_channel 為例,可以通過如下的步驟來實現。

圖 6, 擴充套件 ethtool 的 sideband 管理功能

  1. ethtool 的在使用者空間和核心空間同時新增命令字 ETHTOOL_SELCHANNEL;
  2. 在 ethtool.ops 中新增與 ETHTOOL_SELCHANNEL 相對應的執行函數 ethtool_select_channel;
  3. 在 dev_ethtool 函數中實現 ethtool_select_channel() 功能,這個函數的功能是利用協定棧的包傳送介面向 NIC 的 mac 層傳送包裝後的 NCSI 命令協定包,並且接受相應的回應 , 類似的對於 ethtool_enable_channel(),ethtool_disable_channel 都可以按照相同的方法來擴充套件,可以看出 ethtool 框架的擴充套件性是很好的,有利於開發人員根據實際需要來量身客製化。

總結

ethtool 是一個 Linux 下功能強大的網路管理工具,本文首先介紹了這個工具的實現原理和方法,重點介紹了 IEEE802.3.22 中的 MII 管理暫存器和 MDIO/MDC 標準以及 Linux 網路驅動程式中對 ethtool 的支援,然後範例說明了利用這個工具管理網絡卡的方法,最後介紹了在 ethtool 框架上擴充套件 SideBand 管理的範例,可以作為廣大開發人員的一個參考。

本文永久更新連結地址http://www.linuxidc.com/Linux/2015-10/124530.htm


IT145.com E-mail:sddin#qq.com