l2fwd-cat 增加了对数据包分类的支持,可以根据特定的规则对数据包进行分类和处理。
以下是 l2fwd-cat 的一些应用场景:

  1. 高性能防火墙
    根据源 IP 地址、目的 IP 地址或端口号等字段对数据包进行分类,并应用相应的防火墙规则来过滤和处理数据包。
#include <rte_eal.h>
#include <rte_ethdev.h>
#include <rte_mbuf.h>
#include <rte_ether.h>
#include <rte_ip.h>
#include <stdio.h>

#define MAX_PKT_BURST 32

static void l2fwd_cat_main_loop(void) {
    uint16_t port;
    struct rte_mbuf *bufs[MAX_PKT_BURST];
    unsigned lcore_id = rte_lcore_id();

    while (1) {
        // 遍历所有端口
        for (port = 0; port < rte_eth_dev_count_avail(); port++) {
            // 从接收队列中读取数据包
            const uint16_t nb_rx = rte_eth_rx_burst(port, 0, bufs, MAX_PKT_BURST);
            if (nb_rx == 0)
                continue;

            // 遍历接收到的数据包
            for (uint16_t i = 0; i < nb_rx; i++) {
                struct rte_mbuf *m = bufs[i];
                struct rte_ether_hdr *eth_hdr = rte_pktmbuf_mtod(m, struct rte_ether_hdr *);

                // 分类和处理数据包
                if (eth_hdr->ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)) {
                    struct rte_ipv4_hdr *ip_hdr = (struct rte_ipv4_hdr *)(eth_hdr + 1);

                    // 根据源 IP 地址进行分类
                    if ((ip_hdr->src_addr & 0xFF) == 192) {
                        // 特定处理逻辑
                        printf("Packet from 192.x.x.x\n");
                    }
                }

                // 根据目的 MAC 地址的第6个字节决定转发端口
                uint16_t dst_port = (eth_hdr->d_addr.addr_bytes[5] % rte_eth_dev_count_avail());

                // 发送数据包
                const uint16_t nb_tx = rte_eth_tx_burst(dst_port, 0, &m, 1);

                // 释放未能发送的数据包
                if (nb_tx < 1) {
                    rte_pktmbuf_free(m);
                }
            }
        }
    }
}

