[PIPELINE0]
type = MASTER
[PIPELINE1]
type = ROUTER
input_ports = 0
output_ports = 1
tables = LPM4
[PORT0]
type = PHY
dev_name = net_ixgbe0
[PORT1]
type = PHY
dev_name = net_ixgbe1
[TABLE0]
type = LPM4
size = 1024
actions = DROP, FORWARD
[ROUTE]
table = LPM4
default_action = DROP
rules = 192.168.0.0/24 FORWARD 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <rte_eal.h>
#include <rte_ethdev.h>
#include <rte_mbuf.h>
#include <rte_pipeline.h>
#include <rte_lpm.h>
#include <signal.h>
#include "ini.h" // 使用 inih 库进行 INI 文件解析
#define NUM_MBUFS 8191
#define MBUF_CACHE_SIZE 250
#define BURST_SIZE 32
static volatile bool force_quit;
struct rte_mempool *mbuf_pool;
struct rte_pipeline *pipeline;
struct rte_lpm *lpm_table;
typedef struct {
char type[32];
int input_ports[16];
int output_ports[16];
char tables[16][32];
} pipeline_config_t;
pipeline_config_t pipeline_config;
// 信号处理函数,用于处理终止信号
static void signal_handler(int signum) {
if (signum == SIGINT || signum == SIGTERM) {
printf("\nSignal %d received, preparing to exit...\n", signum);
force_quit = true;
}
}
// 解析 INI 文件的回调函数
static int ini_handler(void* user, const char* section, const char* name, const char* value) {
pipeline_config_t* pconfig = (pipeline_config_t*)user;
if (strcmp(section, "PIPELINE1") == 0) {
if (strcmp(name, "type") == 0) {
strncpy(pconfig->type, value, sizeof(pconfig->type));
} else if (strcmp(name, "input_ports") == 0) {
pconfig->input_ports[0] = atoi(value); // 简化处理,只处理单个端口
} else if (strcmp(name, "output_ports") == 0) {
pconfig->output_ports[0] = atoi(value); // 简化处理,只处理单个端口
} else if (strcmp(name, "tables") == 0) {
strncpy(pconfig->tables[0], value, sizeof(pconfig->tables[0])); // 简化处理,只处理单个表
}
}
return 1;
}
// 初始化管道
static void init_pipeline(void) {
struct rte_pipeline_params pipeline_params = {
.name = "IP_PIPELINE",
.socket_id = rte_socket_id(),
};
pipeline = rte_pipeline_create(&pipeline_params);
if (pipeline == NULL) {
rte_exit(EXIT_FAILURE, "Cannot create pipeline\n");
}
// 初始化 LPM 表
struct rte_lpm_config lpm_config = {
.max_rules = 1024,
.number_tbl8s = 256,
.flags = 0,
};
lpm_table = rte_lpm_create("LPM_TABLE", rte_socket_id(), &lpm_config);
if (lpm_table == NULL) {
rte_exit(EXIT_FAILURE, "Cannot create LPM table\n");
}
// 添加路由规则
rte_lpm_add(lpm_table, rte_cpu_to_be_32(0xC0A80000), 24, 1); // 192.168.0.0/24 -> port 1
// 配置管道的输入端口、表和输出端口
// 这里省略了具体的配置代码,实际应用中需要根据配置文件进行配置
}
// 主循环函数,处理数据包并实现 IP 数据包处理管道
static void ip_pipeline_main_loop(void) {
unsigned lcore_id = rte_lcore_id();
printf("Entering main loop on lcore %u\n", lcore_id);
while (!force_quit) {
rte_pipeline_run(pipeline);
}
}
int main(int argc, char **argv) {
// 初始化 DPDK 环境
int ret = rte_eal_init(argc, argv);
if (ret < 0)
rte_exit(EXIT_FAILURE, "Error with EAL initialization\n");
force_quit = false;
// 注册信号处理函数
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
// 创建内存池,用于存放数据包
mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", NUM_MBUFS, MBUF_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
if (mbuf_pool == NULL)
rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n");
// 解析配置文件
if (ini_parse("config.ini", ini_handler, &pipeline_config) < 0) {
printf("Can't load 'config.ini'\n");
return 1;
}
// 打印解析后的配置
printf("Pipeline type: %s\n", pipeline_config.type);
printf("Input port: %d\n", pipeline_config.input_ports[0]);
printf("Output port: %d\n", pipeline_config.output_ports[0]);
printf("Table: %s\n", pipeline_config.tables[0]);
// 初始化管道
init_pipeline();
// 进入主循环,处理数据包并实现 IP 数据包处理管道
ip_pipeline_main_loop();
// 清理资源
rte_pipeline_free(pipeline);
rte_mempool_free(mbuf_pool);
return 0;
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。