什么是Rx flexible descriptor
Intel E810系列网卡支持Rx flexible descriptor,这是一种可以通过软件定义格式并配置到网卡硬件中的Rx descriptor(吸收描述符)。Flexible descriptor中的metadata和flags字段可以根据需求和运用处景,自定义为特定的内容。
Rx flexible descriptor的浸染
一样平常Rx descriptor的浸染在于网卡吸收和解析数据包后,向驱动软件传达数据包的状态,并携带必要信息。由于硬件限定,传统的descriptor的格式是固定的,在任何运用处景下,面对不同的协议,其内容都是同等的。这会导致数据处理过程去世板,且须要额外的CPU运算资源来将这些原始数据处理成软件须要的数据。Flexible descriptor则是在此根本上,让用户可以自定义descriptor所携带的内容。经由配置后的网卡硬件可以按照flexible descriptor的分外格式,解析数据包并将指定内容直接填入descriptor的相应字段中。这一步简化了后续的软件处理过程,从而大大提高了处理速率,也使得功能更加丰富。
如何定义Rx flexible descriptor
通过利用E810网卡所支持的DDP(Dynamic Device Personalization)package文件,网卡可以在启动时加载DDP中已配置的flexible descriptor格式,并通过RXDID选择对应的flexible descriptor来利用。而根据DDP类型的不同(OS default,COMMS和Custom等),能选择利用的flexible descriptor格式也不同。以是用户在利用时须要特殊把稳DDP package的类型和版本,以及DPDK的版本。
E810网卡对flexible descriptor的支持
E810系列网卡供应了63个Descriptor Builder Profile,可以用来配置63种Rx descriptor格式,包括传统的16字节和32字节的两种legacy descriptor。这些profile都有对应的RXDID,网卡硬件通过由软件写入到相应寄存器中的RXDID值来决定要利用的Rx descriptor格式,软件也可根据收到的Rx descriptor中的RXDID字段验证当下所利用的Rx descriptor格式。
Rx flexible descriptor的通用格式
点击图片可放大
个中,用户可以灵巧配置的字段为
1. metadata (FlexiMD.0 ~ FlexiMD.5)
2. flags (FlexiFlags.0 ~ FlexiFlags.2)
如上文所说,不同的DDP package文件支持的Rx flexible descriptor格式也有所不同。RXDID被用来标示descriptor profile的ID。OS default package利用的RXDID范围为2-15,COMMS package利用的RXDID范围为16-31,剩余的RXDID则被保留以供用户自定义利用。此外,RXDID#0对应16字节的legacy descriptor,RXDID#1对应32字节的legacy descriptor,RXDID#7为硬件保留,这对所有DDP package都适用。
下面以RXDID#16(Comms package Generic default RX descriptor)为例先容一下Rx flexible descriptor的构造
个中,FlexiMD.0-1为Hash值,FlexiMD.2-3为Flow ID(用于flow director),FlexiMD.4-5可以灵巧利用,用于韶光戳或其他赞助数据。如在RXDID#18(Auxiliary IPv4 RX descriptor)中,其内容即为IPv4报文所特有的头部信息:
FlexiMD.4(AUX0): IPHDR1 - IPv4 头部 "TTL" 和 "Protocol" 字段
FlexiMD.5(AUX1): IPHDR0 - IPv4 头部 "Ver", Hdr Len" 和 "Type of Service" 字段
也便是说,这个flexible descriptor通过硬件提取了吸收到的IPv4报文头部的紧张信息,而这些信息可以被直接用于后续DPDK PMD的处理中。
除此之外,还有其他的flexible descriptor格式,包括但不限于如下:
在FlexiMD.4-5位置,不同flexible descriptor格式均定义了各自所须要的赞助信息。
除了metadata,flexible descriptor中的flags字段根据格式不同其详细内容也有所不同,紧张用于表示和“VLAN“以及”TUNNEL“干系的信息,如隧道类型,L2Tag,扩展报文头部选项等。限于篇幅这里不做展开。
DPDK源码解读
于DPDK ICE PMD,我们可以利用如下命令在Testpmd中配置Rx queues,使得driver能够提取收包行列步队中数据包的协议信息并填入mbuf中。
-w 18:00.0,proto_xtr=<queues:protocol>[<queues:protocol>...]
-w 18:00.0,proto_xtr=<protocol>
可用的协议,即“protocol”可选参数为:vlan,ipv4,ipv6,ipv6_flow,tcp。这5个参数对应的正是RXDID#17-#21。
在函数ice_init_proto_xtr中,
for (i = 0; i < pf->lan_nb_qps; i++) {
pf->proto_xtr[i] = ad->devargs.proto_xtr[i] != PROTO_XTR_NONE ?
ad->devargs.proto_xtr[i] :
ad->devargs.proto_xtr_dflt;
if (pf->proto_xtr[i] != PROTO_XTR_NONE) {
uint8_t type = pf->proto_xtr[i];
ice_proto_xtr_ol_flag_params[type].required = true;
proto_xtr_enable = true;
}
}
PF解析参数并记录每个Rx queue对应的协议类型,继而在函数ice_rx_queue_setup
rxq->drop_en = rx_conf->rx_drop_en;
rxq->vsi = vsi;
rxq->rx_deferred_start = rx_conf->rx_deferred_start;
rxq->proto_xtr = pf->proto_xtr != NULL ?
pf->proto_xtr[queue_idx] : PROTO_XTR_NONE;
以及函数ice_program_hw_rx_queue中
rxdid = ice_proto_xtr_type_to_rxdid(rxq->proto_xtr);
PMD_DRV_LOG(DEBUG, "Port (%u) - Rx queue (%u) is set with RXDID : %u",
rxq->port_id, rxq->queue_id, rxdid);
/ Enable Flexible Descriptors in the queue context which
allows this driver to select a specific receive descriptor format
/
regval = (rxdid << QRXFLXP_CNTXT_RXDID_IDX_S) &
QRXFLXP_CNTXT_RXDID_IDX_M;
/ increasing context priority to pick up profile ID;
default is 0x01; setting to 0x03 to ensure profile
is programming if prev context is of same priority
/
regval |= (0x03 << QRXFLXP_CNTXT_RXDID_PRIO_S) &
QRXFLXP_CNTXT_RXDID_PRIO_M;
ICE_WRITE_REG(hw, QRXFLXP_CNTXT(rxq->reg_idx), regval);
选择对应的RXDID并写入寄存器,奉告网卡硬件该当利用的Rx flexible descriptor格式。
如果支持SRIOV并启用VF,DPDK IAVF driver配置Rx flexible descriptor的逻辑略有不同。目前,IAVF默认优先利用的是RXDID#22所对应的格式(IAVF_RXDID_COMMS_OVS_1),和RXDID#16相似,但改换了Hash和Flow ID的位置。VF将首先通过kernel PF查询加载的DDP package所支持的flexible descriptor格式,如果支持RXDID#22,则选择该值;如果不支持,则选择RXDID#1,然后再通过kernel PF写入寄存器。DPDK IAVF设置RXDID的函数为iavf_configure_queues。
#ifndef RTE_LIBRTE_IAVF_16BYTE_RX_DESC
if (vf->vf_res->vf_cap_flags &
VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC &&
vf->supported_rxdid & BIT(IAVF_RXDID_COMMS_OVS_1)) {
vc_qp->rxq.rxdid = IAVF_RXDID_COMMS_OVS_1;
PMD_DRV_LOG(NOTICE, "request RXDID == %d in "
"Queue[%d]", vc_qp->rxq.rxdid, i);
} else {
vc_qp->rxq.rxdid = IAVF_RXDID_LEGACY_1;
PMD_DRV_LOG(NOTICE, "request RXDID == %d in "
"Queue[%d]", vc_qp->rxq.rxdid, i);
}
#else
if (vf->vf_res->vf_cap_flags &
VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC &&
vf->supported_rxdid & BIT(IAVF_RXDID_LEGACY_0)) {
vc_qp->rxq.rxdid = IAVF_RXDID_LEGACY_0;
PMD_DRV_LOG(NOTICE, "request RXDID == %d in "
"Queue[%d]", vc_qp->rxq.rxdid, i);
} else {
PMD_DRV_LOG(ERR, "RXDID == 0 is not supported");
return -1;
}
#endif