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

退出打印视图

更新时间: 2014 年 9 月
 
 

GLDv3 数据路径

    数据路径入口点包括以下组件:

  • 由驱动程序导出、由 GLDv3 框架调用以发送包的回调。

  • 驱动程序为传输流量控制和接收包而调用的 GLDv3 框架入口点。


注 - 如果驱动程序实现了环功能,则驱动程序发送和接收的所有数据都将通过特定于环的入口点进行传送。

传输数据路径

GLDv3 框架调用的用来向驱动程序传送消息块的传送入口点的类型取决于底层驱动程序对 MAC_CAPAB_RINGS 的支持。如果驱动程序支持 MAC_CAPAB_RINGS 功能,则框架将调用 mri_tx(9E) 环入口点。否则,框架将调用 mc_tx(9E) 入口点。

相应地,设备驱动程序必须在 mc_tx()mri_tx() 中提供传送入口点的指针。有关更多信息,请参见GLDv3 MAC Registration Data Structuresmr_rget() Entry Point

示例 19-6  mc_tx()mri_tx() 入口点
mblk_t *
xx_m_tx(void *arg, mblk_t *mp)
{
        xx_t    *xxp = arg;
        mblk_t   *nmp;

        mutex_enter(&xxp->xx_xmtlock);

        if (xxp->xx_flags & XX_SUSPENDED) {
                while ((nmp = mp) != NULL) {
                        xxp->xx_carrier_errors++;
                        mp = mp->b_next;
                        freemsg(nmp);
                }
                mutex_exit(&xxp->xx_xmtlock);
                return (NULL);
        }

        while (mp != NULL) {
                nmp = mp->b_next;
                mp->b_next = NULL;

                if (!xx_send(xxp, mp)) {
                        mp->b_next = nmp;
                        break;
                }
                mp = nmp;
        }
        mutex_exit(&xxp->xx_xmtlock);

        return (mp);
}

以下各节将讨论与将数据传输至硬件相关的主题。

流量控制

如果驱动程序因硬件资源不足而无法发送包,则驱动程序将返回无法发送的包的子链。此后,在更多描述符可用时,驱动程序必须调用 mac_tx_update(9F)mac_tx_ring(9F) 以通知框架。驱动程序将根据它是否实现了环功能来调用这两个函数之一。

硬件校验和:硬件

如果驱动程序指定了硬件校验和支持(请参见Hardware Checksum Offload),则驱动程序必须执行以下任务:

  • 使用 mac_hcksum_get(9F) 检查每个包的硬件校验和元数据。

  • 对硬件进行编程,以执行所需的校验和计算。

大段负载转移

如果驱动程序指定了 LSO 功能(请参见Large Segment (or Send) Offload),则驱动程序必须使用 mac_lso_get(9F) 来查询是否必须在包上执行 LSO。

虚拟 LAN:硬件

管理员配置 VLAN 时,MAC 层将通过 mc_tx() 入口点,在外发包传递至驱动程序之前将所需的 VLAN 头添加到外发包中。不过,如果硬件支持 VLAN 标记,则标记将转移到硬件上。有关更多详细信息,请参见mr_gget() Entry Point

接收数据路径

接收数据路径可能是由中断驱动的,也可能是由轮询驱动的。

接收中断数据路径

注意:如果驱动程序不支持环功能,请在驱动程序的中断处理程序中调用 mac_rx(9F) 函数,以将包含一个或多个数据包的链沿栈向上传送到 MAC 层。避免在调用 mac_rx()mac_rx_ring() 的过程中持有互斥锁或其他锁。需要特别指出的是,在调用 mac_rx()mac_rx_ring() 期间不得持有传输线程可使用的锁。

在中断模式中,只要数据包链被 NIC 接收并且可供驱动程序选取,就将从驱动程序向框架发送数据包链。数据包链由通过 b_next 彼此连接的一个或多个 mblk_t 组成,并且使每个数据包的处理开销降低。通过调用 mac_rx_ring() 入口点,接收的数据包将以中断模式向上传递给框架。

void mac_rx_ring(mac_handle_t mh, mac_ring_handle_t mrh, mblk_t *mp_chain, int64_tmr_gen_num)

通过 mac_register() 函数向内核进行注册后,mh_handle 将响应设备驱动程序获取的 MAC 句柄。mrh _handle 是作为 mr_rget() 调用的一部分传递给驱动程序的框架环句柄。如果接收环是通过 mri_start() 入口点启动的,则 mr_gen_num 必须设置为框架指定的生成号。驱动程序提供的环生成号将与框架内保留的环生成号进行匹配。如果它们不匹配,则接收的数据包将被视为来自早期指定的环的过时数据包,并将被丢弃。

接收轮询数据路径

除了能够通过由中断驱动的路径接收数据包之外,框架还支持基于轮询的数据路径。在轮询模式下,在栈中运行的内核线程通过一个轮询入口点从驱动程序提取数据包。这样便使栈能够有效控制何时处理数据包以及使用何种优先级,同时可基于实际负载减少进入系统的中断数量。此外,轮询还使栈能够对接收的通信流量更有效地实施带宽限制,这在虚拟化方案中尤其重要。主机根据需要在中断模式和轮询模式之间切换。当环处于轮询模式时,驱动程序不应使用 mac_rx_ring() 函数传送通过接收环接收的数据包。这能够得以保证,因为中断在轮询模式下被禁用。相反,框架将调用驱动程序作为 mac_ring_info 结构的一部分公开的 mri_poll() 入口点。有关更多信息,请参见mr_rget() Entry Point

在中断模式和轮询模式之间切换

缺省情况下,环在启动以后应处于中断模式。只要环处于中断模式,它就应通过入口点以链的形式向上传递接收的数据包。当主机将环切换到轮询模式时,它将通过 mac_intr 结构(是之前通过 mac_ring_info 结构公开的)调用入口点来禁用其中断。

硬件校验和:MAC 层

如果驱动程序指定了硬件校验和支持(请参见Hardware Checksum Offload),则驱动程序必须使用 mac_hcksum_set(9F) 函数将硬件校验和元数据与包关联。

虚拟 LAN:MAC 层

VLAN 包必须连同标记一起传递至 MAC 层。切勿剥离数据包中的 VLAN 头。但是,如果硬件支持 VLAN 剥离,并且框架已请求硬件剥离 VLAN 标记,则硬件可以剥离 VLAN 标记以提高性能。有关更多信息,请参见mr_gget() Entry Point