Android 패킷 필터

Android 패킷 필터(APF)를 사용하면 프레임워크에서 런타임에 하드웨어 패킷 필터링을 제어할 수 있습니다. 따라서 시스템이 하드웨어에서 패킷을 삭제하여 전원을 절약할 수 있으며 Android 프레임워크는 네트워크 조건에 따라 런타임에 필터링 규칙을 변경할 수 있습니다.

APF 개요

APF는 다음 두 가지 기본 요소로 구성됩니다.

  • APF 인터프리터는 네트워킹 하드웨어 (일반적으로 Wi-Fi 칩셋)에서 실행됩니다. APF 인터프리터는 하드웨어에서 수신한 패킷에서 APF 바이트 코드를 실행하고 이를 수락, 삭제 또는 응답할지 결정합니다.
  • APF 프로그램 생성 코드는 메인 CPU에서 실행됩니다. 이 코드는 네트워크와 기기 상태에 따라 APF 프로그램을 만들고 업데이트합니다.

Wi-Fi HAL 메서드를 사용하면 Android 프레임워크에서 APF 프로그램 바이트 코드를 설치하고 현재 카운터를 읽을 수 있습니다. 네트워크 스택 메인라인 모듈은 APF가 실행되는 동안 언제든지 APF 프로그램 바이트 코드를 업데이트할 수 있습니다.

여러 APF 필터가 구현되었습니다. 예를 들어 APF에는 허용되지 않는 이더타입을 삭제하는 필터, IPv6 라우터 광고 (RA) 패킷을 필터링하는 필터, 멀티캐스트 잠금이 유지되지 않는 경우 멀티캐스트 및 브로드캐스트 트래픽을 필터링하는 필터, 다른 호스트의 DHCP 패킷을 삭제하는 필터, 요청하지 않은 주소 확인 프로토콜(ARP) 및 이웃 검색 (ND) 패킷을 삭제하는 필터가 포함되어 있습니다. 펌웨어가 APFv6를 지원하는 경우 ApfFilter는 ARP 쿼리 및 NS 쿼리와 같이 응답하기 위해 CPU가 깨어나야 하는 일반적인 패킷 유형에 응답하는 규칙도 생성합니다. 전체 필터 목록은 ApfFilter에 정의되어 있습니다.

APF 프로그램 생성 코드는 네트워크 스택 모듈에 포함되어 있으므로 월간 [메인라인 업데이트]를 사용하여 새 필터를 추가하고 필터링 로직을 업데이트할 수 있습니다.

APF 버전

다음 목록은 APF의 버전 기록을 설명합니다.

  • APFv6: Android 15에서 도입된 이 버전은 패킷 필터링을 지원하고 디버깅 및 측정항목용 카운터를 포함하며 패킷 전송을 지원합니다.
  • APFv4: Android 10에서 도입된 이 버전은 패킷 필터링을 지원하며 디버깅 및 측정항목을 위한 카운터를 포함합니다.
  • APFv2: Android 7에서 도입된 이 버전은 패킷 필터링을 지원합니다.

APF 통합

APF 인터프리터와 하드웨어 간의 APF API는 apf_interpreter.h(APFv4, APFv6)에 정의되어 있습니다. Wi-Fi 펌웨어 코드는 APFv4에서 accept_packet() 또는 APFv6에서 apf_run()를 호출하여 패킷을 삭제해야 하는지 (반환값 0) 앱 프로세서로 전달해야 하는지 (반환값 0이 아님) 결정합니다. 패킷을 전송해야 하는 경우 패킷을 앱 프로세서로 전달할 필요가 없으므로 apf_run()도 0을 반환합니다. 펌웨어가 APFv6을 지원하는 경우 apf_allocate_buffer()apf_transmit_buffer() API를 구현해야 합니다. APF 인터프리터는 패킷 전송 로직 중에 이 두 API를 호출합니다. APF 명령은 가변 길이입니다. 각 명령은 최소 1바이트 길이입니다. APF 명령 코드는 APFv4의 경우 apf.h에 정의되어 있고 APFv6의 경우 apf_interpreter.c 내에 직접 인라인 처리됩니다.

