DPDK2初始化接口及收发包

?

第二篇包括基本的接口初始化及基本的收发包等内容

?端口配置

CCNA教程通常也是从接口IP地址配置开始的,那么我们也从如何配置接口开始讲述.第一个程序很简单,我们看看DPDK支持多少个接口并把MAC地址存下来.

首先需要初始化EAL

intret=rte_eal_init(argc,argv);if(ret0)rte_exit(EXIT_FAILURE,"initlizefail!");

然后通过rte_eth_dev_count_avail()函数获取系统的接口数目:

intnb_ports;nb_ports=rte_eth_dev_count_avail();printf("numberofavailableport:%d\n",nb_ports);

然后我们可以通过rte_eth_dev_info_get如下方式获取deviceinfo:

structrte_eth_dev_infodev_info;for(intportid=0;portidnb_ports;++portid){ret=rte_eth_dev_info_get(portid,dev_info);if(ret0)rte_exit(EXIT_FAILURE,"Cannotgetdeviceinfo:err=%d,port=%d\n",ret,portid);printf("port:%dDriver:%s\n",portid,dev_info.driver_name);}

最后可以根据rte_eth_macaddr_get函数获取接口MAC地址,并放在ports_eth_addr数组中.

staticstructrte_ether_addrports_eth_addr[MAX_PORTS];for(intportid=0;portidnb_ports;++portid){ret=rte_eth_macaddr_get(portid,ports_eth_addr[portid]);if(ret0)rte_exit(EXIT_FAILURE,"CannotgetMACaddress:err=%d,port=%d\n",ret,portid);charmac[18];rte_ether_format_addr(mac[0],18,ports_eth_addr[portid]);printf("port:%d-MAC-%s\n",portid,mac);}

最后整个文件如下,我们将其保存为main.c

#includestdint.h#includeinttypes.h#includerte_eal.h#includerte_ethdev.h#includerte_cycles.h#includerte_lcore.h#includerte_mbuf.h#includerte_ether.h#includerte_ip.h#includerte_udp.h#includepthread.h#includestring.h#defineMAX_PORTS16intmain(intargc,char*argv[]){intret=rte_eal_init(argc,argv);if(ret0)rte_exit(EXIT_FAILURE,"initlizefail!");printf("\n\n\n*****************************************\n");intnb_ports;nb_ports=rte_eth_dev_count_avail();printf("numberofavailableport:%d\n",nb_ports);structrte_eth_dev_infodev_info;for(intportid=0;portidnb_ports;++portid){ret=rte_eth_dev_info_get(portid,dev_info);if(ret0)rte_exit(EXIT_FAILURE,"Cannotgetdeviceinfo:err=%d,port=%d\n",ret,portid);printf("port:%dDriver:%s\n",portid,dev_info.driver_name);}/*ethernetaddressesofports*/staticstructrte_ether_addrports_eth_addr[MAX_PORTS];for(intportid=0;portidnb_ports;++portid){ret=rte_eth_macaddr_get(portid,ports_eth_addr[portid]);if(ret0)rte_exit(EXIT_FAILURE,"CannotgetMACaddress:err=%d,port=%d\n",ret,portid);charmac[18];rte_ether_format_addr(mac[0],18,ports_eth_addr[portid]);printf("port:%d-MAC-%s\n",portid,mac);}return0;}

在同一个目录下建立一个Makefile的文件,这个文件可以在dpdkexample中随便抄一个,不熟悉C编程的读者请注意它的缩进必须要用Tab.

#SPDX-License-Identifier:BSD-3-Clause#Copyright(c)-IntelCorporation#binarynameAPP=portinit#allsourcearestoredinSRCS-ySRCS-y:=main.c#Buildusingpkg-configvariablesifpossibleifneq($(shellpkg-config--existslibdpdkecho0),0)$(error"noinstallationofDPDKfound")endifall:shared.PHONY:sharedstaticshared:build/$(APP)-sharedln-sf$(APP)-sharedbuild/$(APP)static:build/$(APP)-staticln-sf$(APP)-staticbuild/$(APP)PKGCONF?=pkg-configPC_FILE:=$(shell$(PKGCONF)--pathlibdpdk2/dev/null)CFLAGS+=-O3$(shell$(PKGCONF)--cflagslibdpdk)LDFLAGS_SHARED=$(shell$(PKGCONF)--libslibdpdk)LDFLAGS_STATIC=$(shell$(PKGCONF)--static--libslibdpdk)ifeq($(MAKECMDGOALS),static)#checkforbrokenpkg-configifeq($(shellecho$(LDFLAGS_STATIC)

