编写适用于 Oracle® Solaris 11.2 的设备驱动程序

退出打印视图

更新时间: 2014 年 9 月
 
 

GLDv3 功能

GLDv3 实现一种功能机制,允许框架查询和启用 GLDv3 驱动程序支持的功能。请使用 mc_getcapab(9E) 入口点来报告功能。如果驱动程序支持某种功能,请通过 mc_getcapab() 传递关于该功能的信息,例如特定于功能的入口点或标志。传递一个指向 mac_callback 结构中 mc_getcapab() 入口点的指针。有关 mac_callbacks 结构的更多信息,请参阅 GLDv3 MAC 注册数据结构

boolean_t mc_getcapab(void *driver_handle, mac_capab_t cap, void *cap_data);

cap 参数指定所查询的功能类型。cap 的值可以是 MAC_CAPAB_HCKSUM(硬件校验和负载转移)、MAC_CAPAB_LSO(大段负载转移)或 MAC_CAPAB_RINGS。使用 cap_data 参数将功能数据返回框架。

如果驱动程序支持 cap 功能,则 mc_getcapab() 入口点必须返回 B_TRUE。如果驱动程序不支持 cap 功能,则 mc_getcapab() 必须返回 B_FALSE

示例 19-5  mc_getcapab() 入口点
static boolean_t
xx_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
{
        switch (cap) {
        case MAC_CAPAB_HCKSUM: {
                uint32_t *txflags = cap_data;
                *txflags = HCKSUM_INET_FULL_V4 | HCKSUM_IPHDRCKSUM;
                break;
        }
        case MAC_CAPAB_LSO: {
                /* ... */
                break;
        }
			 case MAC_CAPAB_RINGS: {


                /* ... */


                break;


        }
        default:
                return (B_FALSE);
        }
        return (B_TRUE);
}

MAC 环功能

下面各节将介绍所支持的功能和需要返回的相应功能数据。

环和环组第 2 层分类

传送硬件环和接收硬件环都是 DMA 通道,可由设备驱动程序公开。环与环组关联。接收环组与一个或多个 MAC 地址关联,与某个接收组关联的任何 MAC 地址匹配的所有网络通信都必须由 NIC 通过该组的其中一个环进行传送。到接收环组的通信的控制是通过第 2 层分类在硬件中启用的。

接收环到环组的映射可以是动态的也可以是静态的。对于动态环组,环可以根据框架的要求在组之间移动,从而动态地缩小或增加组的大小。但是,对于静态环组,这些环以静态方式指定给组,并且无法更改该指定。

如果某个接收组包含多个环,则 NIC 必须使用某个散列机制(如 RSS(Receive Side Scaling,接收端缩放))在这些环中分散通信流量,从而允许为多个连接指定不同的环。

必须仅将接收组中的一个组指定为缺省组(通常是位于索引 0 处的第一个组)。此接收组具有以下特性:

  • 应至少有一个环。

  • 指定给 NIC 的主 MAC 客户机。主 MAC 客户机指定为 NIC 的主 MAC 地址,通常为 IP 地址。

  • 必须用于接收来自网络的所有多播和广播通信流量。

  • 如果将 NIC 置于混杂模式,则必须使用它来接收与指定给非缺省接收组的 MAC 地址不匹配的所有通信。

就接收环和接收环组的硬件实现而言,需注意以下几点:

  • 如果实现了多个接收环,但不支持第 2 层分类,则硬件应公开单个接收环组和属于框架的该组的所有环。

  • 如果实现了第 2 层硬件分类,但是不支持 RSS,则硬件应注册多个接收组,让每个组包含一个环。

  • 如果同时实现了第 2 层硬件分类和 RSS,则硬件应注册多个接收组,让每个组包含一个或多个环。

  • 如果第 2 层硬件分类和 RSS 都未实现,则硬件不应通告环功能,或不应通告具有单个伪环和环组的环功能(可用来动态轮询适配器的通信)。

注册环和组过程概述

向框架注册环涉及的过程包括从框架到驱动程序的各种调用。以下步骤介绍了注册过程:

  1. 框架通过调用驱动程序查询驱动程序的 MAC_CAPAB_RINGS 功能。为传送环创建一个调用,为接收环创建一个调用。有关更多信息,请参见MAC_CAPAB_RINGS Capability

  2. 此框架使用从前面的步骤中获得的 mr_rget(9E) 和 mr_gget(9E) 入口点来检索有关特定环或环组的信息。有关更多信息,请参见 mr_rget(9E)mr_gget(9E) 手册页。

  3. 当框架要使用某个环时,它使用 mgi_start(9E) 入口点启动环组,然后使用在前面的步骤中通告的 mri_start(9E) 入口点启动环。

    现在,通信流量可以流经环,直到通过 mgi_stop(9E) 和 mri_stop(9E) 入口点将其停止。

MAC_CAPAB_RINGS 功能

为获得有关对硬件传送环和接收环的支持的信息,框架将在 cap 参数中发送 MAC_CAPAB_RINGS,并期待在指向 mac_capab_rings 结构的 cap_data 字段中接收返回的信息。

