关键词不能为空

当前您在: 主页 > 英语 >

DPDK L2 fwd代码走读报告(代码流程分析)

作者:高考题库网
来源:https://www.bjmy2z.cn/gaokao
2021-01-30 07:43
tags:

-

2021年1月30日发(作者:臣)





****



DPDK


学习



L2 fwd


代码走读报告



导师:


***











学生:


***


2016-2-18



目录



一、 对于


DPDK


的认识:



.


................................. .................................................. ............................


2



二、对


L2 fwd


的认识:



.

< br>............................................... .................................................. ................


3


2.1


运行配置


................... .................................................. .................................................. ......


3



2.2


运行环境搭建



.


.................................. .................................................. ................................


3



2.3


功能分析:


< br>.


................................... .................................................. ...................................


6



2.4


详细流程图(调用关系)如下:



.


........................... .................................................. .......


6



2.5


运行截图


............................ .................................................. ...............................................


8



2.6


详细代码注释分析:



.


............................... .................................................. .......................


8





































一、对于


DPDK


的认识:



主要应用


x86


通用平台



转发 处理


网络数据包,


定位在不需要专用网络处理器,


但通用网络处理器对数据处理性能又不能满足需求的客户。



DPDK


,搭载


x86


服务器 ,成本变化不大,但对数据的处理性能又有非常显著


的提高,


对 传统


linux


技术做一定的优化,


特 别之处在于:


hugepage,uio,zero copy,


cpu affinity


等。



关于


hugetlbpage


< p>
在这块大页面上做自己的内存管理系统)


,之前讲过,它

< br>的主要好处当然是通过利用大内存页提高内存使用效率,。由于


DPDK


是应用层平


台,所以与此紧密相连的网卡驱动程序(当然,主要是


intel


自身的千兆


igb


与万



ixgbe


驱动程序) 都通过


uio(


用户层驱动、轮询、


0


拷贝


)


机制运行在用户态下。


cpu affinity



多核架构,核线程 绑定物理核)


机制是多核


cpu


发展的 结果,,在越


来越多核心的


cpu


机器 上,


如何提高外设以及程序工作效率的最直观想法就是让各


个< /p>


cpu


核心各自干专门的事情,比如两个网卡

eth0



eth1


都收包,可以 让


cpu0


专心处理


eth0



cpu1


专心处理


e th1


,没必要


cpu0


一下处理


eth0


,一下又处理


eth1

< p>
,还有一个网卡多队列的情况也是类似,等等,


DPDK

< br>利用


cpu affinity


主要

是将控制面线程以及各个数据面线程绑定到不同的


cpu


, 省却了来回反复调度的性


能消耗,各个线程一个


while


死循环,专心致志的做事,互不干扰(当然还是有通


信的,比如控制 面接收用户配置,转而传递给数据面的参数设置等)。



总结如下:



1




使用大页缓存支持来提高内存访问效率。



2




利用< /p>


UIO


支持,提供应用空间下驱动程序的支持,也就是说网卡驱动 是运


行在用户空间



的,减下了报文在用户空间和应用空间的多次拷贝。




3




利用


LINUX


亲和性支持,把控制面线程 及各个数据面线程绑定到不同的


CPU


核,节省了



线程在各个


CPU


核来回 调度。




4




提供内存池和无锁环形缓存管理,加快内存访问效率。




x86


服务器,


1 G/10G/40G


网卡包转发,


64Byte


小包,基本能做到


70%



上 的转发,而传统


linux


系统只能达


5%


左右,在网络大数据流时代,


DPDK

加码,


优势明显。



二、对


L2fwd


的认识:



2.1


运行配置



虚拟机软件:


VMWare WorkStation 12.0.0 build-2985596


CPU




2



CPU




每个


CPU2


个核心

< br>


内存:



1GB+


网卡:


intel


网卡


*2




用于


dpdk


试验;另一块网卡用于和宿主系统进行通信



2.2


运行环境搭建




root


权限下:



1


)编译


dpdk

< br>进入


dpdk


主目录



,输入



make install T=x86_64-native-linuxapp- gcc


进行编译



2

< br>)配置大页内存(非


NUMA




echo 128 >


/sys/kernel/mm/hu gepages/hugepages-2048kB/nr_hugepages


mkdir /mnt/huge


mount -t hugetlbfs nodev /mnt/huge


可以用以下命令查看大页内存状态:



cat /proc/meminfo | grep Huge

3


)安装


igb_uio


驱动



modprobe uio


insmod x86_64-native-linuxapp- gcc/kmod/igb_


4


)绑定网卡



先看一下当前网卡的状态



./tools/dpdk_nic_ --status




1


网卡已经绑定好



进行绑定:



./tools/dpdk_nic_ -b igb_uio 0000:02:06.0


./tools/dpdk_nic_ -b igb_uio 0000:02:05.0


如果网卡有接口名,如


eth1, eth2,


也可以在


-b igb_uio


后面使用接口名,




不使用


pci


地址。

< br>


5 )


设置环境变量:



export RTE_SDK=/home/lv/dpdk/dpdk-1.7.0