APF는 전용 메모리를 사용합니다. 메모리는 APF 프로그램 자체와 데이터 저장에 모두 사용되며 메모리는 APF HAL 메서드를 통하는 경우를 제외하고 칩셋에서 지우거나 쓰면 안 됩니다. APF 바이트 코드는 데이터 저장소를 사용하여 허용되거나 삭제된 패킷의 카운터를 저장합니다. 데이터 리전은 Android 프레임워크에서 읽을 수 있습니다. APF 명령어는 메모리 효율적이지만 절전 및 기능 잠재력을 극대화하려면 복잡한 동적 필터링 규칙이 필요합니다. 이러한 복잡성으로 인해 칩셋 내 메모리의 전용 부분이 필요합니다. APFv4의 최소 메모리 요구사항은 1,024바이트이고 APFv6의 경우 2,048바이트가 필요합니다. 그러나 최적의 성능을 보장하려면 APFv6에 4, 096바이트를 할당하는 것이 좋습니다. APF 인터프리터를 펌웨어로 컴파일해야 합니다. APFv4 및 APFv6 인터프리터는 모두 코드 크기에 최적화되어 있습니다. arm32 아키텍처에서 컴파일된 APFv4 인터프리터는 약 1.8KB이지만, 추가 기능(예: 네이티브 체크섬 지원 및 네이티브 DNS 압축 해제 코드)이 있는 더 복잡한 APFv6 인터프리터는 약 4KB입니다.

APF 필터는 펌웨어 내의 다른 칩셋 공급업체별 필터와 함께 작동할 수 있습니다. 칩셋 공급업체는 APF 필터링 프로세스 전후에 필터링 로직을 실행하도록 선택할 수 있습니다. 패킷이 APF 필터에 도달하기 전에 삭제되면 APF 필터는 패킷을 처리하지 않습니다.

올바른 APF 필터 기능을 보장하려면 APF가 사용 설정된 경우 펌웨어가 APF 필터에 헤더뿐만 아니라 전체 패킷에 대한 액세스 권한을 제공해야 합니다.

APF 프로그램 샘플

ApfTestApfFilterTest에는 각 APF 필터의 작동 방식을 보여주는 샘플 테스트 프로그램이 포함되어 있습니다. 실제로 생성된 프로그램을 살펴보려면 테스트 사례를 수정하여 프로그램을 16진수 문자열로 출력합니다.

testdata 폴더에는 APF RA 필터용 샘플 APFv4 프로그램이 포함되어 있습니다. samples 폴더에는 APFv6 오프로드 프로그램을 생성하는 Python 유틸리티가 포함되어 있습니다. 자세한 내용은 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: 이 섹션은 16진수 문자열 형식으로 설치된 최신 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.

다음은 패킷을 APF에 전달하여 패킷을 삭제하거나 전달할 수 있는지 확인하는 예입니다.

원시 패킷의 16진수 바이너리 문자열 표시를 제공하려면 --packet 옵션을 사용하세요. APF 카운터를 저장하는 데 사용되는 데이터 리전의 16진수 바이너리 문자열을 제공하려면 --data option을 사용합니다. 각 카운터가 4바이트 길이이므로 데이터 리전은 버퍼 오버플로가 발생하지 않도록 충분히 길어야 합니다.

out/host/linux-x86/bin/apf_run --program 6bfcb03a01b8120c6b9494010c06006b907c010588a27c010088a47c00fb88b87c00f688cd7c00f188e17c00ec88e384003908066a0e6bdca2d40600010800060412147a18016bd882ca021a1c6b8c7ac900686bd4a2b706ffffffffffff6a266bbca2b204c0a814656bf872a8120c84005808000a17821e1112149c00171fffab0d2a108210446a3239a204064651dbcc88ff6bf4727e0a1e52f06bac7a7be06bb41a1e7e0000006effffffff6bb07e00000063c0a814ff6be868a25106ffffffffffff6bb872536bf072497c001086dd686bd0a23806ffffffffffff6bc8723a0a147a0b3a6b980a267a2eff6be072240a366ba87a23858218886a26a2040fff02000000000000000000000000006ba472086be4b03a01b87206b03a01b87201 --packet 5ebcd79a8f0dc244efaab81408060001080006040002c244efaab814c0a8ca1e5ebcd79a8f0d --data 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Packet passed
Data: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000001

