日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

Cisco VPP(3) 啟動流程

 mrjbydd 2018-03-15

還在初學(xué)階段,如果有誤,希望多批評指正。


參照前面的帖子Cisco VPP(3) 啟動流程


這里面的node主要有3種:

1、注冊的時候注冊到node_registrations的node,這個是main函數(shù)運(yùn)行之前就生成的鏈表

2、將注冊的node存儲到vlib_node_main_t->vlib_node_t ** nodes,這個是運(yùn)行register_node時產(chǎn)生的,主要是存儲

3、將2中的node存儲到vlib_node_main_t->vlib_process_t ** processes,運(yùn)行register_node時產(chǎn)生的,運(yùn)行時執(zhí)行此處的node


0x0 注冊

VLIB_REGISTER_NODE主要是用來定義node,并且注冊node到vlib_main_t->vlib_node_main_t->node_registrations,這個鏈表在main()函數(shù)之前創(chuàng)建,比如ip4-input的最初創(chuàng)建如下:

  1. VLIB_REGISTER_NODE (ip4_input_node) = {  
  2.   .function = ip4_input,//mbuf傳入node之后的操作函數(shù),以及下一級node的確定  
  3.   .name = "ip4-input",//name必須唯一,因為串聯(lián)node使用的標(biāo)識為名字  
  4.   .vector_size = sizeof (u32),  
  5.   
  6.   .n_errors = IP4_N_ERROR,//報錯的計數(shù),可以用來報錯,也可以記錄正常的數(shù)據(jù)包數(shù)量,show errors命令顯示  
  7.   .error_strings = ip4_error_strings,//顯示計數(shù)的時候,對計數(shù)的提示,比如正常的ipv4數(shù)據(jù)包,不正確的ipv4數(shù)據(jù)包數(shù)量  
  8.   
  9.   .n_next_nodes = IP4_INPUT_N_NEXT,//next node的數(shù)量  
  10.   .next_nodes = {  
  11.     [IP4_INPUT_NEXT_DROP] = "error-drop",//下一級node丟棄  
  12.     [IP4_INPUT_NEXT_PUNT] = "error-punt",  
  13.     [IP4_INPUT_NEXT_LOOKUP] = "ip4-lookup",//下一級node查表  
  14.     [IP4_INPUT_NEXT_LOOKUP_MULTICAST] = "ip4-lookup-multicast",  
  15.     [IP4_INPUT_NEXT_ICMP_ERROR] = "ip4-icmp-error",//報錯  
  16.   },  
  17.   
  18.   .format_buffer = format_ip4_header,  
  19.   .format_trace = format_ip4_input_trace,//show trace顯示路徑的打印,一般是數(shù)據(jù)包走到這個node時需要輸出的信息  
  20. };  

0x1 初始化

vlib_main()->vlib_register_all_static_nodes()->register_node()主要是將node鏈表中的所有node進(jìn)行初始化,并且根據(jù)node之間的關(guān)系進(jìn)行串聯(lián)。

1、所有注冊的node都會存到vlib_main_t->vlib_node_main_t->vlib_node_t ** nodes中,該nodes存在vec_header_t結(jié)構(gòu)中的u8 vector_data[0]。

  1. typedef struct {  
  2.   u64 len; /**記錄注冊了多少個node*/  
  3.  u8 vector_data[0];  /**< Vector data . 記錄注冊的node,相比鏈表,更容易找到某個node,但是每次添加都要重新申請內(nèi)存,類似realloc */  
  4. } vec_header_t;  
  1. vec_add1 (nm->nodes, n);主要是將新申請的node添加到數(shù)組中,使用的是0數(shù)組的方式,余下需要做的就是將前面注冊的node成員賦值給當(dāng)前node中。主要成員為:  
  2. typedef struct vlib_node_t {  
  3.   vlib_node_function_t * function;//執(zhí)行函數(shù)  
  4.   u8 * name;//名字  
  5.   vlib_node_type_t type;//node類型  
  6.   u32 index;//是由nodes長度算出來的index  
  7.   u16 flags;//node 標(biāo)識  
  8.   u8 state;//node 狀態(tài)  
  9.   u16 scalar_size, vector_size;//標(biāo)量矢量大小  
  10.   char ** next_node_names;//下一級node名字  
  11.   char * sibling_of;  
  12.   u64 * n_vectors_by_next_node;//送到下一級node的vector數(shù)量  
  13.   format_function_t * format_buffer;//以下三項是格式化輸出一些信息  
  14.   unformat_function_t * unformat_buffer;  
  15.   format_function_t * format_trace;  
  16. } vlib_node_t;  