export RTE_TARGET=x86_64-native- linuxapp-gcc


之后进入


/exam ples/l2


,运行


make


,成功 会生成


build


目录,其中


有编译好 的


l2fwd


程序。



6)


运行程序



./build/l2fwd -c f -n 2 -- -q 1 -p 0x3


2.3


功能分析:




DPDK


搭建环境完成后,网卡绑定 到相应


IGB_UIO


驱动接口上,所有的网络数


据包都会到


DPDK


,网卡接收网络数据包,再从另 一个网卡转发出去



2.4


详细流程图(调用关系)如下:



(


初学者,欢迎讨论


QQ:78010 2849


,望各位指错


)






























DPDK L2fwd


详细流程图(调用关系)




main




rte_eal_init




Pthread_create


init


Other inits



libs< /p>



drivers



Pthread_cr


eate


init



Pthread_c


reate


init



rte_eal_mp_remote_launch



Lcore 1



SLAVE




rte_eal_remote_launch


(send messages to cores)



Lcore 2




SLAVE




L


core ……





S LAVE





lcore_config[master].ret = f(arg);



Master Lcore



rte_eth_rx



_burst


(Read


packet



from RX


queues)


l2fwd_se


nd_burst


(enough


pkts to


be sent)



rte_eth_


rx_burst


(Read


packet


from RX


queues)


l2fwd_se


nd_burst


(enough


pkts to


be sent)




eth0


eth1


eth 2


eth 3



lcore_config[master].state = FINISHED;


return 0 (end)




2.5


运行截图




2.6


详细代码注释分析:



1


#include


2


#include


3


#include <


string


.h>


4


#include


5


#include


6


#include


7


#include


8


#include


in


.h>


9


#include


10


#include


11


#include


12


#include


13


#include


14



15


#include


16


#include


17


#include


18


#include


19


#include


20


#include


21


#include


22


#include


23


#include


24


#include


25


#include


26


#include


27


#include


28


#include


29


#include


30


#include


31


#include


32


#include


33


#include


34


#include


35


#include


36


#include


37


#include


38



39


#define


RTE_LOGTYPE_L2FWD RTE_LOGTYPE_USER1


40



41


#define


MBUF_SIZE (2048 + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM)


42


#define


NB_MBUF 8192


43



44


#define


MAX_PKT_BURST 32


45


#define


BURST_TX_DRAIN_US 100 /* TX drain every ~100us */


46



47


/*



48


* Configurable number of RX/TX ring descriptors


49


*/



50


#define


RTE_TEST_RX_DESC_DEFAULT 128


51


#define


RTE_TEST_TX_DESC_DEFAULT 512


52


static


uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT;


53


static


uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;


54



55


/*

物理端口的


mac


地址的数组


ethernet addresses of ports */



56


staticstruct


ether_addr l2fwd_ports_eth_addr[RTE_MAX_ETHPORTS];


57



58


/*


已经启用的物理端口的掩码


/


位 图


mask of enabled ports */



59


static


uint32_t l2fwd_enabled_port_mask =


0


;


60



61


/*


已经启用的目的物理端口编号的数组


list of enabled ports */



62


static


uint32_t l2fwd_dst_ports[RTE_MAX_ETHPORTS];


63



64


static


unsigned


int


l2fwd_rx_queue_per_lcore =


1


;


//


默认值,每个


lcore


负责


的接收 队列数量



65



66


struct


mbuf_table {


//mbuf


数组,可以存放< /p>


32


个数据包



67


unsigned len;


68


struct


rte_mbuf *m_table[MAX_PKT_BURST];


69


};


70



71


#define


MAX_RX_QUEUE_PER_LCORE 16


72


#define


MAX_TX_QUEUE_PER_PORT 16


73


struct


lcore_queue_conf {


74


unsigned n_rx_port;


//


用于接收数据包的物理端口的实际数量


75


unsigned rx_port_list[MAX_RX_QUEUE_PER_LCORE];


76


struct


mbuf_table tx_mbufs[RTE_MAX_ETHPORTS];


//


保存发送数据包的缓存区



77



78


} __rte_cache_aligned;


79


struct


lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE];


80



81


staticconststruct


rte_eth_conf port_conf = {


82


.rxmode = {


83


.split_hdr_size =


0


,


84


.header_split =


0


,


/**< Header Split disabled */



85


.hw_ip_checksum =


0


,


/**< IP checksum offload disabled */



86


.hw_vlan_filter =


0


,


/**< VLAN filtering disabled */



87


.jumbo_frame =


0


,


/**< Jumbo Frame Support disabled */



88


.hw_strip_crc =


0


,


/**< CRC stripped by hardware */



89


},


90


.txmode = {


91


.mq_mode = ETH_MQ_TX_NONE,


92


},


93


};


94



95


struct


rte_mempool * l2fwd_pktmbuf_pool = NULL;


96



97


/*


每个物理端口的统计结构体


Per-port statistics struct */



98


struct


l2fwd_port_statistics {


99


uint64_t tx;


100


uint64_t rx;


101


uint64_t dropped;


102


} __rte_cache_aligned;


