Фильтр пакетов Android

Android Packet Filter (APF) позволяет фреймворку управлять логикой фильтрации пакетов оборудования во время выполнения. Это позволяет системе экономить электроэнергию, отбрасывая пакеты на оборудовании, в то же время позволяя фреймворку Android изменять правила фильтрации во время выполнения на основе сетевых условий.

Обзор АПФ

АПФ состоит из двух основных компонентов:

  • Интерпретатор APF работает на сетевом оборудовании (обычно на чипсете Wi-Fi). Интерпретатор APF запускает байт-код APF на пакетах, полученных оборудованием, и решает, принимать ли их, отбрасывать или отвечать на них.
  • Код генерации программы APF выполняется на главном процессоре. Код создает и обновляет программы APF в соответствии с состоянием сети и устройства.

Методы Wi-Fi HAL позволяют платформе Android устанавливать байт-код программы APF и считывать текущие счетчики. Модуль Network Stack Mainline может обновлять байт-код программы APF в любое время, пока APF работает.

Реализовано несколько фильтров APF. Например, APF включает фильтры для отбрасывания запрещенных ethertypes, фильтрации пакетов IPv6 router advertising (RA), фильтрации многоадресного и широковещательного трафика, если многоадресная блокировка не удерживается, отбрасывания пакетов DHCP для других хостов и отбрасывания пакетов unsolicited address resolution protocol (ARP) и neighbor discovery (ND). Если прошивка поддерживает APFv6, ApfFilter также генерирует правила для ответа на распространенные типы пакетов, которые в противном случае потребовали бы пробуждения ЦП для ответа, такие как запросы ARP и запросы NS. Полный список фильтров определен в ApfFilter .

Поскольку код генерации программы APF является частью модуля сетевого стека, вы можете использовать ежемесячные обновления [Mainline] для добавления новых фильтров и обновления логики фильтрации.

пересмотр АПФ

В следующем списке описывается история изменений APF:

  • APFv6: эта версия, представленная в Android 15, поддерживает фильтрацию пакетов, включает счетчики для отладки и метрик, а также поддерживает передачу пакетов.
  • APFv4: эта версия, представленная в Android 10, поддерживает фильтрацию пакетов и включает счетчики для отладки и метрик.
  • APFv2: эта версия, представленная в Android 7, поддерживает фильтрацию пакетов.

Интеграция АПФ

API APF между интерпретатором APF и оборудованием определены в apf_interpreter.h ( APFv4 , APFv6 ). Код прошивки Wi-Fi вызывает accept_packet() в APFv4 или apf_run() в APFv6, чтобы определить, следует ли отбросить пакет (нулевое возвращаемое значение) или передать его процессору приложения (ненулевое возвращаемое значение). Если пакет необходимо передать, apf_run() также возвращает ноль, поскольку его пакет не нужно передавать процессору приложения. Если прошивка поддерживает APFv6, она должна реализовать API apf_allocate_buffer() и apf_transmit_buffer() . Интерпретатор APF вызывает эти два API во время логики передачи пакетов. Инструкции 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 КБ, тогда как более сложный интерпретатор APFv6 с дополнительными функциями (например, собственной поддержкой контрольных сумм и собственным кодом распаковки DNS) занимает около 4 КБ.

Фильтры APF могут работать вместе с другими фильтрами, специфичными для поставщика чипсета, в рамках прошивки. Поставщики чипсетов могут выбрать запуск своей логики фильтрации до или после процесса фильтрации APF. Если пакет отбрасывается до достижения фильтра APF, фильтр APF не обрабатывает пакет.

Для обеспечения корректной работы фильтра APF при включенном APF прошивка должна предоставлять фильтру APF доступ ко всему пакету, а не только к заголовку, когда APF включен.

Образцы программ APF

ApfTest и ApfFilterTest содержат примеры тестовых программ, которые иллюстрируют, как работает каждый фильтр APF. Чтобы изучить фактическую сгенерированную программу, измените тестовый случай, чтобы распечатать программу в виде шестнадцатеричной строки.

Папка testdata содержит примеры программ APFv4 для фильтров APF RA. Папка 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.

