מסנן Android Packet (APF) מאפשר ללוגיקת סינון חבילות החומרה של framework במהלך זמן ריצה. כך המערכת יכולה לחסוך בצריכת החשמל על ידי שחרור חבילות בחומרה, והמסגרת של Android יכולה לשנות את כללי הסינון בזמן הריצה בהתאם לתנאי הרשת.
סקירה כללית של APF
APF מורכב משני חלקים עיקריים:
- התרגום ב-APF פועל בחומרה של הרשת (בדרך כלל ערכת השבבים ל-Wi-Fi). המתרגם של APF מריץ בייטקוד של APF על חבילות שהחומרה מקבלת, ומחליטים אם לקבל או להסיר אותן.
- קוד הגנרציה של תוכנית APF פועל במעבד הראשי. הקוד יוצר ומעדכן תוכניות APF בהתאם למצב הרשת והמכשיר.
שיטות HAL ב-Wi-Fi מאפשרות ל-framework של Android להתקין את הבייטקוד של תוכנית APF ולקרוא את המוניים הנוכחיים. המודול של Network Stack Mainline יכול לעדכן את הבייטקוד של תוכנית APF בכל שלב בזמן ש-APF פועל.
הוטמעו כמה מסנני APF. לדוגמה, APF כולל מסננים להסרת חבילות ethertype לא מותרות, סינון חבילות פרסום בנתב IPv6 (RA), סינון של תעבורת נתונים בשידורים מרובים (multicast) ותעבורת נתונים אם נעילת השידור הרחב לא מוחזקת, שחרור חבילות DHCP עבור מארחים אחרים ושחרור של פרוטוקולי רזולוציית כתובות (ARP) לא רצויים וחבילות ND (גילוי שכנות). רשימת המסננים המלאה מוגדרת ב-ApfFilter
.
מכיוון שקוד הגנרציה של תוכנית APF הוא חלק מהמודול Network Stack, לכן אפשר לעדכן את לוגיקת הסינון ולהוסיף מסננים חדשים באמצעות עדכונים חודשיים בשיטת Mainline.
שילוב של APF
APF API מוגדר ב-apf_interpreter.h
.
קוד הקושחה של ה-Wi-Fi קורא לפונקציה int accept_packet()
כדי לקבוע אם צריך להשמיט את החבילה (ערך מוחזר אפס) או לעבור (ערך החזרה שאינו אפס). ההוראות של APF הן באורך משתנה. האורך של כל הוראה הוא בייט אחד לפחות. קודי ההוראות של APF מוגדרים ב-apf.h
.
APF מסתמך על זיכרון ייעודי. הזיכרון משמש גם לתוכנית APF עצמה וגם לאחסון נתונים, ואי אפשר לנקות או לכתוב את הזיכרון באמצעות ערכת השבבים, אלא באמצעות methods של APF HAL. הבייטקוד של APF משתמש באחסון הנתונים כדי לאחסן מונה של חבילות שאושרו ונשלחו. אפשר לקרוא את אזור הנתונים מה-framework של Android. נפח הזיכרון המינימלי שזמין ל-APF הוא 1,024 בייטים.
ניפוי באגים ב-APF
כדי לבדוק אם APF מופעל במכשיר, להציג את התוכנית הנוכחית ולהציג את המוניים הנוכחיים, מריצים את הפקודה adb shell dumpsys network_stack
. הדוגמה הבאה היא לפקודה הזו:
adb shell dumpsys network_stack
......
IpClient.wlan0 APF dump:
Capabilities: ApfCapabilities{version: 4, maxSize: 4096, format: 1}
......
Last program:
6bfcb03a01b8120c6b9494026506006b907c025e88a27c025988a47c025488b87c024f88cd7c024a88e17c024588e384004408066a0e6bdca4022b000600010800060412147a1e016bd884021f00021a1c6b8c7c021c0000686bd4a402080006ffffffffffff6a266bbca402010004c0a801eb6bf87401f6120c84005f08000a17821f1112149c00181fffab0d2a108211446a3239a20506c2fc393057dd6bf47401cb0a1e52f06bac7c01c600e06bb41a1e7e000001b9ffffffff6bb07e000001aec0a801ff6be868a4019a0006ffffffffffff6bb874019b6bf07401907c001386dd686bd0a4017d0006ffffffffffff6bc874017e0a147a0e3a6b980a267c017000ff6be07401650a366ba87c016200858219886a26a2050fff02000000000000000000000000006ba4740146aa0e84013700e6aa0f8c0130006068a4011b000f33330000000184c9b26aed4c86dd606a12a2f02600b03afffe8000000000000086c9b2fffe6aed4cff02000000000000000000000000000186006a3aa2e9024000123c92e4606a3ea2d70800000000000000006a56a2ce04030440c01a5a92c9601a5e92c4606a62a2bb04000000006a66a2a6102401fa00049c048400000000000000006a76a29d04030440c01a7a9298601a7e9293606c0082a28904000000006c0086a27310fdfd9ed67950000400000000000000006c0096a2690418033c001a9a9264606c009ea24e102401fa00049c048000000000000000006c00aea24404180330001ab2923f606c00b6a22910fdfd9ed67950000000000000000000006c00c6a21f04190300001aca921a606c00cea20410fdfd9ed67950000400000000000000016bc472086be4b03a01b87206b03a01b87201
APF packet counters:
TOTAL_PACKETS: 469
PASSED_DHCP: 4
PASSED_IPV4: 65
PASSED_IPV6_NON_ICMP: 64
PASSED_IPV4_UNICAST: 64
PASSED_IPV6_ICMP: 223
PASSED_IPV6_UNICAST_NON_ICMP: 6
PASSED_ARP_UNICAST_REPLY: 4
PASSED_NON_IP_UNICAST: 1
DROPPED_RA: 4
DROPPED_IPV4_BROADCAST_ADDR: 7
DROPPED_IPV4_BROADCAST_NET: 27
הפלט של פקודת adb shell dumpsys network_stack
לדוגמה הזו כולל:
ApfCapabilities{version: 4, maxSize: 4096, format: 1}
: המשמעות היא שצ'יפים של Wi-Fi תומכים ב-APF (גרסה 4).Last program
: המקטע הזה הוא הקובץ הבינארי העדכני ביותר של תוכנת APF המותקן, בפורמט של מחרוזת הקסדצימלית.APF packet counters
: בקטע הזה אפשר לראות כמה חבילות מועברות או נופלות על ידי APF, ומה הסיבות הספציפיות לכך.
כדי לפענח ולפרק את הקוד לשפת הרכב קריאה לאנשים, משתמשים בכלי apf_disassembler
. כדי להדר את קובץ ההפעלה הבינארי, מריצים את הפקודה m apf_disassembler
. הדוגמה הבאה היא איך להשתמש בכלי apf_disassembler
.
echo "6bfcb03a01b8120c6b949401e906006b907c01e288a27c01dd88a47c01d888b87c01d388cd7c01ce88e17c01c988e384004008066a0e6bdca401af000600010800060412147a1e016bd88401a300021a1c6b8c7c01a00000686bd4a4018c0006ffffffffffff1a266bc07c018900006bf874017e120c84005408000a17821f1112149c00181fffab0d2a108211446a3239a205065a56483ac3146bf47401530a1e52f06bac7c014e00e06bb41a1e7e00000141ffffffff6be868a4012d0006ffffffffffff6bb874012e6bf07401237c001386dd686bd0a401100006ffffffffffff6bc87401110a147a0d3a6b980a267c010300ff6be072f90a366ba87af8858218886a26a2040fff02000000000000000000000000006ba472ddaa0e82d0aeaa0f8c00c9025868a2b60f5a56483ac3140c8126f3895186dd606a12a28b2600783afffe8000000000000002005efffe00026fff02000000000000000000000000000186006a3aa284024000123c94007d02586a3ea2700800000000000000006a56a26704190500001a5a94006002586a5ea23b2020014860486000000000000000006464200148604860000000000000000000646a7ea23204030440c01a8294002b02581a8694002402586c008aa21a04000000006c008ea204102a0079e10abcf60500000000000000006bc472086be4b03a01b87206b03a01b87201" | out/host/linux-x86/bin/apf_disassembler
0: li r1, -4
2: lddw r0, [r1+0]
3: add r0, 1
5: stdw r0, [r1+0]
6: ldh r0, [12]
8: li r1, -108
10: jlt r0, 0x600, 504
15: li r1, -112
17: jeq r0, 0x88a2, 504
22: jeq r0, 0x88a4, 504
27: jeq r0, 0x88b8, 504
32: jeq r0, 0x88cd, 504
37: jeq r0, 0x88e1, 504
42: jeq r0, 0x88e3, 504
47: jne r0, 0x806, 116
......
כדי לבדוק את תוצאות APF אופליין, משתמשים בכלי apf_run
. כדי להדר את קובץ ההפעלה הבינארי, מריצים את הפקודה m apf_run
. הדוגמה הבאה היא של בדיקה מול חבילה יחידה באמצעות הפקודה apf_run
.
כדי לספק את ההצגה של המחרוזת הבינארית בפורמט הקסדצימלי של החבילה הגולמית, משתמשים באפשרות --packet
. כדי לספק את המחרוזת הבינארית ההקסדצימלית של אזור הנתונים, שמשמשת לאחסון מונה APF, משתמשים ב---data option
. מכיוון שכל מונה הוא 4 בייטים, אזורי הנתונים צריכים להיות ארוכים מספיק כדי לוודא שלא תתבצע גלישת נתונים במאגר הנתונים הזמני.
out/host/linux-x86/bin/apf_run --program 6bfcb03a01b8120c6b9494010c06006b907c010588a27c010088a47c00fb88b87c00f688cd7c00f188e17c00ec88e384003908066a0e6bdca2d40600010800060412147a18016bd882ca021a1c6b8c7ac900686bd4a2b706ffffffffffff6a266bbca2b204c0a814656bf872a8120c84005808000a17821e1112149c00171fffab0d2a108210446a3239a204064651dbcc88ff6bf4727e0a1e52f06bac7a7be06bb41a1e7e0000006effffffff6bb07e00000063c0a814ff6be868a25106ffffffffffff6bb872536bf072497c001086dd686bd0a23806ffffffffffff6bc8723a0a147a0b3a6b980a267a2eff6be072240a366ba87a23858218886a26a2040fff02000000000000000000000000006ba472086be4b03a01b87206b03a01b87201 --packet 5ebcd79a8f0dc244efaab81408060001080006040002c244efaab814c0a8ca1e5ebcd79a8f0d --data 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Packet passed
Data: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000001
כדי לבדוק את תוצאות APF מול קובץ ה-pcap שנוצר על ידי tcpdump, משתמשים בפקודה apf_run
באופן הבא:
out/host/linux-x86/bin/apf_run --program 6bfcb03a01b8120c6b989401df06006b947c01d888a27c01d388a47c01ce88b87c01c988cd7c01c488e17c01bf88e384004408066a0e6bdca401a5000600010800060412147a1e016bd884019900021a1c6b907c01960000686bd4a401820006ffffffffffff6a266bc0a4017b0004c0a82b056bf874017084005f08000a17821f1112149c00181fffab0d2a108211446a3239a20506fabe589435936bf47401470a1e52f06bb07c014200e06bb81a1e7e00000135ffffffff6bb47e0000012ac0a82bff6be868a401160006ffffffffffff6bbc7401176bf074010c7c001086dd686bd0a2fb06ffffffffffff6bcc72fd0a147a0b3a6b9c0a267af1ff6be072e70a366bac7ae6858218886a26a2040fff02000000000000000000000000006ba872cbaa0e82be8eaa0f8c00b7025868a2a40ffabe5894359352a9874d08aa86dd606a12a2792600583afffe80000000000000f7d4e8ccd81ddb43fe80000000000000f8be58fffe94359386006a3aa272024108123c94006b02586a3ea25e0800000000000000006a56a25504030440c01a5a94004e02581a5e94004702586a62a23e04000000006a66a229102409891f9a26ae6d00000000000000006a76a22004190300001a7a94001902586a7ea204102409891f9a26ae6dba98e781ca9ef9ba6bc872086be4b03a01b87206b03a01b87201 --pcap apf.pcap --data 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
37 packets dropped
1733 packets passed
Data: 00000000000000000000000000000000000000000200000005000000000000000000000002000000000000001b000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000689000000000000003c00000000000000000000000000000000000006ea