103


struct


l2fwd_port_statistics port_statistics[RTE_MAX_ETHPORTS];


//


数据包


的统计信息的全局数组



104



105


/* A tsc-based timer responsible for triggering statistics printout */



106


#define


TIMER_MILLISECOND 2ULL /* around 1ms at 2 Ghz */


107


#define


MAX_TIMER_PERIOD 86400 /* 1 day max */


108


static


int64_t timer_period =


10


* TIMER_MILLISECOND *


1


;


/* default peri


od is 10 seconds */



109



110


/* Print out statistics on packets dropped */



static void


//


打印数据包丢失等统计信息



112


print_stats(


void


)


113


{


114


uint64_t total_packets_dropped, total_packets_tx, total_packets_rx;


115


unsigned portid;


116



117


total_packets_dropped =


0


;


118


total_packets_tx =


0


;


119


total_packets_rx =


0


;


120



121


constchar


clr[] = {


27


,


'['


,


'2'


,


'J'


,


'0'


};


122


constchar


topLeft[] = {


27


,


'['


,


'1'


,


';'


,


'1'


,


'H'

,


'0'


};


123



124


/* Clear screen and move to top left */



125


printf(



, clr, topLeft);


126



127


printf(



);


128



129


for


(portid =


0


; portid < RTE_MAX_ETHPORTS; portid++) {


130


/* skip disabled ports */



131


if


((l2fwd_enabled_port_mask & (


1


<< portid)) ==


0


)


132


continue


;


133


printf(




134



PRIu64


135



PRIu64


136



PRIu64,


137


portid,


138


port_statistics[portid].tx,


139


port_statistics[portid].rx,


140


port_statistics[portid].dropped);


141



142


total_packets_dropped += port_statistics[portid].dropped;


143


total_packets_tx += port_statistics[portid].tx;


144


total_packets_rx += port_statistics[portid].rx;


145


}


146


printf(




147



PRIu64


148



PRIu64


149



PRIu64,


150


total_packets_tx,


151


total_packets_rx,


152


total_packets_dropped);


153


printf(



);


154


}


155



156


/* Send the burst of packets on an output interface */


< p>
157


staticint


//

< br>在一个输出接口上


burst


发送数据包



158


l2fwd_send_burst(


struct


lcore_queue_conf *qconf, unsigned n, uint8_t por


t)


159


{


160


struct


rte_mbuf **m_table;


161


unsigned ret;


162


unsigned queueid =


0


;


163



164


m_table = (


struct


rte_mbuf **)qconf->tx_mbufs[port].m_table;


165


//burst


输出数据包



166


ret = rte_eth_tx_burst(port, (uint16_t) queueid, m_table, (uint16_t)


n);


167


port_statistics[port].tx += ret;


//


记录发包数量



168


if


(unlikely(ret < n)) {


169


port_statistics[port].dropped += (n - ret);


//


记录丢包数量



170


do


{


171


rte_pktmbuf_free(m_table[ret]);


172


}


while


(++ret < n);


173


}


174



175


return


0


;


176


}


177



178


/* Enqueue packets for TX and prepare them to be sent */


< br>179


staticint


//


把数据包入队到发送缓冲区



180


l2fwd_send_packet(


struct


rte_mbuf *m, uint8_t port)


181


{


182


unsigned lcore_id, len;


183


struct


lcore_queue_conf *qconf;


184



185


lcore_id = rte_lcore_id();


//


取得正在运行的


lcore


编号



186



187


qconf = &lcore_queue _conf[lcore_id];


//


取得

< br>lcore_queue


的配置



188


len = qconf->tx_mbufs[port].len;


//


得到发包缓存区中数据包的个数



189


qconf->tx_mbufs[port].m_table[len] = m;


//


指向数据包



190


len++;


191



192


/* enough pkts to be sent */



193


if


(unlikely(len == MAX_PKT_BURST)) {


//


如果累计到


32


个数据包

< br>


194


l2fwd_send_burst(qconf, MAX_PKT_BURST, port);


//


实际发送数据包



195


len =


0


;


196


}


197



198


qconf->tx_mbufs[port].len = len;


//

< p>
更新发包缓存区中的数据包的个数



199


return


0


;


200


}


201



202


staticvoid



203


l2fwd_simple_forward(


struct


rte_mbuf *m, unsigned portid)


204


{


205


//


想要满足文生提出的需求,主要在这里修改


ip< /p>


层和


tcp


层的数据内容。



206



207


struct


ether_hdr *eth;


208


void


*tmp;


209


unsigned dst_port;


210



211


dst_port = l2fwd_dst_ports[portid];


212


eth = rte_pktmbuf_mtod(m,


struct


ether_hdr *);


213



214


/* 02:00:00:00:00:xx


修改目的


mac


地址


*/



215


tmp = ð->d__bytes[


0


];

-


-


-


-


-


-


-


-



本文更新与2021-01-30 07:43,由作者提供,不代表本网站立场,转载请注明出处:https://www.bjmy2z.cn/gaokao/590196.html

DPDK L2 fwd代码走读报告(代码流程分析)的相关文章