l2fwd-cat 增加了对数据包分类的支持,可以根据特定的规则对数据包进行分类和处理。
以下是 l2fwd-cat 的一些应用场景:
- 高性能防火墙
根据源 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;
}
流量监控和统计
统计不同类型流量的带宽占用情况,例如 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; }
- 负载均衡
根据数据包的目的 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;
}
- 服务质量(QoS)管理
对实时应用(如 VoIP、视频会议)的流量进行优先处理,确保低延迟和高可靠性。
如何实现优先处理的几种思路: - 标记优先数据包:在数据包处理过程中,识别并标记优先数据包。
- 队列优先级:使用不同的队列来处理优先数据包和普通数据包。优先队列的处理优先级高于普通队列。
- 快速转发:尽可能减少优先数据包的处理延迟,确保它们能够快速转发。
#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;
}
- 入侵检测和防御
根据特定的签名或行为特征,检测并阻止恶意流量。
#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;
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。