框架将分配 mac_capab_rings(9S) 结构,并为接收环将 mr_type 成员设置为 MAC_RING_TYPE_RX,或为传送环将其设置为 MAC_RING_TYPE_TX。然后,mac_capab_rings 结构的其余成员由驱动程序填充。

以下字段是在 mac_capab_rings 结构中定义的:

mr_version

必须设置为 MAC_RINGS_VERSION_1

mr_rnum

环数。

mr_gnum

组数。

mr_group_type

定义以下值:

  • MAC_GROUP_TYPE_DYNAMIC-该组是动态的。

  • MAC_GROUP_TYPE_STATIC-此组为静态组。

有关更多信息,请参见Rings and Ring Groups Layer–2 Classification

mr_gget()

用于获取有关环组的更多信息的驱动程序入口点。有关更多信息,请参见mr_gget() Entry Point

mr_rget()

用于获取有关环的更多信息的驱动程序入口点。有关更多信息,请参见mr_rget() Entry Point

mr_gaddring()

用于向组添加环的驱动程序入口点。请参见 mr_gaddring(9E)

mr_gremring()

用于从组删除环的驱动程序入口点。请参见 mr_gremring(9E)

mr_gget() 入口点

框架为与 mr_gnum 参数指示的组数对应的每个有效组索引调用 mr_gget(9E) 入口点。有关更多信息,请参见 mr_gget(9E)。调用 mr_gget() 之后,驱动程序在 mac_group_info 结构中返回组信息。此结构本身是由框架预分配的,并由驱动程序填充。

以下字段是在 mac_group_info 结构中定义的:

mgi_driver

一个不透明的驱动程序组句柄,框架在将来调用组入口点时使用。

mgi_count

组中的环数。

mgi_flags

组标志 MAC_GROUP_DEFAULT 将组标识为缺省组。有关更多信息,请参见Rings and Ring Groups Layer–2 Classification

mgi_start

组启动入口点。

mgi_stop

组停止入口点。

mgi_addmac

添加单点传送 MAC 地址入口点。

mgi_remmac

删除单点传送 MAC 地址入口点。

mgi_addvlan

用来添加硬件 VLAN 过滤、标记和 VLAN 标记剥离的入口点。

mgi_remvlan

用来删除硬件 VLAN 过滤、标记和 VLAN 标记剥离的入口点。

mgi_setmtu

设置 RX 组 MTU 入口点

mgi_getsriov_info

用于为组检索 SR-IOV 信息的入口点。有关更多信息,请参见Ring Groups and SR-IOV

有关详细信息,请参见 mac_group_info(9S)mac_group_info(9E)


注 - mgi_addmac(9E)mgi_remmac(9E) 入口点仅用于接收组。只要设备驱动程序支持环功能,mc_unicst(9E) 入口点就必须设置为 NULL。

注 - mgi_addvlan() 入口点执行以下操作:
  • 它定义 NIC 必须允许进行传送和接收的 VLAN ID。也就是说,将丢弃未在所配置的列表中列出的任何有标记数据包。

  • 如果设置了 MAC_GROUP_VLAN_TRANSPARENT_ENABLE 标志,则它还将为该特定 VLAN ID 启用硬件 VLAN 标记和剥离。


mr_rget() 入口点

对应于mr_gnum 指示的组数和对 MAC_CAPAB_RINGS 的调用通告的 mr_rnum 指示的环数,框架为每个有效的组和环索引调用 mr_rget(9E) 入口点。有关详细信息,请参见 mr_rget(9E)。

完成对 mr_rget() 的调用后,驱动程序在 mac_ring_info 结构中返回环信息。此结构是由框架预分配的,并由驱动程序填充。

以下字段是在 mac_ring_info 结构中定义的:

mri_driver

一个不透明的驱动程序组句柄,框架在将来调用环入口点时使用。

mri_start

环启动入口点。

mri_stop

环停止入口点

mri_stat

环统计信息入口点。有关更多信息,请参见GLDv3 Network Statistics

mri_tx

环传送入口点。有关更多信息,请参见Transmit Data Path

mri_poll

环轮询入口点。有关更多信息,请参见Receive Data Path

mri_intr_ddi_handle

与此环的中断关联的 DDI 中断句柄。

mri_intr_enable(9E)

启用 RX 环上的中断。有关更多信息,请参见Receive Data Path

mri_intr_disable(9E)

禁用 RX 环上的中断。有关更多信息,请参见Receive Data Path

有关详细信息,请参见 mac_group_info(9S)mac_ring_info(9S) 手册页。


注 - mri_tx() 必须仅为传送环设置,而 mri_poll() 必须仅为接收环设置。

注 - 如果某个驱动程序实现了环功能,则 mac_callbacks 结构中的 mc_tx() 入口点必须设置为 NULL。
环组和 SR-IOV

