美文网首页dpdkDPDK
安装使用DPDK

安装使用DPDK

作者: Jale | 来源:发表于2016-09-15 21:23 被阅读4910次

    mTCP中使用DPDK将网卡上的数据提取到用户态,然后经过用户态的TCP/IP协议进行处理。DPDK全称Data Plane Development Kit,是Intel发布的用于快速处理数据包的开发平台和接口1

    网卡驱动在接收到数据包会产生中断来通知CPU进行处理,然后CPU拷贝数据给内核协议栈进行处理。当数据量非常大时,中断和数据拷贝的开销很大。DPDK将网卡的数据旁路到用户态直接进行处理,不经过内核,不产生中断也不进行昂贵的数据拷贝。Intel自己给出的性能数据是,一个数据包可以在80个时钟周期内处理完成,而正常情况下处理器访问DDR3内存都需要200个时钟周期,还不算协议处理的时间。

    下载安装

    系统要求

    DPDK的文档中对Linux系统的部署有很详细的描述Guide for Linux

    首先由于DPDK的是Intel推出的技术,因此只支持x86架构的机器。

    查看是否支持hpet,如果不支持则无输出内容,需要在BIOS中开启:

    grep hpet /proc/timer_list
    
    Clock Event Device: hpet
     set_next_event: hpet_legacy_next_event
     shutdown: hpet_legacy_shutdown
     periodic: hpet_legacy_set_periodic
     oneshot:  hpet_legacy_set_oneshot
     resume:   hpet_legacy_resume
    

    启动hugepage支持(64位系统推荐使用1G的hugepages):

    # 每块内存大小2MB,共预留1024个2MB内存块
    echo 1024 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
    

    然后将hugepages中的内存给DPDK使用:

    mkdir /mnt/huge
    mount -t hugetlbfs nodev /mnt/huge
    #add item to the /etc/fstab
    nodev /mnt/huge hugetlbfs defaults 0 0
    

    DPDK的源码下载和文档都在官网。下载最新版本的代码:

      wget http://fast.dpdk.org/rel/dpdk-16.07.tar.xz
    

    解压后编译:

    make install T=x86_64-native-linuxapp-gcc
    

    其中T表示Target, Target的描述格式是:

    ARCH-MACHINE-EXECENV-TOOLCHAIN
    - ARCH = i686, x86_64, ppc_64
    - MACHINE = native, ivshmem, power8
    - EXECENV = linuxapp, bsdapp
    - TOOLCHAIN = gcc, icc
    

    编译完成之后生产了环境目录x86_64-native-linuxapp-gcc

    cd x86_64-native-linuxapp-gcc
    ls
    app  build  include  kmod  lib  Makefile
    

    加载uio内核模块:

    modprobe uio_pci_generic
    

    要使用DPDK,必须将网卡绑定到uio_pci_generi模块,DPDK在tools目录下提供了dpdk-devbind.py脚本完成这个工作。首先在绑定前查看一下状态:

    [root@localhost tools]$ ./dpdk-devbind.py --status

    Network devices using DPDK-compatible driver
    ============================================
    <none>
    Network devices using kernel driver
    ===================================
    0000:00:03.0 '82540EM Gigabit Ethernet Controller' if=enp0s3 drv=e1000 unused= *Active*
    0000:00:08.0 '82540EM Gigabit Ethernet Controller' if=enp0s8 drv=e1000 unused= *Active*
    
    Other network devices
    =====================
    <none>
    

    可以看到现在没有绑定到DPDK的网络接口,现在将enp0s8绑定到DPDK:

    #需要先down掉,不然没办法绑定成功
    [root@localhost tools]# ifconfig enp0s8 down
    [root@localhost tools]# ./dpdk-devbind.py --bind=uio_pci_generic enp0s8
    [root@localhost tools]# ./dpdk-devbind.py --status
    Network devices using DPDK-compatible driver
    ============================================
    0000:00:08.0 '82540EM Gigabit Ethernet Controller' drv=uio_pci_generic unused=e1000
    
    Network devices using kernel driver
    ===================================
    0000:00:03.0 '82540EM Gigabit Ethernet Controller' if=enp0s3 drv=e1000 unused=uio_pci_generic *Active*
    
    Other network devices
    =====================
    <none>
    

    可以看出,现在已经有一个设备使用DPDK了。

    编译一个使用DPDK的简单程序

    在编译之前必须将RET_SDKRTE_TARGET导入到环境变量中,其中RET_SDK是DPDK的安装目录,RTE_TARGET是DPDK目标环境目录。

    export RTE_SDK=/home/lyt/dpdk-16.07
    export RTE_TARGET=x86_64-native-linuxapp-gcc
    

    在examples目录里面编译一个简单的应用:

    cd examples/helloworld/
    make
    

    可以看到当前目录下生成了build目录,可执行程序就在build目录中,执行helloworld:

      [root@localhost build]# ./helloworld
      EAL: Detected 2 lcore(s)
      EAL: Probing VFIO support...
      PMD: bnxt_rte_pmd_init() called for (null)
      EAL: PCI device 0000:00:03.0 on NUMA socket -1
      EAL:   probe driver: 8086:100e rte_em_pmd
      EAL: PCI device 0000:00:08.0 on NUMA socket -1
      EAL:   probe driver: 8086:100e rte_em_pmd
      hello from core 1
      hello from core 0
    

    hello world的代码结构

    helloword程序成功编译并运行,来简单看一看代码:

    #include <stdio.h>
    #include <string.h>
    #include <stdint.h>
    #include <errno.h>
    #include <sys/queue.h>
    
    #include <rte_memory.h>
    #include <rte_memzone.h>
    #include <rte_launch.h>
    #include <rte_eal.h>
    #include <rte_per_lcore.h>
    #include <rte_lcore.h>
    #include <rte_debug.h>
    
    static int
    lcore_hello(__attribute__((unused)) void *arg)
    {
            unsigned lcore_id;
            lcore_id = rte_lcore_id();
            printf("hello from core %u\n", lcore_id);
            return 0;
    }
    
    int
    main(int argc, char **argv)
    {
            int ret;
            unsigned lcore_id;
    
            ret = rte_eal_init(argc, argv);
            if (ret < 0)
                    rte_panic("Cannot init EAL\n");
    
            /* call lcore_hello() on every slave lcore */
            RTE_LCORE_FOREACH_SLAVE(lcore_id) {
                    rte_eal_remote_launch(lcore_hello, NULL, lcore_id);
            }
    
            /* call it on master lcore too */
            lcore_hello(NULL);
    
            rte_eal_mp_wait_lcore();
            return 0;
    }
    

    这个hello world代码非常简单,简单进行一下阐述。

    1. 第一步是调用rte_eal_init初始化EAL(Environment Abstraction Layer, 环境抽象层)。EAL在每一个slave核上都创建一个线程,并绑定CPU。
    2. 使用RTE_LCORE_FOREACH_SLAVE遍历分配给DPDK的slave CPU核心,然后调用rte_eal_mp_remote_launch注册回调函数lcore_hello函数打印。
    3. 在master lcore上调用lcore_hello。
    4. rte_eal_mp_wait_lcore等待所有的slave核心退出,然后自己再退出。

    相关文章

      网友评论

        本文标题:安装使用DPDK

        本文链接:https://www.haomeiwen.com/subject/rjbbettx.html