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) 机制,可以为到光纤的端到端连接分配多个 N_Port_ID。即使每个 N_Port_ID 共享一个到交换机的物理链路进行通信,它也会以独立端口的形式显示在光纤上的其他端点上。每个 N_Port_ID 可以基于光纤区域和阵列 lun 掩码对光纤具有唯一视图(就像普通的非 NPIV 适配器一样)。通过使用虚拟光纤 (VF) 机制,在每个帧中添加光纤头允许端口与光纤端口交互以加入多个光纤。端口将在其加入的每个光纤上获取 N_Port_ID。每个光纤都会有其自己对端点和配置参数的唯一视图。NPIV 可以与 VF 一起使用,以便端口可以在每个虚拟光纤上获取多个 N_Port_ID。
FC 传输现在正在识别一个新对象 - vport。vport 是一个具有全球唯一的世界范围端口名称 (wwpn) 和世界范围节点名称 (wwnn) 的实体。传输还允许为 vport 指定 FC4,其中 FCP_Initiator 是预期的主要角色。一旦通过上述方法之一实例化,它将具有不同的 N_Port_ID 以及光纤端点和存储实体的视图。与物理适配器关联的 fc_host 将导出创建 vport 的功能。传输将在 Linux 设备树中创建 vport 对象,并指示 fc_host 的驱动程序实例化虚拟端口。通常,驱动程序将在 vport 上创建一个新的 scsi_host 实例,从而为 vport 产生一个唯一的 <H,C,T,L> 命名空间。因此,无论 FC 端口是基于物理端口还是虚拟端口,每个端口都将显示为具有自己目标和 lun 空间的唯一 scsi_host。
注意
目前,传输的编写仅用于创建基于 NPIV 的 vport。但是,考虑了基于 VF 的 vport,如果需要添加支持,则应该是一个小的更改。其余讨论将集中在 NPIV 上。
注意
世界范围名称分配(和唯一性保证)由控制 vport 的管理实体决定。例如,如果要将 vport 与虚拟机关联,则 XEN 管理实用程序将负责使用其自己的命名机构和 OUI 为 vport 创建 wwpn/wwnn。(注意:它已经为虚拟 MAC 地址执行此操作)。
设备树和 Vport 对象:¶
如今,设备树通常包含 scsi_host 对象,其下是 rports 和 scsi 目标对象。当前,FC 传输创建 vport 对象并将其放置在对应于物理适配器的 scsi_host 对象下。LLDD 将为 vport 分配一个新的 scsi_host 并将其对象链接到 vport 下。vport 的 scsi_host 下的树的其余部分与非 NPIV 的情况相同。当前编写的传输可以轻松地允许 vport 的父级不是 scsi_host。将来可以使用它将对象链接到特定于 vm 的设备树。如果 vport 的父级不是物理端口的 scsi_host,则将在物理端口的 scsi_host 中放置一个指向 vport 对象的符号链接。
以下是设备树中的预期内容
典型的物理端口的 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 类对象,为 vport 添加了以下属性
- 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>”字符串写入该属性。传输将使用相同的 WWN 在 fc_host 上找到 vport 并将其拆除。每个 WWN 都被指定为 16 个十六进制字符,并且可能不包含任何前缀(例如 0x、x 等)。
Vport 状态¶
Vport 实例化包含两个部分
使用内核和 LLDD 创建。这意味着将建立所有传输和驱动程序数据结构,并创建设备对象。这等效于适配器上的驱动程序“附加”,与适配器的链路状态无关。
通过 ELS 流量等在 FC 链路上实例化 vport。这等效于“链路启动”和链路初始化成功。
有关更多信息,请参阅下面有关 Vport 创建的接口部分。
一旦 vport 使用内核/LLDD 实例化,就可以通过 sysfs 属性报告 vport 状态。存在以下状态
- 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 - 没有光纤支持
vport 无法运行。遇到以下条件之一
FC 拓扑不是点对点
FC 端口未连接到 F_Port
F_Port 指示不支持 NPIV。
- FC_VPORT_NO_FABRIC_RSCS - 没有光纤资源
vport 无法运行。光纤 FDISC 失败,状态指示它没有足够的资源来完成操作。
- FC_VPORT_FABRIC_LOGOUT - 光纤注销
vport 无法运行。光纤已 LOGO’d 与 vport 关联的 N_Port_ID。
- FC_VPORT_FABRIC_REJ_WWN - 光纤拒绝的 WWN
vport 无法运行。光纤 FDISC 失败,状态指示 WWN 无效。
- FC_VPORT_FAILED - VPort 失败
vport 无法运行。这是所有其他错误条件的统称。
以下状态表指示不同的状态转换
状态
事件
新状态
不适用
初始化
未知
未知
链路断开
链路断开
链路启动 & 循环
没有光纤支持
链路启动 & 没有光纤
没有光纤支持
链路启动 & FLOGI 响应指示不支持 NPIV
没有光纤支持
链路启动 & 正在发送 FDISC
正在初始化
禁用请求
禁用
链路断开
链路启动
未知
正在初始化
FDISC ACC
活动
FDISC LS_RJT w/ 没有资源
没有光纤资源
FDISC LS_RJT w/ 无效的 pname 或无效的 nport_id
光纤拒绝的 WWN
FDISC LS_RJT 由于其他原因失败
VPort 失败
链路断开
链路断开
禁用请求
禁用
禁用
启用请求
未知
活动
从光纤接收到 LOGO
光纤注销
链路断开
链路断开
禁用请求
禁用
光纤注销
链路仍然启动
未知
以下 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 对象
禁用
如果为“true”,则创建的虚拟端口将处于禁用状态。如果为“false”,则创建虚拟端口后立即启用。
当请求创建新的虚拟端口(通过 sgio/netlink 或 vport_create fc_host 属性)时,传输层将验证 LLDD 是否支持另一个虚拟端口(例如,max_npiv_vports > npiv_vports_inuse)。如果不支持,则创建请求将失败。如果空间足够,传输层将增加虚拟端口计数,创建虚拟端口对象,然后使用新分配的虚拟端口对象调用 LLDD 的 vport_create() 函数。
如上所述,虚拟端口的创建分为两个部分
使用内核和 LLDD 创建。这意味着将建立所有传输和驱动程序数据结构,并创建设备对象。这等效于适配器上的驱动程序“附加”,与适配器的链路状态无关。
通过 ELS 流量等在 FC 链路上实例化 vport。这等效于“链路启动”和链路初始化成功。
LLDD 的 vport_create() 函数不会同步等待两个部分都完全完成后才返回。它必须验证是否存在支持 NPIV 的基础设施,并在返回之前完成虚拟端口创建的第一部分(数据结构构建)。我们不将 vport_create() 绑定到链路侧操作,主要是因为
链路可能已断开。这并非故障。它只是意味着虚拟端口处于不可操作状态,直到链路恢复。这与虚拟端口创建后链路弹跳的情况一致。
虚拟端口可能会在禁用状态下创建。
这与以下模型一致:虚拟端口等同于 FC 适配器。vport_create 与驱动程序附加到适配器同义,它独立于链路状态。
注意
已定义特殊的错误代码来区分基础设施故障情况,以便更快地解决问题。
LLDD 的 vport_create() 函数的预期行为是
验证基础设施
- 如果驱动程序或适配器无法支持另一个虚拟端口,无论是
由于固件不正确,(关于)max_npiv 的虚报,或者缺少其他资源 - 返回 VPCERR_UNSUPPORTED。
- 如果驱动程序根据适配器上已激活的 WWN 验证 WWN,
并检测到重叠 - 返回 VPCERR_BAD_WWN。
- 如果驱动程序检测到拓扑是环路、非光纤网络,或者
FLOGI 不支持 NPIV - 返回 VPCERR_NO_FABRIC_SUPP。
- 分配数据结构。如果遇到错误,例如内存不足,
返回相应的负 Exxx 错误代码。
如果角色是 FCP 发起方,则 LLDD 将执行以下操作:
调用
scsi_host_alloc()
为虚拟端口分配 scsi_host。调用 scsi_add_host(new_shost, &vport->dev) 以启动 scsi_host 并将其绑定为虚拟端口设备的子设备。
初始化 fc_host 属性值。
- 根据禁用标志和
链路状态启动进一步的虚拟端口状态转换 - 并返回成功(零)。
LLDD 实现者注意事项
建议物理端口和虚拟端口使用不同的 fc_function_templates。物理端口的模板将具有 vport_create、vport_delete 和 vport_disable 函数,而虚拟端口则不具有。
建议物理端口和虚拟端口使用不同的 scsi_host_templates。可能存在嵌入在 scsi_host_template 中的驱动程序属性,仅适用于物理端口(链路速度、拓扑设置等)。这确保了这些属性适用于各自的 scsi_host。
虚拟端口禁用/启用
LLDD vport_disable() 的语法是
int vport_disable(struct fc_vport *vport, bool disable)其中
vport
是要启用还是禁用虚拟端口
禁用
如果为“true”,则禁用虚拟端口。如果为“false”,则启用虚拟端口。
当请求更改虚拟端口的禁用状态时,传输层将根据现有虚拟端口状态验证请求。如果请求禁用且虚拟端口已禁用,则请求将失败。同样,如果请求启用且虚拟端口未处于禁用状态,则请求将失败。如果请求对虚拟端口状态有效,则传输层将调用 LLDD 来更改虚拟端口的状态。
在 LLDD 中,如果禁用虚拟端口,它仍会通过内核和 LLDD 实例化,但它不会以任何方式在 FC 链路上激活或可见。(请参阅虚拟端口创建和两部分实例化讨论)。虚拟端口将保持此状态,直到被删除或重新启用。启用虚拟端口时,LLDD 会在 FC 链路上重新实例化虚拟端口 - 本质上是重新启动 LLDD 状态机(请参阅上面的虚拟端口状态)。
虚拟端口删除
LLDD vport_delete() 的语法是
int vport_delete(struct fc_vport *vport)其中
vport:是要删除的虚拟端口
当请求删除虚拟端口(通过 sgio/netlink 或通过 fc_host 或 fc_vport vport_delete 属性)时,传输层将调用 LLDD 以终止 FC 链路上的虚拟端口,并拆除所有其他数据结构和引用。如果 LLDD 成功完成,则传输层将拆除虚拟端口对象并完成虚拟端口的删除。如果 LLDD 删除请求失败,则虚拟端口对象将保留,但将处于不确定状态。
在 LLDD 中,应遵循 scsi_host 拆除的正常代码路径。例如,如果虚拟端口具有 FCP 发起方角色,则 LLDD 将为虚拟端口的 scsi_host 调用
fc_remove_host()
,然后为虚拟端口的 scsi_host 调用scsi_remove_host()
和scsi_host_put()
。
- 其他
- fc_host port_type 属性
有一个新的 fc_host port_type 值 - FC_PORTTYPE_NPIV。必须在所有基于虚拟端口的 fc_hosts 上设置此值。通常,在物理端口上,port_type 属性将根据拓扑类型和光纤网络的存在设置为 NPORT、NLPORT 等。由于这不适用于虚拟端口,因此报告用于创建虚拟端口的 FC 机制更有意义。
- 驱动程序卸载
FC 驱动程序需要在调用
scsi_remove_host()
之前调用fc_remove_host()
。这允许 fc_host 在 scsi_host 被拆除之前拆除所有远程端口。已更新fc_remove_host()
调用,以便删除 fc_host 的所有虚拟端口。
传输层提供的函数¶
以下函数由 FC 传输层提供,供 LLD 使用。
fc_vport_create
创建虚拟端口
fc_vport_terminate
分离并移除虚拟端口
详细信息
/**
* 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