Вот пример передачи одного пакета в 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; изменять область памяти APF разрешено только коду интерпретатора или коду фреймворка (через API HAL).
  • Проблемы установки с программами APF из X байт (X <= maxLen ): Прошивка должна поддерживать чтение или запись любой длины программы до maxLen без сбоев, сбоев или усечения. Записи не должны изменять никакие байты между X и maxLen .
  • Реализация APF в коде драйвера: APF следует реализовывать только в прошивке, а не в коде драйвера. В противном случае нет преимуществ энергосбережения, поскольку ЦП должен просыпаться для обработки пакета.
  • Неправильные значения 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 Мбит/с.
  • Усеченные пакеты, переданные в accept_packet() или apf_run() : Все одноадресные, широковещательные и многоадресные пакеты, переданные в accept_packet() или apf_run() должны быть полными. Передача усеченных пакетов в APF недопустима.

Тесты АПФ

Начиная с Android 15, Android предоставляет как одно-, так и многоустройственные тестовые случаи CTS для интеграции фильтра APF и интерпретатора APF, чтобы гарантировать правильную функциональность APF. Вот разбивка цели каждого тестового случая:

  • Тест интеграции ApfFilter и apf_interpreter : проверяет, что ApfFilter генерирует правильный байт-код, а apf_interpreter правильно выполняет код для получения ожидаемых результатов.
  • APF single-device CTS : использует одно устройство для проверки функциональности APF на чипсете Wi-Fi. Подтверждает, что:
    • APF включается, когда экран выключен, а скорость Wi-Fi-трафика ниже 10 Мбит/с.
    • Возможности APF заявлены правильно.
    • Операции чтения и записи в области памяти APF выполняются успешно, и область памяти не подвергается неожиданным изменениям.
    • Аргументы правильно передаются в accept_packet() или apf_run() .
    • Прошивка, интегрированная с APFv4/APFv6, может отбрасывать пакеты.
    • Интегрированная с APFv6 прошивка может отвечать на пакеты.
  • APF multi-device CTS : использует два устройства (один отправитель, один получатель) для проверки поведения фильтрации APF. На стороне отправителя генерируются различные типы пакетов, и тест подтверждает, правильно ли они отбрасываются, передаются или на них отвечают на основе правил, настроенных в ApfFilter .

Дополнительные инструкции по интеграционному тестированию

Кроме того, мы настоятельно рекомендуем поставщикам чипсетов включать тестирование APF в свои собственные наборы тестов интеграции Wi-Fi в прошивку.

Интеграция тестирования APF в тестовые наборы для интеграции Wi-Fi-прошивки имеет решающее значение для проверки правильной функциональности APF в сложных сценариях подключения Wi-Fi, таких как сценарии подключения «сделай перед разрывом» или «роуминг» Wi-Fi. Подробные инструкции по выполнению интеграционных тестов можно найти в следующем разделе.

Предпосылки

При проведении интеграционных тестов выполните следующие действия:

  • APF должен быть включен во всех тестовых случаях интеграции (например, роуминг, включение-выключение).
  • В начале каждого теста очищайте память APF.
  • Устанавливайте или переустанавливайте программы APF каждые 5 минут во время теста.

Тестовые сценарии

APF должен быть активен во время интеграционных тестов. В этом документе приведены две программы APF, которые можно установить во время тестирования. Программы находятся в формате шестнадцатеричной строки, и тестер должен преобразовать шестнадцатеричную строку в двоичную и установить их в прошивку, чтобы программы могли выполняться apf_interpreter . Во время интеграционного теста тестер должен отправлять пакеты, которые, как ожидается, вызовут логику фильтрации в программе 1 и программе 2.

Программа АПФ 1

Когда экран устройства включен, установите программу APF 1. Эта программа может отбрасывать безвредные пакеты, которые не влияют на функциональность устройства. Эти пакеты используются для проверки того, правильно ли APF фильтрует сетевой трафик.

Логика программы АПФ 1 следующая:

  1. Удалить и увеличить счетчик:
    1. Значения EtherType: 0x88A2 , 0x88A4 , 0x88B8 , 0x88CD , 0x88E1 , 0x88E3
    2. IPv4 DHCP обнаруживает или запрашивает пакеты
    3. RS-пакеты
  2. Пройти и увеличить счетчик: Все остальные пакеты.

1-байтовые коды программы APF следующие:

6BF0B03A01B86BF8AA0FB86BF4AA09B8120C6BEC7C005D88A27C005888A47C005388B87C004E88CD7C004988E17C004488E3120C84002008001A1A821B001A1E8600000010FFFFFFFF0A17820B11AB0D2A108204436BE8721D120C84000E86DD0A1482093A0A368204856BE072086BDCB03A01B87206B03A01B87201
Программа АПФ 2

