# RYU 的那些事 ## RYU 源碼解析 以下是個人的粗淺理解,如果有任何錯誤歡迎各位協助修正 ### Main Function 解析 1. 先找到整個 ryu 中的 main 函數 - cmd/manager.py 2. 從 main 函數開始入手 3. 分析重點內容 #### 區塊一 ```python= 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 進行初始化 #### 區塊二 ```python= webapp = wsgi.start_service(app_mgr) if webapp: thr = hub.spawn(webapp) services.append(thr) ``` 設定 rest api 相關內容(暫時沒有細看) #### 區塊三 ```python= 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 :::info App 會需要的依賴說明 在 RyuApp 中會使用到 set_ev_cls 來監聽某個事件,此時我們其實需要發送該事件的 App 也啟動它才有辦法發送事件,這時就代表目前的 RyuApp 其實需要依賴 set_ev_cls 中發送事件的 App,那我們在 load_apps 時就會記錄下來,並且在後面也會將該 App 進行實例化。 ::: #### create_contexts(self) 實例化在 RyuApp 中所需的 \_CONTEXT 對象 #### \_update_bricks(self) 更新觀察者資訊,在這裡會設定那些 App 發送消息時有哪些 App 應該要收到通知。 :::info 消息通知時作方法 在 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,主要是在檢查是否需要依賴時會看。