2、將vlib_node_main_t->vlib_node_t ** nodes的process類型的node存儲到vlib_node_main_t->vlib_process_t ** processes的node_runtime中,也是利用存在vec_header_t結(jié)構(gòu)中的u8 vector_data[0],這個主要是偏操作的node結(jié)點(diǎn),比如startup-config-process(啟動配置處理),admin-up-down-process(端口up down的處理),其他所有類型的node都存儲到vlib_node_main_t->vlib_node_runtime_t * nodes_by_type中

  1. if(n->type == VLIB_NODE_TYPE_PROCESS)如果是process類型  
  2.     vec_add1 (nm->processes, p);//將新申請的process添加到數(shù)組中,后面將nodes中的主要成員賦值給processes中的node_runtime  
  3. else  
  4.     vec_add2_aligned (nm->nodes_by_type[n->type], rt, 1,  
  5.               /* align */ CLIB_CACHE_LINE_BYTES);//將當(dāng)前不是process類型的node添加到nodes_by_types中,主要是后面node操作中會用到  


0x2 node操作

vlib_main_loop()主要是去處理node中的操作。核心操作包含以下兩個點(diǎn):(忽略VLIB_NODE_TYPE_PROCESS類型結(jié)點(diǎn)和VLIB_NODE_TYPE_PRE_INPUT類型結(jié)點(diǎn)操作)

收包的入口函數(shù),比如dpdk-input的node,里面主要主要執(zhí)行node->function,暫時忽略中斷模式。

  1. /* Next process input nodes. */  
  2.        vec_foreach (n, nm->nodes_by_type[VLIB_NODE_TYPE_INPUT])  
  3.        cpu_time_now = dispatch_node (vm, n,  
  4.                                      VLIB_NODE_TYPE_INPUT,  
  5.                                      VLIB_NODE_STATE_POLLING,  
  6.                                      /* frame */ 0,  
  7.                                      cpu_time_now);  
  1. u64 dispatch_node (vlib_main_t * vm,  
  2.                vlib_node_runtime_t * node,  
  3.                vlib_node_type_t type,  
  4.                vlib_node_state_t dispatch_state,  
  5.                vlib_frame_t * frame,  
  6.                u64 last_time_stamp)  
  7. {  
  8.   
  9.         //執(zhí)行node->function  
  10.         n = node->function (vm, node, frame);  
  11.   
  12.           
  13.         //更新node_runtime里面的一些狀態(tài),比如處理時間、vector數(shù)據(jù)包數(shù)量。  
  14.         v = vlib_node_runtime_update_stats (stat_vm, node,  
  15.                                             /* n_calls */ 1,  
  16.                                             /* n_vectors */ n,  
  17.                                             /* n_clocks */ t - last_time_stamp);  
  18.   
  19.         /*中斷模式下,vector速率超過閾值,切換到polling模式*/  
  20.         if ((DPDK == 0 && dispatch_state == VLIB_NODE_STATE_INTERRUPT)  
  21.                 || (DPDK == 0 && dispatch_state == VLIB_NODE_STATE_POLLING  
  22.                     && (node->flags  
  23.                         & VLIB_NODE_FLAG_SWITCH_FROM_INTERRUPT_TO_POLLING_MODE)))  
  24.         {  
  25.         }  
  26. }  

node->function中會計算下一級node,并且最終調(diào)用vlib_put_next_frame,將下一級的node加入到nm->pending_frames中,比如ethernet-input node的操作如下:

  1. static_always_inline uword  
  2. ethernet_input_inline (vlib_main_t * vm,  
  3.                vlib_node_runtime_t * node,  
  4.                vlib_frame_t * from_frame,  
  5.                ethernet_input_variant_t variant)  
  6. {  
  7.   
  8.   next_index = node->cached_next_index;  
  9.   stats_sw_if_index = node->runtime_data[0];  
  10.   stats_n_packets = stats_n_bytes = 0;  
  11.   
  12.   while (n_left_from > 0)  
  13.   {  
  14.       while (n_left_from > 0 && n_left_to_next > 0)  
  15.       {  
  16.           //確定下一級node  
  17.           determine_next_node(em, variant, is_l20, type0, b0, &error0, &next0);  
  18.         
  19.           // verify speculative enqueue  
  20.       vlib_validate_buffer_enqueue_x1 (vm, node, next_index,  
  21.                        to_next, n_left_to_next,  
  22.                        bi0, next0);  
  23.       }  
  24.       //將下一級的node加入到 nm->pending_frames中  
  25.       vlib_put_next_frame (vm, node, next_index, n_left_to_next);  
  26.    }  
  27.   
  28.   return from_frame->n_vectors;  
  29. }  



繼續(xù)執(zhí)行依賴的node,最終 dispatch_pending_node 還是調(diào)用 dispatch_node
  1. for (i = 0; i < _vec_len (nm->pending_frames); i++)  
  2.            cpu_time_now = dispatch_pending_node (vm, nm->pending_frames + i,  
  3.                                                  cpu_time_now);  

資料來源:https:///


歡迎加入VPP討論群:417538415

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多