天天看點

Ethtool工具源碼剖析

ethool是一個實用的工具,用來給系統管理者以大量的控制網絡接口的操作。可以用來控制接口參數,速度,媒體類型,雙工模式,DMA環設定,硬體校驗和,LAN喚醒操作等。本人經常用于來觀測實體鍊路層的連結狀态,用于判斷網線是否正常,不用去機房看網卡亮沒亮燈了。

            ethtool的版本通過如下指令進行檢視:

# ethtool --version

ethtool version 4.5

            其源碼位于何處呢?

源碼可以在

https://mirrors.edge.kernel.org/pub/software/network/ethtool/ 中下載下傳得到。

            編譯也很簡單:

執行./configure後,運作make指令直接進行編譯。

            相比之前的ifconfig和netstat工具要複雜更多,畢竟ethtool從至此的參數上來也更加龐大。

static const struct option {

        const char *opts;

        int want_device;

        int (*func)(struct cmd_context *);

        char *help;

        char *opthelp;

}

因為ethtool參數複雜龐大,是以單獨定義了結構體option。第一個是參數選項,第二個是bool值,第三個是回調函數,第四個核第五個是幫助的字元串。所有的處理函數都在option的結構體數組args[]中設定了,如:do_gdrv擷取驅動資訊 ,

do_gset 擷取網卡參數  ,do_sset設定網卡參數 等。

結構體cmd_context是控制結構體。

/* Context for sub-commands */

struct cmd_context {

        const char *devname;    /* net device name */

        int fd;                 /* socket suitable for ethtool ioctl */

        struct ifreq ifr;       /* ifreq suitable for ethtool ioctl */

        int argc;               /* number

of arguments to the sub-command */

        char **argp;            /* arguments to the sub-command */

};

從ethtool.c中main主函數開始,首先分析傳入參數。如果沒有參數,則調用exit_bad_args函數來輸出。

第一個參數要麼是裝置名字要麼是合法的選項,而不是一個以’-‘開頭的。

根據輸入的參數,會将func變量設定為結構體option中的回調函數。

最後調用設定過的func函數(例如do_gset函數),參數為cmd_context結構體,其中填充了相關參數(例如裝置名,套接字句柄等)。

            我們可以看到,程式主邏輯非常的清晰,主要是每個參數下其針對的處理函數才是根據需要分析的重點。

            例如參數-s為例,其選項結構為:

        { "-s|--change", 1, do_sset, "Change generic options",

          "             [ speed %d ]\n"

          "             [ duplex

half|full ]\n"

          "             [ port

tp|aui|bnc|mii|fibre ]\n"

          "             [ mdix

auto|on|off ]\n"

          "             [ autoneg on|off

]\n"

          "             [ advertise %x ]\n"

          "             [ phyad %d ]\n"

          "             [ xcvr

internal|external ]\n"

          "             [ wol

p|u|m|b|a|g|s|d... ]\n"

          "             [ sopass %x:%x:%x:%x:%x:%x ]\n"

          "             [ msglvl %d | msglvl type

on|off ... ]\n" },

可以看到其調用的函數為do_sset,該函數會對參數進行詳細的解析,最後确定使用者意圖後調用send_ioctl函數。當然會根據參數的差異,調用不同的參數。

例如會調用函數:send_ioctl(ctx, &ecmd);或者send_ioctl(ctx, &edata)等(send_ioctl調用ioctl系統調用,ioctl是裝置驅動程式中對裝置的I/O通道進行管理的函數,對裝置的一些特性進行控制,例如序列槽的傳輸波特率、馬達的轉速等等)。其中edata為ethtool_value結構體,ecmd為ethtool_command,還有ethtool_wolinfo。

這些結構體都定義在include/uapi/linux/ethtool.h檔案中。

現在網卡驅動程式都有對ethtool 的支援。ethtool 架構包含核心空間和使用者空間兩部分:使用者空間的部分負責将 ethtool 指令發送到核心,然後接收指令在核心中的執行結果。

核心空間的部分根據相應的指令字,通過

MDIO/MDC 讀寫 MII 寄存器,實作對網卡的管理,并把執行結果傳回使用者空間,如下圖所示。

Ethtool工具源碼剖析

            ethtool擔負着使用者空間和具體網絡裝置驅動之間的互動,包括查詢、設定網卡資訊。相關聲明在<b>include/linux/ethtool.h</b><b>檔案中,核心是</b><b>ethtool_ops</b><b>類型的結構。</b>

            對于和裝置一起工作的ethtool,必須放置一個指向ethtool_ops結構的指針在net_device結構中。

            這些底層工具本身都比較複雜,且都和核心互動,單篇材料不能詳述之,後續會根據細節進行分析。

            最後祝大家玩得開心。

繼續閱讀