tcpdump에서 사용하는 pcap 파일을 대상으로 APF 결과를 확인하려면 다음과 같이 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 도구가 디버깅에 유용한 인터프리터 실행의 각 단계에 관한 자세한 출력을 제공합니다. 이 예에서는 APF 프로그램에 ARP 쿼리 패킷을 입력합니다. 출력에는 ARP 쿼리가 삭제되었지만 답장 패킷이 생성되었다고 표시됩니다. 생성된 이 패킷의 세부정보는 transmitted packet 섹션에 표시됩니다.

일반적인 통합 문제

이 섹션에서는 APF 통합 중에 발생하는 몇 가지 일반적인 문제를 강조 표시합니다.

  • 예기치 않은 데이터 영역 삭제: APF 메모리는 전적으로 APF에 전용되어야 합니다. 인터프리터 코드 또는 프레임워크 코드 (HAL API를 통해)만 APF 메모리 영역을 수정할 수 있습니다.
  • X바이트 (X <= maxLen)의 APF 프로그램 설치 문제: 펌웨어는 오류, 비정상 종료 또는 자르기 없이 최대 maxLen의 프로그램 길이를 읽거나 쓸 수 있어야 합니다. 쓰기는 XmaxLen 사이의 바이트는 변경해서는 안 됩니다.
  • 드라이버 코드의 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가 사용 설정되지 않음: 화면이 꺼져 있고 Wi-Fi 링크가 유휴 상태이거나 트래픽이 10Mbps 미만일 때 APF가 사용 설정되어야 합니다.
  • accept_packet() 또는 apf_run()에 전달된 패킷이 잘림: accept_packet() 또는 apf_run()에 전달된 모든 unicast, broadcast, multicast 패킷은 완전해야 합니다. 잘린 패킷을 APF에 전달하는 것은 유효하지 않습니다.

APF 테스트

Android 15부터 Android는 올바른 APF 기능을 보장하기 위해 APF 필터 및 APF 인터프리터 통합에 관한 단일 기기 및 멀티스크린 CTS 테스트 사례를 모두 제공합니다. 다음은 각 테스트 사례의 목적을 분류한 내용입니다.

  • ApfFilterapf_interpreter 통합 테스트: ApfFilter가 올바른 바이트 코드를 생성하고 apf_interpreter가 코드를 올바르게 실행하여 예상 결과를 생성하는지 확인합니다.
  • APF 단일 기기 CTS: 단일 기기를 사용하여 Wi-Fi 칩셋에서 APF 기능을 테스트합니다. 다음 사항을 확인합니다.
    • 화면이 꺼져 있고 Wi-Fi 트래픽이 10Mbps 미만일 때 APF가 사용 설정됩니다.
    • APF 기능이 올바르게 선언되었습니다.
    • APF 메모리 리전의 읽기 및 쓰기 작업이 성공하고 메모리 리전이 예기치 않게 수정되지 않습니다.
    • 인수가 accept_packet() 또는 apf_run()에 올바르게 전달됩니다.
    • APFv4/APFv6와 통합된 펌웨어는 패킷을 삭제할 수 있습니다.
    • APFv6와 통합된 펌웨어는 패킷에 응답할 수 있습니다.
  • APF 멀티 디바이스 CTS: 두 기기 (송신기 1대, 수신기 1대)를 사용하여 APF의 필터링 동작을 테스트합니다. 다양한 유형의 패킷이 발신자 측에서 생성되며 테스트는 ApfFilter에 구성된 규칙에 따라 패킷이 올바르게 삭제, 전달 또는 응답되었는지 확인합니다.

추가 통합 테스트 안내

또한 칩셋 공급업체는 자체 펌웨어 Wi-Fi 통합 테스트 모음에 APF 테스트를 통합하는 것이 좋습니다.

APF 테스트를 펌웨어 Wi-Fi 통합 테스트 모음에 통합하는 것은 make-before-break 또는 로밍 Wi-Fi 연결 시나리오와 같은 복잡한 Wi-Fi 연결 시나리오에서 적절한 APF 기능을 확인하는 데 중요합니다. 통합 테스트를 실행하는 방법에 관한 자세한 안내는 다음 섹션을 참고하세요.

