问题现象

业务程序使用 x710 网卡,收发一万多个巨帧包后就无法正常收包,查看网卡收发包统计发现 imissed 字段一直增加,问题必现。

环境信息

  1. dpdk 版本
    dpdk-16.04
  2. 网卡 pci 信息
    24:00.0 Ethernet controller: Intel Corporation Ethernet Controller X710 for 10GbE SFP+ (rev 02)
    24:00.1 Ethernet controller: Intel Corporation Ethernet Controller X710 for 10GbE SFP+ (rev 02)
    
  3. 接口统计信息
    第一次查看:

         rx_bytes: 124163766000rx_packets: 13772588rx_no_buffer_count: 0rx_errors: 0rx_missed_errors:13755556tx_bytes: 33291648tx_packets: 16224tx_broadcast: 0tx_multicast: 0tx_dropped: 0tx_errors: 0
    

    第二次查看:

         rx_bytes: 124176852000rx_packets: 13774042rx_no_buffer_count: 0rx_errors: 0rx_missed_errors:13757010tx_bytes: 33291648tx_packets: 16224tx_broadcast: 0tx_multicast: 0tx_dropped: 0tx_errors: 0
    

    从上述信息看出,tx_packets 没有增长,rx_packet 与 rx_missed 同时在增长,rx_no_buffer_count 为 0 表示没有出现 mbuf 泄露,同时确认网络流量非常少,rx_packets 的数据减掉 rx_missed_errors 的数据大约在一万5千左右,判断问题为程序无法收包。

  4. 收包 mempool 的 mbuf_size 为 2048

debug 过程记录

1. 查看接口收发包函数

收包函数:i40e_recv_scattered_pkts
发包函数:i40e_xmit_pkts_vec

2. 查看接口 rte_eth_devices[port]->data 中的重要字段