int main(int argc, char **argv) {
    struct rte_mempool *mbuf_pool;
    unsigned nb_ports;
    uint16_t portid;

    // 初始化 DPDK 环境
    int ret = rte_eal_init(argc, argv);
    if (ret < 0)
        rte_exit(EXIT_FAILURE, "Error with EAL initialization\n");
    argc -= ret;
    argv += ret;

    // 检查可用端口数量
    nb_ports = rte_eth_dev_count_avail();
    if (nb_ports < 2)
        rte_exit(EXIT_FAILURE, "Error: number of ports must be >= 2\n");

    // 创建内存池
    mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", 8192 * nb_ports,
                                        MEMPOOL_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_ETH_FOREACH_DEV(portid) {
        if (port_init(portid, mbuf_pool) != 0)
            rte_exit(EXIT_FAILURE, "Cannot init port %" PRIu16 "\n", portid);
    }

    // 启动主循环
    l2fwd_cat_main_loop();

    return 0;
}
  1. 流量监控和统计
    统计不同类型流量的带宽占用情况,例如 HTTP、HTTPS、FTP 等。

    #include <rte_eal.h>
    #include <rte_ethdev.h>
    #include <rte_mbuf.h>
    #include <rte_ether.h>
    #include <rte_ip.h>
    #include <rte_tcp.h>
    #include <stdio.h>
    
    #define MAX_PKT_BURST 32
    
    static uint64_t http_traffic = 0;
    static uint64_t https_traffic = 0;
    
    static void l2fwd_cat_monitor_loop(void) {
     uint16_t port;
     struct rte_mbuf *bufs[MAX_PKT_BURST];
     unsigned lcore_id = rte_lcore_id();
    
     while (1) {
         for (port = 0; port < rte_eth_dev_count_avail(); port++) {
             const uint16_t nb_rx = rte_eth_rx_burst(port, 0, bufs, MAX_PKT_BURST);
             if (nb_rx == 0)
                 continue;
    
             for (uint16_t i = 0; i < nb_rx; i++) {
                 struct rte_mbuf *m = bufs[i];
                 struct rte_ether_hdr *eth_hdr = rte_pktmbuf_mtod(m, struct rte_ether_hdr *);
    
                 if (eth_hdr->ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)) {
                     struct rte_ipv4_hdr *ip_hdr = (struct rte_ipv4_hdr *)(eth_hdr + 1);
    
                     if (ip_hdr->next_proto_id == IPPROTO_TCP) {
                         struct rte_tcp_hdr *tcp_hdr = (struct rte_tcp_hdr *)(ip_hdr + 1);
    
                         if (tcp_hdr->dst_port == rte_cpu_to_be_16(80)) {
                             http_traffic += rte_pktmbuf_pkt_len(m);
                         } else if (tcp_hdr->dst_port == rte_cpu_to_be_16(443)) {
                             https_traffic += rte_pktmbuf_pkt_len(m);
                         }
                     }
                 }
    
                 uint16_t dst_port = (eth_hdr->d_addr.addr_bytes[5] % rte_eth_dev_count_avail());
                 const uint16_t nb_tx = rte_eth_tx_burst(dst_port, 0, &m, 1);
                 if (nb_tx < 1) {
                     rte_pktmbuf_free(m);
                 }
             }
         }
     }
    }
    
    int main(int argc, char **argv) {
     struct rte_mempool *mbuf_pool;
     unsigned nb_ports;
     uint16_t portid;
    
     int ret = rte_eal_init(argc, argv);
     if (ret < 0)
         rte_exit(EXIT_FAILURE, "Error with EAL initialization\n");
     argc -= ret;
     argv += ret;
    
     nb_ports = rte_eth_dev_count_avail();
     if (nb_ports < 2)
         rte_exit(EXIT_FAILURE, "Error: number of ports must be >= 2\n");
    
     mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", 8192 * nb_ports,
                                         MEMPOOL_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_ETH_FOREACH_DEV(portid) {
         if (port_init(portid, mbuf_pool) != 0)
             rte_exit(EXIT_FAILURE, "Cannot init port %" PRIu16 "\n", portid);
     }
    
     l2fwd_cat_monitor_loop();
    
     return 0;
    }
    
  2. 负载均衡
    根据数据包的目的 IP 地址或端口号,将流量分配到不同的后端服务器。
#include <rte_eal.h>
#include <rte_ethdev.h>
#include <rte_mbuf.h>
#include <rte_ether.h>
#include <rte_ip.h>
#include <stdio.h>

#define MAX_PKT_BURST 32

static void l2fwd_cat_load_balancer_loop(void) {
    uint16_t port;
    struct rte_mbuf *bufs[MAX_PKT_BURST];
    unsigned lcore_id = rte_lcore_id();

    while (1) {
        for (port = 0; port < rte_eth_dev_count_avail(); port++) {
            const uint16_t nb_rx = rte_eth_rx_burst(port, 0, bufs, MAX_PKT_BURST);
            if (nb_rx == 0)
                continue;

            for (uint16_t i = 0; i < nb_rx; i++) {
                struct rte_mbuf *m = bufs[i];
                struct rte_ether_hdr *eth_hdr = rte_pktmbuf_mtod(m, struct rte_ether_hdr *);

                if (eth_hdr->ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)) {
                    struct rte_ipv4_hdr *ip_hdr = (struct rte_ipv4_hdr *)(eth_hdr + 1);

                    // 简单负载均衡算法:根据目的 IP 地址的最后一个字节决定转发端口
                    uint16_t dst_port = (ip_hdr->dst_addr & 0xFF) % rte_eth_dev_count_avail();
                    const uint16_t nb_tx = rte_eth_tx_burst(dst_port, 0, &m, 1);
                    if (nb_tx < 1) {
                        rte_pktmbuf_free(m);
                    }
                    continue;
                }

                uint16_t dst_port = (eth_hdr->d_addr.addr_bytes[5] % rte_eth_dev_count_avail());
                const uint16_t nb_tx = rte_eth_tx_burst(dst_port, 0, &m, 1);
                if (nb_tx < 1) {
                    rte_pktmbuf_free(m);
                }
            }
        }
    }
}

