Android Packet Filter (APF) ช่วยให้เฟรมเวิร์กควบคุมตรรกะการกรองแพ็กเกตฮาร์ดแวร์ ขณะรันไทม์ได้ ซึ่งช่วยให้ระบบประหยัดพลังงานได้ด้วยการทิ้ง แพ็กเก็ตในฮาร์ดแวร์ ขณะเดียวกันก็อนุญาตให้เฟรมเวิร์ก Android เปลี่ยนกฎการกรอง ที่รันไทม์ตามสภาพเครือข่าย
ภาพรวม APF
APF ประกอบด้วยองค์ประกอบหลัก 2 อย่าง ได้แก่
- ตัวแปล APF จะทำงานบนฮาร์ดแวร์เครือข่าย (โดยปกติคือชิปเซ็ต Wi-Fi ) ตัวแปล APF จะเรียกใช้ bytecode ของ APF ในแพ็กเก็ตที่ฮาร์ดแวร์ได้รับ และตัดสินใจว่าจะยอมรับ ทิ้ง หรือตอบกลับแพ็กเก็ตเหล่านั้น
- โค้ดการสร้างโปรแกรม APF จะทำงานบน CPU หลัก โค้ดจะสร้าง และอัปเดตโปรแกรม APF ตามสถานะเครือข่ายและอุปกรณ์
เมธอด Wi-Fi HAL ช่วยให้เฟรมเวิร์ก Android ติดตั้งโปรแกรม APF ไบต์โค้ดและอ่านตัวนับปัจจุบันได้ โมดูล Mainline ของสแต็กเครือข่าย สามารถอัปเดตไบต์โค้ดโปรแกรม APF ได้ทุกเมื่อขณะที่ APF ทำงานอยู่
มีการใช้ตัวกรอง APF หลายรายการ ตัวอย่างเช่น APF มีตัวกรองเพื่อ
ทิ้ง Ethertype ที่ไม่อนุญาต กรองแพ็กเก็ตการโฆษณาเราเตอร์ IPv6 (RA)
กรองการเข้าชมแบบมัลติแคสต์และบรอดแคสต์หากไม่ได้ล็อกมัลติแคสต์ ทิ้ง
แพ็กเก็ต DHCP สำหรับโฮสต์อื่นๆ และทิ้งแพ็กเก็ต Address Resolution Protocol
(ARP) และ Neighbor Discovery (ND) ที่ไม่ได้ร้องขอ หากเฟิร์มแวร์รองรับ APFv6
ApfFilter
ก็จะสร้างกฎเพื่อตอบกลับประเภทแพ็กเก็ตทั่วไปที่ปกติแล้ว
ต้องให้ CPU ตื่นขึ้นมาเพื่อตอบสนอง เช่น การค้นหา ARP และการค้นหา NS
ดูรายการตัวกรองทั้งหมดได้ที่
ApfFilter
เนื่องจากโค้ดการสร้างโปรแกรม APF เป็นส่วนหนึ่งของโมดูล Network Stack คุณจึงใช้การอัปเดต Mainline รายเดือนเพื่อเพิ่มตัวกรองใหม่และอัปเดต ตรรกะการกรองได้
การแก้ไข APF
รายการต่อไปนี้อธิบายประวัติการแก้ไขของ APF
- APFv6: เวอร์ชันนี้เปิดตัวใน Android 15 รองรับการกรองแพ็กเก็ต มีตัวนับสำหรับการแก้ไขข้อบกพร่องและเมตริก และ รองรับการส่งแพ็กเก็ต
- APFv4: เวอร์ชันนี้เปิดตัวใน Android 10 และรองรับ การกรองแพ็กเก็ต รวมถึงมีตัวนับสำหรับการแก้ไขข้อบกพร่องและเมตริก
- APFv2: เวอร์ชันนี้เปิดตัวใน Android 7 และรองรับการกรองแพ็กเก็ต
การผสานรวม APF
API ของ APF ระหว่างตัวแปล APF กับฮาร์ดแวร์จะกำหนดไว้ใน
apf_interpreter.h
(APFv4,
APFv6)
โค้ดเฟิร์มแวร์ Wi-Fi จะเรียกใช้
accept_packet()
ใน APFv4 หรือ
apf_run()
ใน APFv6 เพื่อพิจารณาว่าควรทิ้งแพ็กเก็ต (ค่าที่แสดงผลเป็น 0) หรือ
ส่งไปยังโปรเซสเซอร์แอป (ค่าที่แสดงผลไม่ใช่ 0) หากต้องส่งแพ็กเก็ต
apf_run()
ก็จะแสดงผลเป็น 0 ด้วยเช่นกัน เนื่องจากไม่จำเป็นต้องส่งแพ็กเก็ตไปยังตัวประมวลผลแอป หากเฟิร์มแวร์รองรับ APFv6 จะต้องใช้
apf_allocate_buffer()
และ
apf_transmit_buffer()
API ตัวตีความ APF จะเรียกใช้ API ทั้ง 2 รายการนี้ในระหว่างตรรกะการส่งแพ็กเก็ต
คำสั่ง APF มีความยาวที่แตกต่างกัน คำสั่งแต่ละรายการมีความยาวอย่างน้อย 1 ไบต์ รหัสคำสั่ง APF มีการกำหนดไว้ใน
apf.h
สำหรับ APFv4 และอยู่ในบรรทัดโดยตรงภายใน
apf_interpreter.c
สำหรับ APFv6
APF ต้องอาศัยหน่วยความจำเฉพาะ หน่วยความจำนี้ใช้สำหรับทั้งโปรแกรม APF เองและสำหรับการจัดเก็บข้อมูล และชิปเซ็ตต้องไม่ล้างหรือเขียนหน่วยความจำ ยกเว้นผ่านเมธอด APF HAL ไบต์โค้ด APF ใช้ที่เก็บข้อมูลเพื่อจัดเก็บตัวนับสำหรับแพ็กเก็ตที่ยอมรับและแพ็กเก็ตที่ถูกทิ้ง อ่านภูมิภาคข้อมูลได้จากเฟรมเวิร์ก Android คำสั่ง APF ประหยัดหน่วยความจำ แต่การเพิ่มศักยภาพในการประหยัดพลังงานและฟังก์ชันการทำงานให้สูงสุดต้องใช้กฎการกรองแบบไดนามิกที่ซับซ้อน ความซับซ้อนนี้จึงต้องใช้หน่วยความจำบนชิปเซ็ตส่วนหนึ่งโดยเฉพาะ ข้อกำหนดด้านหน่วยความจำขั้นต่ำสำหรับ APFv4 คือ 1024 ไบต์ ขณะที่ APFv6 ต้องใช้ 2048 ไบต์ อย่างไรก็ตาม เราขอแนะนำอย่างยิ่งให้จัดสรร 4096 ไบต์สำหรับ APFv6 เพื่อให้มั่นใจว่ามีประสิทธิภาพสูงสุด ต้องคอมไพล์อินเทอร์พรีเตอร์ APF ลงในเฟิร์มแวร์ ทั้งตัวแปล APFv4 และ APFv6 ได้รับการเพิ่มประสิทธิภาพสำหรับขนาดโค้ด ในสถาปัตยกรรม arm32 ตัวแปล APFv4 ที่คอมไพล์แล้วมีขนาดประมาณ 1.8 KB ส่วนตัวแปล APFv6 ที่ซับซ้อนกว่าพร้อมฟีเจอร์เพิ่มเติม (เช่น การรองรับผลรวมตรวจสอบดั้งเดิมและโค้ดการคลายการบีบอัด DNS ดั้งเดิม) มีขนาด ประมาณ 4 KB
ตัวกรอง APF สามารถทำงานร่วมกับตัวกรองอื่นๆ ที่เจาะจงผู้จำหน่ายชิปเซ็ตภายใน เฟิร์มแวร์ได้ ผู้ให้บริการชิปเซ็ตสามารถเลือกที่จะเรียกใช้ตรรกะการกรองก่อน หรือหลังกระบวนการกรอง APF ก็ได้ หากแพ็กเก็ตถูกทิ้งก่อนที่จะไปถึงตัวกรอง APF ตัวกรอง APF จะไม่ประมวลผลแพ็กเก็ต
เมื่อเปิด APF เฟิร์มแวร์ต้องให้สิทธิ์เข้าถึงแพ็กเก็ตทั้งหมดแก่ตัวกรอง APF ไม่ใช่แค่ส่วนหัว เมื่อเปิดใช้ APF เพื่อให้มั่นใจว่าตัวกรอง APF จะทำงานได้อย่างถูกต้อง
ตัวอย่างโปรแกรม APF
ApfTest
และ
ApfFilterTest
มีโปรแกรมทดสอบตัวอย่างที่แสดงให้เห็นว่าตัวกรอง APF แต่ละตัวทำงานอย่างไร หากต้องการศึกษาโปรแกรมที่สร้างขึ้นจริง ให้แก้ไขกรณีทดสอบเพื่อพิมพ์โปรแกรมเป็นสตริงฐานสิบหก
โฟลเดอร์
testdata
มีโปรแกรม APFv4 ตัวอย่างสำหรับตัวกรอง RA ของ APF โฟลเดอร์
samples
มีเครื่องมือ Python ที่สร้างโปรแกรมการออฟโหลด APFv6 ดูรายละเอียดเพิ่มเติมได้ในเอกสารประกอบในไฟล์ยูทิลิตี Python
แก้ไขข้อบกพร่องของ 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
เครื่องมือนี้รองรับทั้งอินเทอร์พรีเตอร์ APFv4 และ APFv6
ต่อไปนี้คือคู่มือสำหรับคำสั่ง apf_run
โดยค่าเริ่มต้น apf_run
คำสั่งจะทำงานในตัวแปล APFv4 การส่งอาร์กิวเมนต์ --v6
ไปยัง apf_run
จะทำให้เรียกใช้กับตัวแปล APFv6 ได้ อาร์กิวเมนต์อื่นๆ ทั้งหมดใช้ได้กับทั้ง APFv4 และ APFv6
apf_run --help
Usage: apf_run --program <program> --pcap <file>|--packet <packet> [--data <content>] [--age <number>] [--trace]
--program APF program, in hex.
--pcap Pcap file to run through program.
--packet Packet to run through program.
--data Data memory contents, in hex.
--age Age of program in seconds (default: 0).
--trace Enable APF interpreter debug tracing
--v6 Use APF v6
-c, --cnt Print the APF counters
-h, --help Show this message.
ตัวอย่างการส่งแพ็กเก็ต 1 รายการไปยัง APF เพื่อตรวจสอบว่าแพ็กเก็ตสามารถ ทิ้งหรือส่งต่อได้มีดังนี้
หากต้องการระบุการนำเสนอสตริงไบนารีแบบเลขฐานสิบหกของแพ็กเก็ตดิบ ให้ใช้ตัวเลือก
--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
หากต้องการทดสอบความสามารถในการส่ง APFv6 ให้ใช้คำสั่ง apf_run
ดังนี้
$ apf_run --program 75001001020304050608060001080006040002AA300E3CAA0FBA06AA09BA07AA08BA086A01BA09120C84006F08066A0EA30206000108000604032B12147A27017A020203301A1C820200032D68A30206FFFFFFFFFFFF020E1A267E000000020A000001032C020B1A267E000000020A000001032CAB24003CCA0606CB0306CB090ACB0306C60A000001CA0606CA1C04AA 0A3A12AA1AAA25FFFF032F020D120C84001708000A1782100612149C00091FFFAB0D2A10820207032A02117C000E86DD68A30206FFFFFFFFFFFF021603190A1482020002187A023A02120A36820285031F8216886A26A2020FFF020000000000000000000000000003200214 --packet FFFFFFFFFFFF112233445566080600010800060400011122334455660A0000020000000000000A0000 01 --data 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 --age 0 --v6 --trace R0 R1 PC Instruction
------------------------------------------------- 0 0 0: data 16, 01020304050608060001080006040002 0 0 19: debugbuf size=3644 0 0 23: ldm r0, m[15] 0 0 25: stdw counter=6, r0 0 0 27: ldm r0, m[9] 0 0 29: stdw counter=7, r0 0 0 31: ldm r0, m[8] 134d811 0 33: stdw counter=8, r0 134d811 0 35: li r0, 1 1 0 37: stdw counter=9, r0 1 0 39: ldh r0, [12] 806 0 41: jne r0, 0x806, 157 806 0 46: li r0, 14 e 0 48: jbseq r0, 0x6, 59, 000108000604 e 0 59: ldh r0, [20] 1 0 61: jeq r0, 0x1, 103 1 0 103: ldw r0, [38] a000001 0 105: jeq r0, 0xa000001, 116 a000001 0 116: allocate 60 a000001 0 120: pktcopy src=6, len=6 a000001 0 123: datacopy src=3, len=6 a000001 0 126: datacopy src=9, len=10 a000001 0 129: datacopy src=3, len=6 a000001 0 132: write 0x0a000001 a000001 0 137: pktcopy src=6, len=6 a000001 0 140: pktcopy src=28, len=4 a000001 0 143: ldm r0, m[10] 2a 0 145: add r0, 18 3c 0 147: stm r0, m[10] 3c 0 149: transmit ip_ofs=255 3c 0 153: drop counter=47 Packet dropped Data: 00000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000100000011d8340100000000000000000000000000000000000000000100000078563412 transmitted packet: 112233445566010203040506080600010800060400020102030405060a0000011122334455660a000002000000000000000000000000000000000000
เมื่อใช้พารามิเตอร์ --trace
เครื่องมือ apf_run
จะแสดงเอาต์พุตแบบละเอียด
ของแต่ละขั้นตอนในการดำเนินการของอินเทอร์พรีเตอร์ ซึ่งมีประโยชน์สำหรับการ
แก้ไขข้อบกพร่อง ในตัวอย่างนี้ เราจะป้อนแพ็กเก็ตคำค้นหา ARP ลงในโปรแกรม APF
เอาต์พุตแสดงว่าระบบทิ้งการค้นหา ARP แต่สร้างแพ็กเก็ตการตอบกลับ
รายละเอียดของแพ็กเก็ตที่สร้างขึ้นนี้จะแสดงในส่วน transmitted packet
ปัญหาการผสานรวมที่พบบ่อย
ส่วนนี้จะเน้นปัญหาที่พบบ่อยหลายอย่างระหว่างการผสานรวม APF
- การล้างข้อมูลในภูมิภาคโดยไม่คาดคิด: หน่วยความจำ APF ต้องมีไว้สำหรับ APF โดยเฉพาะ และอนุญาตให้เฉพาะโค้ดตัวแปลหรือโค้ดเฟรมเวิร์ก (ผ่าน HAL API) เท่านั้นที่แก้ไขภูมิภาคหน่วยความจำ APF ได้
- ปัญหาการติดตั้งโปรแกรม APF ขนาด X ไบต์ (X <=
maxLen
): เฟิร์มแวร์ต้องรองรับการอ่านหรือเขียนความยาวของโปรแกรมใดก็ได้สูงสุดmaxLen
โดยไม่มีข้อผิดพลาด การขัดข้อง หรือการตัดทอน การเขียนต้องไม่เปลี่ยนแปลงไบต์ใดๆ ระหว่างX
กับmaxLen
- การติดตั้งใช้งาน APF ในโค้ดไดรเวอร์: ควรติดตั้งใช้งาน APF ภายในเฟิร์มแวร์เท่านั้น ไม่ใช่โค้ดไดรเวอร์ มิฉะนั้นจะไม่มีประโยชน์ในการประหยัดพลังงานเนื่องจาก CPU ต้องตื่นขึ้นมาเพื่อประมวลผลแพ็กเก็ต
- ค่า
filter_age
หรือfilter_age_16384th
ไม่ถูกต้อง: ค่าfilter_age
(APFv4) และfilter_age_16384th
(APFv6) ต้องส่งไปยังฟังก์ชันaccept_packet()
และapf_run()
อย่างถูกต้อง ดูรายละเอียดเกี่ยวกับการคำนวณfilter_age_16384th
ได้ในเอกสารประกอบที่apf_interpreter.h
- ไม่ได้เปิดใช้ APF เมื่อจำเป็น: ต้องเปิดใช้ APF เมื่อหน้าจอปิดอยู่และลิงก์ Wi-Fi ไม่ได้ใช้งานหรือมีการรับส่งข้อมูลต่ำกว่า 10 Mbps
- แพ็กเก็ตที่ถูกตัดทอนซึ่งส่งไปยัง
accept_packet()
หรือapf_run()
: แพ็กเก็ตแบบ Unicast, Broadcast และ Multicast ทั้งหมดที่ส่งไปยังaccept_packet()
หรือapf_run()
ต้องสมบูรณ์ การส่งแพ็กเก็ตที่ถูกตัดทอนไปยัง APF ไม่ถูกต้อง
การทดสอบ APF
ตั้งแต่ Android 15 เป็นต้นไป Android จะมีทั้งกรณีทดสอบ CTS แบบอุปกรณ์เดียวและแบบหลายอุปกรณ์สำหรับการผสานรวมตัวกรอง APF และตัวแปล APF เพื่อให้มั่นใจว่าฟังก์ชัน APF ทำงานได้อย่างถูกต้อง ต่อไปนี้คือรายละเอียด วัตถุประสงค์ของกรณีทดสอบแต่ละรายการ
ApfFilter
และapf_interpreter
การทดสอบการผสานรวม: ตรวจสอบว่าApfFilter
สร้างไบต์โค้ดที่ถูกต้อง และapf_interpreter
เรียกใช้โค้ดอย่างถูกต้องเพื่อให้ได้ผลลัพธ์ที่คาดไว้- CTS แบบอุปกรณ์เดียวของ APF:
ใช้อุปกรณ์เครื่องเดียวเพื่อทดสอบฟังก์ชัน APF ในชิปเซ็ต Wi-Fi
ยืนยันว่า
- APF จะเปิดเมื่อหน้าจอปิดอยู่และการรับส่งข้อมูล Wi-Fi ต่ำกว่า 10 Mbps
- มีการประกาศความสามารถของ APF อย่างถูกต้อง
- การดำเนินการอ่านและเขียนในรีเจียนหน่วยความจำ APF จะสำเร็จ และ รีเจียนหน่วยความจำจะไม่ได้รับการแก้ไขโดยไม่คาดคิด
- ส่งผ่านอาร์กิวเมนต์ไปยัง
accept_packet()
หรือapf_run()
อย่างถูกต้อง - เฟิร์มแวร์ที่ผสานรวมกับ APFv4/APFv6 สามารถทิ้งแพ็กเก็ตได้
- เฟิร์มแวร์ที่ผสานรวมกับ APFv6 จะตอบกลับแพ็กเก็ตได้
- CTS แบบหลายอุปกรณ์ของ APF:
ใช้อุปกรณ์ 2 เครื่อง (เครื่องส่ง 1 เครื่องและเครื่องรับ 1 เครื่อง) เพื่อทดสอบลักษณะการทำงานของการกรอง
ของ APF ระบบจะสร้างแพ็กเก็ตประเภทต่างๆ ที่ฝั่งผู้ส่ง
และการทดสอบจะยืนยันว่ามีการทิ้ง ส่งต่อ หรือตอบกลับแพ็กเก็ตอย่างถูกต้องหรือไม่
โดยอิงตามกฎที่กำหนดค่าไว้ใน
ApfFilter
วิธีการทดสอบการผสานรวมเพิ่มเติม
นอกจากนี้ เราขอแนะนำอย่างยิ่งให้ผู้จำหน่ายชิปเซ็ตนำการทดสอบ APF ไปรวมไว้ในชุดทดสอบการผสานรวม Wi-Fi ของเฟิร์มแวร์ของตนเอง
การผสานรวมชุดทดสอบการผสานรวม Wi-Fi ของเฟิร์มแวร์เข้ากับการทดสอบ APF เป็นสิ่งสำคัญ ในการยืนยันฟังก์ชัน APF ที่เหมาะสมในสถานการณ์การเชื่อมต่อ Wi-Fi ที่ซับซ้อน เช่น สถานการณ์การเชื่อมต่อ Wi-Fi แบบ Make-Before-Break หรือการโรมมิ่ง ดูคําแนะนําโดยละเอียด เกี่ยวกับวิธีทําการทดสอบการผสานรวมได้ในส่วนต่อไปนี้
สิ่งที่ต้องมีก่อน
เมื่อทำการทดสอบการผสานรวม ให้ทำดังนี้
- ต้องเปิดใช้ APF ในกรณีทดสอบการผสานรวมทั้งหมด (เช่น การโรมมิ่ง การสร้างก่อนหยุด)
- เมื่อเริ่มการทดสอบแต่ละครั้ง ให้ล้างหน่วยความจำ APF
- ติดตั้งหรือติดตั้งโปรแกรม APF อีกครั้งทุก 5 นาทีระหว่างการทดสอบ
สถานการณ์การทดสอบ
APF ต้องทำงานตลอดการทดสอบการผสานรวม เอกสารนี้มีโปรแกรม APF 2 โปรแกรม
ที่ติดตั้งได้ในระหว่างการทดสอบ โปรแกรมอยู่ในรูปแบบสตริงเลขฐานสิบหก และผู้ทดสอบต้องแปลงสตริงเลขฐานสิบหกเป็นไบนารีและ
ติดตั้งลงในเฟิร์มแวร์เพื่อให้ apf_interpreter
เรียกใช้โปรแกรมได้ ในระหว่างการทดสอบการผสานรวม ผู้ทดสอบควรส่งแพ็กเก็ต
ที่คาดว่าจะทริกเกอร์ตรรกะการกรองในโปรแกรม 1 และโปรแกรม 2
โปรแกรม APF 1
เมื่อหน้าจออุปกรณ์เปิดอยู่ ให้ติดตั้งโปรแกรม APF 1 โปรแกรมนี้สามารถทิ้ง แพ็กเก็ตที่ไม่มีอันตรายซึ่งไม่ส่งผลต่อฟังก์ชันการทำงานของอุปกรณ์ แพ็กเก็ตเหล่านี้ใช้เพื่อทดสอบว่า APF กรองการเข้าชมเครือข่ายอย่างถูกต้องหรือไม่
ตรรกะของโปรแกรม APF 1 มีดังนี้
- วางและเพิ่มตัวนับ
- ค่า EtherType:
0x88A2
,0x88A4
,0x88B8
,0x88CD
,0x88E1
0x88E3
- แพ็กเก็ตการค้นหาหรือคำขอ DHCP IPv4
- แพ็กเกต RS
- ค่า EtherType:
- ส่งผ่านและเพิ่มตัวนับ: แพ็กเก็ตอื่นๆ ทั้งหมด
รหัส 1 ไบต์ของโปรแกรม APF มีดังนี้
6BF0B03A01B86BF8AA0FB86BF4AA09B8120C6BEC7C005D88A27C005888A47C005388B87C004E88CD7C004988E17C004488E3120C84002008001A1A821B001A1E8600000010FFFFFFFF0A17820B11AB0D2A108204436BE8721D120C84000E86DD0A1482093A0A368204856BE072086BDCB03A01B87206B03A01B87201
โปรแกรม APF 2
เมื่อหน้าจออุปกรณ์ปิดอยู่ ให้ติดตั้งโปรแกรม APF 2 โปรแกรมนี้จะกรอง แพ็กเก็ตทั้งหมดที่โปรแกรม APF 1 กรอง รวมถึงแพ็กเก็ตคำขอ ping หากต้องการยืนยันว่าได้ติดตั้งโปรแกรม APF 2 อย่างถูกต้องแล้ว ให้ส่งแพ็กเก็ต ping ไปยังอุปกรณ์ที่อยู่ระหว่างการทดสอบ
ตรรกะของโปรแกรม APF 2 มีดังนี้
- วางและเพิ่มตัวนับ
- ค่า EtherType:
0x88A2
,0x88A4
,0x88B8
,0x88CD
,0x88E1
0x88E3
- แพ็กเก็ตการค้นหาหรือคำขอ DHCP IPv4
- แพ็กเกต RS
- ค่า EtherType:
- ลดและเพิ่มตัวนับ: แพ็กเก็ตคำขอ ping ของ ICMP
- ส่งต่อและเพิ่มตัวนับ: แพ็กเก็ตอื่นๆ ทั้งหมด
รหัส 2 ไบต์ของโปรแกรม APF มีดังนี้
6BF0B03A01B86BF8AA0FB86BF4AA09B8120C6BEC7C007488A27C006F88A47C006A88B87C006588CD7C006088E17C005B88E3120C84002008001A1A821B001A1E8600000010FFFFFFFF0A17820B11AB0D2A108204436BE87234120C84000E86DD0A1482093A0A368204856BE0721F120C84001008000A17820B01AB0D220E8204086BE472086BDCB03A01B87206B03A01B87201
การยืนยันข้อมูล
หากต้องการยืนยันว่าโปรแกรม APF ทำงานและส่งต่อหรือทิ้งแพ็กเก็ตอย่างถูกต้อง ให้ทำดังนี้
- ดึงข้อมูล APF และยืนยันภูมิภาคของข้อมูลทุกๆ 5 นาที
- อย่าล้างตัวนับ
- สร้างแพ็กเก็ตทดสอบเพื่อเรียกใช้กฎตัวกรองแต่ละรายการ
ยืนยันการเพิ่มเคาน์เตอร์โดยใช้ตำแหน่งหน่วยความจำต่อไปนี้
ชื่อตัวนับ ตำแหน่งหน่วยความจำ DROPPED_ETHERTYPE_DENYLISTED
[ApfRamSize - 20, ApfRamSize - 16] DROPPED_DHCP_REQUEST_DISCOVERY
[ApfRamSize - 24, ApfRamSize - 20] DROPPED_ICMP4_ECHO_REQUEST
[ApfRamSize - 28, ApfRamSize - 24] DROPPED_RS
[ApfRamSize - 32, ApfRamSize - 28] PASSED_PACKET
[ApfRamSize - 36, ApfRamSize - 32]
Pseudocode สำหรับโปรแกรม APF 1 และโปรแกรม APF 2
รหัสเทียมต่อไปนี้จะอธิบายตรรกะของโปรแกรม APF 1 และโปรแกรม APF 2 อย่างละเอียด
// ethertype filter
If the ethertype in [0x88A2, 0x88A4, 0x88B8, 0x88CD, 0x88E1, 0x88E3]:
drop packet and increase counter: DROPPED_ETHERTYPE_DENYLISTED
// dhcp discover/request filter
if ethertype != ETH_P_IP:
skip the filter
if ipv4_src_addr != 0.0.0.0:
skip the filter
if ipv4_dst_addr != 255.255.255.255
skip the filter
if not UDP packet:
skip the filter
if UDP src port is not dhcp request port:
skip the filter
else:
drop the packet and increase the counter: DROPPED_DHCP_REQUEST_DISCOVERY
// Router Solicitation filter:
if ethertype != ETH_P_IPV6:
skip the filter
if not ICMP6 packet:
skip the filter
if ICMP6 type is not a Router Solicitation:
skip the filter
else:
drop the packet and increase the counter: DROPPED_RS
// IPv4 ping filter (only included in Program 2)
if ethertype != ETH_P_IP:
skip the filter
if it ipv4 protocol is not ICMP:
skip the filter
if port is not a ping request port
skip the filter
else:
drop the packet and increase the counter: DROPPED_ICMP4_ECHO_REQUEST
pass the packet and increase: PASSED_PACKET