(gdb) print *rte_eth_devices[0]->data
$4 = {name = "24:0.0", '\000' <repeats 25 times>,rx_queues = 0x600025f12940,tx_queues = 0x600025f128c0,nb_rx_queues = 8,nb_tx_queues = 8,..................................dev_private = 0x60000019d880,dev_link = {link_speed = 10000,link_duplex = 1,link_autoneg = 1,link_status = 1},dev_conf = {link_speeds = 0,rxmode = {mq_mode = ETH_MQ_RX_RSS,max_rx_pkt_len = 9728,split_hdr_size = 0,header_split = 0,hw_ip_checksum = 1,hw_vlan_filter = 0,hw_vlan_strip = 0,hw_vlan_extend = 0,jumbo_frame = 1,hw_strip_crc = 0,enable_scatter = 0,enable_lro = 0,enable_hash_offload = 0},txmode = {mq_mode = ETH_MQ_TX_NONE,pvid = 0,hw_vlan_reject_tagged = 0 '\000',hw_vlan_reject_untagged = 0 '\000',hw_vlan_insert_pvid = 0 '\000'},.......................................rx_mbuf_alloc_failed = 0,.................................port_id = 0 '\000',promiscuous = 1 '\001',scattered_rx = 1 '\001',all_multicast = 0 '\000',dev_started = 1 '\001',

从 data 结构能够确认如下信息:

  1. 接口混淆模式开启
  2. 接口正常 up 且 link 状态为 up
  3. 接口收发包队列配置正常
  4. 网卡 rx_mode 中使能了 hw_ip_checksum、jumbo_frame,并将支持的最大收包大小 max_rx_pkt_len 设置为了 9728。

3. 查看收包队列重要字段

(gdb) print *(struct i40e_rx_queue *)rte_eth_devices[0]->data->rx_queues[0]
$8 = {mp = 0x60002d1f9ec0,rx_ring = 0x60002624ee80,rx_ring_phys_addr = 937750144,sw_ring = 0x60002624dd40,nb_rx_desc = 512,rx_free_thresh = 32,rx_tail = 412,...............................rx_free_trigger = 31,...............................rxrearm_nb = 0,rxrearm_start = 0,mbuf_initializer = 0,port_id = 0 '\000',crc_len = 4 '\004',queue_id = 0,reg_idx = 1,drop_en = 0 '\000',qrx_tail = 0x600064128004 "\230\001",vsi = 0x60000011bb40,rx_buf_len = 2048,rx_hdr_len = 0,max_pkt_len = 9728,.........................

rx_ring 与 sw_ring 配置正常,描述符大小为 512 个,其它字段未见明显异常,同时注意到 rx_buf_len 设置大小为 2048,max_pkt_len 设置为 9728,这种配置时网卡会使用多个 mbuf 保存巨帧,驱动的收包函数会使用 xxx_recv_scattered_xxx 类型。

查看 rx_tail 指向的 rx 描述符数据:

(gdb) print /x ((struct i40e_rx_queue *)rte_eth_devices[1]->data->rx_queues[0])->rx_ring[412]
$55 = {read = {pkt_addr = 0xe8e3e8e300000000,hdr_addr = 0x2000600003019,rsvd1 = 0x0,rsvd2 = 0x0},wb = {qword0 = {lo_dword = {mirr_fcoe = {mirroring_status = 0x0,fcoe_ctx_id = 0x0},l2tag1 = 0x0},hi_dword = {rss = 0xe8e3e8e3,fcoe_param = 0xe8e3e8e3,fd_id = 0xe8e3e8e3}},qword1 = {status_error_len = 0x2000600003019},.....................................}
}

上述信息中 pkt_addr 的地址明显不太正常。

提问环节

  1. 使用的驱动高版本是否有更新?

    无更新,收包函数代码完全一致。

  2. debug 观察到的疑点
    rx_tail 指向的下一个要处理的收包描述符上的报文地址异常,分析驱动代码,不应该存在这种情况,说明可能是网卡填充描述符出现了异常。

  3. pcie 侧是否存在问题?
    lspci -nvv 查看异常接口状态,与正常接口对比,没有发现异常点,暂且排除。

尝试异常恢复

做了如下测试:

  1. 接口 down、up 不能恢复正常
  2. 重启引擎后仍旧收了几万个包后不能收包
    如果是 pcie 异常,重启引擎让驱动重新初始化也不能恢复,上述测试进一步排除了 pcie 的问题,怀疑可能是网卡已经处于某种异常工作状态。

l2fwd 对照测试发现的问题

考虑到可能有其它因素干扰且问题必现,我判断如果是驱动侧的问题,使用 l2fwd 理论上也应该能够复现出问题。于是进行了如下测试:

在配置 rx_mode 开启 hw_ip_checksum 与 jumbo_frame 并设置 max_rx_pkt_len 为 9728 的条件下,进行了如下对比实验:

  1. 测试创建 mbuf dataroom 为 9728 + headroom 大小的 mempool
    正常收发包。

  2. 创建 mbuf dataroom 为 2048 + headroom 大小的 mempool
    收发几百个包后就无法收包。

  3. 在 2 的基础上,将 l2fwd 修改为只收包不发包的工作模式,能够持续收包,表明问题出在发包上

进行了上述测试后,问题缩小到 l2fwd 收发包使用的 mempool 创建的 mbuf 结构中的 dataroom 大小上,可这个大小是怎样影响到收发包过程的呢?

dpdk 中处理巨帧的两种工作模式

  1. 巨帧由一个 mbuf 的 dataroom 保存,这种方式称为 singlesegs,表明由一个 mbuf 装载报文
  2. 巨帧拆成多个 mbuf,拼成 mbuf 链的形式保存,这种方式可称为 multisegs 模式,表明由多个 mbuf 组成的链表共同装载报文

xxx_recv_scattered_xxx 这种收包函数支持 multisegs 模式,它需要使用匹配的支持 multisegs 模式的发包函数,否则会出现发包异常。
那网卡如何知道要用哪种模式?
其实是驱动侧在上层调用 xxx_dev_start 接口时,会将每个收包队列的 rx_buf_len 写入到网卡寄存器中,网卡寄存器检查此大小与 mtu 的关系就能够判断使用哪种工作模式处理报文。

当 rx_buf_len 大于等于 mtu 的时候,使用 singlesegs,当 rx_buf_len 小于 mtu 的时候使用 multisegs 模式。同时驱动侧也会做类似的检查来使用匹配的收包函数,但是发包函数的选择却没有使用这些条件,这就可能存在误用的情况。

哪个 i40e 的发包函数支持 multisegs 模式?

写到这里,回顾下 debug 记录中查看接口收发包函数内容:

  1. 收包函数:i40e_recv_scattered_pkts
  2. 发包函数:i40e_xmit_pkts_vec

结合队列信息中 rx_buf_len 的值为 2048,而 max_rx_pkt_len 为 9728,此时会使用 multisegs 模式来收包。阅读代码确定只有 i40e_xmit_pkts 发包函数支持 multisegs 模式,i40e_xmit_pkts_vec 发包函数不支持 multisegs,这两个收发包函数不匹配,就会触发发包异常导致网卡工作异常进而无法收包。

那为什么 l2fwd 会使用 i40e_xmit_pkts_vec 发包函数呢?

分析代码有如下结论:

  1. l2fwd 的 tx_queue_setup 调用中 tx_conf 配置为 NULL
  2. rte_eth_tx_queue_setup 函数中判断到 tx_conf 为空则调用驱动的 dev_infos_get 接口获取默认的 txconf 配置,然后调用底层驱动中的 tx_queue_setup 函数
  3. i40e 驱动中默认的 txconf 配置中将 txq_flags 配置为 ETH_TXQ_FLAGS_NOMULTSEGS |
    ETH_TXQ_FLAGS_NOOFFLOADS
  4. i40e 驱动设置发包函数的时候判断 txq_flags 开启了 ETH_TXQ_FLAGS_NOMULTSEGS |
    ETH_TXQ_FLAGS_NOOFFLOADS 则使用不支持 multsegs 的发包函数

我确定只需要在 tx_queue_setup 的时候传递个 tx_conf 避免使用默认值就能够让 l2fwd 使用支持 multsegs 模式的发包函数,为此对 l2fwd 代码进行如下修改:

Index: main.c
===================================================================
--- main.c
+++ main.c
@@ -114,10 +114,11 @@.rxmode = {.split_hdr_size = 0,.header_split   = 0, /**< Header Split disabled */
-               .hw_ip_checksum = 0, /**< IP checksum offload disabled */
+               .hw_ip_checksum = 1, /**< IP checksum offload disabled */.hw_vlan_filter = 0, /**< VLAN filtering disabled */
-               .jumbo_frame    = 0, /**< Jumbo Frame Support disabled */
+               .jumbo_frame    = 1, /**< Jumbo Frame Support disabled */.hw_strip_crc   = 0, /**< CRC stripped by hardware */
+               .max_rx_pkt_len = 9728,},.txmode = {.mq_mode = ETH_MQ_TX_NONE,
@@ -225,12 +226,6 @@BURST_TX_DRAIN_US;struct rte_eth_dev_tx_buffer *buffer;prev_tsc = 0;timer_tsc = 0;@@ -668,9 +661,13 @@/* init one TX queue on each port */fflush(stdout);
+               struct rte_eth_txconf txconf;
+               memset(&txconf, 0x00, sizeof(txconf));
+               txconf.txq_flags = 0;
+ret = rte_eth_tx_queue_setup(portid, 0, nb_txd,rte_eth_dev_socket_id(portid),
-                               NULL);
+                               &txconf);if (ret < 0)rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup:err=%d, port=%u\n",ret, (unsigned) portid);

修改完成后重新编译并运行 l2fwd,此时收发包正常,使用 perf 观测到热点函数调用如下:

  54.11%  l2fwd             [.] l2fwd_launch_one_lcore45.22%  l2fwd             [.] i40e_recv_scattered_pkts.......................................................0.02%  l2fwd             [.] i40e_xmit_pkts

收包函数使用 i40e_recv_scattered_pkts,发包函数为 i40e_xmit_pkts,这两个收发包函数均支持 multisegs,问题得到解决。按照这个思路排查业务代码,发现业务代码调用 tx_queue_setup 时传递的 tx_conf 参数配置了 ETH_TXQ_FLAGS_NOMULTSEGS | ETH_TXQ_FLAGS_NOOFFLOADS,针对 x710 网卡去掉相应的配置,重新测试问题得到解决。

延伸

写到这里我觉得驱动的这种实现不合理,它不应该将默认的 txq_flags 设置为某个特定的值,高版本应该会修改,查看 dpdk git log 发现在如下 commit 中移除了 tx_conf 的相关配置:

commit 7d1daae8c7d28ae5b2b7fe054d1dc507edb405a9
Author: Qi Zhang <qi.z.zhang@intel.com>
Date:   Wed May 2 11:56:33 2018 +0800

这个 commit 的提交信息如下:

Since we move to new offload APIs, txq_flags is no long needed.
This patch remove the dependence on that.

这个修改并不是为了解决本文描述的问题,只是为了使用新的 offloads 结构而去除了 txq_flags 的配置,而新的 offloads 结构的默认值为 0,就不存在本文描述的问题。

总结

写到最后回顾下发现其实问题在 debug 过程查看的第一个信息中就已经能够明确了,只是由于自己对底层原理不够清楚才忽略了这个信息,这让我想到“要在不疑处存疑”这句名言。有时候自己判断某些信息没有疑问不过是快思考迅速给出的轻松结论,问题可能就在其中隐含,这点需要不断的训练来改善。

想想如果我对 debug 记录中的每处信息都了如指掌,那这类问题的解决速度将会大大加快,这可能是自己向领域专家前进的道路。

dpdk 收发包问题案例:使用不匹配的收发包函数触发的不收包问题定位相关推荐

  1. 超市收银程序_超市收银系统案例|千平超市再开2家,星耀助力门店年关创收...

    思迅天店星耀版收银系统案例_超市收银系统:千平超市再开2家,星耀助力门店年关创收 年关冲刺,收银压力,库存管理...... 都是现在超市老板们的工作重点 近期开业 横溪购物中心和汇隆购物广场 妥妥的千 ...

  2. 实践案例丨GaussDB网络重传/丢包问题定位总结

    摘要:本文将介绍几种常用手段,用于梳理数据库网络故障可能存在的问题,从而快速定位恢复. 1 问题背景 在GaussDB各类问题场景中,网络故障是最难定位及恢复的问题之一,其不仅可能影响着数据库的性能, ...

  3. python count函数用法 comm_Python学习第六天课后练习案例 (主要针对的内容是python函数的定义和使用)...

    Python学习第六天课后练习案例 2019.07.19 1.定义一个函数,该函数可以实现在内部输入一个信息,如果该信息不能转换为正整数,则重新输入,直到能转换为正整数,则对外返回转换的正整数 程序代 ...

  4. 《R语言机器学习:实用案例分析》——1.3节使用函数

    本节书摘来自华章社区<R语言机器学习:实用案例分析>一书中的第1章,第1.3节使用函数,作者[印度] 拉格哈夫·巴利(Raghav Bali)迪潘简·撒卡尔(Dipanjan Sarkar ...

  5. outlook 收件箱分组_如何在Mac版Outlook 2016中禁用统一收件箱(和分组文件夹)

    outlook 收件箱分组 By default, the folder list in Outlook 2016 for Mac is grouped into similar folders, w ...

  6. 超市服务器安装哪个系统好,超市收银系统哪个好?如何挑选到适合自家超市用的收银系统?...

    原标题:超市收银系统哪个好?如何挑选到适合自家超市用的收银系统? 超市收银系统哪个好?如何才能挑选到适合自家超市用的收银系统?我想这是很多商家开店时都会头疼的一件事情.收银系统的好坏直接影响店铺经营的 ...

  7. python正则表达式匹配c语言的函数

    背景 当前在工程中有已经实现好了的很多c函数,由于某些原因,需要在所有c函数中临时加些一样的语句,这些语句最后会删除 解决方案1 参考: https://codeantenna.com/a/Rh6TZ ...

  8. 创新案例|香氛DTC品牌Scentbird从0到月收百万美元的4大增长运营策略

    Scentbird作为一家提供香氛订阅服务的DTC品牌,她旨在影响人们用香氛来表达自己的专属个性与生活态度.自推出以来,Scentbird经历了商业模式的探索.变化和快速发展,一个香水品牌如何能够在推 ...

  9. 流程引擎动态任务实现(收发文流程案例)

    1.  原始需求  收发文流程原始需求如下: 2.  需求说明   2.1. 收文登记 普通环节处理(普通用户任务)   2.2. 收文拟办 选择1:领导阅示(1).领导阅(2).主办(3).协办(4 ...

最新文章

  1. 文本编辑器中查找对话框及功能实现
  2. android高德自定义图标,Android 高德地图显示在线图标
  3. C#后台创建Excel文件的那点事儿
  4. java jee curd_Java / JEE中的有效日志记录–映射的诊断上下文
  5. HDU1114 Piggy-Bank 完全背包
  6. HTML期末作业-网上书城网上书店
  7. x86系统MySQL_deepin20.1系统安装MySQL8.0.23(最美国产Liunx系统,最新,最详细的MySQL8安装教程)...
  8. 直接在电脑屏幕上画画_电脑屏幕保护膜有那些你知道吗?
  9. 远程桌面连接无法全屏显示
  10. MongoDB学习(黑马教程)-7-数据库MongoDB的集合关联
  11. Git 三款经典可视化管理工具-对比分享
  12. 拼音工具类(多音字处理)
  13. arduino水温度传感器数字显示_温度传感器 LM35
  14. 电脑假死卡的动不了_win10电脑突然卡死动不了怎么办 四种方法快速解决电脑卡死...
  15. SAP ABAP BDC录屏 数据导入和检验-实例
  16. 2022哈工大(深圳)计算机854考研经验贴|双非跨考|初试367 复试293
  17. linux命令行 随机排列,有趣的Linux命令行:随机输出唐诗宋词
  18. 两周之后,英特尔或将宣布启用芯片代工:直接4nm,2023年出货?
  19. MIGO BAPI BAPI_GOODSMVT_CREATE 使用汇总
  20. 路由与交换(一):路由概念及基本配置

热门文章

  1. 白盒测试与黑盒测试分别有哪些测试方法?
  2. Android不同APP间共享数据:sharedUserId
  3. Java编程03--XML文件
  4. 一个蒙文系统设计与实现
  5. java 免费图表控件_给你一杯java润润喉 10款免费的图表JS插件
  6. 1.Java基础-注解
  7. 华硕顽石电脑共享名和计算机名称,华硕顽石五代FL8000UF:如同它的名字,像顽石一般实用...
  8. 软件工程实践——软件测评
  9. Mybatis 传入数组参数
  10. 人工智能教程 - 1.2.2 神经网络是如何进行预测的?