Try   HackMD

RYU 的那些事

RYU 源碼解析

以下是個人的粗淺理解,如果有任何錯誤歡迎各位協助修正

Main Function 解析

  1. 先找到整個 ryu 中的 main 函數
    • cmd/manager.py
  2. 從 main 函數開始入手
  3. 分析重點內容

區塊一

app_mgr = AppManager.get_instance() app_mgr.load_apps(app_lists) contexts = app_mgr.create_contexts() services = [] services.extend(app_mgr.instantiate_apps(**contexts))

這塊內容主要是在創建 RyuApp 相關內容

  1. 獲取 AppManager 單例
  2. 將指定的 RyuApp 進行解析(動態 import )
  3. 如果 RyuApp 中有使用到 _CONTEXT 進行加載
  4. 對指定的 RyuApp 進行初始化

區塊二

webapp = wsgi.start_service(app_mgr) if webapp: thr = hub.spawn(webapp) services.append(thr)

設定 rest api 相關內容(暫時沒有細看)

區塊三

try: hub.joinall(services) except KeyboardInterrupt: logger.debug("Keyboard Interrupt received. " "Closing RYU application manager...") finally: app_mgr.close()

等待所有的服務結束

AppManager 解析

檔案位置: base/app_manager.py

run_apps(app_lists)

基本上就是把 main function 中重點部分搬移過來

get_instance()

獲取 AppManager 單例對象

load_app(self, name)

透過動態 import 方式將指定的 module import 進來,並且從中提取出真正需要的 RyuApp 類別
註: 是類別不是實例化後的對象

load_apps(self, app_list)

加載多個 RyuApp 在每個 App中會去使用到 load_app function ,並且會在其中獲取該 App 依賴的 _CONTEXT 與可能會需要的其他 App

App 會需要的依賴說明
在 RyuApp 中會使用到 set_ev_cls 來監聽某個事件,此時我們其實需要發送該事件的 App 也啟動它才有辦法發送事件,這時就代表目前的 RyuApp 其實需要依賴 set_ev_cls 中發送事件的 App,那我們在 load_apps 時就會記錄下來,並且在後面也會將該 App 進行實例化。

create_contexts(self)

實例化在 RyuApp 中所需的 _CONTEXT 對象

_update_bricks(self)

更新觀察者資訊,在這裡會設定那些 App 發送消息時有哪些 App 應該要收到通知。

消息通知時作方法
在 app_manager.py 中有個全局變數 SERVICE_BRICKS 該變數會存放所有 RyuApp 當一個 App 要發送消息時會透過該變數獲取有訂閱消息的 App 並將消息放入該 App 須處理的 event queue 中。

_instantiate(self, app_name, cls, *args, **kwargs)

將指定的 App 進行實例化

RyuApp 解析

靜態變數

  1. _CONTEXT: 說明需要哪些額外的 App 輔助
  2. _EVENT: 需要哪些額外的事件
  3. OFP_VERSIONS: 支援的 OpenFlow 版本

register_handler(self, ev_cls, handler)

註冊有哪些函數是用來處理哪些事件的

  1. ev_cls: 事件的 class
  2. handler: 處理該事件的函數

register_observer(self, ev_cls, name, states)

註冊有哪些 App 監聽某個事件
通常由[發送]事件的 class 調用

  1. ev_cls: 事件的 class
  2. name: 需要監聽 ev_cls 事件的 App 名稱
  3. state: 是在哪些階段需要監聽

observe_event(self, ev_cls, state)

監聽某些事件
通常由[接收]事件的 class 調用

get_handlers(self, ev, state)

獲取某個事件由哪些 function 來處理

_event_loop(self)

這裡就是 RyuApp 無窮迴圈的部分,主要就是在不停檢查 events 中是否有需要處理的事件

_send_event(self, ev, state)

將收到的 event 放到自己的 event queue 當中

send_event_to_observers(self, ev, state)

將事件發送到有觀察的對象當中

handler 解析

Class _Caller(object)

如果有使用 set_ev_cls 該 function 當中就會有一個 'callers' 並且當中的資訊會是 _Caller 資料型態。
用來記錄該 function 是監聽什麼類型的事件的。

set_ev_cls(ev_cls, dispatchers)

我們主要在設定監聽 function 時使用到的 Decorator。
會在 function 中添加一個 'callers' 變數並且在當中存放一些相關資訊。

register_instance(i):

將 App 中的某些 function 綁訂到對應的消息,讓消息進來的時候知道要 call 哪些 function。

get_dependent_services(cls):

獲取該 class 需要哪些額外的 App 協助完成監聽。

register_service(service):

設定 module 的 _SERVICE_NAME,主要是在檢查是否需要依賴時會看。