SCSI FC 傳輸¶
日期:2008 年 11 月 18 日
功能相關的核心修訂
rports : <<TBS>>
vports : 2.6.22
bsg support : 2.6.30 (?TBD?)
引言¶
本檔案記錄了 SCSI FC 傳輸的功能和元件。它還提供了傳輸與 FC LLDD 之間的 API 文件。
FC 傳輸可在以下位置找到:
drivers/scsi/scsi_transport_fc.c
include/scsi/scsi_transport_fc.h
include/scsi/scsi_netlink_fc.h
include/scsi/scsi_bsg_fc.h
此檔案位於 SCSI FC 傳輸
FC 遠端埠 (rports)¶
<< 待補充 >>
FC 虛擬埠 (vports)¶
概述¶
新的 FC 標準定義了允許單個物理埠顯示為多個通訊埠的機制。使用 N_Port ID 虛擬化 (NPIV) 機制,可以為到 Fabric 的點對點連線分配多個 N_Port_ID。每個 N_Port_ID 在 Fabric 上顯示為獨立的埠,儘管它共享一個物理鏈路與交換機進行通訊。每個 N_Port_ID 可以根據 Fabric 分割槽和陣列 LUN 掩碼擁有獨特的 Fabric 檢視(就像一個普通的非 NPIV 介面卡一樣)。使用虛擬 Fabric (VF) 機制,為每個幀新增 Fabric 頭部允許埠與 Fabric 埠互動以加入多個 Fabric。埠將在其加入的每個 Fabric 上獲取一個 N_Port_ID。每個 Fabric 將擁有其自身獨特的端點和配置引數檢視。NPIV 可以與 VF 一起使用,以便埠可以在每個虛擬 Fabric 上獲取多個 N_Port_ID。
FC 傳輸現在識別一個新的物件——vport(虛擬埠)。vport 是一個具有全球唯一埠名稱 (WWPN) 和全球節點名稱 (WWNN) 的實體。傳輸還允許為 vport 指定 FC4 角色,其中 FCP_Initiator 是預期的主要角色。一旦透過上述方法之一例項化,它將擁有一個獨特的 N_Port_ID 和 Fabric 端點及儲存實體的檢視。與物理介面卡關聯的 fc_host 將匯出建立 vports 的能力。傳輸將在 Linux 裝置樹中建立 vport 物件,並指示 fc_host 的驅動程式例項化虛擬埠。通常,驅動程式將在 vport 上建立一個新的 scsi_host 例項,從而為 vport 形成一個唯一的 <H,C,T,L> 名稱空間。因此,無論 FC 埠是基於物理埠還是基於虛擬埠,每個都將作為唯一的 scsi_host 出現,擁有自己的目標和 LUN 空間。
注意
目前,傳輸層僅支援建立基於 NPIV 的 vport。然而,我們已考慮了基於 VF 的 vport,如果需要,新增支援應僅需少量修改。接下來的討論將集中在 NPIV 上。
注意
全球名稱的分配(和唯一性保證)由控制 vport 的管理實體負責。例如,如果 vports 要與虛擬機器關聯,XEN 管理工具將負責為 vport 建立 WWPN/WWNN,使用其自身的命名許可權和 OUI。(注意:它已經為虛擬 MAC 地址做了這些。)
裝置樹和 Vport 物件:¶
如今,裝置樹通常包含 scsi_host 物件,其下方有 rport 和 SCSI 目標物件。目前,FC 傳輸層會建立 vport 物件並將其放置在與物理介面卡對應的 scsi_host 物件之下。LLDD 將為 vport 分配一個新的 scsi_host,並將其物件連結到 vport 之下。vport 的 scsi_host 之下樹的其餘部分與非 NPIV 情況相同。當前編寫的傳輸層易於允許 vport 的父級是 scsi_host 以外的其他物件。這在未來可用於將物件連結到虛擬機器特定的裝置樹。如果 vport 的父級不是物理埠的 scsi_host,則指向 vport 物件的符號連結將放置在物理埠的 scsi_host 中。
以下是裝置樹中預期的結構:
典型的物理埠 Scsi_Host
/sys/devices/.../host17/並且它具有典型的子樹結構
/sys/devices/.../host17/rport-17:0-0/target17:0:0/17:0:0:0:然後 vport 在物理埠上建立
/sys/devices/.../host17/vport-17:0-0然後 vport 的 Scsi_Host 被建立
/sys/devices/.../host17/vport-17:0-0/host18然後樹的其餘部分繼續,例如
/sys/devices/.../host17/vport-17:0-0/host18/rport-18:0-0/target18:0:0/18:0:0:0:以下是 sysfs 樹中預期的結構
scsi_hosts: /sys/class/scsi_host/host17 physical port's scsi_host /sys/class/scsi_host/host18 vport's scsi_host fc_hosts: /sys/class/fc_host/host17 physical port's fc_host /sys/class/fc_host/host18 vport's fc_host fc_vports: /sys/class/fc_vports/vport-17:0-0 the vport's fc_vport fc_rports: /sys/class/fc_remote_ports/rport-17:0-0 rport on the physical port /sys/class/fc_remote_ports/rport-18:0-0 rport on the vport
Vport 屬性¶
新的 fc_vport 類物件具有以下屬性:
- node_name: 只讀
vport 的 WWNN
- port_name: 只讀
vport 的 WWPN
- roles: 只讀
指示 vport 上啟用的 FC4 角色。
- symbolic_name: 讀寫
一個字串,附加到驅動程式的符號埠名稱字串後,並在交換機上註冊以識別 vport。例如,一個管理程式可以將此字串設定為“Xen Domain 2 VM 5 Vport 2”,並且這組識別符號可以在交換機管理螢幕上看到,用於識別該埠。
- vport_delete: 只寫
當寫入“1”時,將銷燬 vport。
- vport_disable: 只寫
當寫入“1”時,將把 vport 轉換到停用狀態。vport 仍將在 Linux 核心中例項化,但不會在 FC 鏈路上處於活動狀態。當寫入“0”時,將啟用 vport。
- vport_last_state: 只讀
指示 vport 的前一狀態。請參閱下面關於“Vport 狀態”的部分。
- vport_state: 只讀
指示 vport 的當前狀態。請參閱下面關於“Vport 狀態”的部分。
- vport_type: 只讀
反映用於建立虛擬埠的 FC 機制。目前僅支援 NPIV。
對於 fc_host 類物件,為 vports 添加了以下屬性:
- max_npiv_vports: 只讀
指示驅動程式/介面卡在 fc_host 上支援的最大 NPIV vport 數量。
- npiv_vports_inuse: 只讀
指示在 fc_host 上已例項化的 NPIV vport 數量。
- vport_create: 只寫
一個“簡單”的建立介面,用於在 fc_host 上例項化一個 vport。將一個“<WWPN>:<WWNN>”字串寫入屬性。傳輸層隨後例項化 vport 物件並呼叫 LLDD 以 FCP_Initiator 角色建立 vport。每個 WWN 都指定為 16 個十六進位制字元,並且 *不能* 包含任何字首(例如 0x, x 等)。
- vport_delete: 只寫
一個“簡單”的刪除介面,用於銷燬 vport。將一個“<WWPN>:<WWNN>”字串寫入屬性。傳輸層將定位 fc_host 上具有相同 WWN 的 vport 並將其銷燬。每個 WWN 都指定為 16 個十六進位制字元,並且 *不能* 包含任何字首(例如 0x, x 等)。
Vport 狀態¶
Vport 例項化包括兩部分:
在核心和 LLDD 中建立。這意味著所有傳輸和驅動程式資料結構都已構建,並且裝置物件已建立。這等同於驅動程式在介面卡上的“附加”,這與介面卡的鏈路狀態無關。
透過 ELS 流量等方式在 FC 鏈路上例項化 vport。這等同於“鏈路啟用”和成功的鏈路初始化。
有關 Vport 建立的更多資訊,請參閱下面的介面部分。
一旦 vport 在核心/LLDD 中例項化,其狀態可以透過 sysfs 屬性報告。存在以下狀態:
- FC_VPORT_UNKNOWN - 未知
一個臨時狀態,通常只在 vport 正在核心和 LLDD 中例項化時設定。
- FC_VPORT_ACTIVE - 活動
vport 已在 FC 鏈路上成功建立。它功能齊全。
- FC_VPORT_DISABLED - 停用
vport 已例項化,但處於“停用”狀態。vport 未在 FC 鏈路上例項化。這等同於物理埠的鏈路“已斷開”。
- FC_VPORT_LINKDOWN - 鏈路斷開
vport 無法執行,因為物理鏈路未執行。
- FC_VPORT_INITIALIZING - 初始化中
vport 正在 FC 鏈路上例項化。LLDD 將在開始 ELS 流量以建立 vport 之前設定此狀態。此狀態將持續到 vport 成功建立(狀態變為 FC_VPORT_ACTIVE)或失敗(狀態為以下值之一)。由於此狀態是暫時的,它不會保留在“vport_last_state”中。
- FC_VPORT_NO_FABRIC_SUPP - 無 Fabric 支援
vport 無法執行。遇到以下條件之一:
FC 拓撲不是點對點
FC 埠未連線到 F_Port
F_Port 已指示不支援 NPIV。
- FC_VPORT_NO_FABRIC_RSCS - 無 Fabric 資源
vport 無法執行。Fabric 的 FDISC 操作失敗,狀態指示其沒有足夠的資源完成該操作。
- FC_VPORT_FABRIC_LOGOUT - Fabric 登出
vport 無法執行。Fabric 已登出與 vport 關聯的 N_Port_ID。
- FC_VPORT_FABRIC_REJ_WWN - Fabric 拒絕 WWN
vport 無法執行。Fabric 的 FDISC 操作失敗,狀態指示 WWN 無效。
- FC_VPORT_FAILED - VPort 失敗
vport 無法執行。這是所有其他錯誤條件的通用捕獲。
下表顯示了不同的狀態轉換:
狀態
事件
新狀態
不適用
初始化
未知
未知
鏈路斷開
鏈路斷開
鏈路啟用 & 環路
無 Fabric 支援
鏈路啟用 & 無 Fabric
無 Fabric 支援
鏈路啟用 & FLOGI 響應指示不支援 NPIV
無 Fabric 支援
鏈路啟用 & 正在傳送 FDISC
初始化中
停用請求
停用
鏈路斷開
鏈路啟用
未知
初始化中
FDISC ACC
活動
FDISC LS_RJT(無資源)
無 Fabric 資源
FDISC LS_RJT(pname 或 nport_id 無效)
Fabric 拒絕 WWN
FDISC LS_RJT 因其他原因失敗
Vport 失敗
鏈路斷開
鏈路斷開
停用請求
停用
停用
啟用請求
未知
活動
從 Fabric 收到 LOGO
Fabric 登出
鏈路斷開
鏈路斷開
停用請求
停用
Fabric 登出
鏈路仍啟用
未知
以下 4 種錯誤狀態都具有相同的轉換:
No Fabric Support:
No Fabric Resources:
Fabric Rejected WWN:
Vport Failed:
Disable request Disable
Link goes down Linkdown
傳輸 <-> LLDD 介面¶
LLDD 對 Vport 的支援
LLDD 透過在傳輸模板中提供 `vport_create()` 函式來表明對 vport 的支援。此函式的存在將導致在 fc_host 上建立新的屬性。作為物理埠相對於傳輸層完成初始化的一部分,它應該設定 `max_npiv_vports` 屬性,以指示驅動程式和/或介面卡支援的最大 vport 數量。
Vport 建立
LLDD `vport_create()` 語法為:
int vport_create(struct fc_vport *vport, bool disable)其中
vport
是新分配的 vport 物件
disable
如果為“true”,vport 將在停用狀態下建立。如果為“false”,vport 將在建立時啟用。
當請求建立新的 vport 時(透過 sgio/netlink,或 vport_create fc_host 屬性),傳輸層將驗證 LLDD 是否可以支援另一個 vport(例如 `max_npiv_vports` > `npiv_vports_inuse`)。如果不支援,建立請求將失敗。如果仍有空間,傳輸層將增加 vport 計數,建立 vport 物件,然後呼叫 LLDD 的 `vport_create()` 函式,傳入新分配的 vport 物件。
如上所述,vport 建立分為兩部分:
在核心和 LLDD 中建立。這意味著所有傳輸和驅動程式資料結構都已構建,並且裝置物件已建立。這等同於驅動程式在介面卡上的“附加”,這與介面卡的鏈路狀態無關。
透過 ELS 流量等方式在 FC 鏈路上例項化 vport。這等同於“鏈路啟用”和成功的鏈路初始化。
LLDD 的 `vport_create()` 函式不會在返回之前同步等待兩部分完全完成。它必須驗證支援 NPIV 的基礎設施是否存在,並在返回之前完成 vport 建立的第一部分(資料結構構建)。我們不將 `vport_create()` 依賴於鏈路側操作,主要是因為:
鏈路可能已斷開。如果鏈路斷開,這不是故障。它僅表示 vport 處於不可操作狀態,直到鏈路啟用。這與 vport 建立後鏈路跳動的情況一致。
vport 可以在停用狀態下建立。
這與以下模型一致:vport 等同於一個 FC 介面卡。`vport_create` 與驅動程式附加到介面卡同義,而這與鏈路狀態無關。
注意
已定義了特殊的錯誤程式碼,以區分基礎設施故障情況,從而加快解決速度。
LLDD `vport_create()` 函式的預期行為是:
驗證基礎設施
- 如果驅動程式或介面卡不能支援另一個 vport,無論是因為
韌體不正確、(虛報)`max_npiv`,或缺少其他資源——則返回 `VPCERR_UNSUPPORTED`。
- 如果驅動程式針對已在介面卡上活動的 WWN 驗證新 WWN,並檢測到重疊——則返回 `VPCERR_BAD_WWN`。
介面卡並檢測到重疊 - 返回 VPCERR_BAD_WWN。
- 如果驅動程式檢測到拓撲是環路、非 Fabric,或者
FLOGI 不支援 NPIV——則返回 `VPCERR_NO_FABRIC_SUPP`。
- 分配資料結構。如果遇到錯誤,例如記憶體不足,則返回相應的負數 `Exxx` 錯誤程式碼。
記憶體狀況,返回相應的負 Exxx 錯誤程式碼。
如果角色是 FCP Initiator,LLDD 應:
呼叫
scsi_host_alloc()為 vport 分配一個 `scsi_host`。呼叫 `scsi_add_host(new_shost, &vport->dev)` 以啟動 `scsi_host` 並將其繫結為 vport 裝置的子級。
初始化 `fc_host` 屬性值。
- 根據停用標誌和鏈路狀態啟動進一步的 vport 狀態轉換——並返回成功(零)。
鏈路狀態 - 並返回成功(零)。
LLDD 實現者注意事項
建議物理埠和虛擬埠使用不同的 `fc_function_templates`。物理埠的模板將包含 `vport_create`、`vport_delete` 和 `vport_disable` 函式,而 vport 則不包含。
建議物理埠和虛擬埠使用不同的 `scsi_host_templates`。很可能有些驅動程式屬性(如鏈路速度、拓撲設定等)嵌入在 `scsi_host_template` 中,僅適用於物理埠。這確保了屬性適用於各自的 `scsi_host`。
Vport 停用/啟用
LLDD `vport_disable()` 語法為:
int vport_disable(struct fc_vport *vport, bool disable)其中
vport
vport 是啟用還是停用
disable
如果為“true”,vport 將被停用。如果為“false”,vport 將被啟用。
當請求更改 vport 的停用狀態時,傳輸層將根據現有 vport 狀態驗證該請求。如果請求是停用,且 vport 已被停用,則請求將失敗。類似地,如果請求是啟用,而 vport 不處於停用狀態,則請求也將失敗。如果請求對於 vport 狀態有效,傳輸層將呼叫 LLDD 更改 vport 的狀態。
在 LLDD 內部,如果 vport 被停用,它仍將在核心和 LLDD 中例項化,但不會以任何方式在 FC 鏈路上活動或可見。(參見 Vport 建立和兩部分例項化討論)。vport 將保持此狀態,直到被刪除或重新啟用。啟用 vport 時,LLDD 將在 FC 鏈路上重新例項化 vport——本質上是重啟 LLDD 狀態機(參見上面的 Vport 狀態)。
Vport 刪除
LLDD `vport_delete()` 語法為:
int vport_delete(struct fc_vport *vport)其中
vport: 要刪除的 vport
當請求刪除 vport 時(透過 sgio/netlink,或透過 `fc_host` 或 `fc_vport` 的 `vport_delete` 屬性),傳輸層將呼叫 LLDD 以終止 FC 鏈路上的 vport,並銷燬所有其他資料結構和引用。如果 LLDD 成功完成,傳輸層將銷燬 vport 物件並完成 vport 刪除。如果 LLDD 刪除請求失敗,vport 物件將保留,但會處於不確定狀態。
在 LLDD 內部,應遵循 `scsi_host` 拆卸的常規程式碼路徑。例如,如果 vport 具有 FCP Initiator 角色,LLDD 將為 vport 的 `scsi_host` 呼叫
fc_remove_host(),然後呼叫scsi_remove_host()和scsi_host_put()。
- 其他
- fc_host 的 `port_type` 屬性
新增了一個 `fc_host` `port_type` 值 - `FC_PORTTYPE_NPIV`。此值必須設定在所有基於 vport 的 `fc_host` 上。通常,在物理埠上,`port_type` 屬性會根據拓撲型別和 Fabric 的存在設定為 NPORT、NLPORT 等。由於這不適用於 vport,因此報告用於建立 vport 的 FC 機制更有意義。
- 驅動程式解除安裝
FC 驅動程式必須在呼叫
scsi_remove_host()之前呼叫fc_remove_host()。這允許 `fc_host` 在 `scsi_host` 拆卸之前拆卸所有遠端埠。`fc_remove_host()` 呼叫已更新,以同時刪除 `fc_host` 的所有 vport。
傳輸層提供的函式¶
以下函式由 FC 傳輸層提供給 LLD 使用。
`fc_vport_create`
建立 vport
`fc_vport_terminate`
分離並移除 vport
詳情
/**
* fc_vport_create - Admin App or LLDD requests creation of a vport
* @shost: scsi host the virtual port is connected to.
* @ids: The world wide names, FC4 port roles, etc for
* the virtual port.
*
* Notes:
* This routine assumes no locks are held on entry.
*/
struct fc_vport *
fc_vport_create(struct Scsi_Host *shost, struct fc_vport_identifiers *ids)
/**
* fc_vport_terminate - Admin App or LLDD requests termination of a vport
* @vport: fc_vport to be terminated
*
* Calls the LLDD vport_delete() function, then deallocates and removes
* the vport from the shost and object tree.
*
* Notes:
* This routine assumes no locks are held on entry.
*/
int
fc_vport_terminate(struct fc_vport *vport)
FC BSG 支援 (CT & ELS 透傳等)¶
<< 待補充 >>
致謝¶
以下人員對本文件做出了貢獻:
James Smart james.smart@broadcom.com