前言

自从加入中心的网络组,一直在参与用户态协议栈的相关工作。目前接触的用户态一般都使用Intel的DPDK包转发框架,实现kernel-bypass。网卡被DPDK接管后,内核的ifconfig,tcpdump等工具将不再适用(由mTCP中修改后的DPDK绑定的网卡,是可以通过ifconfig命令看到的),所以开发调试中,抓包就成了问题。一般对端没有使用DPDK的话,会选择在对端使用tcpdump抓包或者经过交换机,在交换机抓包。但是,如果想在DPDK的出入口抓包,或者收发两端都使用DPDK,使用Linux提供的工具直接抓包就很难实现。本文主要介绍DPDK的抓包工具pdump。

pdump库是在DPDK 16.07版本引入的,提供了一个抓包调试功能。在$(RTE_SDK)/app目录下有一个dpdk-pdump工具,可以用于抓取指定接口、队列 的网络包。

pdump抓包原理

  • pdump抓包采用的是 CS 模式,即应用进程作为server,拷贝数据包,提供给dpdk-pdump;dpdk-dump作为client,接收数据包,并dump到pcap文件中

  • dpdk-pdump作为 secondary 进程 依附于 primary 进程

  • primary进程中启动 server 端,初始化pdump抓包框架任务;

  • dpdk-pdump进程是作为 client端 向primary进程发送开始/停止抓包请求;

  • primary进程 拷贝 一份数据包到ring中,secondary进程从ring中读取出来,保存为pcap文件;

使用 DPDK pdump的抓包框架如下图所示:

pdump工作流程

  1. A采用rx-worker-tx的模型进行报文的处理,其中调用rte_pdump_init会启动dump_thread;

  2. pdump采用secondary模式启动,与A共享mmap映射的内存空间;

  3. pdump启动过程中会创建mbuf_pool和ring,用于后续接收A中报文的拷贝;

  4. pdump会通过rte_eth_dev_attach方式创建vdev,且采用eth_pcap驱动进行初始化,留意init中的open_tx_pcap;

  5. pdump向A发送开启抓包的消息(UDP方式),消息内容为前面创建的mbuf_pool、ring以及抓包的port和对应的queue;

  6. A中的dump_thread收到消息后,获取相应信息,在port上注册call_back函数;

  7. 对于开启抓包的port,在rx_burst/tx_burst时会先调用call_back,这里对应pdump_rx/pdump_tx,它会由mbuf_pool中分配mbuf进行报文的复制,同时enqueue到ring中;(mbuf_pool和ring在步骤3中创建,在步骤5中传递给A);

  8. pdump进行ring的dequeue操作获取拷贝报文;

  9. 拷贝报文通过rte_eth_tx_burst发送给vdev;

  10. vdev通过eth_pcap的tx_pkt_burst发送报文,即调用eth_pcap_tx_dumper完成报文的pcap存储(pcap_dump)。

pdump使用

1.编译选项

  • pdump依赖 libpcap 库和 libpcap-dev

  • 依赖基于libpcap的PMD驱动,使用时需要打开config中的PCAP和PDUMP,即

1
2
CONFIG_RTE_LIBRTE_PMD_PCAP=y (config/common_base)
CONFIG_RTE_LIBRTE_PDUMP=y

2. 使用

  • 在程序初始化过程中调用rte_pdump_init,启动dump_thread进行消息的监听:
1
2
3
4
#ifdef RTE_LIBRTE_PDUMP
/* initialize packet capture framework */
rte_pdump_init(NULL);
#endif
  • 在程序退出前调用rte_pdump_uninit进行资源的释放:
1
2
3
4
#ifdef RTE_LIBRTE_PDUMP
/* uninitialize packet capture framework */
rte_pdump_uninit();
#endif
  • 启动pdump程序,发送抓包命令,进行抓包。

参考

DPDK pdump Library and pdump Tool
DPDK capture原理