DPDK应用持续出现rx_phy_discard_packets问题求助
问题:ConnectX-6网卡在70-85Gbps区间出现rx_phy_discard_packets增长
背景信息
我正在使用DPDK从Mellanox ConnectX-6网卡端口获取并处理数据包,目标流量为100Gbps。用于打印网卡统计信息的线程代码如下:
static void lcore_main_display_stats(void) { struct rte_eth_xstat_name xstat_names[MAX_XSTATS]; int retval; int num_xstats = 0; struct rte_eth_stats stats; struct rte_eth_xstat xstats[MAX_XSTATS]; uint64_t prev_reading = 0; uint64_t current_diff = 0; while (MAIN_KEEP_RUNNING == main_keep_running) { fflush(stdout); if (PORT_ACTIVE == downlink1_port.port_status) { // Get standard statistics retval = rte_eth_stats_get(downlink1_port.port_id, &stats); // Get extended statistics names num_xstats = rte_eth_xstats_get_names(downlink1_port.port_id, xstat_names, MAX_XSTATS); // Get extended statistics retval = rte_eth_xstats_get(downlink1_port.port_id, xstats, num_xstats); current_diff = stats.ibytes - prev_reading; Gbps = (current_diff / 1024.0 / 1024.0 / 1024.0) * 8; prev_reading = stats.ibytes; // Get standard statistics retval = rte_eth_stats_get(downlink1_port.port_id, &stats); if (retval != 0) { fprintf(stderr, "Failed to get standard stats for port %u: %s\n", downlink1_port.port_id, rte_strerror(-retval)); return; } printf("\n--- Standard Statistics ---\n"); printf("Packets received: %" PRIu64 "\n", stats.ipackets); printf("Packets transmitted: %" PRIu64 "\n", stats.opackets); printf("Bytes received: %" PRIu64 "\n", stats.ibytes); printf("Giga bytes received: %f\n", ((double)stats.ibytes / 1024.0 / 1024.0 / 1024.0)); printf("Bytes transmitted: %" PRIu64 "\n", stats.obytes); printf("RX errors: %" PRIu64 "\n", stats.ierrors); printf("TX errors: %" PRIu64 "\n", stats.oerrors); printf("Missed packets: %" PRIu64 "\n", stats.imissed); printf("Missed packets%%: %f\n", ((double)stats.imissed/stats.ipackets)*100); for (int i = 0; i < num_xstats; i++) { if (!strcmp("rx_phy_discard_packets", xstat_names[i].name)) { printf("%s: %" PRIu64 "\n", xstat_names[i].name, xstats[i].value); printf("Discarded packet percentage: %f%%\n", ((double)xstats[i].value / stats.ipackets) * 100); } } printf("RX no mbuf errors: %" PRIu64 "\n", stats.rx_nombuf); printf("Gbps: %f \n", Gbps); } sleep(ONE_SECOND_SLEEP_TIME); fflush(stdout); } }
异常现象
rx_phy_discard_packets(物理层接收丢弃包)在吞吐量处于70-85Gbps区间时持续增长,当吞吐量达到90Gbps后停止增长imissed(错过的数据包)数值保持初始值无增长- 已尝试将MTU调整至9600,问题仍未解决
统计输出示例:
Packets received: 6113919634 Packets transmitted: 0 Bytes received: 6369429122446 Giga bytes received: 5931.993129 Bytes transmitted: 0 RX errors: 0 TX errors: 0 Missed packets: 148596 Missed packets%: 0.002430 rx_phy_discard_packets: 12258048 Discarded packet percentage: 0.200494% RX no mbuf errors: 0 Gbps: 78.914868
原因分析
- 物理层流量适配瓶颈:ConnectX-6的PHY层在中等速率区间(70-85Gbps)可能无法高效处理突发流量,当速率提升到90Gbps时,流量模式可能更稳定(如大包占比升高),PHY层缓冲压力降低,丢弃停止
- RX队列配置不匹配:DPDK的RX队列描述符数量不足,或者队列与CPU核绑定不合理,导致PHY层无法及时将数据包递送到DPDK的mbuf,触发物理层丢弃
- 硬件缓冲调度策略:ConnectX系列的硬件缓冲(Packet Buffer)在中等速率下可能预留部分资源给其他功能(如RDMA),导致RX侧缓冲不足;高速率时调度策略切换为优先保障转发,缓冲资源向RX倾斜
- 流量特征影响:70-85Gbps区间可能小包占比更高,小包会增加PHY层的帧处理开销,更容易触发丢弃;而90Gbps时大包占比提升,单帧处理效率更高,减少了PHY层的压力
排查建议
- 检查网卡硬件缓冲配置:使用
mlxconfig工具查看LOG_BAR、RX_BUFFER_SIZE等参数,确认RX路径分配的缓冲是否充足 - 调整DPDK RX队列参数:尝试增加RX队列描述符数量(建议设置为2048或4096),同时确保每个RX队列绑定到独立的CPU核,避免核资源竞争
- 分析流量特征:用
rte_pdump抓取流量,统计小包(<64字节)和大包的占比,确认是否在70-85Gbps区间小包占比偏高 - 查看更多扩展统计:除
rx_phy_discard_packets外,检查rx_phy_errors、rx_buffer_overflows等指标,定位具体丢弃原因 - 验证驱动版本:确认DPDK版本与MLNX_OFED驱动版本匹配,建议升级到DPDK 22.11+、MLNX_OFED 5.8+等稳定版本
解决方案
- 优化RX队列配置:将RX描述符数量调整为4096,根据CPU核数配置足够的RX队列,每个队列绑定到独占CPU核(通过
rte_eth_dev_configure和rte_eth_rx_queue_setup实现) - 调整硬件缓冲:使用
mlxconfig增大RX_BUFFER_SIZE(如设置为4096KB),关闭不需要的功能(如RDMA)以释放更多缓冲给RX路径 - 优化流量模式:若小包占比高是诱因,可在发送端合并小包,或在网卡侧开启LRO(Large Receive Offload)功能(需DPDK驱动支持)
- 调整内存配置:增大mbuf池的大小,确保RX队列有足够的mbuf可用(尽管当前
rx_nombuf为0,适当增大rte_pktmbuf_pool_create的参数可预留冗余) - 升级驱动与固件:更新ConnectX-6的网卡固件到最新版本,同时升级DPDK和MLNX_OFED驱动至匹配的稳定版本
内容的提问来源于stack exchange,提问作者Alsayed Alsisi
相关产品推荐
相关产品推荐

