Discovery服務過程跟蹤
對於NVMe over Fabrics的subsystem,有兩種類型:Discovery子系統和NVM子系統。這里介紹與Discovery子系統相關的交互內容(即:在Linux系統上使用nvme discover命令后的交互過程)。
Discovery子系統無Namespace存儲空間,只響應相關的Fabric命令和Admin命令。這也就意味着主機與Discovery子系統只需要NVMe協議規格說明書中定義的Admin Submission Queue,而不需要IO Submission Queue。(之后描述Submission Queue簡寫SQ,描述Completion Queue簡寫CQ)。
參考NVMe over Fabrics協議規格說明書1.5.3 Capsules and Data Transfer章節中定義,交互內容格式如下邊截圖:
SQ請求使用的格式為:(其中前64字節為NVMe Command)
CQ回復使用的格式為:(其中前16字節為Completion內容)
Discovery子系統可以處理的命令包括Fabric命令和一部分Admin命令:
接下來按交互過程順序來介紹。
1. 連接connect命令
此命令歸屬Fabric命令。
主機initiator端與target端Discovery子系統交互(注意:此connect命令前,需要已經存在Fabric鏈路作為SQ和CQ),由主機端發起connect命令。
參考下邊抓包信息可以看到,connect命令包含了如下關鍵數值:
opcode為0x7f、命令ID為0、Fabric Command Type為0x01、QueueID為0、Queue最大值31、Keep Alive Timeout為0(不超時)。
在此交互的Capsule的數據內容大小占用1024字節,包含了主機標識、Controller ID、被請求的NQN、主機NQN,這4個主要內容。
本例子中,Controller ID填寫了0xFFFF(65535),表示不指定controller。
允許連接的情況,回復如下內容:
其中Value: 1表示建立連接的controller的ID號為1。
備注:連接兩種NVM子系統的過程是一樣的,只是連接Discovery子系統時,請求的NQN是固定的nqn.2014-08.org.nvmexpress.discovery |
2. 獲取property屬性(CAP)
此命令歸屬Fabric命令。
查詢property屬性(此屬性對應PCIe場景下的register map for the controller),opcode用0x7f,Fabric命令類型為0x04(即表示property Get),如下示例中的查詢property屬性,Attribute為1表示讀取8個字節,offset為0表示從property空間的偏移0開始讀取。
從propert屬性定義可以看出,此命令請求目的是獲取CAP(Controller Capabilities):
補充說明:對於Discovery子系統的控制器來說,只支持如下屬性,其他的被Reserved:
對應的回應如下,此Response回應對應的是命令ID 14,查詢出來的內容是CAP屬性,值為十六進制ff 03 00 0f 20 00 00 00。
從NVMe規格說明書中查詢CAP的8字節(64 bit)中各bit位表示的意思如下:
對照可以得出:
15:00對應的值ff 03,表示MQES隊列深度可以支持1023(0x03ff=1023)。
23:16對應的值是00,表示CQR不是物理連續的,AMS仲裁機制支持也為0不支持。
31:24對應的值是0f,表示TO,從CC.EN使能到等待CSTS.RDY就緒的最壞超時時間。
37bit設置了1,表示CSS命令集支持,1表示支持NVM command Set。
3. 設置property屬性(CC.EN)
此命令歸屬Fabric命令。
下邊截圖中,Attributes值為0表示設置4字節,offset是0x14,從前邊截圖Figure 30 Discovery Controller -properties可以得出是在設置CC(Controller Configuration)。
參照NVMe規格說明書,Controller Configuration對應bit位的意思,如下邊截圖Figure 78: Offset 14h: CC - Controller Configuration
本例子中的設置property屬性目的是Enable使能controller。
回應的response如下:
4. 查詢property屬性(CSTS.RDY)
本次查詢property屬性時填寫的offset偏移量0x1c,Attribute為0即讀取4個字節,參照property屬性表可知,本次查詢的是CSTS(Controller STATUS)。
接下來,看回應response的內容:
對應查詢命令ID 23的回復值是Value為1。
參照CSTS對應bit位的意思,可知,本次查詢的CSTS.RDY為1,表示Controller已經ready。
5. 查詢property屬性(VS)
此命令歸屬Fabric命令,查詢property屬性中的offset偏移0x08位置,參照Figue 30即可得知查詢的是version版本號。
回應此命令24的response內容為:
參照property屬性表解釋,可得知,Controller使用的NVMe協議版本是1.3.0。
附加說明:
對於主機端,查詢此版本號,可以區分1.1.0版本及以后的版本,CAP中有NSSRC功能,此bit位的意思如下:
在linux系統中,主機就用查詢版本號判斷是不是1.1.0版本及以后的版本,來區分是否支持CAP.NSSRC功能。其他的當前還未看到主機端用版本區分功能的地方。
6. 獲取property屬性(CAP)
獲取CAP,本次查詢到的信息與使能前查詢的到的信息一樣。
這里出現了重復查詢。本例子是使用的NVMe over TCP方式抓包的,是Linux系統下的操作,相關代碼:
nvme_tcp_configure_admin_queue()
--> ctrl->ops->reg_read64(ctrl, NVME_REG_CAP, &ctrl->cap); //讀一次
--> nvme_enable_ctrl(ctrl, ctrl->cap);
--> nvme_init_identify(ctrl);
--> ctrl->ops->reg_read32(ctrl, NVME_REG_VS, &ctrl->vs);
--> ctrl->ops->reg_read64(ctrl, NVME_REG_CAP, &cap); //又讀一次
回應如下:
以上完成了主機與target端Discovery服務的Fabric連接過程。
接下來開始進行Admin Command處理分析。
7. Identify查詢命令id-ctrl(Admin Command)
此命令歸屬Admin Command。
執行nvme id-ctrl命令的結果。
這里Identify查詢命令,opcode為0x06,CNS字段填充0x01,表示查詢controller Identify,注意:Discovery只定義了CNS為0x01的處理,其他情況未定義。
結合上邊Figure 33: DiscoveryController - Identify Controller Data Structure回應內容解析,可知回應的內容大小為3072字節。
本例子操作時獲取到的回應數據為:
Completion Queue Entry對應的16字節內容為:
接下來數據參照Figure 33分析:
Firmware Revision (FR): 5.0.7
Maximum Data Transfer Size (MDTS): 0 //固定填寫0
Controller ID (CNTLID): 1
Version (VER): 1.3.0
Log Page Attributes (LPA): 0x04
Error Log Page Attributes (ELPE): 0x00
Maximum Outstanding Commands (MAXCMD): 0x00000000
SGL Support (SGLS): 0x00000000
NVM Subsystem NVMe Qualified Name (SUBNQN): 固定字符串
備注:
測試時使用了NVMe over TCP,分析截圖使用了wirshark,需要wirshark 3.0.3之后的版本。