目录
文章目录
前文列表
《DPDK — 安装部署》
《DPDK — TestPMD》
DPDK PDUMP
librte_pdump 库是在 DPDK 16.07 版本引入的一个 DPDK 数据包捕获开发框架,dpdk-pdump Tool 就是基于 librte_pdump 库开发出来的 DPDK App 抓包工具。因为 DPDK App 是完全内核旁路(Kernel-bypass)的用户态网络协议栈,所以无法使用 tcpdump 工具来进行抓包。使用 dpdk-pdump 可以用于抓取被 DPDK App 接管的指定接口、队列的数据包。
官方文档:http://doc.dpdk.org/guides/howto/packet_capture_framework.html
安装部署
DPDK PDUMP 依赖基于 libpcap 的 PMD 驱动,需要预先安装:
- libpcap 网络数据包捕获函数库(A system-independent interface for user-level packet capture)。
- libpcap-devel 用于编译和使用基于 libcap 的 PMD 轮询模式驱动程序。
yum install -y libpcap.x86_64 libpcap-devel.x86_64
默认情况下,该驱动程序被禁用,需要通过修改 Target Env 的配置文件来开启:
$ vim dpdk-18.08/x86_64-native-linuxapp-gcc/.config
CONFIG_RTE_LIBRTE_PMD_PCAP=y
CONFIG_RTE_LIBRTE_PDUMP=y
$ make
最后再安装 pdump:
$ cd dpdk-18.08/app/pdump
$ make && make install
librte_pdump 库
Server 端:
- rte_pdump_init():初始化 PDUMP 抓包框架,并创建线程和 Server Socket。Socket 在线程里监听 Client Start/Stop 抓包的请求。
- rte_pdump_uninit():清理退出 PDUMP 抓包框架,并关闭线程和 Server Socket。
Client 端:
- rte_pdump_enable():在一个端口队列开启抓包。
- rte_pdump_enable_by_deviceid():在一个设备 ID(vdev 名称或者 PCI 地址)和队列抓包。
每调用一次这两个 API,PDUMP 库就会创建一个独立的 Client Socket,并发送 pdump enable 的请求到 Server。Server 监听到这个请求就会通过给定的端口或者设备 ID 以及队列的组合,在 Ethernet RX/TX 注册回调函数,之后 Server 就会镜像数据包到一个新的内存池,并将让它们在 Client 传入的 rte_ring 队列上入队。Server 会发送响应给 Client 关于请求处理的状态。在收到 Server 的回应后,Client 的 Socket 就关闭了。
- rte_pdump_disable():在一个端口队列停止抓包。
- rte_pdump_disable_by_deviceid():停止在一个设备 ID(vdev 名称或者 PCI 地址)和队列抓包。
每调用一次这两个 API,PDUMP 库就会创建一个独立的 Client Socket,并发送 pdump disable 的请求到 Server。Server 监听到这个请求就会通过给定的端口或者设备 ID 以及队列的组合,在 Ethernet RX/TX 删除回调函数,之后 Server 就会镜像数据包到一个新的内存池,并将让它们在 Client 传入的 rte_ring 队列上入队。Server 会发送请求回应给 Client 关于请求处理的状态。在收到 Server 的回应后,Client 的 Socket 就关闭了。
- rte_pdump_set_socket_dir():设置 Server 或 Client 的 Socket 文件的路径。注意,这个接口是非线程安全的,并在 DPDK 18.05 版本移除。
运行原理
在使用 dpdk-pdump 时,dpdk-pdump 会作为 Secondary(从)进程,并依附于 Primary(主)进程,即 DPDK App,例如:testpmd、l2fwd、l3fwd。Primary 进程作为 Server 端,需要 include rte_pdump 库进行开发,初始化 PDUMP 抓包框架。Secondary 进程作为 Client 端,同样需要 include rte_pdump 库进行开发,通过标准接口向 Primary 进程发送 Start/Stop 抓包的请求,然后 Primary 进程会拷贝一份数据包到 Ring 中,Secondary 进程再从 Ring 中读取出来,并发送到 PCAP PMD 设备。可以保存为 pcap 文件,或发送至 Linux Console 等外部接口输出。
注意:因为 dpdk-pdump 抓包存在报文 Copy 的过程,所以对性能会有影响,建议仅在 DEBUG 时使用。
PDUMP 的工作流程
- DPDK App 采用 rx-worker-tx 的模型进行报文的处理,其中调用 rte_pdump_init 会启动 dump_thread;
- dpdk-pdump 采用 secondary 模式启动,与 App 共享 mmap 映射的内存空间;
- dodk-pdump 启动过程中会创建 mbuf_pool 和 ring,用于后续接收 App 中报文的拷贝;
- dpdk-pdump 会通过 rte_eth_dev_attach 方式创建 vdev,且采用 eth_pcap 驱动进行初始化,留意 init 中的 open_tx_pcap;
- dpdk-pdump 向 App 发送开启抓包的消息(UDP 方式),消息内容为前面创建的 mbuf_pool、ring 以及抓包的 Port 和对应的 Queue;
- App 中的 dump_thread 收到消息后,获取相应信息,在 Port 上注册 call_back 函数;
- 对于开启抓包的 Port,在 rx_burst/tx_burst 时会先调用 call_back(回调函数),这里对应 pdump_rx/pdump_tx,它会由 mbuf_pool 中分配 mbuf 进行报文的复制,同时 enqueue 到 ring 中;(mbuf_pool 和 ring 在步骤 3 中创建,在步骤 5 中传递给 App);
- dpdk-pdump 进行 ring 的 dequeue 操作获取拷贝报文;
- 拷贝报文通过 rte_eth_tx_burst 发送给 vdev;
- vdev 通过 eth_pcap 的 tx_pkt_burst 发送报文,即调用 eth_pcap_tx_dumper 完成报文的 pcap 存储(pcap_dump)。
操作步骤
以 testpmd 为例,使用 dpdk-pdump 进行抓包。
- 启动 testpmd 作为 Primary 进程
$ ./testpmd -l 1,2,3 --socket-mem 1024 -n 4 --log-level=8 -- -i
- 启动 dpdk-pdump 作为 Secondary 进程
$ ./build/app/dpdk-pdump -- --pdump 'port=0,queue=*,rx-dev=/tmp/capture.pcap'
- 查看 pcap 文件
$ tcpdump -nr /tmp/capture.pcap
dpdk-pdump 指令
./build/app/dpdk-pdump -- --pdump '(port=<port id> | device_id=<pci id or vdev name>), (queue=<queue_id>), (rx-dev=<iface or pcap file> | tx-dev=<iface or pcap file>), [ring-size=<ring size>], [mbuf-size=<mbuf data size>], [total-num-mbufs=<number of mbufs>]' [--server-socket-path=<server socket dir>] [--client-socket-path=<client socket dir>]
- –pdump:是必选的,多个 --pdump 可以用于捕获不同的接口和队列
- –server-socket-path:是可选的,指定 Server socket 的目录。root 用户就默认为 /var/run/.dpdk/,非 root 用户默认为 ~/.dpdk/。
- –client-socket-path:是可选的,指定 Client Socket 的目录。root 用户就默认为 /var/run/.dpdk/,非 root 用户默认为 ~/.dpdk/。
–pdump 的子参数:
- port:需要被抓包的以太网 Port id。
- device_id:需要被抓包的以太网 PCI 设备的 id。
- queue:需要被抓包的以太网 PCI 设备的 Queue id,
*
表示所有队列。 - rx-dev:入口方向被抓取的报文,参数应该是一个 pcap 文件名或者 Linux 接口。
- tx-dev:出口方向被抓取的报文,参数应该是一个 pcap 文件名或者 Linux 接口。
NOTE:如果两个方向都分别要,tx-dev 与 rx-dev 应该被同时指定两个不同的文件或者接口;如果两个方向都同时要,tx-dev 与 rx-dev 应该指定相同的文件或接口。
-
ring-size:指定用于存储数据包的 Ring 的大小,默认是16384。用于主程序向抓包程序入队用的。
-
mbuf-sizze:MBuf Data 的 大小,用于 mempool 的创建,默认是2176。用于入队列的mbuf用的。用于主程序向抓包程序传数据用的。
-
total-num-mbufs:指创建 mbug 的个数,默认值为 65535。
-
–server-socket-path 和 --client-socket-path 用于指定 Server 和 Client 之间进行通信的 Socket 路径。默认的,DPDK App 的 Socket 路径为 /var/run/dpdk/rte/,但是在多 DPDK App 进行的环境中,可能回味每个 DPDK App 指定不同的路径,从而隔离开配置空间。此时就需要使用 --server-socket-path 来指定特定 DPDK App 的配置路径了。
注意:DPDK 18.05 后把 rte_pdump_set_socket_dir() 函数移除了,所以 --server-socket-path 是不生效的,依旧会到 /var/run/dpdk/rte 路径下读取配置和 Socket 文件。
Use the Data Plane Development Kit Pdump Feature with Open vSwitch*
https://software.intel.com/content/www/us/en/develop/articles/dpdk-pdump-in-open-vswitch-with-dpdk.html
相关阅读: