操作狀態

1. 簡介

Linux 區分介面的管理狀態和操作狀態。管理狀態是“ip link set dev <dev> up 或 down”的結果,反映了管理員是否希望使用該裝置來傳輸流量。

但是,一個介面不僅僅因為管理員啟用了它就可以使用 - 乙太網需要插入交換機,並且根據站點的網路策略和配置,在使用者資料可以傳輸之前,需要執行 802.1X 身份驗證。操作狀態顯示介面傳輸此使用者資料的能力。

由於 802.1X,必須授予使用者空間影響操作狀態的可能性。為了適應這一點,操作狀態被分成兩個部分:兩個只能由驅動程式設定的標誌,以及一個與 RFC2863 相容的狀態,該狀態從這些標誌、策略派生而來,並且可以在某些規則下從使用者空間更改。

2. 從使用者空間查詢

可以透過 netlink 操作 RTM_GETLINK 查詢管理狀態和操作狀態。也可以訂閱 RTNLGRP_LINK 以在介面處於管理啟用狀態時接收更新通知。這對於從使用者空間進行設定非常重要。

這些值包含介面狀態

ifinfomsg::if_flags & IFF_UP

介面處於管理啟用狀態

ifinfomsg::if_flags & IFF_RUNNING

介面處於 RFC2863 操作狀態 UP 或 UNKNOWN。這是為了向後相容,路由守護程序,dhcp 客戶端可以使用此標誌來確定是否應該使用該介面。

ifinfomsg::if_flags & IFF_LOWER_UP

驅動程式已發出訊號 netif_carrier_on()

ifinfomsg::if_flags & IFF_DORMANT

驅動程式已發出訊號 netif_dormant_on()

TLV IFLA_OPERSTATE

包含介面的 RFC2863 狀態的數字表示

IF_OPER_UNKNOWN (0)

介面處於未知狀態,驅動程式和使用者空間都未設定操作狀態。必須考慮將該介面用於使用者資料,因為並非所有驅動程式都已實現設定操作狀態。

IF_OPER_NOTPRESENT (1)

當前核心未使用(不存在的介面通常會消失),只是一個數值佔位符。

IF_OPER_DOWN (2)

介面無法在 L1 上傳輸資料,例如,乙太網未插入或介面已停用 ADMIN。

IF_OPER_LOWERLAYERDOWN (3)

堆疊在 IF_OPER_DOWN 介面上的介面顯示此狀態(例如,VLAN)。

IF_OPER_TESTING (4)

介面處於測試模式,例如執行驅動程式自測或媒體(電纜)測試。在測試完成之前,它不能用於正常流量。

IF_OPER_DORMANT (5)

介面 L1 啟動,但正在等待外部事件,例如,等待協議建立。(802.1X)

IF_OPER_UP (6)

介面已啟動並可以用來操作。

此 TLV 也可以透過 sysfs 查詢。

TLV IFLA_LINKMODE

包含連結策略。 這是下面描述的使用者空間互動所需要的。

此 TLV 也可以透過 sysfs 查詢。

3. 核心驅動程式 API

核心驅動程式可以訪問對映到 IFF_LOWER_UP 和 IFF_DORMANT 的兩個標誌。 這些標誌可以從任何地方設定,甚至可以從中斷中設定。 可以保證只有驅動程式具有寫入訪問許可權,但是,如果驅動程式的各個層操縱相同的標誌,則驅動程式必須提供所需的同步。

__LINK_STATE_NOCARRIER, 對映到 !IFF_LOWER_UP

驅動程式使用 netif_carrier_on() 清除,使用 netif_carrier_off() 設定此標誌。 在 netif_carrier_off() 上,排程程式停止傳送資料包。 名稱“carrier”和反轉是歷史遺留的,可以將其視為下層。

請注意,對於某些型別的軟裝置,它們不管理任何真正的硬體,可以從使用者空間設定此位。 應該使用 TLV IFLA_CARRIER 來執行此操作。

netif_carrier_ok() 可用於查詢該位。

__LINK_STATE_DORMANT, 對映到 IFF_DORMANT

由驅動程式設定,以表示該裝置尚不能使用,因為必須完成某些驅動程式控制的協議建立。 相應的函式是 netif_dormant_on() 設定標誌, netif_dormant_off() 清除標誌, netif_dormant() 進行查詢。

在裝置分配時,標誌 __LINK_STATE_NOCARRIER 和 __LINK_STATE_DORMANT 均被清除,因此有效狀態等效於 netif_carrier_ok() 和 !netif_dormant()

每當驅動程式更改這些標誌之一時,就會排程一個工作佇列事件,以將標誌組合轉換為 IFLA_OPERSTATE,如下所示

!netif_carrier_ok()

如果介面已堆疊,則為 IF_OPER_LOWERLAYERDOWN,否則為 IF_OPER_DOWN。 核心可以識別堆疊的介面,因為它們的 ifindex != iflink。

netif_carrier_ok() && netif_dormant()

IF_OPER_DORMANT

netif_carrier_ok() && !netif_dormant()

如果停用使用者空間互動,則為 IF_OPER_UP。 否則,IF_OPER_DORMANT 允許使用者空間在之後啟動 IF_OPER_UP 轉換。

4. 從使用者空間設定

應用程式必須使用 netlink 介面來影響介面的 RFC2863 操作狀態。 透過 RTM_SETLINK 將 IFLA_LINKMODE 設定為 1 會指示核心,當驅動程式設定了組合 netif_carrier_ok() && !netif_dormant() 時,介面應轉到 IF_OPER_DORMANT 而不是 IF_OPER_UP。 此後,只要驅動程式未設定 netif_carrier_off()netif_dormant_on(),使用者空間應用程式就可以將 IFLA_OPERSTATE 設定為 IF_OPER_DORMANT 或 IF_OPER_UP。 使用者空間所做的更改將在 netlink 組 RTNLGRP_LINK 上進行多播。

因此,基本上 802.1X 請求者與核心的互動如下

  • 訂閱 RTNLGRP_LINK

  • 透過 RTM_SETLINK 將 IFLA_LINKMODE 設定為 1

  • 查詢 RTM_GETLINK 一次以獲取初始狀態

  • 如果初始標誌不是 (IFF_LOWER_UP && !IFF_DORMANT),請等到 netlink 多播發出此狀態訊號

  • 執行 802.1X,如果標誌再次下降,最終中止

  • 如果身份驗證成功,則傳送 RTM_SETLINK 以將 operstate 設定為 IF_OPER_UP,否則設定為 IF_OPER_DORMANT

  • 檢視 operstate 和 IFF_RUNNING 如何透過 netlink 多播回顯

  • 如果 802.1X 重新身份驗證失敗,則將介面設定回 IF_OPER_DORMANT

  • 如果核心更改 IFF_LOWER_UP 或 IFF_DORMANT 標誌,則重新啟動

如果請求者停止執行,則將 IFLA_LINKMODE 帶回 0,並將 IFLA_OPERSTATE 設定為合理值。

路由守護程序或 dhcp 客戶端只需要注意 IFF_RUNNING 或等待 operstate 轉到 IF_OPER_UP/IF_OPER_UNKNOWN,然後才考慮介面/查詢 DHCP 地址。

如有技術問題和/或意見,請傳送電子郵件至 Stefan Rompf (stefan at loplof.de)。