Когда экран устройства выключен, установите программу APF 2. Эта программа отфильтровывает все пакеты, которые фильтрует программа APF 1 , а также пакеты запросов ping. Чтобы проверить правильность установки программы APF 2 , отправьте пакеты ping на тестируемое устройство.

Логика программы АПФ 2 следующая:

  1. Удалить и увеличить счетчик:
    1. Значения EtherType: 0x88A2 , 0x88A4 , 0x88B8 , 0x88CD , 0x88E1 , 0x88E3
    2. IPv4 DHCP обнаруживает или запрашивает пакеты
    3. RS-пакеты
  2. Счетчик сброса и увеличения: пакеты запросов ICMP ping
  3. Пройти и увеличить счетчик: Все остальные пакеты

Коды 2-байтовой программы APF следующие:

6BF0B03A01B86BF8AA0FB86BF4AA09B8120C6BEC7C007488A27C006F88A47C006A88B87C006588CD7C006088E17C005B88E3120C84002008001A1A821B001A1E8600000010FFFFFFFF0A17820B11AB0D2A108204436BE87234120C84000E86DD0A1482093A0A368204856BE0721F120C84001008000A17820B01AB0D220E8204086BE472086BDCB03A01B87206B03A01B87201
Проверка данных

Чтобы убедиться, что программа APF выполняется и пакеты передаются или отбрасываются правильно, выполните следующие действия:

  • Извлекайте и проверяйте регион данных APF каждые 5 минут.
  • Не очищайте счетчик.
  • Сгенерируйте тестовые пакеты для запуска каждого правила фильтра.
  • Проверьте приращение счетчика, используя следующие области памяти:

    Имя счетчика Расположение памяти
    DROPPED_ETHERTYPE_DENYLISTED [Размер ОЗУ Apf - 20, Размер ОЗУ Apf - 16]
    DROPPED_DHCP_REQUEST_DISCOVERY [Размер ОЗУ Apf - 24, Размер ОЗУ Apf - 20]
    DROPPED_ICMP4_ECHO_REQUEST [Размер ОЗУ Apf - 28, Размер ОЗУ Apf - 24]
    DROPPED_RS [Размер ОЗУ Apf - 32, Размер ОЗУ Apf - 28]
    PASSED_PACKET [Размер ОЗУ Apf - 36, Размер ОЗУ Apf - 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
,

Android Packet Filter (APF) позволяет фреймворку управлять логикой фильтрации пакетов оборудования во время выполнения. Это позволяет системе экономить электроэнергию, отбрасывая пакеты на оборудовании, в то же время позволяя фреймворку Android изменять правила фильтрации во время выполнения на основе сетевых условий.

Обзор АПФ

АПФ состоит из двух основных компонентов:

  • Интерпретатор APF работает на сетевом оборудовании (обычно на чипсете Wi-Fi). Интерпретатор APF запускает байт-код APF на пакетах, полученных оборудованием, и решает, принимать ли их, отбрасывать или отвечать на них.
  • Код генерации программы APF выполняется на главном процессоре. Код создает и обновляет программы APF в соответствии с состоянием сети и устройства.

Методы Wi-Fi HAL позволяют платформе Android устанавливать байт-код программы APF и считывать текущие счетчики. Модуль Network Stack Mainline может обновлять байт-код программы APF в любое время, пока APF работает.

Реализовано несколько фильтров APF. Например, APF включает фильтры для отбрасывания запрещенных ethertypes, фильтрации пакетов IPv6 router advertising (RA), фильтрации многоадресного и широковещательного трафика, если многоадресная блокировка не удерживается, отбрасывания пакетов DHCP для других хостов и отбрасывания пакетов unsolicited address resolution protocol (ARP) и neighbor discovery (ND). Если прошивка поддерживает APFv6, ApfFilter также генерирует правила для ответа на распространенные типы пакетов, которые в противном случае потребовали бы пробуждения ЦП для ответа, такие как запросы ARP и запросы NS. Полный список фильтров определен в ApfFilter .

Поскольку код генерации программы APF является частью модуля сетевого стека, вы можете использовать ежемесячные обновления [Mainline] для добавления новых фильтров и обновления логики фильтрации.

пересмотр АПФ

В следующем списке описывается история изменений APF:

  • APFv6: эта версия, представленная в Android 15, поддерживает фильтрацию пакетов, включает счетчики для отладки и метрик, а также поддерживает передачу пакетов.
  • APFv4: эта версия, представленная в Android 10, поддерживает фильтрацию пакетов и включает счетчики для отладки и метрик.
  • APFv2: эта версия, представленная в Android 7, поддерживает фильтрацию пакетов.

Интеграция АПФ

API APF между интерпретатором APF и оборудованием определены в apf_interpreter.h ( APFv4 , APFv6 ). Код прошивки Wi-Fi вызывает accept_packet() в APFv4 или apf_run() в APFv6, чтобы определить, следует ли отбросить пакет (нулевое возвращаемое значение) или передать его процессору приложения (ненулевое возвращаемое значение). Если пакет необходимо передать, apf_run() также возвращает ноль, поскольку его пакет не нужно передавать процессору приложения. Если прошивка поддерживает APFv6, она должна реализовать API apf_allocate_buffer() и apf_transmit_buffer() . Интерпретатор APF вызывает эти два API во время логики передачи пакетов. Инструкции 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 КБ, тогда как более сложный интерпретатор APFv6 с дополнительными функциями (например, собственной поддержкой контрольных сумм и собственным кодом распаковки DNS) занимает около 4 КБ.

Фильтры APF могут работать вместе с другими фильтрами, специфичными для поставщика чипсета, в рамках прошивки. Поставщики чипсетов могут выбрать запуск своей логики фильтрации до или после процесса фильтрации APF. Если пакет отбрасывается до достижения фильтра APF, фильтр APF не обрабатывает пакет.

Для обеспечения корректной работы фильтра APF при включенном APF прошивка должна предоставлять фильтру APF доступ ко всему пакету, а не только к заголовку, когда APF включен.

Образцы программ APF

ApfTest и ApfFilterTest содержат примеры тестовых программ, которые иллюстрируют, как работает каждый фильтр APF. Чтобы изучить фактическую сгенерированную программу, измените тестовый случай, чтобы распечатать программу в виде шестнадцатеричной строки.

Папка testdata содержит примеры программ APFv4 для фильтров APF RA. Папка 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.

Вот пример передачи одного пакета в 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; изменять область памяти APF разрешено только коду интерпретатора или коду фреймворка (через API HAL).
  • Проблемы установки с программами APF из X байт (X <= maxLen ): Прошивка должна поддерживать чтение или запись любой длины программы до maxLen без сбоев, сбоев или усечения. Записи не должны изменять никакие байты между X и maxLen .
  • Реализация APF в коде драйвера: APF следует реализовывать только в прошивке, а не в коде драйвера. В противном случае нет преимуществ энергосбережения, поскольку ЦП должен просыпаться для обработки пакета.
  • Неправильные значения 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 Мбит/с.
  • Усеченные пакеты, переданные в accept_packet() или apf_run() : Все одноадресные, широковещательные и многоадресные пакеты, переданные в accept_packet() или apf_run() должны быть полными. Передача усеченных пакетов в APF недопустима.

Тесты АПФ

Начиная с Android 15, Android предоставляет как одно-, так и многоустройственные тестовые случаи CTS для интеграции фильтра APF и интерпретатора APF, чтобы гарантировать правильную функциональность APF. Вот разбивка цели каждого тестового случая:

  • Тест интеграции ApfFilter и apf_interpreter : проверяет, что ApfFilter генерирует правильный байт-код, а apf_interpreter правильно выполняет код для получения ожидаемых результатов.
  • APF single-device CTS : использует одно устройство для проверки функциональности APF на чипсете Wi-Fi. Подтверждает, что:
    • APF включается, когда экран выключен, а скорость Wi-Fi-трафика ниже 10 Мбит/с.
    • Возможности APF заявлены правильно.
    • Операции чтения и записи в области памяти APF выполняются успешно, и область памяти не подвергается неожиданным изменениям.
    • Аргументы правильно передаются в accept_packet() или apf_run() .
    • Прошивка, интегрированная с APFv4/APFv6, может отбрасывать пакеты.
    • Интегрированная с APFv6 прошивка может отвечать на пакеты.
  • APF multi-device CTS : использует два устройства (один отправитель, один получатель) для проверки поведения фильтрации APF. На стороне отправителя генерируются различные типы пакетов, и тест подтверждает, правильно ли они отбрасываются, передаются или на них отвечают на основе правил, настроенных в ApfFilter .

Дополнительные инструкции по интеграционному тестированию

Кроме того, мы настоятельно рекомендуем поставщикам чипсетов включать тестирование APF в свои собственные наборы тестов интеграции Wi-Fi в прошивку.

Интеграция тестирования APF в тестовые наборы для интеграции Wi-Fi-прошивки имеет решающее значение для проверки правильной функциональности APF в сложных сценариях подключения Wi-Fi, таких как сценарии подключения «сделай перед разрывом» или «роуминг» Wi-Fi. Подробные инструкции по выполнению интеграционных тестов можно найти в следующем разделе.

Предпосылки

При проведении интеграционных тестов выполните следующие действия:

  • APF должен быть включен во всех тестовых случаях интеграции (например, роуминг, включение-выключение).
  • В начале каждого теста очищайте память APF.
  • Устанавливайте или переустанавливайте программы APF каждые 5 минут во время теста.

Тестовые сценарии

APF должен быть активен во время интеграционных тестов. В этом документе приведены две программы APF, которые можно установить во время тестирования. Программы находятся в формате шестнадцатеричной строки, и тестер должен преобразовать шестнадцатеричную строку в двоичную и установить их в прошивку, чтобы программы могли выполняться apf_interpreter . Во время интеграционного теста тестер должен отправлять пакеты, которые, как ожидается, вызовут логику фильтрации в программе 1 и программе 2.

Программа АПФ 1

Когда экран устройства включен, установите программу APF 1. Эта программа может отбрасывать безвредные пакеты, которые не влияют на функциональность устройства. Эти пакеты используются для проверки того, правильно ли APF фильтрует сетевой трафик.

Логика программы АПФ 1 следующая:

  1. Удалить и увеличить счетчик:
    1. Значения EtherType: 0x88A2 , 0x88A4 , 0x88B8 , 0x88CD , 0x88E1 , 0x88E3
    2. IPv4 DHCP обнаруживает или запрашивает пакеты
    3. RS-пакеты
  2. Пройти и увеличить счетчик: Все остальные пакеты.

1-байтовые коды программы APF следующие:

6BF0B03A01B86BF8AA0FB86BF4AA09B8120C6BEC7C005D88A27C005888A47C005388B87C004E88CD7C004988E17C004488E3120C84002008001A1A821B001A1E8600000010FFFFFFFF0A17820B11AB0D2A108204436BE8721D120C84000E86DD0A1482093A0A368204856BE072086BDCB03A01B87206B03A01B87201
Программа АПФ 2

Когда экран устройства выключен, установите программу APF 2. Эта программа отфильтровывает все пакеты, которые фильтрует программа APF 1 , а также пакеты запросов ping. Чтобы проверить правильность установки программы APF 2 , отправьте пакеты ping на тестируемое устройство.

Логика программы АПФ 2 следующая:

  1. Удалить и увеличить счетчик:
    1. Значения EtherType: 0x88A2 , 0x88A4 , 0x88B8 , 0x88CD , 0x88E1 , 0x88E3
    2. IPv4 DHCP обнаруживает или запрашивает пакеты
    3. RS-пакеты
  2. Счетчик сброса и увеличения: пакеты запросов ICMP ping
  3. Пройти и увеличить счетчик: Все остальные пакеты

Коды 2-байтовой программы APF следующие:

6BF0B03A01B86BF8AA0FB86BF4AA09B8120C6BEC7C007488A27C006F88A47C006A88B87C006588CD7C006088E17C005B88E3120C84002008001A1A821B001A1E8600000010FFFFFFFF0A17820B11AB0D2A108204436BE87234120C84000E86DD0A1482093A0A368204856BE0721F120C84001008000A17820B01AB0D220E8204086BE472086BDCB03A01B87206B03A01B87201
Проверка данных

Чтобы убедиться, что программа APF выполняется и пакеты передаются или отбрасываются правильно, выполните следующие действия:

  • Извлекайте и проверяйте регион данных APF каждые 5 минут.
  • Не очищайте счетчик.
  • Сгенерируйте тестовые пакеты для запуска каждого правила фильтра.
  • Проверьте приращение счетчика, используя следующие области памяти:

    Имя счетчика Расположение памяти
    DROPPED_ETHERTYPE_DENYLISTED [Размер ОЗУ Apf - 20, Размер ОЗУ Apf - 16]
    DROPPED_DHCP_REQUEST_DISCOVERY [Размер ОЗУ Apf - 24, Размер ОЗУ Apf - 20]
    DROPPED_ICMP4_ECHO_REQUEST [Размер ОЗУ Apf - 28, Размер ОЗУ Apf - 24]
    DROPPED_RS [Размер ОЗУ Apf - 32, Размер ОЗУ Apf - 28]
    PASSED_PACKET [Размер ОЗУ Apf - 36, Размер ОЗУ Apf - 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