操作狀態¶
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)。