기본 요건

통합 테스트를 실행할 때는 다음을 실행합니다.

  • 모든 통합 테스트 사례 (예: 로밍, 중단 전 만들기)에서 APF를 사용 설정해야 합니다.
  • 각 테스트를 시작할 때 APF 메모리를 지웁니다.
  • 테스트 중에 5분마다 APF 프로그램을 설치하거나 재설치합니다.

테스트 시나리오

APF는 통합 테스트 전반에서 활성 상태여야 합니다. 이 문서에는 테스트 중에 설치할 수 있는 두 가지 APF 프로그램이 제공됩니다. 프로그램은 16진수 문자열 형식이며 테스터는 16진수 문자열을 바이너리로 변환하고 apf_interpreter에서 프로그램을 실행할 수 있도록 펌웨어에 설치해야 합니다. 통합 테스트 중에 테스터는 프로그램 1과 프로그램 2에서 필터링 로직을 트리거할 것으로 예상되는 패킷을 전송해야 합니다.

APF 프로그램 1

기기 화면이 켜져 있으면 APF 프로그램 1을 설치합니다. 이 프로그램은 기기 기능에 영향을 미치지 않는 무해한 패킷을 삭제할 수 있습니다. 이러한 패킷은 APF가 네트워크 트래픽을 올바르게 필터링하는지 테스트하는 데 사용됩니다.

APF 프로그램 1 로직은 다음과 같습니다.

  1. 카운터 감소 및 증분:
    1. EtherType 값: 0x88A2, 0x88A4, 0x88B8, 0x88CD, 0x88E1, 0x88E3
    2. IPv4 DHCP 검색 또는 요청 패킷
    3. RS 패킷
  2. 패스 및 카운터 증분: 기타 모든 패킷

APF 프로그램 1 바이트 코드는 다음과 같습니다.

6BF0B03A01B86BF8AA0FB86BF4AA09B8120C6BEC7C005D88A27C005888A47C005388B87C004E88CD7C004988E17C004488E3120C84002008001A1A821B001A1E8600000010FFFFFFFF0A17820B11AB0D2A108204436BE8721D120C84000E86DD0A1482093A0A368204856BE072086BDCB03A01B87206B03A01B87201
APF 프로그램 2

기기 화면이 꺼져 있으면 APF 프로그램 2를 설치합니다. 이 프로그램은 APF 프로그램 1에서 필터링하는 모든 패킷과 핑 요청 패킷을 필터링합니다. APF 프로그램 2가 올바르게 설치되었는지 확인하려면 테스트 대상 기기에 핑 패킷을 전송합니다.

APF 프로그램 2 로직은 다음과 같습니다.

  1. 카운터 감소 및 증분:
    1. EtherType 값: 0x88A2, 0x88A4, 0x88B8, 0x88CD, 0x88E1, 0x88E3
    2. IPv4 DHCP 검색 또는 요청 패킷
    3. RS 패킷
  2. 카운터 삭제 및 증분: ICMP 핑 요청 패킷
  3. 패스 및 카운터 증분: 기타 모든 패킷

APF 프로그램 2바이트 코드는 다음과 같습니다.

6BF0B03A01B86BF8AA0FB86BF4AA09B8120C6BEC7C007488A27C006F88A47C006A88B87C006588CD7C006088E17C005B88E3120C84002008001A1A821B001A1E8600000010FFFFFFFF0A17820B11AB0D2A108204436BE87234120C84000E86DD0A1482093A0A368204856BE0721F120C84001008000A17820B01AB0D220E8204086BE472086BDCB03A01B87206B03A01B87201
데이터 확인

APF 프로그램이 실행되고 패킷이 올바르게 전달 또는 삭제되는지 확인하려면 다음을 실행합니다.

  • 5분마다 APF 데이터 리전을 가져와 확인합니다.
  • 카운터를 지우지 않습니다.
  • 각 필터 규칙을 트리거하는 테스트 패킷을 생성합니다.
  • 다음 메모리 위치를 사용하여 카운터 증분을 확인합니다.

    카운터 이름 메모리 위치
    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]

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