4 VPP原始碼分析(graph node 2

2021-09-20 08:13:05 字數 3115 閱讀 9863

每個process結點是由jump機制構成的乙個協程,協程主要用於等待、處理事件。

使用longjmp/setjmp的輕量級多工協程,由應用程序自行進行排程,不受作業系統排程機制的影響,上下文切換只損耗呼叫longjmp/setjmp的時間。

協程中執行的函式類似於執行緒函式,區別在於協程函式can be suspended, wait for events, be resumed… (based on setjump/longjump).

2.2.2.1. vlib_process_t結構體

協程間的切換最重要的是要保護cpu暫存器和私有棧。

這裡clib_longjmp_t中儲存上下文切換時cpu暫存器的資訊,而相應的棧資訊儲存在process結構體中stack後續的記憶體空間中。

2.2.2.2. process node的初始化

在vlib_main_or_worker_loop開始包處理迴圈之前,main執行緒會對所有的process結點都排程一次,執行相應的node函式,類似於初始化操作。

在dispatch_process函式中講呼叫vlib_process_startup函式,處理所有process結點的初始化工作。

vlib_process_startup先記錄每個process結點正常返回時的jmp資訊(return_longjmp),之後跳到vlib_process_bootstrap函式中執行process結點函式。

2.2.2.3. process node函式

以下為某個典型的process結點函式:

該函式為while (1)的形式,說明該node函式將一直執行直到應用程序退出為止。

而在開始的時候這裡先呼叫了vlib_process_wait_for_event函式,檢查是否由事件需要處理。

該函式先去檢查non_empty_event_type_bitmap是否置位,如有說明有需要處理的事件則立刻返回進行處理,否則說明該process node任然需要等待事件,暫不需要分配cpu時間,可以進入suspend狀態。

所以,這裡先記錄下當前的位置(記為resume_longjmp),然後再跳回return_longjmp所記錄的位置,完成一次結點排程過程。

這樣,初始化時呼叫的dispatch_process可以先初始化所有的process node,而各process node暫時處於suspend狀態,等待某個條件的到來進入resume狀態並執行業務邏輯,執行完後退出釋放cpu資源。

internal結點主要用於處理資料報業務邏輯,結點通過函式流程上與input結點大致相同。

static uword sample_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)

2.2.3.1. 從本node frame中取包

vlib_frame_t *frame    -> 由node函式入口傳入 

u32 *from -> 當前frame中vector的起始資料

from = vlib_frame_vector_args(frame);

呼叫vlib_frame_vector_args函式返回本node vlib_frame_t中資料報的起始位置,對包進行處理使用from[0],from[1]…

2.2.3.2. to_next指標的獲得

vlib_main_t *vm  = vlib_get_main ();

u32 next_index = vnet_device_input_next_ethernet_input;

vlib_node_runtime_t *node;

u32 n_left_to_next;

u32 *to_next;

vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);

呼叫vlib_get_next_frame函式,找到下一node對應的vlib_frame_t中合適的存放資料報的起始位置並儲存到to_next

如果要傳送資料報,則可以修改to_next[0],to_next[1]……中的資料報索引值

2.2.3.3. 驗證處理結果

vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, pi0, next0);

next_index -> 預設的下一結點的index

next0 -> 實際的下乙個結點的index

當next0 != next_index時,說明該包被正確處理,該巨集將do nothing

否則,說明本來該包應去next_index但是經過包處理需要去往其他結點

使得next0 != next_index,該巨集會將該包索引pi0發往到next0實際的下乙個結點

2.2.3.4. 登記排程

vlib_put_next_frame(vm, node, next_index, n_left_to_next);

所有流程都正確處理完畢後,下一結點的frame上已經有本結點處理過後的資料索引

執行該函式,將相關資訊登記到vlib_pending_frame_t中,準備開始排程處理

2.2.3.5. 具體例項

思科VPP原始碼分析(dpo機制原始碼分析)

vpp的dpo機制跟路由緊密結合在一起。路由表查詢 ip4 lookup 的最後結果是乙個load balance t結構。該結構可以看做是乙個hash表,裡面包含了很多dpo,指向為下一步處理動作。每個dpo都是新增路由時的乙個path的結果。dpo標準型別有 dpo drop,dpo ip nu...

vpp原始碼之Makefile分析(編譯除錯)

下面是vpp的命令 root localhost vpp 18.07 make make targets install dep install software dependencies wipe wipe all products of debug build wipe release wipe...

VPP的原始碼編譯安裝

最近在虛擬機器上搞vpp的編譯安裝,遇到很多問題,先記錄下來。vpp編譯一定要聯網,切記!不聯網的話乙個個的依賴包會讓你懷疑人生的。1.原始碼獲取 git clone 獲取當前最新 2.安裝各種軟體依賴包 原始碼獲取後,假設放在 home目錄下 cd home vpp 3.清除之前編譯殘留 如果是第...