ตัวกรองแพ็กเก็ต Android

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 มีดังนี้

  1. วางและเพิ่มตัวนับ
    1. ค่า EtherType: 0x88A2, 0x88A4, 0x88B8, 0x88CD, 0x88E1 0x88E3
    2. แพ็กเก็ตการค้นหาหรือคำขอ DHCP IPv4
    3. แพ็กเกต RS
  2. ส่งผ่านและเพิ่มตัวนับ: แพ็กเก็ตอื่นๆ ทั้งหมด

รหัส 1 ไบต์ของโปรแกรม APF มีดังนี้

6BF0B03A01B86BF8AA0FB86BF4AA09B8120C6BEC7C005D88A27C005888A47C005388B87C004E88CD7C004988E17C004488E3120C84002008001A1A821B001A1E8600000010FFFFFFFF0A17820B11AB0D2A108204436BE8721D120C84000E86DD0A1482093A0A368204856BE072086BDCB03A01B87206B03A01B87201
โปรแกรม APF 2

เมื่อหน้าจออุปกรณ์ปิดอยู่ ให้ติดตั้งโปรแกรม APF 2 โปรแกรมนี้จะกรอง แพ็กเก็ตทั้งหมดที่โปรแกรม APF 1 กรอง รวมถึงแพ็กเก็ตคำขอ ping หากต้องการยืนยันว่าได้ติดตั้งโปรแกรม APF 2 อย่างถูกต้องแล้ว ให้ส่งแพ็กเก็ต ping ไปยังอุปกรณ์ที่อยู่ระหว่างการทดสอบ

ตรรกะของโปรแกรม APF 2 มีดังนี้

  1. วางและเพิ่มตัวนับ
    1. ค่า EtherType: 0x88A2, 0x88A4, 0x88B8, 0x88CD, 0x88E1 0x88E3
    2. แพ็กเก็ตการค้นหาหรือคำขอ DHCP IPv4
    3. แพ็กเกต RS
  2. ลดและเพิ่มตัวนับ: แพ็กเก็ตคำขอ ping ของ ICMP
  3. ส่งต่อและเพิ่มตัวนับ: แพ็กเก็ตอื่นๆ ทั้งหมด

รหัส 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