grepwhole-archive.*l:lib.*no-whole-archive),)$(warning"pkg-configoutputlistdoesnotcontaindriversbetweenwhole-archive/no-whole-archiveflags.")$(error"Cannotgeneratestatically-linkedbinarieswiththisversionofpkg-config")endifendifCFLAGS+=-DALLOW_EXPERIMENTAL_APIbuild/$(APP)-shared:$(SRCS-y)Makefile$(PC_FILE)

build$(CC)$(CFLAGS)$(SRCS-y)-o$

$(LDFLAGS)$(LDFLAGS_SHARED)build/$(APP)-static:$(SRCS-y)Makefile$(PC_FILE)

build$(CC)$(CFLAGS)$(SRCS-y)-o$

$(LDFLAGS)$(LDFLAGS_STATIC)build:

mkdir-p$

.PHONY:cleanclean:rm-fbuild/$(APP)build/$(APP)-staticbuild/$(APP)-sharedtest-dbuildrmdir-pbuild

true

然后我们用make编译,输入的执行文件会在新创建的build目录下,执行即可:

zartbot

zartbotWS:~/learn/dpdk/01_port_init$sudo./build/portinitEAL:Detected96lcore(s)EAL:Detected2NUMAnodesEAL:DetectedsharedlinkageofDPDKEAL:Multi-processsocket/var/run/dpdk/rte/mp_socketEAL:SelectedIOVAmodeVAEAL:NoavailablekBhugepagesreportedEAL:ProbingVFIOsupport...EAL:VFIOsupportinitializedEAL:usingIOMMUtype1(Type1)EAL:ProbePCIdriver:net_i40e(:)device::5e:00.0(socket0)EAL:ProbePCIdriver:net_i40e(:)device::5e:00.1(socket0)EAL:ProbePCIdriver:net_i40e(:)device::5e:00.2(socket0)EAL:ProbePCIdriver:net_i40e(:)device::5e:00.3(socket0)EAL:Nolegacycallbacks,legacysocketnotcreated*****************************************numberofavailableport:4port:0Driver:net_i40eport:1Driver:net_i40eport:2Driver:net_i40eport:3Driver:net_i40eport:0-MAC-3C:FD:FE:A9:A8:88port:1-MAC-3C:FD:FE:A9:A8:89port:2-MAC-3C:FD:FE:A9:A8:8Aport:3-MAC-3C:FD:FE:A9:A8:8B更复杂的接口初始化

在需要用DPDK收发包时,通常我们需要做更复杂的接口初始化操作,因此我们通常会专门写一个port_init函数,这个函数的参数为portid和相关的mbuf_pool:

staticinlineintport_init(uint16_tport,structrte_mempool*mbuf_pool){...}

首先我们需要定义一些常量,主要是RX_RING/TX_RING的大小,MBUF的大小和Cache_size等

#defineRX_RING_SIZE#defineTX_RING_SIZE#defineNUM_MBUFS#defineMBUF_CACHE_SIZE#defineBURST_SIZE32

接着定义一个defaultconfig的结构体

staticconststructrte_eth_confport_conf_default={.rxmode={.max_rx_pkt_len=RTE_ETHER_MAX_LEN,},};

接下来就是整个port_init函数了:

