DPDK:硬件卸载 UDP 校验和计算不起作用

Dav*_*idA 2 dpdk

我正在使用 Intel X722 NIC 在 Linux 上使用 DPDK 版本 18.11.8 稳定版本。

如果我在软件中计算 IP 和 UDP 校验和,我的应用程序工作正常,但如果我在硬件中计算,则会出现分段错误。这是我的代码:

local_port_conf.txmode.offloads  = local_port_conf.txmode.offloads | DEV_TX_OFFLOAD_IPV4_CKSUM  | DEV_TX_OFFLOAD_UDP_CKSUM;
Run Code Online (Sandbox Code Playgroud)
mb->ol_flags |= PKT_TX_IPV4 | PKT_TX_IP_CKSUM | PKT_TX_UDP_CKSUM; 
mb->l2_len = sizeof(struct ether_hdr);
mb->l3_len = sizeof(struct ipv4_hdr);
mb->l4_len = sizeof(struct udp_hdr);        
p_ip_hdr->hdr_checksum = 0;
p_udp_hdr->dgram_cksum = rte_ipv4_phdr_cksum((const ipv4_hdr*)(mb->l3_len), mb->ol_flags);
Run Code Online (Sandbox Code Playgroud)

rte_ipv4_phdr_cksum() 调用很神秘,我是否理解正确的做法?

可以理解的是,C++编译器给出了警告:

warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
         p_udp_hdr->dgram_cksum = rte_ipv4_phdr_cksum((const ipv4_hdr*)(ptMbuf->l3_len), ptMbuf->ol_flags);
                                                                                      ^
Run Code Online (Sandbox Code Playgroud)

我的代码有什么问题吗?

Vip*_*ese 7

以下是 DPDK 中 IP 和 UDP 硬件校验和卸载所需的步骤:

\n
    \n
  1. 检查硬件是否支持硬件校验和卸载。
  2. \n
  3. 准备数据包 IP 和 UDP 标头字段。
  4. \n
  5. 初始化校验和字段。如果支持部分 UDP 校验和卸载,请使用 IP 伪标头的校验和初始化 UDP 校验和。
  6. \n
\n

注意:Intel NIC X553、X710 和 X722(可能还有其他)仅支持部分 UDP 校验和卸载,

\n

[根据 @maxschlepzig 评论中的查询进行编辑]是否有支持完整 UDP 校验和卸载的 NIC?如果是,是否有某种 DPDK 方法来检查是否完全支持?

\n

[答] 是的,有一个简单的方法可以检查。在NIC 功能中,表 1.1 突出显示了校验和卸载是否可用、部分或不存在。但真正的问题是检查NIC 特定固件的发行说明,因为硬件 ASIC 或固定功能已启用或禁用。

\n

这需要这样的片段:

\n
/* during port configuration */\ntxmode = {\n    .offloads = DEV_TX_OFFLOAD_IPV4_CKSUM | DEV_TX_OFFLOAD_UDP_CKSUM\n};\n\n/* during device configuration */\nif (!(dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_CKSUM) || !(dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPV4_CKSUM)) {\n    rte_panic(" offload not supported");\n}\n\n/* mb is mbuf packet to transmit */\nmb->ol_flags = PKT_TX_IPV4 | PKT_TX_IP_CKSUM | PKT_TX_UDP_CKSUM;\nmb->l2_len = sizeof(struct ether_hdr);\nmb->l3_len = sizeof(struct ipv4_hdr);      \n\nstruct rte_ether_hdr *eth_hdr = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);\nstruct ipv4_hdr *p_ipv4_hdr = (struct ipv4_hdr*) ((char *)eth_hdr + sizeof(struct ether_hdr));\nstruct udp_hdr *p_udp_hdr = (struct udp_hdr *)((unsigned char *) + sizeof(struct ipv4_hdr));\n\n/* update v4 header fields with version, length, ttl, ip and others */\n/* update udp headers */\n\n/* in case hardware offload is unavailable */ \np_udp_hdr->dgram_cksum = rte_ipv4_udptcp_cksum(p_ip_hdr, p_udp_hdr);\np_ip_hdr->hdr_checksum = rte_ipv4_cksum(p_ip_hdr)\n\n/* otherwise, equivalent offloaded checksum computation */ \np_udp_hdr->dgram_cksum = rte_ipv4_phdr_cksum(p_ipv4_hdr, ol_flags);\np_ip_hdr->hdr_checksum = 0; \n
Run Code Online (Sandbox Code Playgroud)\n

[EDIT-2] 感谢 @maxschlepzig 指出l4_lenUDP 校验和卸载不需要。这是仅TX 的 TCP 段卸载l4_len所需的正确信息。

\n

根据 @DavidA 的实时调试,段错误原因被确定为不正确的使用,并且在注释中,代码更新为

\n
@VipinVarghese Thanks so I now have: struct ipv4_hdr* p_ipv4_hdr = rte_pktmbuf_mtod(mb, struct ipv4_hdr *) + mb->l2_len; p_udp_hdr->dgram_cksum = rte_ipv4_phdr_cksum(p_ipv4_hdr, mb->ol_flags); but the udp checksum is still incorrect.\n\nHi David, I believe you have not st the right values. Will update in couple of hours \xe2\x80\x93 Vipin Varghese\n
Run Code Online (Sandbox Code Playgroud)\n

与 David 分享的行动项目之一是更新伪代码,因为真正的问题围绕着DPDk: HW offloaded calculation of UDP checksum not working。感谢 @maxschlepzig 解释了这一切,因为许多人很容易错过注释和实时调试

\n