[dpdk] 熟悉SDK與初步使用 (二)(skeleton源碼分析)


接續前節:[dpdk] 熟悉SDK與初步使用 (一)(qemu搭建實驗環境) 

程序邏輯:

運行參數:

關鍵API:

入口函數:

  int rte_eal_init(int argc, char **argv) 

 

內存池函數:

  rte_pktmbuf_pool_create。  它是函數 rte_mempool_create 的一個封裝。 

struct rte_mempool *          
rte_pktmbuf_pool_create(const char *name, unsigned n,
        unsigned cache_size, uint16_t priv_size, uint16_t data_room_size,
        int socket_id)

name是內存池名字。為了獲得更好的性能,n應該為2的冪減1 。

 

網卡操作函數:

  rte_eth_dev_configure()  設置網卡設備。在其他操作之前,應該先調用這個函數進行設置。

  rte_eth_rx_queue_setup()  申請並設置一個收包隊列。

    關鍵參數:

      struct rte_mempool *mp; 由前文創建的pool

  rte_eth_tx_queue_setup()  同上。

  rte_eth_dev_start() 就是設置好了之后就啟動啊,該收的收,該發的發。

  rte_eth_promiscuous_enable()  啟動混雜模式,不解釋。

 

收發包函數:

  rte_eth_rx_burst()  收一大批包

    該接口不提供任何錯誤檢測功能,上層應用可以在返回包數為零時,去主動檢測link狀態來完成接口異常及錯誤檢測機制。

    關鍵參數:

      struct rte_mbuf** rx_pkts;  一個指針數組,數組中的每一個指針指向收取到的一個包,具體的包結構查看下文的數據結構章節。指針所指向的內存空間為queue_setup(mpool) 函數中的參數pool提供。

      const uint16_t nb_pkts;  簡單來說,就是數組大小。

    返回值:

      收到的報數,數組中被填充的item個數。

      當返回值== nb_pkts時,隱含說明,收包性能已經跟不上了。

      當返回值== 0 時,應該啟動異常檢測,查看接口狀態等。

  rte_eth_tx_burst()  發一大批包

  rte_pktmbuf_free()  收到了但是沒有被發出去的包,應該將其free,即還給mpool。咦,不過為什么會有沒發出去的呢?奇怪

 

其他函數:

rte_eth_dev_count():  

  返回可以被dpdk使用的網口個數。即(加載了UIO驅動,或VFIO ??) rte_eal_init 之后就可以用了。

rte_socket_id():  

  返回CPU sock 的ID,即命令參數中指定的lcore所屬的CPU socket。

 

回過頭來,對比一下Helloworld。在helloworld里多使用了一個函數

rte_eal_remote_launch()   用於在多個核上啟動多線程,原例子中用法如下:

        /* 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);
        
       lcore_id = rte_lcore_id();
       printf("hello from master core %u\n", lcore_id);

主線程,跑着編號最小的那個核上,不知道是否可修改。

 

[root@dpdk ~]# ps -eLF |grep -E "UID|helloworld"
UID        PID  PPID   LWP  C NLWP    SZ   RSS PSR STIME TTY          TIME CMD
root      2671  2531  2671 99    5 274512 3668   4 18:44 pts/0    00:05:22 ./helloworld -l4,5,6,7
root      2671  2531  2672  0    5 274512 3668   4 18:44 pts/0    00:00:00 ./helloworld -l4,5,6,7
root      2671  2531  2673  0    5 274512 3668   5 18:44 pts/0    00:00:00 ./helloworld -l4,5,6,7
root      2671  2531  2674  0    5 274512 3668   6 18:44 pts/0    00:00:00 ./helloworld -l4,5,6,7
root      2671  2531  2675  0    5 274512 3668   7 18:44 pts/0    00:00:00 ./helloworld -l4,5,6,7
root      2778  2679  2778  0    1 28162   964   0 18:50 pts/1    00:00:00 grep --color=auto -E UID|helloworld
[root@dpdk ~]# 

 

數據結構:

struct rte_mbuf {}

 

gdb之: 去掉 -O3

設斷點:

(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000435829 in lcore_main at /root/src/sdk/@dpdk/dpdk-stable-16.07.1/examples/skeleton/basicfwd.c:143
        breakpoint already hit 1 time
(gdb) l 143
138             for (;;) {
139                     /*
140                      * Receive packets on a port and forward them on the paired
141                      * port. The mapping is 0 -> 1, 1 -> 0, 2 -> 3, 3 -> 2, etc.
142                      */
143                     for (port = 0; port < nb_ports; port++) {
144
145                             /* Get burst of RX packets, from first port of pair. */
146                             struct rte_mbuf *bufs[BURST_SIZE];
147                             const uint16_t nb_rx = rte_eth_rx_burst(port, 0,
(gdb) 

 

debug一個包:

包格式如下:

 

進入斷點,看數據結構,如下:

(gdb) p bufs[0]
$20 = (struct rte_mbuf *) 0x7fffd9791b00
(gdb) p *bufs[0]
$21 = {cacheline0 = 0x7fffd9791b00, buf_addr = 0x7fffd9791b80, buf_physaddr = 972626816, buf_len = 2176, rearm_data = 0x7fffd9791b12 "\200", data_off = 128, {
    refcnt_atomic = {cnt = 1}, refcnt = 1}, nb_segs = 1 '\001', port = 0 '\000', ol_flags = 0, rx_descriptor_fields1 = 0x7fffd9791b20, {packet_type = 0, {
      l2_type = 0, l3_type = 0, l4_type = 0, tun_type = 0, inner_l2_type = 0, inner_l3_type = 0, inner_l4_type = 0}}, pkt_len = 42, data_len = 42, vlan_tci = 0, 
  hash = {rss = 0, fdir = {{{hash = 0, id = 0}, lo = 0}, hi = 0}, sched = {lo = 0, hi = 0}, usr = 0}, seqn = 0, vlan_tci_outer = 0, cacheline1 = 0x7fffd9791b40, {
    userdata = 0x0, udata64 = 0}, pool = 0x7fffd64436c0, next = 0x0, {tx_offload = 0, {l2_len = 0, l3_len = 0, l4_len = 0, tso_segsz = 0, outer_l3_len = 0, 
      outer_l2_len = 0}}, priv_size = 0, timesync = 0}
(gdb) x/42xb (bufs[0].buf_addr + 128)
0x7fffd9791c00: 0xff    0xff    0xff    0xff    0xff    0xff    0x00    0x00
0x7fffd9791c08: 0x00    0x01    0x00    0x01    0x08    0x06    0x00    0x01
0x7fffd9791c10: 0x08    0x00    0x06    0x04    0x00    0x01    0x00    0x00
0x7fffd9791c18: 0x00    0x01    0x00    0x01    0x01    0x01    0x01    0x01
0x7fffd9791c20: 0x00    0x00    0x00    0x00    0x00    0x00    0x01    0x01
0x7fffd9791c28: 0x01    0x02
(gdb) where

 

 

回調函數和CPU cycle

  例子 rxtx_callback 在 skeleton 的基礎之上增加了兩個回調函數,在回調函數中做了cpu cycles的計算。

  rte_eth_add_rx_callback() 

  rte_eth_add_tx_callback()

  關於CPU cycles可以參見另一篇博 [daily]使用rdtsc指令,測量程序的運行速度 [轉]  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM