ZBLOG

dpdk使用nDPI过滤http协议

使用DPDK和nDPI库过滤HTTP协议需要进行以下步骤:

  1. 安装DPDK并配置环境变量,使其能够正常运行。
  2. 在代码中使用DPDK提供的API初始化网卡接口,并绑定到对应的物理网卡上。
  3. 在代码中引入nDPI库,并初始化该库。
  4. 使用nDPI API对接收到的数据包进行解析和分类,根据判断结果进行处理。

下面是一些基本代码示例,仅供参考:

#include <rte_ethdev.h>
#include <rte_mbuf.h>
#include <ndpi_api.h>

#define RX_RING_SIZE 1024
#define TX_RING_SIZE 1024

#define NUM_MBUFS 8191
#define MBUF_CACHE_SIZE 250

// 初始化 DPDK 环境和网卡接口
int init_dpdk(char* port_name) {
    int ret;

    // 初始化 DPDK 环境
    ret = rte_eal_init(argc, argv);
    if (ret < 0)
        rte_exit(EXIT_FAILURE, "Cannot init EAL\n");

    // 绑定物理网卡接口到 DPDK 应用程序
    uint16_t nb_ports = rte_eth_dev_count_avail();
    if (nb_ports < 1)
        rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n");

    uint16_t portid;
    for (portid = 0; portid < nb_ports; portid++) {
        struct rte_eth_dev_info dev_info;
        memset(&dev_info, 0, sizeof(dev_info));
        rte_eth_dev_info_get(portid, &dev_info);

        if (strcmp(dev_info.driver_name, "net_e1000_em") == 0) {
            ret = rte_eth_dev_configure(portid, 1, 1, NULL);
            if (ret < 0)
                rte_exit(EXIT_FAILURE, "Cannot configure device: err=%d, port=%u\n", ret, portid);

            struct ether_addr addr;
            ether_aton_r("00:00:00:00:00:01", &addr);
            rte_eth_macaddr_set(portid, &addr);

            ret = rte_eth_rx_queue_setup(portid, 0, RX_RING_SIZE,
                                          rte_eth_dev_socket_id(portid),
                                          NULL,
                                          mbuf_pool);
            if (ret < 0)
                rte_exit(EXIT_FAILURE, "Cannot init RX queue for port %u\n", portid);

            ret = rte_eth_tx_queue_setup(portid, 0, TX_RING_SIZE,
                                          rte_eth_dev_socket_id(portid),
                                          NULL);
            if (ret < 0)
                rte_exit(EXIT_FAILURE,"Cannot init TX queue for port %u\n", portid);

            ret = rte_eth_dev_start(portid);
            if (ret < 0)
                rte_exit(EXIT_FAILURE,"Cannot start port %u\n", portid);

        }
    }

    return nb_ports;
}

// 初始化 nDPI 库
void init_ndpi() {
    // 初始化 nDPI 库
    ndpi_init_detection_module();

    // 设置协议识别级别
    ndpi_set_protocol_detection_bitmask2(ndpi_struct,
                                         NDPI_PROTOCOL_CATEGORY_WEBMAIL,
                                         NDPI_PROTOCOL_BITMASK_HTTP |
                                         NDPI_PROTOCOL_BITMASK_POP3 |
                                         NDPI_PROTOCOL_BITMASK_IMAP |
                                         NDPI_PROTOCOL_BITMASK_SMTP |
                                         NDPI_PROTOCOL_BITMASK_SMTP);

    ndpi_set_protocol_detection_bitmask2(ndpi_struct,
                                         NDPI_PROTOCOL_CATEGORY_WEB,
                                         NDPI_PROTOCOL_BITMASK_HTTP |
                                         NDPI_PROTOCOL_BITMASK_SSL |
                                         NDPI_PROTOCOL_BITMASK_QUIC |
                                         NDPI_PROTOCOL_BITMASK_DNS);
}

// 解析并分类数据包
void process_packet(struct rte_mbuf* pkt) {
    // 调用 nDPI 库进行协议识别和分类
    struct ndpi_flow_struct *flow = ndpi_malloc(sizeof(*flow));
    memset(flow, 0, sizeof(*flow));

    flow->iph = (struct ndpi_iphdr *) (rte_pktmbuf_mtod(pkt, unsigned char*) + sizeof(struct ether_hdr));
    flow->tcp = (struct ndpi_tcphdr *) ((char*)flow->iph + 4 * flow->iph->ihl);

    u_int16_t ipsize = ntohs(flow->iph->tot_len);
    u_int16_t tcpsize = ipsize - 4 * flow->iph->ihl - 4 * flow->tcp->doff;

    if ((pkt->packet_type & RTE_PTYPE_L3_MASK) != RTE_PTYPE_L3_IPV4 ||
        (pkt->packet_type & RTE_PTYPE_L4_MASK) != RTE_PTYPE_L4_TCP) {
        return;
    }

    int detected_protocol = ndpi_detection_process_packet(ndpi_struct, flow,
                                                           pkt_data, pkt_len,
                                                           time(NULL),
                                                           packet_counter++);
    
    // 根据协议判断是否为 HTTP 数据包
    if (detected_protocol == NDPI_PROTOCOL_HTTP || detected_protocol == NDPI_PROTOCOL_SSL || detected_protocol == NDPI_PROTOCOL_QUIC) {
        printf("HTTP packet received\n");
        // 进行处理...
    }
}

int main(int argc, char** argv) {
    int ret;
    char* port_name = "eth0";

    // 初始化 DPDK
    init_dpdk(port_name);

    // 初始化 nDPI 库
    init_ndpi();

    struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
    const uint16_t nb_ports = rte_eth_dev_count_avail();
    const uint64_t drain_cycles = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * BURST_TX_DRAIN_US;
    
    while (true) {
        // 接收数据包
        for (portid = 0; portid < nb_ports; portid++) {
            const uint16_t nb_rx = rte_eth_rx_burst(portid, 0,
                                                    pkts_burst, MAX_PKT_BURST);
            for (uint16_t i = 0; i < nb_rx; i++) {
                process_packet(pkts_burst[i]);
            }
        }

        // 发送数据包
        for (portid = 0; portid < nb_ports; portid++) {
            const uint16_t nb_tx = rte_eth_tx_burst(portid ^ 1, 0,
                                                    pkts_burst, num_tx);
            if (unlikely(nb_tx < num_tx)) {
                uint16_t buf;
                do {
                    buf = tx_buffer[nb_tx + sent];
                    rte_pktmbuf_free(tx_pkts[buf]);
                } while (++nb_tx < num_tx);
            }
        }
        
        rte_delay_us_sleep(BURST_TX_DRAIN_US);

        packet_counter++;
    }
}

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://sdn.0voice.com/?id=1077

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?