. ****DPDK 学习L2 fwd代码走读报告导师:*** 学生:***2016-2-18目录一、对于DPDK的认识:2二、对L2 fwd的认识:32.1运行配置32.2运行环境搭建42.3功能分析:62.4详细流程图(调用关系)如下:62.5运行截图82.6详细代码注释分析:8一、对于DPDK的认识:主要应用x86通用平台,转发处理网络数据包,定位在不需要专用网络处理器,但通用网络处理器对数据处理性能又不能满足需求的客户DPDK,搭载x86服务器,成本变化不大,但对数据的处理性能又有非常显著的提高,对传统linux技术做一定的优化,特别之处在于:hugepage,uio,zero copy, cpu affinity等关于hugetlbpage(在这块大页面上做自己的存管理系统),之前讲过,它的主要好处当然是通过利用大存页提高存使用效率,由于DPDK是应用层平台,所以与此紧密相连的网卡驱动程序(当然,主要是intel自身的千兆igb与万兆ixgbe驱动程序)都通过uio(用户层驱动、轮询、0拷贝)机制运行在用户态下。
cpu affinity(多核架构,核线程绑定物理核)机制是多核cpu发展的结果,,在越来越多核心的cpu机器上,如何提高外设以与程序工作效率的最直观想法就是让各个cpu核心各自干专门的事情,比如两个网卡eth0和eth1都收包,可以让cpu0专心处理eth0,cpu1专心处理eth1,没必要cpu0一下处理eth0,一下又处理eth1,还有一个网卡多队列的情况也是类似,等等,DPDK利用cpu affinity主要是将控制面线程以与各个数据面线程绑定到不同的cpu,省却了来回反复调度的性能消耗,各个线程一个while死循环,专心致志的做事,互不干扰(当然还是有通信的,比如控制面接收用户配置,转而传递给数据面的参数设置等)总结如下:1、 使用大页缓存支持来提高存访问效率2、 利用UIO支持,提供应用空间下驱动程序的支持,也就是说网卡驱动是运行在用户空间 的,减下了报文在用户空间和应用空间的多次拷贝 3、 利用LINUX亲和性支持,把控制面线程与各个数据面线程绑定到不同的CPU核,节省了 线程在各个CPU核来回调度 4、 提供存池和无锁环形缓存管理,加快存访问效率在x86服务器,1G/10G/40G网卡包转发,64Byte小包,基本能做到70%以上的转发,而传统linux系统只能达5%左右,在网络大数据流时代,DPDK加码,优势明显。
二、对L2fwd的认识:2.1运行配置虚拟机软件:VMWare WorkStation 12.0.0 build-2985596CPU: 2个CPU, 每个CPU 2个核心存: 1GB+网卡:intel网卡*2, 用于dpdk试验;另一块网卡用于和宿主系统进行通信2.2运行环境搭建在root权限下:1)编译dpdk进入dpdk主目录,输入make install T=x86_64-native-linuxapp-gcc进行编译2)配置大页存(非NUMA)echo 128 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepagesmkdir /mnt/hugemount -t hugetlbfs nodev /mnt/huge可以用以下命令查看大页存状态:cat /proc/meminfo | grep Huge3)安装igb_uio驱动modprobe uioinsmod x86_64-native-linuxapp-gcc/kmod/igb_uio.ko4)绑定网卡先看一下当前网卡的状态./tools/dpdk_nic_bind.py --status图1 网卡已经绑定好进行绑定:./tools/dpdk_nic_bind.py -b igb_uio 0000:02:06.0./tools/dpdk_nic_bind.py -b igb_uio 0000:02:05.0如果网卡有接口名,如eth1, eth2, 也可以在-b igb_uio后面使用接口名, 而不使用pci地址。
5 ) 设置环境变量:export RTE_SDK=/home/lv/dpdk/dpdk-1.7.0export RTE_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详细流程图(调用关系)如下:(初学者,欢迎讨论 :780102849,望各位指错)lcore_config[master].state = FINISHED; return 0 (end)Lcore ……(SLAVE)Pthread_createinitmaineth 1eth 0l2fwd_send_burst(enough pkts to be sent)Pthread_createinitPthread_createinitLcore 2(SLAVE)Lcore 1(SLAVE)Master LcoreOther inits(libs,drivers)rte_eal_initrte_eal_remote_launch(send messages to cores)eth 3eth 2rte_eal_mp_remote_launchlcore_config[master].ret = f(arg);DPDK L2fwd详细流程图(调用关系)rte_eth_rx_burst(Read packet from RX queues)l2fwd_send_burst(enough pkts to be sent)rte_eth_rx_burst(Read packet from RX queues)2.5运行截图2.6详细代码注释分析:1 #include 2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include 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 52static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; 53static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; 54 55/*物理端口的mac地址的数组 ethernet addresses of ports */ 56staticstruct ether_addr l2fwd_ports_eth_addr[RTE_MAX_ETHPORTS]; 57 58/*已经启用的物理端口的掩码/位图 mask of enabled ports */ 59static uint32_t l2fwd_enabled_port_mask = 0; 60 61/*已经启用的目的物理端口编号的数组 list of enabled ports */ 62static uint32_t l2fwd_dst_ports[RTE_MAX_ETHPORTS]; 63 64static unsigned int l2fwd_rx_queue_per_lcore = 1; //默认值,每个lcore负责的接收队列数量 65。