You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

DPDK绑定网卡无法接收PC B数据的技术求助

咱们一步步拆解可能的问题,你的配置和代码里有几个明显的问题点,大概率是这些导致收不到包:

一、先排查DPDK网卡绑定与基础配置问题
  • 确认网卡是否正确从内核解绑并绑定到DPDK兼容驱动
    从你的EAL日志看,网卡是0000:00:1f.6,驱动是net_e1000_em,但要确保你已经用dpdk-devbind.py工具把网卡从原生内核驱动(比如e1000e)解绑,绑定到vfio-pci或者uio_pci_generic。可以执行dpdk-devbind.py --status查看状态,确认目标网卡的Driver列是DPDK兼容驱动,而不是内核原生驱动。如果还是内核驱动,那DPDK应用虽然能初始化,但实际无法接管网卡收发。
  • 检查DPDK端口是否开启混杂模式
    port_init函数里,一定要调用rte_eth_promiscuous_enable(0)开启混杂模式。默认情况下,网卡会过滤掉目的MAC不是自身的帧,如果你没开混杂,只有目标MAC匹配的帧才会被收到。尤其是你用PC B ping的时候,ping会先发送ARP请求(广播帧),如果没开混杂,DPDK网卡可能收不到广播帧。
二、PC B的DPDK发送代码存在致命错误

你的发送代码里有几个直接导致收不到包的问题:

  • 源MAC和目的MAC完全相同
    你设置的s_addrd_addr都是0x94,0xC6,0x91,0x14,0xAB,0xDD,这相当于给自己发数据包,PC A的网卡根本不会接收这个帧(因为目的MAC不是它自己的,也不是广播/组播)。你需要把d_addr改成PC A网卡的实际MAC地址,s_addr改成PC B网卡的实际MAC地址。可以用ip link show命令在两台机器上分别查看各自网卡的MAC。
  • 未检查mbuf分配是否成功
    代码里rte_pktmbuf_alloc(mbuf_pool)没有判断返回值,如果mbuf池分配失败,pkt[i]会是NULL,后续操作会出问题,甚至导致程序崩溃。一定要加判断:
    pkt[i] = rte_pktmbuf_alloc(mbuf_pool);
    if (pkt[i] == NULL) {
        rte_exit(EXIT_FAILURE, "Failed to allocate mbuf for packet %d\n", i);
    }
    
  • 自定义EtherType可能被过滤
    你设置的ether_type = 0x0a00是自定义值,不是标准的EtherType(比如IPv4是0x0800,ARP是0x0806)。如果你的PC A的DPDK接收代码有过滤EtherType的逻辑,会收不到这个自定义类型的帧。测试阶段可以改成标准类型,或者确保接收端没有过滤逻辑。
三、关于PC B ping PC A的特殊说明

你提到用PC B ping PC A,但要注意:当PC A的网卡被DPDK绑定后,操作系统的TCP/IP栈就不再管理这个网卡了。也就是说,你在PC A上给这个网卡配置的IP,内核是无法处理的,ping请求到达PC A的网卡后,内核不会响应ICMP回复。而且如果你的DPDK应用只是用rte_eth_rx_burst轮询,你需要自己解析收到的ARP和ICMP帧,才能看到ping的数据包——不是没收到,只是你没解析输出而已。

四、其他排查步骤
  • 检查网线连接:虽然现在大部分网卡支持自动MDI-X,但还是要确认网线是好的,或者换一根网线试试。
  • 确认DPDK应用的端口号是否正确:你发送用的是端口0,接收端的DPDK应用是不是也在监听端口0?可以用rte_eth_dev_count_avail()确认可用端口数量,避免端口号写错。
  • 打印接收日志验证:修改你的接收代码,打印收到的包信息,确认到底有没有收到包:
    uint16_t nb_rx = rte_eth_rx_burst(0, 0, rx_pkts, BURST_SIZE);
    if (nb_rx > 0) {
        for (int i = 0; i < nb_rx; i++) {
            struct ether_hdr *eth = rte_pktmbuf_mtod(rx_pkts[i], struct ether_hdr *);
            printf("Received packet, dst MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
                   eth->d_addr.addr_bytes[0], eth->d_addr.addr_bytes[1],
                   eth->d_addr.addr_bytes[2], eth->d_addr.addr_bytes[3],
                   eth->d_addr.addr_bytes[4], eth->d_addr.addr_bytes[5]);
            rte_pktmbuf_free(rx_pkts[i]);
        }
    }
    

内容的提问来源于stack exchange,提问作者coiedulci

火山引擎 最新活动