staticinlineintport_init(uint16_tport,structrte_mempool*mbuf_pool){structrte_eth_confport_conf=port_conf_default;constuint16_trx_rings=1,tx_rings=1;uint16_tnb_rxd=RX_RING_SIZE;uint16_tnb_txd=TX_RING_SIZE;intretval;uint16_tq;structrte_eth_dev_infodev_info;structrte_eth_txconftxconf;//查看这个接口是否为valid,非法则返回-1if(!rte_eth_dev_is_valid_port(port))return-1;//获取接口信息retval=rte_eth_dev_info_get(port,dev_info);if(retval!=0){printf("Errorduringgettingdevice(port%u)info:%s\n",port,strerror(-retval));returnretval;}printf("\n\ninitializingport%d...\n",port);//查看接口硬件Offload的能力是否支持,如果支持打开该功能if(dev_info.rx_offload_capaDEV_RX_OFFLOAD_CHECKSUM){printf("port[%u]supportRXcheksumoffload.\n",port);port_conf.rxmode.offloads

=DEV_RX_OFFLOAD_CHECKSUM;}if(dev_info.tx_offload_capaDEV_TX_OFFLOAD_MBUF_FAST_FREE){printf("port[%u]supportTXmbuffastfreeoffload.\n",port);port_conf.txmode.offloads

=DEV_TX_OFFLOAD_MBUF_FAST_FREE;}if(dev_info.tx_offload_capaDEV_TX_OFFLOAD_IPV4_CKSUM){printf("port[%u]supportTXIPv4checksumoffload.\n",port);port_conf.txmode.offloads

=DEV_TX_OFFLOAD_IPV4_CKSUM;}if(dev_info.tx_offload_capaDEV_TX_OFFLOAD_UDP_CKSUM){printf("port[%u]supportTXUDPchecksumoffload.\n",port);port_conf.txmode.offloads

=DEV_TX_OFFLOAD_UDP_CKSUM;}//配置接口retval=rte_eth_dev_configure(port,rx_rings,tx_rings,port_conf);if(retval!=0)returnretval;retval=rte_eth_dev_adjust_nb_rx_tx_desc(port,nb_rxd,nb_txd);if(retval!=0)returnretval;//分配RX队列for(q=0;qrx_rings;q++){retval=rte_eth_rx_queue_setup(port,q,nb_rxd,rte_eth_dev_socket_id(port),NULL,mbuf_pool);if(retval0)returnretval;}txconf=dev_info.default_txconf;txconf.offloads=port_conf.txmode.offloads;//分配TX队列for(q=0;qtx_rings;q++){retval=rte_eth_tx_queue_setup(port,q,nb_txd,rte_eth_dev_socket_id(port),txconf);if(retval0)returnretval;}//使能接口retval=rte_eth_dev_start(port);if(retval0)returnretval;//获取接口MAC地址structrte_ether_addraddr;retval=rte_eth_macaddr_get(port,addr);if(retval!=0)returnretval;printf("Port[%u]MAC:%02"PRIx8"%02"PRIx8"%02"PRIx8"%02"PRIx8"%02"PRIx8"%02"PRIx8"\n",port,addr.addr_bytes[0],addr.addr_bytes[1],addr.addr_bytes[2],addr.addr_bytes[3],addr.addr_bytes[4],addr.addr_bytes[5]);//打开混杂模式retval=rte_eth_promiscuous_enable(port);if(retval!=0)returnretval;return0;}

然后main函数就很简单的了,初始化EAL,然后创建Mbufpool

mbuf_pool=rte_pktmbuf_pool_create("MBUF_POOL",NUM_MBUFS*nb_ports,MBUF_CACHE_SIZE,0,RTE_MBUF_DEFAULT_BUF_SIZE,rte_socket_id());if(mbuf_pool==NULL)rte_exit(EXIT_FAILURE,"Cannotcreatembufpool\n");

然后初始化接口时,可以使用一个宏RTE_ETH_FOREACH_DEV(portid)将每个接口使能.

intmain(intargc,char*argv[]){structrte_mempool*mbuf_pool;unsignednb_ports;uint16_tportid;intret=rte_eal_init(argc,argv);if(ret0)rte_exit(EXIT_FAILURE,"initlizefail!");printf("\n\n\n*****************************************\n");nb_ports=rte_eth_dev_count_avail();printf("numberofavailableport:%d\n",nb_ports);/*Createsanewmempoolinmemorytoholdthembufs.*/mbuf_pool=rte_pktmbuf_pool_create("MBUF_POOL",NUM_MBUFS*nb_ports,MBUF_CACHE_SIZE,0,RTE_MBUF_DEFAULT_BUF_SIZE,rte_socket_id());if(mbuf_pool==NULL)rte_exit(EXIT_FAILURE,"Cannotcreatembufpool\n");/*Initializeallports.*/RTE_ETH_FOREACH_DEV(portid)if(port_init(portid,mbuf_pool)!=0)rte_exit(EXIT_FAILURE,"Cannotinitport%"PRIu16"\n",portid);return0;}收包程序

