以下是一个简单的DPDK应用程序,通过vhost-user-sock读取数据包:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <rte_eal.h>
#include <rte_ethdev.h>
#include <rte_mbuf.h>
#include <rte_vhost.h>
#define MAX_PACKET_SZ 2048
#define NUM_MBUFS 8191
#define MBUF_CACHE_SIZE 250
int main(int argc, char **argv)
{
int ret;
unsigned int i, portid;
struct rte_mempool *mbuf_pool;
struct rte_eth_conf port_conf = {0};
struct rte_eth_rxconf rx_conf = {0};
/* Initialize DPDK EAL */
ret = rte_eal_init(argc, argv);
if (ret < 0) {
rte_exit(EXIT_FAILURE, "Error: Failed to initialize DPDK EAL.\n");
}
argc -= ret;
argv += ret;
/* Create memory pool for mbufs */
mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", NUM_MBUFS, MBUF_CACHE_SIZE,
0, RTE_MBUF_DEFAULT_BUF_SIZE,
rte_socket_id());
if (mbuf_pool == NULL) {
rte_exit(EXIT_FAILURE, "Error: Failed to create mbuf pool.\n");
}
/* Initialize vhost-user interface */
struct sockaddr_un un = {0};
const char *socket_path = "/tmp/vhost-user.sock";
int vhost_sock;
memset(&un, 0, sizeof(struct sockaddr_un));
un.sun_family = AF_UNIX;
strncpy(un.sun_path, socket_path, sizeof(un.sun_path) - 1);
if ((vhost_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
rte_exit(EXIT_FAILURE, "Error: Failed to create socket for vhost-user.\n");
}
if (connect(vhost_sock, (struct sockaddr *)&un, sizeof(struct sockaddr_un)) == -1) {
rte_exit(EXIT_FAILURE, "Error: Failed to connect to vhost-user socket.\n");
}
/* Configure Ethernet port */
portid = 0;
ret = rte_eth_dev_configure(portid, 1, 1, &port_conf);
if (ret < 0) {
rte_exit(EXIT_FAILURE, "Error: Failed to configure Ethernet port.\n");
}
/* Configure RX queue */
rx_conf.rx_drop_en = 1;
ret = rte_eth_rx_queue_setup(portid, 0, 128, rte_eth_dev_socket_id(portid), &rx_conf, mbuf_pool);
if (ret < 0) {
rte_exit(EXIT_FAILURE, "Error: Failed to configure RX queue.\n");
}
/* Start Ethernet port */
ret = rte_eth_dev_start(portid);
if (ret < 0) {
rte_exit(EXIT_FAILURE, "Error: Failed to start Ethernet port.\n");
}
/* Main loop */
struct rte_mbuf *mbufs[MAX_PACKET_SZ];
unsigned int num_pkts;
ssize_t recv_len;
while (1) {
recv_len = recv(vhost_sock, mbufs, sizeof(mbufs), MSG_WAITALL);
if (recv_len <= 0) {
rte_exit(EXIT_FAILURE, "Error: Failed to receive data from vhost-user socket.\n");
}
num_pkts = recv_len / sizeof(struct rte_mbuf *);
for (i = 0; i < num_pkts; i++) {
ret = rte_eth_tx_burst(portid, 0, &mbufs[i], 1);
if (ret < 1) {
rte_pktmbuf_free(mbufs[i]);
}
}
}
return 0;
}
这个应用程序初始化了DPDK环境以及vhost-user接口,并通过一个无限循环不断从vhost-user socket中读取消息包。它通过rte_eth_dev_configure
和rte_eth_rx_queue_setup
设置了Ethernet端口的配置,然后启动了该端口(通过rte_eth_dev_start
)。在循环中,收到的消息被发送到Ethernet端口(通过rte_eth_tx_burst
),并在发送完成之后释放rte_mbuf
缓冲区(通过rte_pktmbuf_free
)。