Zoom out
的实例中包含了五个DPDK pipeline
处理模块,每个pipeline
作为一个特定功能的包处理模块。一个报文从进入到发送,会有两个不同的路径,上面的路径有三个模块(解析、分类、发送),下面的路径有四个模块(解析、查表、修改、发送)。Zoom in
的图示中代表在查表的pipeline
中有两张查找表,报文根据不同的条件可以通过一级表或两级表的查询从不同的端口发送出去。
DPDK
的pipeline
是由三大部分组成的:
Pipeline要素 | 选项 |
---|---|
逻辑口(port) | 硬件队列,软件队列,IP Fragmentation, IP Reassembly, 发包器,内核网络接口,Source/Sink |
查找表(Table) | Exact Match, 哈希, Access Control List(ACL),Longest Prefix Match(LPM),数组,Pattern Matching |
处理逻辑(action) | 缺省处理逻辑:发送到端口,发送到查找表,丢弃。 报文修改逻辑:压入队列,弹出队列,修改报文头 报文流:限速、统计、按照APPID分类 报文加速:加解密、压缩 负载均衡 |
现在DPDK
支持的pipeline
有以下几种:
Packet I/O
Flow classification
Firewall
Routing
Metering
- Traffic Mgmt
DPDK以上几个pipleline都是DPDK在packet framework中直接提供给用户的,用户可以通过简单的配置文件去利用这些现成的pipline,加快开发速度。
以Routing pipline为例子可以有以下构建形式:
DPDK Routing Pipeline
dpdk发送数据包
在DPDK中发送数据包通常涉及以下步骤:
-
初始化 EAL(Environment Abstraction Layer)。
-
配置并初始化网络设备。
-
为数据包分配 mbuf。
-
设置数据包内容。
-
使用 rte_eth_tx_burst() 函数发送数据包。
以下是一个简单的示例代码,演示如何在DPDK中发送数据包:
#include <rte_eal.h>
#include <rte_ethdev.h>
#include <rte_mbuf.h>
#define RTE_ETH_TX_BUFFER_SIZE 1024
int main(int argc, char **argv) {
// 初始化EAL
int ret = rte_eal_init(argc, argv);
if (ret < 0) {
rte_exit(EXIT_FAILURE, "Cannot init EAL\n");
}
// 配置并初始化网络设备
uint16_t port_id = 0; // 假设我们使用的是第一个网络设备
struct rte_eth_conf port_conf = {0};
ret = rte_eth_dev_configure(port_id, 1, 1, &port_conf);
if (ret < 0) {
rte_exit(EXIT_FAILURE, "Cannot configure device\n");
}
// 启用设备
ret = rte_eth_dev_start(port_id);
if (ret < 0) {
rte_exit(EXIT_FAILURE, "Cannot start device\n");
}
// 为数据包分配 mbuf
struct rte_mbuf *mbufs[RTE_ETH_TX_BUFFER_SIZE];
unsigned int i;
for (i = 0; i < RTE_ETH_TX_BUFFER_SIZE; i++) {
mbufs[i] = rte_pktmbuf_alloc(rte_eth_dev_socket_id(port_id), 0);
if (mbufs[i] == NULL) {
rte_exit(EXIT_FAILURE, "Cannot allocate mbuf\n");
}
}
// 设置数据包内容
for (i = 0; i < RTE_ETH_TX_BUFFER_SIZE; i++) {
// 填充mbufs[i]的data部分
// ...
}
// 发送数据包
uint16_t tx_pkts = RTE_ETH_TX_BUFFER_SIZE;
ret = rte_eth_tx_burst(port_id, 0, mbufs, tx_pkts);
if (ret < tx_pkts) {
// 处理没有发送的数据包
// ...
}
// 释放mbuf
for (i = 0; i < RTE_ETH_TX_BUFFER_SIZE; i++) {
rte_pktmbuf_free(mbufs[i]);
}
return 0;
}
在实际应用中,您需要根据您的具体需求和环境来调整上述代码。例如,您可能需要根据实际的网络设备ID和配置来修改port_id
和port_conf
。您还需要确保在调用rte_eth_tx_burst()
之前,数据包已正确填充到对应的mbuf中。