收包主要是采用rte_eth_rx_burst函数,首先需要从mbuf_pool中分配一些空间,采用dpdk自带的rte_pktmbuf_alloc函数

structrte_mbuf*rx_pkt[BURST_SIZE];for(inti=0;iBURST_SIZE;i++){rx_pkt[i]=rte_pktmbuf_alloc(mbuf_pool);}

然后一个for循环,不停的接收就行了,接收时rte_eth_rx_burst(1,0,rx_pkt,BURST_SIZE)中第一个参数为portid,第二个为队列id,由于我们这个示例每个接口只有一个队列,同时我们采用loopbackcable把port0和port1对连的,因此主要就是一个port0发,port1收的场景,因此接收的portid=1.收到报文后可以通过rte_pktbuf_mtod函数去解析报文,然后可以通过结构体内变量赋值的方式修改值,更具体的示例我们在发包函数里讲,这里只有一个简单的parse源MAC的地址的场景

for(;;){uint16_tnb_rx=rte_eth_rx_burst(1,0,rx_pkt,BURST_SIZE);if(nb_rx==0){continue;}structrte_ether_hdr*eth_hdr;for(inti=0;inb_rx;i++){eth_hdr=rte_pktmbuf_mtod(rx_pkt[i],structrte_ether_hdr*);printf("RecvPkt[%d]fromMAC:%02"PRIx8"%02"PRIx8"%02"PRIx8"%02"PRIx8"%02"PRIx8"%02"PRIx8"\n",i,eth_hdr-s_addr.addr_bytes[0],eth_hdr-s_addr.addr_bytes[1],eth_hdr-s_addr.addr_bytes[2],eth_hdr-s_addr.addr_bytes[3],eth_hdr-s_addr.addr_bytes[4],eth_hdr-s_addr.addr_bytes[5]);rte_pktmbuf_free(rx_pkt[i]);}}发包程序

本次发包程序的示例是以UDP发包为主,因此我们需要逐层初始化报文,然后报文的发送可以Burst的方式一次发送32个,我们也用这种方式来处理,报文发送的函数如下rte_eth_tx_burst.

首先我们初始化源目的MAC地址、IP地址和UDPPayload里面的内容,我们以SRoUheader的一部分为例,相关的结构体定义如下:

structrte_ether_hdr*eth_hdr;structrte_ipv4_hdr*ipv4_hdr;structrte_udp_hdr*udp_hdr;//DefinedheaderinUDPstructSRoU{uint8_tmagic_num;uint8_tsrou_length;uint8_tflags;uint8_tnext_protcol;uint64_tpad;};

然后我们分别来初始化每一层

//initmacstructrte_ether_addrs_addr={{0x14,0x02,0xEC,0x89,0x8D,0x24}};structrte_ether_addrd_addr={{0x3c,0xfd,0xfe,0xa9,0xa8,0x89}};//initIPheaderrte_be32_ts_ip_addr=string_to_ip("1.0.0.");rte_be32_td_ip_addr=string_to_ip("1.0.0.1");uint16_tether_type=rte_cpu_to_be_16(0x);//initudppayloadstructSRoUobj={.magic_num=1,.srou_length=4,.flags=0xFF,.next_protcol=0,};

初始化IP地址时有一个函数是从string转换为be32值

rte_be32_tstring_to_ip(char*s){unsignedchara[4];intrc=sscanf(s,"%hhd.%hhd.%hhd.%hhd",a+0,a+1,a+2,a+3);if(rc!=4){fprintf(stderr,"badsourceIPaddressformat.Uselike:1.2.3.4\n");exit(1);}return(rte_be32_t)(a[3])24

(rte_be32_t)(a[2])16

(rte_be32_t)(a[1])8

(rte_be32_t)(a[0]);}

接下来我们来从mbuf中分配空间并初始化每个报文,注意其中rte_pktmbuf_mtod_offset函数的用法,大量的报文修改都采用这种方式.

