环境:dpdk19.11 ubuntu-18.04.5
两台ubuntu机器,一台基于dpdk进行L4处理(tcp/udp/icmp),另一台作为对端正常使用
求一套可以使用的基于dpdk19.11进行L4处理的c程序代码,
使用igb_uio或者vfio驱动,程序能够收发tcp/udp包、有自定义建立tcp/udp的套接字。
能够与未绑定dpdk驱动的对端电脑,互相进行tcp/udp连接、ping。
环境:dpdk19.11 ubuntu-18.04.5
两台ubuntu机器,一台基于dpdk进行L4处理(tcp/udp/icmp),另一台作为对端正常使用
求一套可以使用的基于dpdk19.11进行L4处理的c程序代码,
使用igb_uio或者vfio驱动,程序能够收发tcp/udp包、有自定义建立tcp/udp的套接字。
能够与未绑定dpdk驱动的对端电脑,互相进行tcp/udp连接、ping。
send.c
#include <stdio.h>
#include <arpa/inet.h>
#include <rte_eal.h>
#include <rte_ethdev.h>
#include <rte_mbuf.h>
#define NUM_MBUFS (4096-1)
#define MBUFS_SIZE 32
#define ENABLE_SEND 1
uint16_t port_id = 0;
#if ENABLE_SEND
static uint32_t gSrcIp;
static uint32_t gDstIp;
static uint8_t gSrcMac[RTE_ETHER_ADDR_LEN];
static uint8_t gDstMac[RTE_ETHER_ADDR_LEN];
static uint16_t gSrcPort;
static uint16_t gDstPort;
#endif
static const struct rte_eth_conf port_conf_default = {
.rxmode = {.max_rx_pkt_len = RTE_ETHER_MAX_LEN }
};
static void init_port(struct rte_mempool *mbufpool)
{
/*Get the number of ports which are usable for the application.*/
uint16_t sys_port = rte_eth_dev_count_avail();
if(sys_port == 0){
rte_exit(EXIT_FAILURE, "Not available eth\n");
}
/*Get ethernet information*/
struct rte_eth_dev_info dev_info;
rte_eth_dev_info_get(port_id, &dev_info);
/*Configure an Ethernet device*/
uint16_t nb_rx_q = 1;
uint16_t nb_tx_q = 1;
struct rte_eth_conf dev_conf = port_conf_default;
rte_eth_dev_configure(port_id, nb_rx_q, nb_tx_q, &dev_conf);
/*Allocate and set up a receive queue for an Ethernet device*/
uint16_t rx_queue_id = nb_rx_q - 1;
unsigned int socket_id = rte_eth_dev_socket_id(port_id);
if(rte_eth_rx_queue_setup(port_id, rx_queue_id, 1024, socket_id, NULL, mbufpool) < 0)
rte_exit(EXIT_FAILURE, "Receive queue error\n");
#if ENABLE_SEND
/*Allocate and set up a transmit queue for an Ethernet device*/
struct rte_eth_txconf txq_conf = dev_info.default_txconf;
txq_conf.offloads = dev_conf.rxmode.offloads;
if (rte_eth_tx_queue_setup(port_id, 0 , 1024, socket_id, &txq_conf) < 0)
rte_exit(EXIT_FAILURE, "Could not setup TX queue\n");
#endif
/*Start an Ethernet device*/
if(rte_eth_dev_start(port_id) < 0)
rte_exit(EXIT_FAILURE, "Start ethernet error\n");
}
int main(int argc, char **argv)
{
unsigned int i =0;
//uint8_t au8SendMsg[] = "hello misss";
/*init*/
if(rte_eal_init(argc, argv) < 0)
rte_exit(EXIT_FAILURE, "EAL init Error\n");
/*create a mbuf pool*/
struct rte_mempool *mbufpool = rte_pktmbuf_pool_create("mbufpool", NUM_MBUFS, 0, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
if(mbufpool == NULL)
rte_exit(EXIT_FAILURE, "Create mbufpool Error\n");
/*init port*/
init_port(mbufpool);
rte_eth_macaddr_get(port_id, (struct rte_ether_addr *)gSrcMac);
while(1){
struct rte_mbuf *rx_pkts[MBUFS_SIZE];
/*Retrieve a burst of input packets from a receive queue of an Ethernet device*/
unsigned num_recv = rte_eth_rx_burst(port_id, 0, rx_pkts, MBUFS_SIZE);
if(num_recv > MBUFS_SIZE)
rte_exit(EXIT_FAILURE, "Receive from eth error\n");
for(i = 0; i < num_recv; i++){
struct rte_ether_hdr *ehdr = rte_pktmbuf_mtod(rx_pkts[i], struct rte_ether_hdr*);
if (ehdr->ether_type != rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)) {
rte_pktmbuf_free(rx_pkts[i]);
continue;
}
struct rte_ipv4_hdr *iphdr = rte_pktmbuf_mtod_offset(rx_pkts[i], struct rte_ipv4_hdr *, sizeof(struct rte_ether_hdr));
if (iphdr->next_proto_id == IPPROTO_UDP) {
/*IPPROTO_UDP is defined in kernel source code include/uapi/inux/in.h*/
struct rte_udp_hdr *udphdr = (struct rte_udp_hdr *)(iphdr + 1);
#if ENABLE_SEND
//rte_eth_macaddr_get(port_id, (struct rte_ether_addr *)gSrcMac);
rte_memcpy(gDstMac, ehdr->s_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
rte_memcpy(&gSrcIp, &iphdr->dst_addr, sizeof(uint32_t));
rte_memcpy(&gDstIp, &iphdr->src_addr, sizeof(uint32_t));
rte_memcpy(&gSrcPort, &udphdr->dst_port, sizeof(uint16_t));
rte_memcpy(&gDstPort, &udphdr->src_port, sizeof(uint16_t));
#endif
uint16_t length = ntohs(udphdr->dgram_len);
*((char*)udphdr + length) = '\0';
struct in_addr addr;
addr.s_addr = iphdr->src_addr;
printf("<- src: %s:%d, ", inet_ntoa(addr), udphdr->src_port);
addr.s_addr = iphdr->dst_addr;
printf("dst: %s:%d, %s\n", inet_ntoa(addr), udphdr->dst_port, (char *)(udphdr+1));
#if ENABLE_SEND
//20220926add
rte_memcpy(&iphdr->src_addr, &gSrcIp, sizeof(uint32_t));
rte_memcpy(&iphdr->dst_addr, &gDstIp, sizeof(uint32_t));
addr.s_addr = iphdr->src_addr;
printf("-> src: %s:%d, ", inet_ntoa(addr), udphdr->src_port);
addr.s_addr = iphdr->dst_addr;
printf("dst: %s:%d, %s\n", inet_ntoa(addr), udphdr->dst_port, (char *)(udphdr+1));
rte_memcpy(ehdr->s_addr.addr_bytes, gSrcMac, RTE_ETHER_ADDR_LEN);
rte_memcpy(ehdr->d_addr.addr_bytes, gDstMac, RTE_ETHER_ADDR_LEN);
//调测增加,实际使用可去掉端口限制
if (4369 == udphdr->src_port)
{
rte_eth_tx_burst(port_id , 0, rx_pkts, num_recv);
}
#endif
rte_pktmbuf_free(rx_pkts[i]);
}
}
}
}