ניטור תנועה ב-eBPF

כלי התנועה ברשת 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. התשתית החדשה גמישה יותר וקל יותר לתחזק אותה, ולא נדרש בה קוד ליבת מערכת הפעלה מחוץ לעץ.

ההבדלים העיקריים בעיצוב בין ניטור תנועה מדור קודם לבין ניטור תנועה באמצעות eBPF מוצגים באיור 1.

הבדלים בתכנון של מעקב תנועה בגרסה הקודמת וב-eBPF

איור 1. הבדלים בין העיצוב של מעקב תנועת הגולשים בגרסה הקודמת (משמאל) לבין העיצוב ב-eBPF (מימין)

העיצוב החדש של trafficController מבוסס גם על מסנן eBPF לכל cgroup וגם על מודול xt_bpf netfilter בתוך הליבה. מסנני ה-eBPF האלה מוחלים על חבילות tx/rx כשהן עוברות דרך המסנן. מסנן cgroup eBPF ממוקם בשכבת התעבורה ואחראי לספירת התעבורה לפי ה-UID הנכון, בהתאם ל-UID של השקע ולהגדרה של מרחב המשתמש. ‫xt_bpf netfilter מחובר לשרשרת bw_raw_PREROUTING ולשרשרת bw_mangle_POSTROUTING ואחראי על ספירת התעבורה בממשק הנכון.

בזמן האתחול, תהליך המרחב של המשתמש trafficController יוצר את מיפויי ה-eBPF שמשמשים לאיסוף נתונים, ומצמיד את כל המיפויים כקובץ וירטואלי ב-sys/fs/bpf. לאחר מכן, התהליך עם ההרשאות bpfloader טוען את תוכנית ה-eBPF שעברה קומפילציה מראש לתוך הליבה ומצרף אותה ל-cgroup הנכון. יש שורש אחדcgroup לכל התנועה, ולכן כל התהליך צריך להיכלל בcgroup כברירת מחדל.

בזמן הריצה, trafficController יכול לתייג או לבטל תיוג של שקע על ידי כתיבה ל-traffic_cookie_tag_map ול-traffic_uid_counterSet_map. האפליקציה NetworkStatsService יכולה לקרוא את נתוני סטטיסטיקת התנועה מ-traffic_tag_stats_map, ‏ traffic_uid_stats_map ו-traffic_iface_stats_map. בנוסף לפונקציה של איסוף נתוני התנועה, המסנן trafficController ו-cgroup eBPF אחראי גם לחסימת תנועה ממזהי משתמש מסוימים, בהתאם להגדרות הטלפון. התכונה של חסימת תנועת רשת שמבוססת על 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 החדש.

דרישות

  1. ההגדרות הבאות צריכות להיות מופעלות בקובץ ההגדרות של ליבת המערכת:

    1. CONFIG_CGROUP_BPF=y
    2. CONFIG_BPF=y
    3. CONFIG_BPF_SYSCALL=y
    4. CONFIG_NETFILTER_XT_MATCH_BPF=y
    5. CONFIG_INET_UDP_DIAG=y

    בדיקת ההגדרה של ליבת VTS עוזרת לוודא שההגדרה הנכונה מופעלת.

תהליך הוצאה משימוש של xt_qtaguid מדור קודם

הכלי החדש eBPF מחליף את המודולxt_qtaguid ואת המודולxt_owner שהוא מבוסס עליו. נתחיל להסיר את מודול xt_qtaguid מליבת Android ונשבית את ההגדרות המיותרות שלו.

בגרסה Android 9, המודול xt_qtaguid מופעל בכל המכשירים, אבל כל ממשקי ה-API הציבוריים שקוראים ישירות את קובץ התהליך של המודול xt_qtaguid מועברים לשירות NetworkManagement. בהתאם לגרסת ליבת המכשיר ולרמת ה-API הראשונה, שירות NetworkManagement יודע אם כלי eBPF מופעלים ובוחר את המודול הנכון לקבלת נתוני השימוש ברשת של כל אפליקציה. אפליקציות עם SDK ברמה 28 ומעלה נחסמות מגישה לקבצים NetworkManagement proc על ידי sepolicy.xt_qtaguid

בגרסת Android הבאה אחרי גרסה 9, הגישה של אפליקציות לקובצי xt_qtaguid proc האלה תיחסם לחלוטין, ונתחיל להסיר את מודול xt_qtaguid מליבות Android הנפוצות החדשות. אחרי ההסרה, נעדכן את הגדרת הבסיס של Android עבור גרסת הליבה הזו כדי להשבית את מודול xt_qtaguid באופן מפורש. מודול xt_qtaguid יוצא משימוש באופן סופי כשדרישת גרסת הליבה המינימלית לגרסת Android היא 4.9 ומעלה.

בגרסה Android 9, רק מכשירים שהושקו עם גרסה Android 9 נדרשים לכלול את התכונה החדשה eBPF. למכשירים שנשלחו עם ליבת מערכת שיכולה לתמוך בכלים של eBPF, מומלץ לעדכן אותה לתכונת ה-eBPF החדשה כשמשדרגים לגרסה Android 9. אין בדיקת CTS לאכיפת העדכון.

אימות

מומלץ להחיל תיקונים באופן קבוע מליבות נפוצות של Android ומ-Android AOSP main. מוודאים שההטמעה עוברת את הבדיקות הרלוונטיות של VTS ו-CTS, את netd_unit_test ואת libbpf_test.

בדיקה

יש kernel net_tests כדי לוודא שהתכונות הנדרשות מופעלות ושהתיקונים הנדרשים בגרסת הליבה הועברו לאחור. הבדיקות משולבות כחלק מבדיקות VTS של גרסת Android 9. יש כמה בדיקות יחידה ב-system/netd/ (netd_unit_test ו-libbpf_test). יש כמה בדיקות ב-netd_integration_test כדי לאמת את ההתנהגות הכוללת של הכלי החדש.

CTS ו-CTS Verifier

מכיוון ששני מודולי מעקב התנועה נתמכים בגרסה Android 9, אין בדיקת CTS שמאלצת הטמעה של המודול החדש בכל המכשירים. אבל במכשירים עם גרסת ליבה גבוהה מ-4.9 שסופקו במקור עם גרסת Android 9 (כלומר, רמת ה-API הראשונה >= 28), יש בדיקות CTS ב-GSI כדי לאמת שהמודול החדש מוגדר בצורה נכונה. אפשר להשתמש בבדיקות CTS ישנות כמו TrafficStatsTest, NetworkUsageStatsTest ו-CtsNativeNetTestCases כדי לוודא שההתנהגות עקבית עם מודול UID ישן.

בדיקה ידנית

יש כמה בדיקות יחידה ב-system/netd/ (netd_unit_test, netd_integration_test and libbpf_test). יש תמיכה ב-dumpsys לבדיקה ידנית של הסטטוס. הפקודה dumpsys netd מציגה את הסטטוס הבסיסי של מודול trafficController ואם eBPF מופעל בצורה תקינה. אם eBPF מופעל, הפקודה dumpsys netd trafficcontroller מציגה את התוכן המפורט של כל מפת eBPF, כולל מידע על שקע מתויג, נתונים סטטיסטיים לכל תג, UID ו-iface, והתאמה של UID של בעלים.

מיקומי בדיקה

בדיקות CTS ממוקמות ב:

הבדיקות של VTS ממוקמות בכתובת https://android.googlesource.com/kernel/tests/+/android16-release/net/test/bpf_test.py.

בדיקות היחידה נמצאות ב: