還在初學(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)建如下:
- VLIB_REGISTER_NODE (ip4_input_node) = {
- .function = ip4_input,
- .name = "ip4-input",
- .vector_size = sizeof (u32),
-
- .n_errors = IP4_N_ERROR,
- .error_strings = ip4_error_strings,
-
- .n_next_nodes = IP4_INPUT_N_NEXT,
- .next_nodes = {
- [IP4_INPUT_NEXT_DROP] = "error-drop",
- [IP4_INPUT_NEXT_PUNT] = "error-punt",
- [IP4_INPUT_NEXT_LOOKUP] = "ip4-lookup",
- [IP4_INPUT_NEXT_LOOKUP_MULTICAST] = "ip4-lookup-multicast",
- [IP4_INPUT_NEXT_ICMP_ERROR] = "ip4-icmp-error",
- },
-
- .format_buffer = format_ip4_header,
- .format_trace = format_ip4_input_trace,
- };
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]。 - typedef struct {
- u64 len;
- u8 vector_data[0];
- } vec_header_t;
- vec_add1 (nm->nodes, n);主要是將新申請的node添加到數(shù)組中,使用的是0數(shù)組的方式,余下需要做的就是將前面注冊的node成員賦值給當(dāng)前node中。主要成員為:
- typedef struct vlib_node_t {
- vlib_node_function_t * function;
- u8 * name;
- vlib_node_type_t type;
- u32 index;
- u16 flags;
- u8 state;
- u16 scalar_size, vector_size;
- char ** next_node_names;
- char * sibling_of;
- u64 * n_vectors_by_next_node;
- format_function_t * format_buffer;
- unformat_function_t * unformat_buffer;
- format_function_t * format_trace;
- } 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中- if(n->type == VLIB_NODE_TYPE_PROCESS)如果是process類型
- vec_add1 (nm->processes, p);
- else
- vec_add2_aligned (nm->nodes_by_type[n->type], rt, 1,
- CLIB_CACHE_LINE_BYTES);
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,暫時忽略中斷模式。 -
- vec_foreach (n, nm->nodes_by_type[VLIB_NODE_TYPE_INPUT])
- cpu_time_now = dispatch_node (vm, n,
- VLIB_NODE_TYPE_INPUT,
- VLIB_NODE_STATE_POLLING,
- 0,
- cpu_time_now);
- u64 dispatch_node (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_node_type_t type,
- vlib_node_state_t dispatch_state,
- vlib_frame_t * frame,
- u64 last_time_stamp)
- {
-
-
- n = node->function (vm, node, frame);
-
-
-
- v = vlib_node_runtime_update_stats (stat_vm, node,
- 1,
- n,
- t - last_time_stamp);
-
-
- if ((DPDK == 0 && dispatch_state == VLIB_NODE_STATE_INTERRUPT)
- || (DPDK == 0 && dispatch_state == VLIB_NODE_STATE_POLLING
- && (node->flags
- & VLIB_NODE_FLAG_SWITCH_FROM_INTERRUPT_TO_POLLING_MODE)))
- {
- }
- }
node->function中會計算下一級node,并且最終調(diào)用vlib_put_next_frame,將下一級的node加入到nm->pending_frames中,比如ethernet-input node的操作如下: - static_always_inline uword
- ethernet_input_inline (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * from_frame,
- ethernet_input_variant_t variant)
- {
-
- next_index = node->cached_next_index;
- stats_sw_if_index = node->runtime_data[0];
- stats_n_packets = stats_n_bytes = 0;
-
- while (n_left_from > 0)
- {
- while (n_left_from > 0 && n_left_to_next > 0)
- {
-
- determine_next_node(em, variant, is_l20, type0, b0, &error0, &next0);
-
-
- vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
- to_next, n_left_to_next,
- bi0, next0);
- }
-
- vlib_put_next_frame (vm, node, next_index, n_left_to_next);
- }
-
- return from_frame->n_vectors;
- }
繼續(xù)執(zhí)行依賴的node,最終 dispatch_pending_node 還是調(diào)用 dispatch_node- for (i = 0; i < _vec_len (nm->pending_frames); i++)
- cpu_time_now = dispatch_pending_node (vm, nm->pending_frames + i,
- cpu_time_now);
資料來源:https:///
歡迎加入VPP討論群:417538415
|