eBPF 網(wǎng)絡流量工具結(jié)合使用內(nèi)核與用戶空間實現(xiàn)來監(jiān)控設備自上次啟動以來的網(wǎng)絡使用情況。它提供了額外的功能(如套接字標記、分離前臺/后臺流量,以及按 UID 劃分的防火墻),以根據(jù)手機狀態(tài)阻止應用訪問網(wǎng)絡。從該工具收集的統(tǒng)計數(shù)據(jù)存儲在稱為 eBPF maps 的內(nèi)核數(shù)據(jù)結(jié)構(gòu)中,并且相應結(jié)果由 NetworkStatsService 等服務用來提供自設備上次啟動以來的持久流量統(tǒng)計數(shù)據(jù)。
示例和來源
用戶空間更改主要在 system/netd 和 framework/base 項目中。開發(fā)工作在 AOSP 中完成,因此 AOSP 代碼將始終保持最新狀態(tài)。源代碼主要位于 system/netd/server/TrafficController*、system/netd/bpfloader 和 system/netd/libbpf/ 中。此外,一些必要的框架變更也在 framework/base/ 和 system/core 中。
實現(xiàn)
從 Android 9 開始,內(nèi)核版本為 4.9 或更高且最初搭載了 Android P 版本的 Android 設備必須使用基于 eBPF 的網(wǎng)絡流量監(jiān)控記帳模塊,而不是 xt_qtaguid。新的基礎架構(gòu)更靈活且更易于維護,并且不需要任何外部內(nèi)核代碼。
舊版流量監(jiān)控和 eBPF 流量監(jiān)控之間的主要設計差異如圖 1 所示。
圖 1.舊版流量監(jiān)控(左)和 eBPF 流量監(jiān)控(右)的設計差異
新的 trafficController 設計基于 cgroup 級的 eBPF 過濾器以及內(nèi)核中的 xt_bpf netfilter 模塊。這些 eBPF 過濾器在收發(fā)數(shù)據(jù)包時應用,數(shù)據(jù)包需要通過這些過濾器。cgroup eBPF 過濾器位于傳輸層,負責根據(jù)套接字 UID 以及用戶空間設置對正確的 UID 計算流量。xt_bpf netfilter 掛接在 bw_raw_PREROUTING 和 bw_mangle_POSTROUTING 鏈上,負責對正確的接口計算流量。
在啟動時,用戶空間進程 trafficController 會創(chuàng)建用于收集數(shù)據(jù)的 eBPF 映射,并將所有映射作為虛擬文件固定在 sys/fs/bpf。然后,特權進程 bpfloader 將預編譯的 eBPF 程序加載到內(nèi)核中,并將其附加到正確的 cgroup。所有流量都對應于同一個根 cgroup,因此默認情況下,所有進程都應包含在該 cgroup 中。
在運行時,trafficController 可以通過將數(shù)據(jù)寫入 traffic_cookie_tag_map 和 traffic_uid_counterSet_map 來標記/取消標記套接字。NetworkStatsService 可以從 traffic_tag_stats_map、traffic_uid_stats_map 和 traffic_iface_stats_map 中讀取流量統(tǒng)計數(shù)據(jù)。除了流量統(tǒng)計數(shù)據(jù)收集功能之外,trafficController 和 cgroup eBPF 過濾器還負責根據(jù)手機設置屏蔽來自某些 UID 的流量?;?UID 的網(wǎng)絡流量屏蔽功能取代了內(nèi)核中的 xt_owner 模塊,并且可以通過將數(shù)據(jù)寫入 traffic_powersave_uid_map、traffic_standby_uid_map 和 traffic_dozable_uid_map 來配置詳細模式。
新實現(xiàn)遵循舊版 xt_qtaguid 模塊實現(xiàn),因此 TrafficController 和 NetworkStatsService 將使用舊版實現(xiàn)或新實現(xiàn)運行。如果應用使用公共 API,那么無論在后臺使用 xt_qtaguid 還是 eBPF 工具,應該沒有任何區(qū)別。
如果設備內(nèi)核基于 Android 通用內(nèi)核 4.9(SHA39c856663dcc81739e52b02b77d6af259eb838f6 或更高版本),則無需修改 HAL、驅(qū)動程序或內(nèi)核代碼,即可實現(xiàn)新的 eBPF 工具。
要求
內(nèi)核配置必須開啟以下配置:
驗證是否已開啟正確配置時,VTS 內(nèi)核配置測試非常有用。
CONFIG_CGROUP_BPF=y
CONFIG_BPF=y
CONFIG_BPF_SYSCALL=y
CONFIG_NETFILTER_XT_MATCH_BPF=y
CONFIG_INET_UDP_DIAG=y
設備 MEM_LOCK 資源限制必須設為 8 MB 或更多。
舊版 xt_qtaguid 棄用過程
新的 eBPF 工具正在逐步取代 xt_qtaguid 模塊以及它所基于的 xt_owner 模塊。我們將開始從 Android 內(nèi)核中移除 xt_qtaguid 模塊,并停用不必要的配置。
在 Android 9 版本中,xt_qtaguid 模塊在所有設備上都處于開啟狀態(tài),但直接讀取 xt_qtaguid 模塊 proc 文件的所有公共 API 都移到了 NetworkManagement 服務中。根據(jù)設備內(nèi)核版本和初始 API 級別,NetworkManagement 服務能夠知道 eBPF 工具是否處于開啟狀態(tài),并選擇正確的模塊來獲取每個應用的網(wǎng)絡使用情況統(tǒng)計數(shù)據(jù)。sepolicy 會阻止 SDK 級別為 28 及以上的應用訪問 xt_qtaguid proc 文件。
在 Android 9 之后的下一個版本中,我們將完全阻止應用訪問這些 xt_qtaguid proc 文件,并開始從新的 Android 通用內(nèi)核中移除 xt_qtaguid 模塊。移除該模塊后,我們將更新相應內(nèi)核版本的 Android 基礎配置,以明確關閉 xt_qtaguid 模塊。當 Android 版本的最低內(nèi)核版本要求為 4.9 或更高時,我們將徹底棄用 xt_qtaguid 模塊。
在 Android 9 版本中,只有搭載 Android 9 版本的設備才需要具備新的 eBPF 功能。如果設備搭載的內(nèi)核可以支持 eBPF 工具,我們建議在升級到 Android 9 版本時,將設備更新為采用新的 eBPF 功能。沒有強制執(zhí)行該更新的 CTS 測試。
驗證
您應該定期從 Android 通用內(nèi)核和 Android AOSP 主分支獲取補丁程序。請確保您的實現(xiàn)通過適用的 VTS 和 CTS 測試,即 netd_unit_test 和 libbpf_test。
測試
提供了內(nèi)核 net_tests,用來確保您開啟了必需的功能,并向后移植了必需的內(nèi)核補丁程序。這些測試已集成到 Android 9 版本 VTS 測試中。system/netd/ 中有一些單元測試(netd_unit_test 和 libbpf_test)。netd_integration_test 中有一些驗證新工具整體行為的測試。
CTS 和 CTS 驗證程序
由于這兩個流量監(jiān)控模塊在 Android 9 版本中都得到支持,因此沒有強制在所有設備上實現(xiàn)新模塊的 CTS 測試。不過,對于內(nèi)核版本高于 4.9 且最初搭載了 Android 9 版本(即,初始 API 級別大于等于 28)的設備,提供了基于 GSI 的 CTS 測試,用于驗證是否正確配置了新模塊。舊的 CTS 測試(如TrafficStatsTest、NetworkUsageStatsTest 和 CtsNativeNetTestCases)可用于驗證新模塊的行為是否與舊的 UID 模塊一致。
手動測試
system/netd/中有一些單元測試(netd_unit_test、netd_integration_test 和 libbpf_test)。此外,還提供了 dumpsys 支持,以便手動檢查狀態(tài)。dumpsys netd 命令可顯示 trafficController 模塊的基本狀態(tài)以及是否正確開啟了 eBPF。如果 eBPF 處于開啟狀態(tài),dumpsys netd trafficcontroller 命令會顯示每個 eBPF 映射的詳細內(nèi)容,包括帶標記的套接字信息、每個標記的統(tǒng)計數(shù)據(jù)、UID 和 iface,以及所有者 UID 匹配項。
-
Android
+關注
關注
12文章
3937瀏覽量
127454 -
流量監(jiān)控
+關注
關注
0文章
17瀏覽量
7373 -
BPF
+關注
關注
0文章
25瀏覽量
4007
發(fā)布評論請先 登錄
相關推薦
評論