int main(int argc, char **argv) {
    struct rte_mempool *mbuf_pool;
    unsigned nb_ports;
    uint16_t portid;

    int ret = rte_eal_init(argc, argv);
    if (ret < 0)
        rte_exit(EXIT_FAILURE, "Error with EAL initialization\n");
    argc -= ret;
    argv += ret;

    nb_ports = rte_eth_dev_count_avail();
    if (nb_ports < 2)
        rte_exit(EXIT_FAILURE, "Error: number of ports must be >= 2\n");

    mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", 8192 * nb_ports,
                                        MEMPOOL_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_ETH_FOREACH_DEV(portid) {
        if (port_init(portid, mbuf_pool) != 0)
            rte_exit(EXIT_FAILURE, "Cannot init port %" PRIu16 "\n", portid);
    }

    l2fwd_cat_load_balancer_loop();

    return 0;
}
  1. 服务质量(QoS)管理
    对实时应用(如 VoIP、视频会议)的流量进行优先处理,确保低延迟和高可靠性。
    如何实现优先处理的几种思路:
  2. 标记优先数据包:在数据包处理过程中,识别并标记优先数据包。
  3. 队列优先级:使用不同的队列来处理优先数据包和普通数据包。优先队列的处理优先级高于普通队列。
  4. 快速转发:尽可能减少优先数据包的处理延迟,确保它们能够快速转发。
#include <rte_eal.h>
#include <rte_ethdev.h>
#include <rte_mbuf.h>
#include <rte_ether.h>
#include <rte_ip.h>
#include <rte_udp.h>
#include <stdio.h>

#define MAX_PKT_BURST 32

static void l2fwd_cat_qos_loop(void) {
    uint16_t port;
    struct rte_mbuf *bufs[MAX_PKT_BURST];
    unsigned lcore_id = rte_lcore_id();

    while (1) {
        for (port = 0; port < rte_eth_dev_count_avail(); port++) {
            const uint16_t nb_rx = rte_eth_rx_burst(port, 0, bufs, MAX_PKT_BURST);
            if (nb_rx == 0)
                continue;

            for (uint16_t i = 0; i < nb_rx; i++) {
                struct rte_mbuf *m = bufs[i];
                struct rte_ether_hdr *eth_hdr = rte_pktmbuf_mtod(m, struct rte_ether_hdr *);

                if (eth_hdr->ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)) {
                    struct rte_ipv4_hdr *ip_hdr = (struct rte_ipv4_hdr *)(eth_hdr + 1);

                    if (ip_hdr->next_proto_id == IPPROTO_UDP) {
                        struct rte_udp_hdr *udp_hdr = (struct rte_udp_hdr *)(ip_hdr + 1);

                        // 简单 QoS 管理:对目标端口为 5060 (SIP) 的流量进行优先处理
                        if (udp_hdr->dst_port == rte_cpu_to_be_16(5060)) {
                            // 优先处理逻辑
                            printf("High priority packet (SIP)\n");
                            uint16_t dst_port = (eth_hdr->d_addr.addr_bytes[5] % rte_eth_dev_count_avail());
                            const uint16_t nb_tx = rte_eth_tx_burst(dst_port, 0, &m, 1);
                            if (nb_tx < 1) {
                                rte_pktmbuf_free(m);
                            }
                            continue;
                        }
                    }
                }

                uint16_t dst_port = (eth_hdr->d_addr.addr_bytes[5] % rte_eth_dev_count_avail());
                const uint16_t nb_tx = rte_eth_tx_burst(dst_port, 0, &m, 1);
                if (nb_tx < 1) {
                    rte_pktmbuf_free(m);
                }
            }
        }
    }
}

