כלי התנועה ברשת של eBPF משתמש בשילוב של הטמעה בליבה ובמרחב המשתמש כדי לעקוב אחרי השימוש ברשת במכשיר מאז ההפעלה האחרונה שלו. הוא מספק פונקציונליות נוספת, כמו תיוג שקעים, הפרדת תעבורת נתונים בחזית/ברקע וחומת אש לכל מזהה משתמש (UID) כדי לחסום את הגישה של אפליקציות לרשת בהתאם למצב הטלפון. הנתונים הסטטיסטיים שנאספים מהכלי מאוחסנים במבנה נתונים של הליבה שנקרא eBPF maps
, והתוצאה משמשת שירותים כמו NetworkStatsService
כדי לספק נתונים סטטיסטיים של תעבורת נתונים מתמשכת מאז האתחול האחרון.
דוגמאות ומקור
השינויים במרחב המשתמש מתבצעים בעיקר בפרויקטים system/netd
ו-framework/base
. הפיתוח מתבצע ב-AOSP, כך שקוד ה-AOSP תמיד יהיה עדכני. המקור נמצא בעיקר ב-system/netd/server/TrafficController*
, ב-system/netd/bpfloader
וב-system/netd/libbpf/
.
חלק מהשינויים הנדרשים במסגרת מופיעים גם ב-framework/base/
וב-system/core
.
הטמעה
החל מ-Android 9, במכשירי Android שפועלים עם ליבה מגרסה 4.9 ואילך ושנשלחו במקור עם גרסת P, חובה להשתמש בחישוב מבוסס-eBPF למעקב אחר תעבורת הנתונים ברשת במקום ב-xt_qtaguid
. התשתית החדשה גמישה יותר וניתנת לתחזוקה יותר ואין צורך בקוד ליבה (kernel) מחוץ לעץ.
ההבדלים העיקריים בתכנון בין מעקב התנועה הקודם לבין מעקב התנועה באמצעות eBPF מפורטים באיור 1.
איור 1. ההבדלים בתכנון של מעקב אחר תעבורת נתונים בגרסה הקודמת (שמאל) וב-eBPF (ימין)
העיצוב החדש של trafficController
מבוסס על מסנן eBPF לכל cgroup
, וגם על מודול netfilter של xt_bpf
בתוך הליבה. המסננים האלה של eBPF חלים על ה-tx/rx של החבילות כשהן עוברות דרך המסנן. המסנן cgroup
eBPF נמצא בשכבת התעבורה והוא אחראי לספירת התנועה לפי ה-UID הנכון, בהתאם ל-UID של השקע ולהגדרה של מרחב המשתמש.
ה-netfilter של xt_bpf
מחובר לשרשרת bw_raw_PREROUTING
ו-bw_mangle_POSTROUTING
, והוא אחראי לספירת התנועה בממשק הנכון.
בזמן האתחול, בתהליך מרחב המשתמשים trafficController
נוצר מפות eBPF שמשמשות לאיסוף נתונים, והצמדת כל המפות כקובץ וירטואלי ב-sys/fs/bpf
.
לאחר מכן, התהליך בעל ההרשאות bpfloader
טוען את תוכנית ה-eBPF שעבר הידור מראש לליבה ומצרף אותה ל-cgroup
הנכון. יש רק cgroup
root אחד לכל התנועה, ולכן כל התהליך צריך להיכלל ב-cgroup
הזה כברירת מחדל.
בזמן הריצה, trafficController
יכול לתייג או לבטל תיוג של שקע על ידי כתיבה אל traffic_cookie_tag_map
ואל traffic_uid_counterSet_map
. ה-NetworkStatsService
יכול לקרוא את נתוני סטטיסטיקת התנועה מ-traffic_tag_stats_map
, מ-traffic_uid_stats_map
ומ-traffic_iface_stats_map
.
מלבד הפונקציה לאיסוף נתונים סטטיסטיים של תנועה, מסנן eBPF trafficController
ו-cgroup
אחראי גם לחסימת התנועה ממזהי UID מסוימים, בהתאם להגדרות הטלפון. התכונה של חסימה של תעבורת רשתות שמבוססת על UID מחליפה את המודול xt_owner
בתוך הליבה, וניתן להגדיר את מצב הפירוט על ידי כתיבת traffic_powersave_uid_map
, traffic_standby_uid_map
ו-traffic_dozable_uid_map
.
ההטמעה החדשה תואמת להטמעה הקודמת של מודול xt_qtaguid
, כך ש-TrafficController
ו-NetworkStatsService
יפעלו עם ההטמעה הקודמת או החדשה. אם האפליקציה משתמשת בממשקי API ציבוריים, לא אמורה להיות לה השפעה אם xt_qtaguid
או כלים של eBPF משמשים ברקע.
אם הליבה של המכשיר מבוססת על הליבה המשותפת של Android מגרסה 4.9 (SHA 39c856663dcc81739e52b02b77d6af259eb838f6 ואילך), לא נדרשים שינויים ב-HAL, בקודרים או בקוד הליבה כדי להטמיע את הכלי החדש של eBPF.
הדרישות
בהגדרות הליבה חייבות להיות מופעלות ההגדרות הבאות:
CONFIG_CGROUP_BPF=y
CONFIG_BPF=y
CONFIG_BPF_SYSCALL=y
CONFIG_NETFILTER_XT_MATCH_BPF=y
CONFIG_INET_UDP_DIAG=y
בדיקת תצורת הליבה של VTS עוזרת לוודא שהתצורה הנכונה מופעלת.
תהליך ההוצאה משימוש של המאפיין xt_qtaguid מדור קודם
הכלי החדש של eBPF מחליף את המודול xt_qtaguid
ואת המודול xt_owner
שהוא מבוסס עליו. נתחיל להסיר את המודול xt_qtaguid
מליבת Android ולהשבית את ההגדרות המיותרות שלו.
במהדורה של Android 9, המודול xt_qtaguid
מופעל בכל המכשירים, אבל כל ממשקי ה-API הציבוריים שקוראים ישירות לקובץ ה-proc של המודול xt_qtaguid
מועברים לשירות NetworkManagement
.
בהתאם לגרסה של הליבה של המכשיר ולרמת ה-API הראשונה, השירות NetworkManagement
יודע אם הכלים של eBPF מופעלים ובוחר את המודול הנכון לקבלת כל נתון סטטיסטי של שימוש ברשת באפליקציה. אפליקציות עם SDK ברמה 28 ואילך חסרות גישה לקובצי ה-proc של xt_qtaguid
על ידי sepolicy.
בגרסה הבאה של Android אחרי 9, הגישה של האפליקציה לקובצי ה-proc האלה של xt_qtaguid
תיחסם לחלוטין ונתחיל להסיר את המודול xt_qtaguid
מהליבות הנפוצות החדשות של Android. אחרי ההסרה, נעדכן את הגדרת הבסיס של Android לגרסה הזו של הליבה כדי להשבית באופן מפורש את המודול xt_qtaguid
. המודול xt_qtaguid
יוסר לחלוטין כשדרישת הגרסה המינימלית של הליבה למהדורת Android תהיה 4.9 ואילך.
במהדורת Android 9, רק במכשירים שיושקו עם מהדורת Android 9 תהיה צורך בתכונה החדשה של eBPF. במכשירים שסופקו עם ליבה שיכולה לתמוך בכלים של eBPF, מומלץ לעדכן אותה לתכונה החדשה של eBPF כשמשדרגים לגרסה 9 של Android. אין בדיקת CTS לאכיפת העדכון הזה.
אימות
מומלץ להשתמש באופן קבוע בתיקונים מליבת Android הנפוצה ומ-Android AOSP main. מוודאים שההטמעה עוברת את בדיקות VTS ו-CTS הרלוונטיות, netd_unit_test
ו-libbpf_test
.
בדיקה
יש net_tests של הליבה כדי לוודא שהתכונות הנדרשות מופעלות ותיקוני הליבה הנדרשים הועברו לגרסאות קודמות. הבדיקות משולבות כחלק מבדיקות VTS של Android 9. יש כמה בדיקות יחידה ב-system/netd/
(netd_unit_test
ו-libbpf_test
). יש כמה בדיקות ב-netd_integration_test
כדי לאמת את ההתנהגות הכוללת של הכלי החדש.
CTS ומאמת CTS
מאחר ששני המודולים למעקב אחר תעבורת הנתונים נתמכים במהדורה 9 של Android, אין בדיקת CTS שמאלצת הטמעה של המודול החדש בכל המכשירים. עם זאת, במכשירים עם גרסת ליבה גבוהה מ-4.9 ששווקו במקור עם גרסת Android 9 (כלומר, רמת ה-API הראשונה שגדולה מ-28), יש בדיקות CTS ב-GSI כדי לאמת שהמודול החדש מוגדר בצורה נכונה. אפשר להשתמש בבדיקות CTS ישנות כמו TrafficStatsTest
, NetworkUsageStatsTest
ו-CtsNativeNetTestCases
כדי לוודא שההתנהגות תואמת למודול ה-UID הישן.
בדיקה ידנית
יש כמה בדיקות יחידה ב-system/netd/
(netd_unit_test
, netd_integration_test
ו-libbpf_test
). יש תמיכה ב-dumpsys לבדיקה ידנית של הסטטוס. הפקודה dumpsys netd
מציגה את הסטטוס הבסיסי של המודול trafficController
ואת הסטטוס של הפעלת eBPF. אם eBPF מופעל, הפקודה dumpsys netd trafficcontroller
מציגה את התוכן המפורט של כל מפת eBPF, כולל מידע על שקע מתויג, נתונים סטטיסטיים לכל תג, UID ו-iface והתאמת UID של הבעלים.
מיקומי בדיקה
בדיקות CTS ממוקמות בכתובת:
- https://android.googlesource.com/platform/cts/+/main/tests/tests/net/src/android/net/cts/TrafficStatsTest.Java
- https://android.googlesource.com/platform/cts/+/main/tests/tests/app.usage/src/android/app/usage/cts/NetworkUsageStatsTest.java
- https://android.googlesource.com/platform/system/netd/+/main/tests/bpf_base_test.cpp
בדיקות VTS נמצאות בכתובת https://android.googlesource.com/kernel/tests/+/main/net/test/bpf_test.py.
בדיקות היחידה נמצאות בכתובת:
- https://android.googlesource.com/platform/system/netd/+/main/libbpf/BpfNetworkStatsTest.cpp
- https://android.googlesource.com/platform/system/netd/+/main/server/TrafficControllerTest.cpp