ZBLOG

20版本的dpdk 输出数据包ip地址 mac地址 tcp端口 代码

以下是一个简单的DPDK程序示例,可以输出数据包的IP地址、MAC地址和TCP端口:

#include <stdio.h>
#include <stdint.h>
#include <rte_eal.h>
#include <rte_ethdev.h>
#include <rte_mbuf.h>
#include <rte_udp.h>
#include <rte_tcp.h>
#include <arpa/inet.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 = RTE_ETHER_MAX_LEN,
    },
};

int main(int argc, char *argv[])
{
    int ret;
    uint16_t nb_ports;
    uint16_t portid;
    struct rte_mempool *mbuf_pool;
    struct rte_eth_dev_info dev_info;
    struct rte_eth_txconf txconf;
    uint64_t prev_tsc, diff_tsc, cur_tsc;
    unsigned lcore_id, rx_lcore_id;
    uint8_t *data;
    struct rte_mbuf *mbuf;
    struct ether_hdr *eth_hdr;
    struct ipv4_hdr *ipv4_hdr;
    struct tcp_hdr *tcp_hdr;

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

    argc -= ret;
    argv += ret;

    /* 获取端口数量 */
    nb_ports = rte_eth_dev_count_avail();
    if (nb_ports == 0)
        rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n");

    /* 创建内存池 */
    mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", NUM_MBUFS * nb_ports,
        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");

    /* 配置端口 */
    for (portid = 0; portid < nb_ports; portid++) {
        /* 获取端口信息 */
        rte_eth_dev_info_get(portid, &dev_info);

        /* 配置端口 */
        ret = rte_eth_dev_configure(portid, 1, 1, &port_conf_default);
        if (ret < 0)
            rte_exit(EXIT_FAILURE, "Cannot configure device: err=%d, port=%u\n",
                ret, (unsigned) portid);

        /* 分配并设置 RX/TX 队列 */
        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 allocate RX queue: err=%d, port=%u\n",
                ret, (unsigned) portid);

        txconf = dev_info.default_txconf;
        txconf.txq_flags = ETH_TXQ_FLAGS_IGNORE;

        ret = rte_eth_tx_queue_setup(portid, 0, TX_RING_SIZE,
            rte_eth_dev_socket_id(portid), &txconf);
        if (ret < 0)
            rte_exit(EXIT_FAILURE, "Cannot allocate TX queue: err=%d, port=%u\n",
                ret, (unsigned) portid);

        /* 启动端口 */
        ret = rte_eth_dev_start(portid);
        if (ret < 0)
            rte_exit(EXIT_FAILURE, "Cannot start device: err=%d, port=%u\n",
                ret, (unsigned) portid);

        /* 启用混杂模式 */
        rte_eth_promiscuous_enable(portid);
    }

    /* 获取 RX 核心 ID */
    rx_lcore_id = rte_get_next_lcore(-1, 0, 1);
    if (rx_lcore_id == RTE_MAX_LCORE)
        rte_exit(EXIT_FAILURE, "Cannot get RX core id\n");

    printf("Core %u is receiving packets. [Ctrl+C to quit]\n", rx_lcore_id);

    prev_tsc = cur_tsc = rte_rdtsc();

    /* 接收数据包 */
    while (!rte_atomic64_read(&force_quit)) {
        cur_tsc = rte_rdtsc();
        diff_tsc = cur_tsc - prev_tsc;
        if (diff_tsc > TIMER_RESOLUTION_CYCLES) {
            /* 输出统计信息 */
            printf("[Port statistics]\n");
            for (portid = 0; portid < nb_ports; portid++) {
                struct rte_eth_stats stats;
                rte_eth_stats_get(portid, &stats);
                printf("Port %u: RX %lu packets (%lu bytes), TX %lu packets (%lu bytes)\n",
                    (unsigned) portid, stats.ipackets, stats.ibytes,
                    stats.opackets, stats.obytes);
            }
            prev_tsc = cur_tsc;
        }

        /* 接收和处理数据包 */
        RTE_ETH_FOREACH_DEV(portid) {
            if (rte_eth_rx_burst(portid, 0, &mbuf, 1) > 0) {
                /* 从 Mbuf 中获取数据 */
                data = rte_pktmbuf_mtod(mbuf, uint8_t *);

                /* 解析 Ethernet 头 */
                eth_hdr = (struct ether_hdr *) data;

                /* 判断是否为 IPv4 数据包 */
                if (eth_hdr->ether_type == rte_cpu_to_be_16(ETHER_TYPE_IPv4)) {
                    /* 解析 IPv4 头 */
                    ipv4_hdr = (struct ipv4_hdr *) (data + sizeof(struct ether_hdr));

                    /* 判断是否为 TCP 数据包 */
                    if (ipv4_hdr->next_proto_id == IPPROTO_TCP) {
                        /* 解析 TCP 头 */
                        tcp_hdr = (struct tcp_hdr *) (data + sizeof(struct ether_hdr) +
                            sizeof(struct ipv4_hdr));

                        /* 输出 IP 地址、MAC 地址和 TCP 端口 */
                        printf("IP: %s, MAC: %02X:%02X:%02X:%02X:%02X:%02X, TCP Port: %u\n",
                            inet_ntoa(*(struct in_addr *) &ipv4_hdr->dst_addr),
                            eth_hdr->s_addr.addr_bytes[0],
                            eth_hdr->s_addr.addr_bytes[1],
                            eth_hdr->s_addr.addr_bytes[2],
                            eth_hdr->s_addr.addr_bytes[3],
                            eth_hdr->s_addr.addr_bytes[4],
                            eth_hdr->s_addr.addr_bytes[5],
                            rte_be_to_cpu_16(tcp_hdr->dst_port));
                    }
                }

                /* 释放 Mbuf */
                rte_pktmbuf_free(mbuf);
            }
        }
    }

    /* 停止所有端口 */
    RTE_ETH_FOREACH_DEV(portid) {
        rte_eth_dev_stop(portid);
        rte_eth_dev_close(portid);
    }

    return 0;
}

这个程序可以在单个核心上运行,接收来自所有端口的数据包,并输出它们的IP地址、MAC地址和TCP端口。由于DPDK通过绕过操作系统内核来提高性能,因此需要以root权限运行。

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

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

还没有评论,快来说点什么吧~

联系我们

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

微信号:3007537140

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

关注我们
x

注册

已经有帐号?