int main(int argc, char **argv) {
    struct rte_mempool *mbuf_pool;
    unsigned nb_ports;
    uint16_t portid;

    int ret = rte_eal_init(argc, argv);
    if (ret < 0)
        rte_exit(EXIT_FAILURE, "Error with EAL initialization\n");
    argc -= ret;
    argv += ret;

    nb_ports = rte_eth_dev_count_avail();
    if (nb_ports < 2)
        rte_exit(EXIT_FAILURE, "Error: number of ports must be >= 2\n");

    mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", 8192 * nb_ports,
                                        MEMPOOL_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_ETH_FOREACH_DEV(portid) {
        if (port_init(portid, mbuf_pool) != 0)
            rte_exit(EXIT_FAILURE, "Cannot init port %" PRIu16 "\n", portid);
    }

    l2fwd_cat_qos_loop();

    return 0;
}
  1. 入侵检测和防御
    根据特定的签名或行为特征,检测并阻止恶意流量。
#include <rte_eal.h>
#include <rte_ethdev.h>
#include <rte_mbuf.h>
#include <rte_ether.h>
#include <rte_ip.h>
#include <rte_tcp.h>
#include <stdio.h>

#define MAX_PKT_BURST 32

static void l2fwd_cat_ids_loop(void) {
    uint16_t port;
    struct rte_mbuf *bufs[MAX_PKT_BURST];
    unsigned lcore_id = rte_lcore_id();

    while (1) {
        for (port = 0; port < rte_eth_dev_count_avail(); port++) {
            const uint16_t nb_rx = rte_eth_rx_burst(port, 0, bufs, MAX_PKT_BURST);
            if (nb_rx == 0)
                continue;

            for (uint16_t i = 0; i < nb_rx; i++) {
                struct rte_mbuf *m = bufs[i];
                struct rte_ether_hdr *eth_hdr = rte_pktmbuf_mtod(m, struct rte_ether_hdr *);

                if (eth_hdr->ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)) {
                    struct rte_ipv4_hdr *ip_hdr = (struct rte_ipv4_hdr *)(eth_hdr + 1);

                    if (ip_hdr->next_proto_id == IPPROTO_TCP) {
                        struct rte_tcp_hdr *tcp_hdr = (struct rte_tcp_hdr *)(ip_hdr + 1);

                        // 简单 IDS 规则:丢弃目标端口为 23 (Telnet) 的数据包
                        if (tcp_hdr->dst_port == rte_cpu_to_be_16(23)) {
                            printf("Detected and dropped Telnet packet\n");
                            rte_pktmbuf_free(m);
                            continue;
                        }
                    }
                }

                uint16_t dst_port = (eth_hdr->d_addr.addr_bytes[5] % rte_eth_dev_count_avail());
                const uint16_t nb_tx = rte_eth_tx_burst(dst_port, 0, &m, 1);
                if (nb_tx < 1) {
                    rte_pktmbuf_free(m);
                }
            }
        }
    }
}

int main(int argc, char **argv) {
    struct rte_mempool *mbuf_pool;
    unsigned nb_ports;
    uint16_t portid;

    int ret = rte_eal_init(argc, argv);
    if (ret < 0)
        rte_exit(EXIT_FAILURE, "Error with EAL initialization\n");
    argc -= ret;
    argv += ret;

    nb_ports = rte_eth_dev_count_avail();
    if (nb_ports < 2)
        rte_exit(EXIT_FAILURE, "Error: number of ports must be >= 2\n");

    mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", 8192 * nb_ports,
                                        MEMPOOL_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_ETH_FOREACH_DEV(portid) {
        if (port_init(portid, mbuf_pool) != 0)
            rte_exit(EXIT_FAILURE, "Cannot init port %" PRIu16 "\n", portid);
    }

    l2fwd_cat_ids_loop();

    return 0;
}

putao
5 声望0 粉丝

推动世界向前发展,改善民生。