intel dpdk api testpmd 程序源码详解

声明:此文档只做学习交流使用,请勿用作其他商业用途

author:朝阳_tony
E-mail : [email protected]
Create Date: 2013-7-28 16:34:51 Sunday
Last Change: 2013-7-28 18:25:31 Sunday

转载请注明出处:http://blog.csdn.net/linzhaolove


此文请结合intel dpdk源码去阅读,源码可以去http://dpdk.org/dev 网页中下载;更多官方文档请访问http://dpdk.org


intel DPDK交流群希望大家加入互相学习,QQ群号:289784125

摘要

testpmd程序是测试dpdk代码性能的一个测试程序,由intel 官方提供,其源码就存放在 dpdk/app/test-pmd目录中;本文章用代码是在app/test-pmd/testpmd.c  中的代码;

1、程序初始化过程

从main函数讲起,我看程序总是喜欢从main函数看起,了解大概有几个模块,初始化了哪些东西,调用了哪些东西,了解个大概,然后再一个一个函数详细去看;

1)、早起底层初始化

在main函数中分别调用一下函数对dpdk套件进行初始化,
rte_eal_init() //去初始化dpdk抽象层的信息,如cpu 分配,hpet模块初始,pci设备信息的扫描等等;
rte_igb_pmd_init()  //注册用户态的igb 驱动信息,如果中断回调函数;网络回调函数的指针初始化等 ;
rte_eal_pci_probe() // 绑定新的igb_uio驱动到相应的设备;
有些调用到函数已经在之前我写的博文讲过,我就不详细讲了,如想详细了解,请看我之前写的博文;
nb_ports = (portid_t) rte_eth_dev_count()
获取你当前有效网卡,网口的个数;
set_def_fwd_config();
这个程序主要测试dpdk的数据包转发性能,调用set_def_fwd_config()函数,是去分配cpu core  和port ;同时设置端口的缺省的mac信息;
launch_args_parse(argc, argv);
调用launch_args_parse去分析testpmd自身的参数,通常我们会传递一个   -i  参数,就是interactive单词,意思是进行交互模式测试,等程序启动起来,你就需要一个一个的敲命令进行测试,当然你也可采用非交互的模式进行测试;

2)、内层池初始化

调用init_config();函数去分配内存池,端口结构体,转发信息结构体空间;
下面详解一下init_config()函数,
    fwd_lcores = rte_zmalloc("testpmd: fwd_lcores",
                sizeof(struct fwd_lcore *) * nb_lcores,
                CACHE_LINE_SIZE);
fwd_lcores是一个二级指针,所以要先给这个指针分配一块空间,用于存储一级的指针,而起数量为nb_lcores个,就是之前通过set_def_fwd_config函数设置的 core数;
        fwd_lcores[lc_id] = rte_zmalloc("testpmd: struct fwd_lcore",
                           sizeof(struct fwd_lcore),
                           CACHE_LINE_SIZE);
初始化一级指针,在一个for循环中实现,先单个结构体分配,然后将单个结构体的指针赋值给了fwd_lcores[lc_id];
mbuf_pool_create(mbuf_data_size, nb_mbuf_per_pool, 0);
根据你才用的是hugepage的NUMA模式还是non-NUMA模式来分配内存池;
mbp = mbuf_pool_find(rte_lcore_to_socket_id(lc_id));
根据core id 来分配每个单独的core应该拥有那个内存池;fwd_lcores[lc_id]->mbp = mbp; 然后赋值给fwd_lcores结构体中;
    /* Configuration of Ethernet ports. */
    ports = rte_zmalloc("testpmd: ports",
                sizeof(struct rte_port) * nb_ports,
                CACHE_LINE_SIZE);
接下来 配置分配端口空间并配置其信息;
rte_eth_dev_info_get(pt_id, &port->dev_info);
调用rte_eth_dev_info_get会将一些设备信息和端口设定信息赋值给dev_info ,在接下来会用获取到的信息,判断其发送和接收队列值是否符合;
    fwd_streams = rte_zmalloc("testpmd: fwd_streams",
                  sizeof(struct fwd_stream *) * nb_fwd_streams,
                  CACHE_LINE_SIZE);
最后分配fwd_streams转发信息结构体空间;

3)、端口信息初始化

调用 init_ports();函数去初始化端的的mac地址,发送队列,和接收队列,
下面详细解释一下 init_ports函数;
port = &ports[pi];
ports结构体数组,就是在上面init_config()函数中分配到的端口结构体内存空间;
diag = rte_eth_dev_configure(pi, nb_rxq, nb_txq, &port_conf);
在init_ports中循环调用rte_eth_dev_configure()函数去初始端口的默认配置;
rte_eth_macaddr_get(pi, &port->eth_addr);
获取有效网卡的mac地址信息;
            diag = rte_eth_tx_queue_setup(pi, qi, nb_txd,
                              sock_id,
                              &tx_conf);
初始发送队列,
            diag = rte_eth_rx_queue_setup(pi, qi, nb_rxd, sock_id,
                              &rx_conf,
                              mbuf_pool_find(sock_id));
初始接收队列;
diag = rte_eth_dev_start(pi);
启动端口;
rte_eth_link_get(pi, &link);
查看端口是否连接正常,连个状态, up 或者 down ,如果是down说明你的网卡端口网线连接不正常;呵呵
rte_eth_promiscuous_enable(pi);
最后判断你的网卡设置的是否混咋模式接收信息,如果是混杂模式,说明你任何网络信息都接收,否则只接收你上面设置的mac地址,为目的地址的网络信息;

4)、交互模式启动

我们在执行testpmd程序的时候传递了一个 -i 参数,目地是启动交互模式;
因此会调用prompt();函数进入交互模式;
 cl = cmdline_stdin_new(main_ctx, "testpmd> ");
在prompt()函数中,调用cmdline_stdin_new()初始化dpdk提供的命令行交互模块,其实主要是将main_ctx个结构体初始化进模块,
注意,有用testpmd启动后可执行命令的回调函数,都放在了main_ctx结构体中;
cmdline_interact(cl);
调用命令交互函数;
cmdline_stdin_exit(cl);
等你退出命令行交互模式是,就可以调用cmdline_stdin_exit() 函数退出了;

2、testpmd编译运行测试

make -C app/test-pmd/
编译程序;

运行程序测试;
./app/test-pmd/testpmd -c 1f -n 4  -- -i
-c 1f 是指,最多可以分配 5个core给dpdk程序,  1f = 00011111 ; 
-n 4  分配4个内存通道;
--  由于有主次参数,因此会中间穿插两个 “  -- ”  ,
-i  采用交互模式;

3、程序运行时命令使用

程序启动后你可以执行help命令查看帮助信息;
start  启动数据转发;
stop   停止并统计数据转发结果
程序启动后默认是io转发模式,
set  fwd  io|mac|rxonly|txonly|csum  设置其他转发模式,如    set  fwd  mac   设置为mac转发模式;


技术水平有待提高,如果文章有错误的地方希望读者指正,相互交流,互相学习;O(∩_∩)O~

你可能感兴趣的:(intel,dpdk,intel,dpdk,学习交流)