DPDK L2 fwd代码走读报告代码流程分析Word文件下载.docx
《DPDK L2 fwd代码走读报告代码流程分析Word文件下载.docx》由会员分享,可在线阅读,更多相关《DPDK L2 fwd代码走读报告代码流程分析Word文件下载.docx(33页珍藏版)》请在冰豆网上搜索。
mkdir/mnt/huge
mount-thugetlbfsnodev/mnt/huge
可以用以下命令查看大页内存状态:
cat/proc/meminfo|grepHuge
3)安装igb_uio驱动
modprobeuio
insmodx86_64-native-linuxapp-gcc/kmod/igb_uio.ko
4)绑定网卡
先看一下当前网卡的状态
./tools/dpdk_nic_bind.py--status
图1网卡已经绑定好
进行绑定:
./tools/dpdk_nic_bind.py-bigb_uio0000:
02:
06.0
05.0
如果网卡有接口名,如eth1,eth2,也可以在-bigb_uio后面使用接口名,而不使用pci地址。
5)设置环境变量:
exportRTE_SDK=/home/lv/dpdk/dpdk-1.7.0
exportRTE_TARGET=x86_64-native-linuxapp-gcc
之后进入<
/examples/l2,运行make,成功会生成build目录,其中有编译好的l2fwd程序。
6)运行程序
./build/l2fwd
-c
f
-n
2
--
-q
1
-p
0x3
2.3功能分析:
DPDK搭建环境完成后,网卡绑定到相应IGB_UIO驱动接口上,所有的网络数据包都会到DPDK,网卡接收网络数据包,再从另一个网卡转发出去
2.4详细流程图(调用关系)如下:
(初学者,欢迎讨论QQ:
780102849,望各位指错)
DPDKL2fwd详细流程图(调用关系)
2.5运行截图
2.6详细代码注释分析:
1#include<
stdio.h>
2#include<
stdlib.h>
3#include<
string.h>
4#include<
stdint.h>
5#include<
inttypes.h>
6#include<
sys/types.h>
7#include<
sys/queue.h>
8#include<
netinet/in.h>
9#include<
setjmp.h>
10#include<
stdarg.h>
11#include<
ctype.h>
12#include<
errno.h>
13#include<
getopt.h>
14
15#include<
rte_common.h>
16#include<
rte_log.h>
17#include<
rte_memory.h>
18#include<
rte_memcpy.h>
19#include<
rte_memzone.h>
20#include<
rte_eal.h>
21#include<
rte_per_lcore.h>
22#include<
rte_launch.h>
23#include<
rte_atomic.h>
24#include<
rte_cycles.h>
25#include<
rte_prefetch.h>
26#include<
rte_lcore.h>
27#include<
28#include<
rte_branch_prediction.h>
29#include<
rte_interrupts.h>
30#include<
rte_pci.h>
31#include<
rte_random.h>
32#include<
rte_debug.h>
33#include<
rte_ether.h>
34#include<
rte_ethdev.h>
35#include<
rte_ring.h>
36#include<
rte_mempool.h>
37#include<
rte_mbuf.h>
38
39#defineRTE_LOGTYPE_L2FWDRTE_LOGTYPE_USER1
40
41#defineMBUF_SIZE(2048+sizeof(structrte_mbuf)+RTE_PKTMBUF_HEADROOM)
42#defineNB_MBUF8192
43
44#defineMAX_PKT_BURST32
45#defineBURST_TX_DRAIN_US100/*TXdrainevery~100us*/
46
47/*
48*ConfigurablenumberofRX/TXringdescriptors
49*/
50#defineRTE_TEST_RX_DESC_DEFAULT128
51#defineRTE_TEST_TX_DESC_DEFAULT512
52staticuint16_tnb_rxd=RTE_TEST_RX_DESC_DEFAULT;
53staticuint16_tnb_txd=RTE_TEST_TX_DESC_DEFAULT;
54
55/*物理端口的mac地址的数组ethernetaddressesofports*/
56staticstructether_addrl2fwd_ports_eth_addr[RTE_MAX_ETHPORTS];
57
58/*已经启用的物理端口的掩码/位图maskofenabledports*/
59staticuint32_tl2fwd_enabled_port_mask=0;
60
61/*已经启用的目的物理端口编号的数组listofenabledports*/
62staticuint32_tl2fwd_dst_ports[RTE_MAX_ETHPORTS];
63
64staticunsignedintl2fwd_rx_queue_per_lcore=1;
//默认值,每个lcore负责的接收队列数量
65
66structmbuf_table{//mbuf数组,可以存放32个数据包
67unsignedlen;
68structrte_mbuf*m_table[MAX_PKT_BURST];
69};
70
71#defineMAX_RX_QUEUE_PER_LCORE16
72#defineMAX_TX_QUEUE_PER_PORT16
73structlcore_queue_conf{
74unsignedn_rx_port;
//用于接收数据包的物理端口的实际数量
75unsignedrx_port_list[MAX_RX_QUEUE_PER_LCORE];
76structmbuf_tabletx_mbufs[RTE_MAX_ETHPORTS];
//保存发送数据包的缓存区
77
78}__rte_cache_aligned;
79structlcore_queue_conflcore_queue_conf[RTE_MAX_LCORE];
80
81staticconststructrte_eth_confport_conf={
82.rxmode={
83.split_hdr_size=0,
84.header_split=0,/**<
HeaderSplitdisabled*/
85.hw_ip_checksum=0,/**<
IPchecksumoffloaddisabled*/
86.hw_vlan_filter=0,/**<
VLANfilteringdisabled*/
87.jumbo_frame=0,/**<
JumboFrameSupportdisabled*/
88.hw_strip_crc=0,/**<
CRCstrippedbyhardware*/
89},
90.txmode={
91.mq_mode=ETH_MQ_TX_NONE,
92},
93};
94
95structrte_mempool*l2fwd_pktmbuf_pool=NULL;
96
97/*每个物理端口的统计结构体Per-portstatisticsstruct*/
98structl2fwd_port_statistics{
99uint64_ttx;
100uint64_trx;
101uint64_tdropped;
102}__rte_cache_aligned;
103structl2fwd_port_statisticsport_statistics[RTE_MAX_ETHPORTS];
//数据包的统计信息的全局数组
104
105/*Atsc-basedtimerresponsiblefortriggeringstatisticsprintout*/
106#defineTIMER_MILLISECOND2ULL/*around1msat2Ghz*/
107#defineMAX_TIMER_PERIOD86400/*1daymax*/
108staticint64_ttimer_period=10*TIMER_MILLISECOND*1;
/*defaultperiodis10seconds*/
109
110/*Printoutstatisticsonpacketsdropped*/
staticvoid//打印数据包丢失等统计信息
112print_stats(void)
113{
114uint64_ttotal_packets_dropped,total_packets_tx,total_packets_rx;
115unsignedportid;
116
117total_packets_dropped=0;
118total_packets_tx=0;
119total_packets_rx=0;
120
121constcharclr[]={27,'
['
'
2'
J'
\0'
};
122constchartopLeft[]={27,'
1'
;
'
H'
'
123
124/*Clearscreenandmovetotopleft*/
125printf("
%s%s"
clr,topLeft);
126
127printf("
\nPortstatistics===================================="
);
128
129for(portid=0;
portid<
RTE_MAX_ETHPORTS;
portid++){
130/*skipdisabledports*/
131if((l2fwd_enabled_port_mask&
(1<
<
portid))==0)
132continue;
133printf("
\nStatisticsforport%u"
134"
\nPacketssent:
%24"
PRIu64
135"
\nPacketsreceived:
%20"
136"
\nPacketsdropped:
%21"
PRIu64,
137portid,
138port_statistics[portid].tx,
139port_statistics[portid].rx,
140port_statistics[portid].dropped);
141
142total_packets_dropped+=port_statistics[portid].dropped;
143total_packets_tx+=port_statistics[portid].tx;
144total_packets_rx+=port_statistics[portid].rx;
145}
146printf("
\nAggregatestatistics==============================="
147"
\nTotalpacketssent:
%18"
148"
\nTotalpacketsreceived:
%14"
149"
\nTotalpacketsdropped:
%15"
150total_packets_tx,
151total_packets_rx,
152total_packets_dropped);
153printf("
\n====================================================\n"
154}
155
156/*Sendtheburstofpacketsonanoutputinterface*/
157staticint//在一个输出接口上burst发送数据包
158l2fwd_send_burst(structlcore_queue_conf*qconf,unsignedn,uint8_tport)
159{
160structrte_mbuf**m_table;
161unsignedret;
162unsignedqueueid=0;
163
164m_table=(structrte_mbuf**)qconf->
tx_mbufs[port].m_table;
165//burst输出数据包
166ret=rte_eth_tx_burst(port,(uint16_t)queueid,m_table,(uint16_t)n);
167port_statistics[port].tx+=ret;
//记录发包数量
168if(unlikely(ret<
n)){
169port_statistics[port].dropped+=(n-ret);
//记录丢包数量
170do{
171rte_pktmbuf_free(m_table[ret]);
172}while(++ret<
n);
173}
174
175return0;
176}
177
178/*EnqueuepacketsforTXandpreparethemtobesent*/
179staticint//把数据包入队到发送缓冲区
180l2fwd_send_packet(structrte_mbuf*m,uint8_tport)
181{
182unsignedlcore_id,len;
183structlcore_queue_conf*qconf;
184
185lcore_id=rte_lcore_id();
//取得正在运行的lcore编号
186
187qconf=&
lcore_queue_conf[lcore_id];
//取得lcore_queue的配置
188len=qconf->
tx_mbufs[port].len;
//得到发包缓存区中数据包的个数
189qconf->
tx_mbufs[port].m_table[len]=m;
//指向数据包
190len++;
191
192/*enoughpktstobesent*/
193if(unlikely(len==MAX_PKT_BURST)){//如果累计到32个数据包
194l2fwd_send_burst(qconf,MAX_PKT_BURST,port);
//实际发送数据包
195len=0;
196}
197
198qconf->
tx_mbufs[port].len=len;
//更新发包缓存区中的数据包的个数
199return0;
200}
201
202staticvoid
203l2fwd_simple_forward(structrte_mbuf*m,unsignedportid)
204{
205//想要满足文生提出的需求,主要在这里修改ip层和tcp层的数据内容。
206
207structether_hdr*eth;
208void*tmp;
209unsigneddst_port;
210
211dst_port=l2fwd_dst_ports[portid];
212eth=rte_pktmbuf_mtod(m,structether_hdr*);
213
214/*02:
00:
xx修改目的mac地址*/
215tmp=&
eth->
d_addr.addr_bytes[0];
216*((uint64_t*)tmp)=0x002+((uint64_t)dst_port<
40);
217
218/*srcaddr修改进入包的目的mac地址为转发包的源mac地址*/
219ether_addr_copy(&
l2fwd_ports_eth_addr[dst_port],&
s_addr);
220
221l2fwd_send_packet(m,(uint8_t)dst_port);
//在dst_port上发送数据包
}
223
224/*mainprocessingloop*/
225staticvoid//线程的主处理循环
226l2fwd_main_loop(void)
227{
228structrte_mbuf*pkts_burst[MAX_PKT_BURST];
229structrte_mbuf*m;
230unsignedlcore_id;
231uint64_tprev_tsc,diff_tsc,cur_tsc,timer_tsc;
232unsignedi,j,portid,nb_rx;
233structlcore_queue_conf*qconf;
234constuint64_tdrain_tsc=(rte_get_tsc_hz()+US_PER_S-1)/US_PER_S*BURST_TX_DRAIN_US;
235
236prev_tsc=0;
237timer_tsc=0;
238
239lcore_id=rte_lcore_id();
//获取当期lcore的编号
240qconf=&
//读取此lcore上的配置信息
241
242if(qconf->
n_rx_port==0){//如果此lcore上的用于接收的物理端口数量为0
243RTE_LOG(INFO,L2FWD,"
lcore%uhasnothingtodo\n"
lcore_id);
244