以下是一个简单的DPDK使用最新版nDPI过滤HTTP协议的示例代码:
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <rte_eal.h>
#include <rte_ethdev.h>
#include <rte_mbuf.h>
#include "ndpi_api.h"
#define RX_RING_SIZE 128
#define TX_RING_SIZE 512
#define NUM_MBUFS 8191
#define MBUF_CACHE_SIZE 250
#define BURST_SIZE 32
static const struct rte_eth_conf port_conf_default = {
.rxmode = { .max_rx_pkt_len = ETHER_MAX_LEN }
};
struct app_lcore_params {
uint16_t port;
} __rte_cache_aligned;
static struct app_lcore_params lcore_params[RTE_MAX_LCORE];
static void packet_handler(struct rte_mbuf *pkt, uint16_t portid) {
/* Perform nDPI protocol detection */
ndpi_detection_module_struct *ndpi_mod = ndpi_init_detection_module();
ndpi_flow_info_t flow_info;
memset(&flow_info, 0, sizeof(flow_info));
ndpi_protocol_t detected_proto = NDPI_PROTOCOL_UNKNOWN;
if (pkt->packet_type & RTE_PTYPE_L2_ETHER) {
if (pkt->packet_type & RTE_PTYPE_L3_IPV4) {
detected_proto =
ndpi_detection_process_packet(ndpi_mod,
pkt->buf_addr + pkt->data_off,
pkt->data_len,
&flow_info);
} else if (pkt->packet_type & RTE_PTYPE_L3_IPV6) {
detected_proto =
ndpi_detection_process_packet6(ndpi_mod,
pkt->buf_addr + pkt->data_off,
pkt->data_len,
&flow_info);
}
}
/* Check if protocol is HTTP */
if (detected_proto == NDPI_PROTOCOL_HTTP ||
detected_proto == NDPI_PROTOCOL_SSL) {
printf("HTTP packet received on port %u\n", portid);
/* Print out some HTTP information */
struct ndpi_http_response_t *http_response =
ndpi_match_http_request(ndpi_mod, &flow_info);
if (http_response != NULL) {
printf("Method: %s\n", http_response->method.ptr);
printf("URI: %s\n", http_response->uri.ptr);
printf("Version: %s\n", http_response->version.ptr);
}
}
rte_pktmbuf_free(pkt);
ndpi_exit_detection_module(ndpi_mod, NULL);
}
static int lcore_main(__attribute__((unused)) void *arg) {
uint16_t port;
RTE_LCORE_FOREACH_SLAVE(port) {
if (lcore_params[rte_lcore_id()].port != port)
continue;
printf("Initializing RX/TX queues for port %u...\n", port);
struct rte_eth_dev_info dev_info;
rte_eth_dev_info_get(port, &dev_info);
struct rte_eth_rxconf rx_conf = dev_info.default_rxconf;
struct rte_eth_txconf tx_conf = dev_info.default_txconf;
/* Configure the Ethernet device. */
rte_eth_dev_configure(port, 1, 1, &port_conf_default);
/* Allocate and set up RX queue(s). */
rte_eth_rx_queue_setup(port, 0, RX_RING_SIZE,
rte_eth_dev_socket_id(port),
&rx_conf,
mbuf_pool);
/* Allocate and set up TX queue(s). */
rte_eth_tx_queue_setup(port, 0, TX_RING_SIZE,
rte_eth_dev_socket_id(port),
&tx_conf);
/* Start the Ethernet port. */
rte_eth_dev_start(port);
printf("Port %u initialized.\n", port);
}
while (1) {
RTE_LCORE_FOREACH_SLAVE(port) {
if (lcore_params[rte_lcore_id()].port != port)
continue;
struct rte_mbuf *bufs[BURST_SIZE];
const uint16_t nb_rx = rte_eth_rx_burst(port, 0, bufs, BURST_SIZE);
for (uint16_t i = 0; i < nb_rx; i++)
packet_handler(bufs[i], port);
rte_delay_us(10);
}
}
return 0;
}
static int parse_args(int argc, char **argv) {
int num_ports = rte_eth_dev_count_avail();
if (num_ports == 0)
return -1;
for (int i = 0; i < RTE_MAX_LCORE; ++i) {
lcore_params[i].port = UINT16_MAX;
}
int opt;
while ((opt = getopt(argc, argv, "p:")) != EOF) {
switch (opt) {
case 'p':
lcore_params[0].port = strtoul(optarg, NULL, 10);
break;
default:
return -1;
}
}
if (lcore_params[0].port == UINT16_MAX)
return -1;
return 0;
}
int main(int argc, char **argv) {
int ret;
ret = rte_eal_init(argc, argv);
if (ret < 0)
rte_exit(EXIT_FAILURE, "Error with EAL initialization\n");
argc -= ret;
argv += ret;
if (parse_args(argc, argv) < 0) {
printf("Usage: %s -p <port_id>\n", argv[0]);
rte_exit(EXIT_FAILURE, "Invalid command-line arguments\n");
}
/* Create the mbuf pool. */
struct rte_mempool *mbuf_pool =
rte_pktmbuf_pool_create("MBUF_POOL", NUM_MBUFS * RTE_MAX_LCORE,
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");
RTE_LCORE_FOREACH_SLAVE(ret) {
if (lcore_params[ret].port == UINT16_MAX)
continue;
rte_eal_remote_launch(lcore_main, NULL, ret);
}
lcore_main(NULL);
return 0;
}
请注意,此示例代码并未完全测试,可能需要进行修改才能正常工作。此外,如果要使用最新版的nDPI库,请确保已正确安装和配置该库。