一. 缘由
继续学习DPDK示例,主要熟悉每个环节和设计理念,今天要学习的是一个相对简答的服务,仅仅从一个网口抓取数据包转发到另外一个网口,这样做双向转发,相当于桥的功能。
二. 直接上源码分析
#include <stdint.h>
#include <inttypes.h>
#include <rte_eal.h>
#include <rte_ethdev.h>
#include <rte_cycles.h>
#include <rte_lcore.h>
#include <rte_mbuf.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 }
};
/* basicfwd.c: Basic DPDK skeleton forwarding example. */
/*
* 用全局默认的配置来初始化网口。在内存池中分配接收队列和发送队列。
*/
static inline int
port_init(uint8_t port, struct rte_mempool *mbuf_pool)
{
struct rte_eth_conf port_conf = port_conf_default; //全部配置模式
const uint16_t rx_rings = 1, tx_rings = 1; //每个网口队列多少,这里都为1
int retval;
uint16_t q;
if (port >= rte_eth_dev_count()) //检查网口编号
return -1;
/* 配置以太网设备 */
retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf);
if (retval != 0)
return retval;
/* 为每个以太网网口分配和设置1个接收队列 */
for (q = 0; q < rx_rings; q++) {
retval = rte_eth_rx_queue_setup(port, q, RX_RING_SIZE,
rte_eth_dev_socket_id(port), NULL, mbuf_pool);
if (retval < 0)
return retval;
}
/* 为每个以太网网口分配和设置1个发送队列 */
for (q = 0; q < tx_rings; q++) {
retval = rte_eth_tx_queue_setup(port, q, TX_RING_SIZE,
rte_eth_dev_socket_id(port), NULL);
if (retval < 0)
return retval;
}
/* 开启以太网网口 */
retval = rte_eth_dev_start(port);
if (retval < 0)
return retval;
/* 打印网卡地址 MAC address. */
struct ether_addr addr;
rte_eth_macaddr_get(port, &addr);
printf("Port %u MAC: %02" PRIx8 " %02" PRIx8 " %02" PRIx8
" %02" PRIx8 "