XDP 程序丢包 0.1%,如何定位是驱动还是程序逻辑问题

解读

0.1% 的丢包率在国内金融、电商大促、运营商 5G 核心网等场景已足以触发 SLA 告警。面试官想确认候选人能否在“黑盒”表象下,把问题拆成“驱动层”和“程序层”两个正交维度,并用可量化的方法给出排障路径。核心考点:

  1. 能否把“丢包”拆成“未进入 XDP”“XDP 主动丢弃”“驱动 DMA 失败”三类;
  2. 能否用国内线上可落地的工具链(bcc、libbpf、perf、ethtool、pktgen)做分层取证;
  3. 能否给出可重复的压测脚本及通过/失败判定标准,而不是拍脑袋调参数。

知识点

  1. XDP 在 Linux 中的 4 条执行路径:XDP_DROP、XDP_PASS、XDP_TX、XDP_REDIRECT;驱动只在 XDP_PASS 时把帧放入内核协议栈。
  2. 驱动丢包常见计数:rx_nohandler、rx_crc_errors、rx_missed_errors、rx_fifo_errors、rx_length_errors、rx_over_errors;可通过 ethtool -S 查看。
  3. BPF 程序自身丢包常见计数:xdp.*drop(由 BPF_PROG_TYPE_XDP 的 tracepoint 输出);若程序内调用 bpf_xdp_adjust_head 失败或自行返回 XDP_DROP,也会累加。
  4. 国内内核版本(CentOS 8/Alibaba Cloud Linux 3/Anolis OS 8)默认打开 CONFIG_BPF_EVENTS,可用 bpftrace 一行脚本挂 kprobe/xdp_return_frame 统计真正“掉地”的帧数。
  5. 压力模型:用 pktgen(内核态)或 dpdk-pktgen(用户态)打 14 Mpps 64 B 小包,把 CPU 其中一个核打满,观察丢包率是否随 pps 线性增长;若线性增长,瓶颈在驱动;若突然跳变,瓶颈在程序逻辑。
  6. 对照实验:把 XDP 程序换成最简单的 “XDP_PASS” 模式,若丢包率归零,则驱动无问题;若仍有 0.1%,则驱动或硬件 FIFO 溢出。
  7. 国内云厂商限速模型:ENAV2/ENA3、Mellanox CX5/6 网卡在超 95% 线速时会硬丢包,需确认是否触发了流控或 PPS 上限。
  8. 量化标准:连续 5 次 60 s 测试,丢包率置信区间 <0.05% 方可认为修复。

答案

定位分五步,全部用线上可落地的命令,无需改内核:

  1. 复现与基线
    a. 用 pktgen 打 10 Gbps/14 Mpps 64 B 小包,持续 60 s,记录总发 tx_cnt 与收 rx_cnt,确认丢包 0.1% 可复现。
    b. 在同一物理机、同一队列、同一 NUMA 节点执行,排除跨 NUMA 干扰。

  2. 区分驱动还是 XDP 程序
    a. ethtool -S eth0 | grep -E ‘rx_(nohandler|crc|missed|fifo|length|over)’,若任何一项 >0,则驱动已丢。
    b. 挂载 tracepoint:bpftrace -e ‘tracepoint:xdp/xdp_exception { @[probe] = count(); }’,若 xdp_exception 有计数,说明程序返回 XDP_DROP 或异常。
    c. 对照实验:把 XDP 程序换成 return XDP_PASS;重新打流,若丢包率降到 0,则驱动无问题,矛头指向程序逻辑;若仍有 0.1%,则驱动或硬件 FIFO 溢出。

  3. 若驱动丢包
    a. 逐步降速到 9 Gbps,观察丢包率是否线性下降;若线性,则为硬限速,需调大网卡 RX Ring:ethtool -G eth0 rx 4096(或厂商允许的最大值)。
    b. 检查是否开流控:ethtool -a eth0,若 RX 流控 off 而仍丢包,可临时打开验证:ethtool -A eth0 rx on tx on。
    c. 确认 CPU 处理核未跑满:mpstat -P ALL 1,若 softirq% > 80%,把网卡中断绑到空闲核:echo 3 > /proc/irq/24/smp_affinity_list。

  4. 若程序逻辑丢包
    a. 在 BPF 程序内用 BPF_MAP_TYPE_PERCPU_ARRAY 自定义计数器,对每条返回 XDP_DROP 的路径 +1;再用 bpftool map dump 观察哪条分支丢包。
    b. 检查 bpf_xdp_adjust_head/bpf_xdp_adjust_tail 返回值,若 <0 说明调整失败导致丢包。
    c. 若程序用 map 做限速(如令牌桶),查看桶是否设置过严:把初始令牌数翻倍再测,若丢包消失,则属策略过严而非性能瓶颈。

  5. 量化与闭环
    a. 修复后连续跑 5 轮 60 s 测试,丢包率置信区间 <0.05% 视为通过。
    b. 把以上步骤写成内部 Wiki 脚本,下次回归可直接一键执行,减少 80% 重复人力。

通过以上五步,可在 30 分钟内给出“驱动”或“程序”维度的量化证据,避免拍脑袋调参,满足国内一线互联网公司性能测试对“可重复、可量化、可闭环”的要求。

拓展思考

  1. 若业务要求 0.01% 丢包,如何设计 10 Gbps 下的采样精度?
    答:至少发 1e7 个包才能看到 100 个丢包,采样误差 1%。用 pktgen 打 200 s 可发 2.8e9 包,丢包 2800 个,误差降至 0.2%,满足精度。
  2. 若网卡支持 XDP_HW_OFFLOAD,如何把上述步骤迁移到硬件计数器?
    答:Mellanox 驱动提供 mlx5e_xdp_drop 计数,可用 ethtool -S 查看;同时确认固件 >= 16.35.1000,否则 offload 有静默丢包 bug。
  3. 在容器场景下,如何排除 veth/xdp 附件点丢失?
    答:宿主机上 bpftool net 查看 prog_id 是否 attach 到容器 veth 的 ingress 钩子;若 attach 失败,内核版本需 >= 5.8 且打开 CONFIG_XDP_VETH。
  4. 如果丢包只在 UDP 大包(4 KB)出现,如何进一步拆分?
    答:先确认网卡是否开 LRO/GRO,再检查 BPF 程序是否对大于 PAGE_SIZE 的帧调用 adjust_tail 失败;可临时关 GRO 验证:ethtool -K eth0 gro off。