structSRoU*msg;structrte_mbuf*pkt[BURST_SIZE];for(inti=0;iBURST_SIZE;i++){//分配空间pkt[i]=rte_pktmbuf_alloc(mbuf_pool);//利用rte_pktmbuf_mtod函数修改二层头,eth_hdr=rte_pktmbuf_mtod(pkt[i],structrte_ether_hdr*);eth_hdr-d_addr=d_addr;//这里我们根据burst循环改改源MAC地址玩~structrte_ether_addrs_addr={{0x14,0x02,0xEC,0x89,0x8D,i}};eth_hdr-s_addr=s_addr;eth_hdr-ether_type=ether_type;//然后利用rte_pktmbuf_mtod_offset函数,移到IPv4头开始的地方,并定义结构体ipv4_hdr=rte_pktmbuf_mtod_offset(pkt[i],structrte_ipv4_hdr*,sizeof(structrte_ether_hdr));ipv4_hdr-version_ihl=0x45;ipv4_hdr-next_proto_id=0x11;ipv4_hdr-src_addr=s_ip_addr;ipv4_hdr-dst_addr=d_ip_addr;ipv4_hdr-time_to_live=0x40;//修改UDP头,注意大端小端转换的rte_cpu_to_be_16函数udp_hdr=rte_pktmbuf_mtod_offset(pkt[i],structrte_udp_hdr*,sizeof(structrte_ether_hdr)+sizeof(structrte_ipv4_hdr));udp_hdr-dgram_len=rte_cpu_to_be_16(sizeof(structSRoU)+sizeof(structrte_udp_hdr));udp_hdr-src_port=rte_cpu_to_be_16();udp_hdr-dst_port=rte_cpu_to_be_16();msg=(structSRoU*)(rte_pktmbuf_mtod(pkt[i],char*)+sizeof(structrte_ether_hdr)+sizeof(structrte_ipv4_hdr)+sizeof(structrte_udp_hdr));*msg=obj;intpkt_size=sizeof(structSRoU)+sizeof(structrte_ether_hdr)+sizeof(structrte_ipv4_hdr)+sizeof(structrte_udp_hdr);//最后是采用HWOffload的方式去计算Checksumpkt[i]-l2_len=sizeof(structrte_ether_hdr);pkt[i]-l3_len=sizeof(structrte_ipv4_hdr);pkt[i]-l4_len=sizeof(structrte_udp_hdr);pkt[i]-ol_flags

=PKT_TX_IPV4

PKT_TX_IP_CKSUM

PKT_TX_UDP_CKSUM;ipv4_hdr-total_length=rte_cpu_to_be_16(sizeof(structSRoU)+sizeof(structrte_udp_hdr)+sizeof(structrte_ipv4_hdr));ipv4_hdr-hdr_checksum=0;udp_hdr-dgram_cksum=rte_ipv4_phdr_cksum(ipv4_hdr,pkt[i]-ol_flags);//定义报文长度pkt[i]-data_len=pkt_size;pkt[i]-pkt_len=pkt_size;}

然后我们采用每两秒发送一次的方式

for(;;){uint16_tnb_tx=rte_eth_tx_burst(0,0,pkt,BURST_SIZE);printf("successfulsend%dpkts\n",nb_tx);sleep(2);}for(inti=0;iBURST_SIZE;i++){rte_pktmbuf_free(pkt[i]);}

执行时,我们希望收发并行执行,因此我们可以将发包函数封装好,并在main函数中调用

staticintlcore_send(structrte_mempool*mbuf_pool){...}intmain(){rte_eal_remote_launch((lcore_function_t*)lcore_send,mbuf_pool,1);}

完成后的整个程序如下

#includestdint.h#includeunistd.h#includeinttypes.h#includerte_eal.h#includerte_ethdev.h#includerte_cycles.h#includerte_lcore.h#includerte_mbuf.h#includerte_ether.h#includerte_ip.h#includerte_udp.h#includepthread.h#includestring.h#defineMAX_PORTS16#defineRX_RING_SIZE#defineTX_RING_SIZE#defineNUM_MBUFS#defineMBUF_CACHE_SIZE#defineBURST_SIZE32staticconststructrte_eth_confport_conf_default={.rxmode={.max_rx_pkt_len=RTE_ETHER_MAX_LEN,},};staticinlineintport_init(uint16_tport,structrte_mempool*mbuf_pool){structrte_eth_confport_conf=port_conf_default;constuint16_trx_rings=1,tx_rings=1;uint16_tnb_rxd=RX_RING_SIZE;uint16_tnb_txd=TX_RING_SIZE;intretval;uint16_tq;structrte_eth_dev_infodev_info;structrte_eth_txconftxconf;if(!rte_eth_dev_is_valid_port(port))return-1;retval=rte_eth_dev_info_get(port,dev_info);if(retval!=0){printf("Errorduringgettingdevice(port%u)info:%s\n",port,strerror(-retval));returnretval;}printf("\n\ninitializingport%d...\n",port);if(dev_info.rx_offload_capaDEV_RX_OFFLOAD_CHECKSUM){printf("port[%u]supportRXcheksumoffload.\n",port);port_conf.rxmode.offloads

=DEV_RX_OFFLOAD_CHECKSUM;}if(dev_info.tx_offload_capaDEV_TX_OFFLOAD_MBUF_FAST_FREE){printf("port[%u]supportTXmbuffastfreeoffload.\n",port);port_conf.txmode.offloads

=DEV_TX_OFFLOAD_MBUF_FAST_FREE;}if(dev_info.tx_offload_capaDEV_TX_OFFLOAD_MT_LOCKFREE){printf("port[%u]supportTXMTlockfreeoffload.\n",port);port_conf.txmode.offloads

=DEV_TX_OFFLOAD_MT_LOCKFREE;}if(dev_info.tx_offload_capaDEV_TX_OFFLOAD_IPV4_CKSUM){printf("port[%u]supportTXIPv4checksumoffload.\n",port);port_conf.txmode.offloads

=DEV_TX_OFFLOAD_IPV4_CKSUM;}if(dev_info.tx_offload_capaDEV_TX_OFFLOAD_UDP_CKSUM){printf("port[%u]supportTXUDPchecksumoffload.\n",port);port_conf.txmode.offloads

=DEV_TX_OFFLOAD_UDP_CKSUM;}if(dev_info.tx_offload_capaDEV_TX_OFFLOAD_TCP_CKSUM){printf("port[%u]supportTXTCPchecksumoffload.\n",port);port_conf.txmode.offloads

=DEV_TX_OFFLOAD_TCP_CKSUM;}if(dev_info.tx_offload_capaDEV_TX_OFFLOAD_SCTP_CKSUM){printf("port[%u]supportTXSCTPchecksumoffload.\n",port);port_conf.txmode.offloads

=DEV_TX_OFFLOAD_SCTP_CKSUM;}/*ConfiguretheEthernetdevice.*/retval=rte_eth_dev_configure(port,rx_rings,tx_rings,port_conf);if(retval!=0)returnretval;retval=rte_eth_dev_adjust_nb_rx_tx_desc(port,nb_rxd,nb_txd);if(retval!=0)returnretval;/*Allocateandsetup1RXqueueperEthernetport.*/for(q=0;qrx_rings;q++){retval=rte_eth_rx_queue_setup(port,q,nb_rxd,rte_eth_dev_socket_id(port),NULL,mbuf_pool);if(retval0)returnretval;}txconf=dev_info.default_txconf;txconf.offloads=port_conf.txmode.offloads;/*Allocateandsetup1TXqueueperEthernetport.*/for(q=0;qtx_rings;q++){retval=rte_eth_tx_queue_setup(port,q,nb_txd,rte_eth_dev_socket_id(port),txconf);if(retval0)returnretval;}/*StarttheEthernetport.*/retval=rte_eth_dev_start(port);if(retval0)returnretval;structrte_eth_linklink;do{retval=rte_eth_link_get_nowait(port,link);if(retval0){printf("Failedlinkget(port%u):%s\n",port,rte_strerror(-retval));returnretval;}elseif(link.link_status)break;printf("WaitingforLinkuponport%"PRIu16"\n",port);sleep(1);}while(!link.link_status);/*DisplaytheportMACaddress.*/structrte_ether_addraddr;retval=rte_eth_macaddr_get(port,addr);if(retval!=0)returnretval;printf("Port[%u]MAC:%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8"\n",port,addr.addr_bytes[0],addr.addr_bytes[1],addr.addr_bytes[2],addr.addr_bytes[3],addr.addr_bytes[4],addr.addr_bytes[5]);/*EnableRXinpromiscuousmodefortheEthernetdevice.*/retval=rte_eth_promiscuous_enable(port);if(retval!=0)returnretval;return0;}rte_be32_tstring_to_ip(char*s){unsignedchara[4];intrc=sscanf(s,"%hhd.%hhd.%hhd.%hhd",a+0,a+1,a+2,a+3);if(rc!=4){fprintf(stderr,"badsourceIPaddressformat.Uselike:1.1.1.1\n");exit(1);}return(rte_be32_t)(a[3])24

(rte_be32_t)(a[2])16

(rte_be32_t)(a[1])8

(rte_be32_t)(a[0]);}staticintlcore_send(structrte_mempool*mbuf_pool){structrte_ether_hdr*eth_hdr;structrte_ipv4_hdr*ipv4_hdr;structrte_udp_hdr*udp_hdr;//DefinedheaderinUDPstructSRoU{uint8_tmagic_num;uint8_tsrou_length;uint8_tflags;uint8_tnext_protcol;uint64_tpad;};//initmacstructrte_ether_addrs_addr={{0x14,0x02,0xEC,0x89,0x8D,0x24}};structrte_ether_addrd_addr={{0x3c,0xfd,0xfe,0xa9,0xa8,0x89}};//initIPheaderrte_be32_ts_ip_addr=string_to_ip("1.0.0.");rte_be32_td_ip_addr=string_to_ip("1.0.0.1");uint16_tether_type=rte_cpu_to_be_16(0x);//initudppayloadstructSRoUobj={.magic_num=1,.srou_length=4,.flags=0xFF,.next_protcol=0,};structSRoU*msg;structrte_mbuf*pkt[BURST_SIZE];for(inti=0;iBURST_SIZE;i++){pkt[i]=rte_pktmbuf_alloc(mbuf_pool);eth_hdr=rte_pktmbuf_mtod(pkt[i],structrte_ether_hdr*);eth_hdr-d_addr=d_addr;structrte_ether_addrs_addr={{0x14,0x02,0xEC,0x89,0x8D,i}};eth_hdr-s_addr=s_addr;eth_hdr-ether_type=ether_type;ipv4_hdr=rte_pktmbuf_mtod_offset(pkt[i],structrte_ipv4_hdr*,sizeof(structrte_ether_hdr));ipv4_hdr-version_ihl=0x45;ipv4_hdr-next_proto_id=0x11;ipv4_hdr-src_addr=s_ip_addr;ipv4_hdr-dst_addr=d_ip_addr;ipv4_hdr-time_to_live=0x40;udp_hdr=rte_pktmbuf_mtod_offset(pkt[i],structrte_udp_hdr*,sizeof(structrte_ether_hdr)+sizeof(structrte_ipv4_hdr));udp_hdr-dgram_len=rte_cpu_to_be_16(sizeof(structSRoU)+sizeof(structrte_udp_hdr));udp_hdr-src_port=rte_cpu_to_be_16();udp_hdr-dst_port=rte_cpu_to_be_16();ipv4_hdr-total_length=rte_cpu_to_be_16(sizeof(structSRoU)+sizeof(structrte_udp_hdr)+sizeof(structrte_ipv4_hdr));msg=(structSRoU*)(rte_pktmbuf_mtod(pkt[i],char*)+sizeof(structrte_ether_hdr)+sizeof(structrte_ipv4_hdr)+sizeof(structrte_udp_hdr));*msg=obj;intpkt_size=sizeof(structSRoU)+sizeof(structrte_ether_hdr)+sizeof(structrte_ipv4_hdr)+sizeof(structrte_udp_hdr);pkt[i]-l2_len=sizeof(structrte_ether_hdr);pkt[i]-l3_len=sizeof(structrte_ipv4_hdr);pkt[i]-l4_len=sizeof(structrte_udp_hdr);pkt[i]-ol_flags

=PKT_TX_IPV4

PKT_TX_IP_CKSUM

PKT_TX_UDP_CKSUM;ipv4_hdr-hdr_checksum=0;udp_hdr-dgram_cksum=rte_ipv4_phdr_cksum(ipv4_hdr,pkt[i]-ol_flags);pkt[i]-data_len=pkt_size;pkt[i]-pkt_len=pkt_size;}for(;;){uint16_tnb_tx=rte_eth_tx_burst(0,0,pkt,BURST_SIZE);printf("successfulsend%dpkts\n",nb_tx);sleep(2);}for(inti=0;iBURST_SIZE;i++){rte_pktmbuf_free(pkt[i]);}}intmain(intargc,char*argv[]){structrte_mempool*mbuf_pool;unsignednb_ports;uint16_tportid;intret=rte_eal_init(argc,argv);if(ret0)rte_exit(EXIT_FAILURE,"initlizefail!");printf("\n\n\n*****************************************\n");nb_ports=rte_eth_dev_count_avail();printf("numberofavailableport:%d\n",nb_ports);/*Createsanewmempoolinmemorytoholdthembufs.*/mbuf_pool=rte_pktmbuf_pool_create("MBUF_POOL",NUM_MBUFS*nb_ports,MBUF_CACHE_SIZE,0,RTE_MBUF_DEFAULT_BUF_SIZE,rte_socket_id());if(mbuf_pool==NULL)rte_exit(EXIT_FAILURE,"Cannotcreatembufpool\n");/*Initializeallports.*/RTE_ETH_FOREACH_DEV(portid)if(port_init(portid,mbuf_pool)!=0)rte_exit(EXIT_FAILURE,"Cannotinitport%"PRIu16"\n",portid);/*startpacketsendfunctiononlcore-1*/rte_eal_remote_launch((lcore_function_t*)lcore_send,mbuf_pool,1);structrte_mbuf*rx_pkt[BURST_SIZE];for(inti=0;iBURST_SIZE;i++){rx_pkt[i]=rte_pktmbuf_alloc(mbuf_pool);}for(;;){uint16_tnb_rx=rte_eth_rx_burst(1,0,rx_pkt,BURST_SIZE);if(nb_rx==0){continue;}structrte_ether_hdr*eth_hdr;for(inti=0;inb_rx;i++){eth_hdr=rte_pktmbuf_mtod(rx_pkt[i],structrte_ether_hdr*);printf("RecvPkt[%d]fromMAC:%02"PRIx8"%02"PRIx8"%02"PRIx8"%02"PRIx8"%02"PRIx8"%02"PRIx8"\n",i,eth_hdr-s_addr.addr_bytes[0],eth_hdr-s_addr.addr_bytes[1],eth_hdr-s_addr.addr_bytes[2],eth_hdr-s_addr.addr_bytes[3],eth_hdr-s_addr.addr_bytes[4],eth_hdr-s_addr.addr_bytes[5]);rte_pktmbuf_free(rx_pkt[i]);}}return0;}

最后编译执行

zartbot

zartbotWS:~/learn/dpdk/01_port_init$makecc-O3-includerte_config.h-march=native-I/usr/local/include-I/usr/include/libnl3-DALLOW_EXPERIMENTAL_APImain.c-obuild/portinit-shared-L/usr/local/lib/x86_64-linux-gnu-Wl,--as-needed-lrte_node-lrte_graph-lrte_bpf-lrte_flow_classify-lrte_pipeline-lrte_table-lrte_port-lrte_fib-lrte_ipsec-lrte_vhost-lrte_stack-lrte_security-lrte_sched-lrte_reorder-lrte_rib-lrte_regexdev-lrte_rawdev-lrte_pdump-lrte_power-lrte_member-lrte_lpm-lrte_latencystats-lrte_kni-lrte_jobstats-lrte_ip_frag-lrte_gso-lrte_gro-lrte_eventdev-lrte_efd-lrte_distributor-lrte_cryptodev-lrte_

转载请注明:http://www.sonphie.com/lcbx/14413.html

网站简介| 发布优势| 服务条款| 隐私保护| 广告合作| 网站地图| 版权申明

当前时间: