你好, 我用的是18.11 dpdk的ip_pipeline程序, 使其过流 1GB/s, 发现0核CPU占用很高(ip_pipeline主函数的for循环中已经加了usleep, 应该不会占用很高的CPU). 使用 perf 发现占用主要在 dw_readl 上面.
perf 情况:
- 61.60% 61.60% [kernel] [k] dw_readl
+ 5.89% ret_from_fork
1.57% ordered_events__flush
+ 1.25% 0xe1
+ 1.13% x86_64_start_kernel
1.02% hist_entry_iter__add
+ 1.02% 0xd1
+ 22.14% 0.00% [kernel] [k] __irqentry_text_start
+ 22.11% 0.00% [kernel] [k] handle_irq
+ 22.08% 0.01% [kernel] [k] handle_irq_event_percpu
+ 19.31% 0.00% [unknown] [k] 0xffffffff8168dd6d
+ 19.30% 0.00% [unknown] [k] 0xffffffff81698bef
+ 19.28% 0.00% [unknown] [k] 0xffffffff8102d26
+ 19.28% 0.00% [unknown] [k] 0xffffffff811337d
+ 19.27% 0.00% [unknown] [k] 0xffffffff8113033
+ 19.25% 0.00% [unknown] [k] 0xffffffff8113015
+ 17.14% 0.02% [kernel] [k] i2c_dw_isr
+ 14.50% 0.00% [unknown] [k] 0xffffffffa04f406
这是我的硬件信息:
CPU 型号 : Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz
网卡型号及版本: i40e 1.5.10-k, 两张网卡
网卡固件: 6.01 0x8000372b 0.0.0
lscpi 查看网卡信息:
03:00.0 Ethernet controller: Intel Corporation Ethernet Controller X710 for 10GbE SFP+ (rev 02)
03:00.1 Ethernet controller: Intel Corporation Ethernet Controller X710 for 10GbE SFP+ (rev 02)
网卡驱动使用: vfio-pci
修改 ip_pipeline 主要功能:
/* Script */
if (app.script_name)
cli_script_process(app.script_name,
app.conn.msg_in_len_max,
app.conn.msg_out_len_max);
#include <unistd.h>
/* Dispatch loop */
for ( ; ; ) {
conn_poll_for_conn(conn);
usleep(5000);
conn_poll_for_msg(conn);
kni_handle_request();
}
CLI 启动参数:
./ip_pipeline -c f -- -s ./l2fwd.cli
命令行内容:
mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
link LINK0 dev 0000:03:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
link LINK1 dev 0000:03:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
;link LINK2 dev 0000:06:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
;link LINK3 dev 0000:06:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
pipeline PIPELINE0 period 10 offset_port_id 0 cpu 0
pipeline PIPELINE0 port in bsz 32 link LINK0 rxq 0
pipeline PIPELINE0 port in bsz 32 link LINK1 rxq 0
;pipeline PIPELINE0 port in bsz 32 link LINK2 rxq 0
;pipeline PIPELINE0 port in bsz 32 link LINK3 rxq 0
pipeline PIPELINE0 port out bsz 32 link LINK0 txq 0
pipeline PIPELINE0 port out bsz 32 link LINK1 txq 0
;pipeline PIPELINE0 port out bsz 32 link LINK2 txq 0
;pipeline PIPELINE0 port out bsz 32 link LINK3 txq 0
pipeline PIPELINE0 table match stub
pipeline PIPELINE0 table match stub
;pipeline PIPELINE0 table match stub
;pipeline PIPELINE0 table match stub
pipeline PIPELINE0 port in 0 table 0
pipeline PIPELINE0 port in 1 table 1
;pipeline PIPELINE0 port in 2 table 2
;pipeline PIPELINE0 port in 3 table 3
thread 1 pipeline PIPELINE0 enable
pipeline PIPELINE0 table 0 rule add match default action fwd port 1
pipeline PIPELINE0 table 1 rule add match default action fwd port 0
;pipeline PIPELINE0 table 2 rule add match default action fwd port 3
;pipeline PIPELINE0 table 3 rule add match default action fwd port 2
我做了这些测试
1. 使用E5-2620 CPU的i40e设备做同样的测试, 没有这个问题
2. 依然使用用 i7-6700 i40e 设备, 回滚到18.05版本测试, 没有这个问题.
3. 回退代码定位到导致这个问题的代码节点为 4205c7ccec4fc2aeafe3e7ccf6b028d9476fccaf , 这个节点之前代码没有问题, 之后有问题.
4. 我发现这个i7-6700设备上有两个内核模块: idma64. i2c_designware, 当我卸载这两个模块时, 不会出现这种现象.
5. 我发现出现问题的时候一个中断的调用频率达到每秒好几万! 没有问题的时候这个中断调用频率为0.
6. 在18.11的基础上, 在i40e_dev_start函数中
if (dev->data->dev_conf.intr_conf.rxq == 0) {
rte_eal_alarm_set(I40E_ALARM_INTERVAL,
i40e_dev_alarm_handler, dev);
} 别的 {
/* 在回调注册后启用 uio intr */
rte_intr_enable(intr_handle);
}
改成
/* 在回调注册后启用 uio intr */
rte_intr_enable(intr_handle);
if (dev->data->dev_conf.intr_conf.rxq == 0) {
rte_eal_alarm_set(I40E_ALARM_INTERVAL,
i40e_dev_alarm_handler, dev);
}
那么这个问题就不会出现了.
从上面的场景看, 如果我想正常使用18.11 dpdk版本, 要么卸载模块, 要么添加 rte_intr_enable, 但不知道这样做会有什么影响? 请问这是一个 bug 吗?