具有 SR-IOV 功能的设备驱动程序使用 MAC_CAPAB_RINGS 功能,通过实现 mgi_getsriov_info(9E) 组入口点来通知框架它们具有 SR-IOV 功能。PF 驱动程序负责实现该入口点。

在调用 mgi_getsriov_info(9E) 后,驱动程序在 mac_sriov_info 结构中返回 SR-IOV 信息。此结构是由框架预分配的,并由驱动程序填充。

PF(Physical Function,物理功能)驱动程序实例与 VF(Virtual Function,虚拟功能)注册相同数量的传送和接收环组。PF 驱动程序通告的这些环组很特殊,用于管理 VF。这些环组中没有任何数据流过。它们用于配置单点传送 MAC 地址、设置 MTU、添加 VLAN 过滤器、删除 VLAN 过滤器、删除 VLAN 硬件以及为 VF 执行 VLAN 标记和剥离。


注 - VF 驱动程序对驱动程序希望加入的 MAC 多播组进行编程。PF 驱动程序不会控制这些地址的编程。

由 PF 驱动程序设置的 msi_vf_index 结构成员捕获与环组对应的 VF 索引。这是与驱动程序调用 pci_plist_getvf(9F) 函数时设备驱动程序使用的索引相同的索引。

有关 SR-IOV 驱动程序的详细信息,请参见Chapter 21, SR-IOV Drivers

硬件校验和负载转移

为了获得关于硬件校验和负载转移支持的数据,框架将在 cap 参数中发送 MAC_CAPA _HCKSUM。请参见硬件校验和负载转移功能信息

要在启用硬件校验和的情况下查询校验和负载转移元数据以及检索每个包的硬件校验和元数据,请使用 mac_hcksum_get(9F)。请参见mac_hcksum_get() 函数标志

要设置校验和负载转移元数据,请使用 mac_hcksum_set(9F)。请参见mac_hcksum_set() 函数标志

有关更多信息,请参见硬件校验和:硬件硬件校验和:MAC 层

硬件校验和负载转移功能信息

要将关于 MAC_CAPAB_HCKSUM 功能的信息传递给框架,驱动程序必须在指向 uint32_tcap_data 中设置以下标志的组合。这些标志指明驱动程序能够为外发包执行的硬件校验和负载转移的级别。

HCKSUM_INET_PARTIAL

1 的补码的部分校验和功能

HCKSUM_INET_FULL_V4

针对 IPv4 包的 1 的补码的完全校验和能力

HCKSUM_INET_FULL_V6

针对 IPv6 包的 1 的补码的完全校验和能力

HCKSUM_IPHDRCKSUM

IPv4 头校验和负载转移功能

mac_hcksum_get()() 函数标志

mac_hcksum_get()flags 参数是以下值的组合:

HCK_FULLCKSUM

计算此包的完整校验和。

HCK_FULLCKSUM_OK

完整校验和已在硬件中通过验证,证实是正确的。

HCK_PARTIALCKSUM

根据传递给 mac_hcksum_get() 的其他参数计算 1 的补码的部分校验和。HCK_PARTIALCKSUM HCK_FULLCKSUM 互斥。

HCK_IPV4_HDRCKSUM

计算 IP 报头校验和。

HCK_IPV4_HDRCKSUM_OK

IP 头校验和已在硬件中通过验证,证实是正确的。

mac_hcksum_set()() 函数标志

mac_hcksum_setflags() 参数是以下值的组合:

HCK_FULLCKSUM

通过 value 参数计算和传递完整校验和。

HCK_FULLCKSUM_OK

完整校验和已在硬件中通过验证,证实是正确的。

HCK_PARTIALCKSUM

通过 value 参数计算和传递部分校验和。HCK_PARTIALCKSUM HCK_FULLCKSUM 互斥。

HCK_IPV4_HDRCKSUM

通过 value 参数计算和传递 IP 头校验和。

HCK_IPV4_HDRCKSUM_OK

IP 头校验和已在硬件中通过验证,证实是正确的。

大段(或大量传送)负载转移

为了查询大段(或大量传送)负载转移支持,框架将在 cap 参数中发送 MAC_CAPAB_LSO,并等待接收在指向 mac_capab_lso(9S) 结构的 cap_data 中返回的信息。框架将分配 mac_capab_lso 结构,并在 cap_data 中传递指向此结构的指针。mac_capab_lso 结构包含一个 lso_basic_tcp_ipv4(9S) 结构和一个 lso_flags 成员。如果驱动程序实例支持对应于 IPv4 上的 TCP 的 LSO,请设置 lso_flags 中的 LSO_TX_BASIC_TCP_IPV4 标志,并将 lso_basic_tcp_ipv4 结构的 lso_max 成员设置为驱动程序实例支持的最大有效载荷大小。

使用 mac_lso_get(9F) 获得每个包的 LSO 元数据。如果为此包启用了 LSO,则将在 mac_lso_get() flags 参数中设置 HW_LSO 标志。在大段的分段过程中使用的最大段大小 (maximum segment size, MSS) 将通过 mss 参数指向的位置返回。有关更多信息,请参见Large Segment Offload