Filtro de paquetes de Android

El filtro de paquetes de Android (APF) permite que el framework controle la lógica de filtrado de paquetes de hardware en el tiempo de ejecución. Esto permite que el sistema ahorre energía descartando paquetes en el hardware, mientras que el framework de Android puede cambiar las reglas de filtrado en el tiempo de ejecución según las condiciones de la red.

Descripción general de APF

APF consta de dos componentes principales:

  • El intérprete de APF se ejecuta en el hardware de red (por lo general, el chipset de Wi-Fi). El intérprete de APF ejecuta el código de bytes de APF en los paquetes que recibe el hardware y decide si los acepta, los descarta o responde a ellos.
  • El código de generación del programa APF se ejecuta en la CPU principal. El código crea y actualiza programas APF según el estado de la red y del dispositivo.

Los métodos HAL de Wi-Fi permiten que el framework de Android instale el código de bytes del programa APF y lea los contadores actuales. El módulo de Mainline de la pila de red puede actualizar el código de bytes del programa APF en cualquier momento mientras se ejecuta APF.

Se implementaron varios filtros de APF. Por ejemplo, APF incluye filtros para descartar tipos de Ethernet no permitidos, filtrar paquetes de anuncio de router (RA) de IPv6, filtrar tráfico de transmisión y multidifusión si no se mantiene el bloqueo de multidifusión, descartar paquetes DHCP para otros hosts y descartar paquetes de protocolo de resolución de direcciones (ARP) y descubrimiento de vecinos (ND) no solicitados. Si el firmware admite APFv6, ApfFilter también genera reglas para responder a tipos de paquetes comunes que, de lo contrario, requerirían que la CPU se active para responder, como las consultas ARP y las consultas NS La lista completa de filtros se define en ApfFilter.

Debido a que el código de generación del programa APF forma parte del módulo de la pila de red, puedes usar las actualizaciones mensuales de Mainline para agregar filtros nuevos y actualizar la lógica de filtrado.

Revisión de APF

En la siguiente lista, se describe el historial de revisiones de APF:

  • APFv6: Presentada en Android 15, esta versión admite el filtrado de paquetes, incluye contadores para la depuración y las métricas, y admite la transmisión de paquetes.
  • APFv4: Presentada en Android 10, esta versión admite el filtrado de paquetes y incluye contadores para la depuración y las métricas.
  • APFv2: Presentada en Android 7, esta versión admite el filtrado de paquetes.

Integración de APF

Las APIs de APF entre el intérprete de APF y el hardware se definen en apf_interpreter.h (APFv4, APFv6). El código de firmware de Wi-Fi llama a accept_packet() en APFv4 o apf_run() en APFv6 para determinar si se debe descartar el paquete (valor de retorno cero ) o pasarlo al procesador de la app (valor de retorno distinto de cero). Si se debe transmitir un paquete, apf_run() también muestra cero porque no es necesario pasarlo al procesador de la app. Si el firmware admite APFv6, debe implementar las APIs apf_allocate_buffer() y apf_transmit_buffer(). El intérprete de APF llama a estas dos APIs durante la lógica de transmisión de paquetes. Las instrucciones de APF tienen una longitud variable. Cada instrucción tiene al menos 1 byte de longitud. Los códigos de instrucción de APF se definen en apf.h para APFv4 y se insertan directamente en apf_interpreter.c para APFv6.

APF se basa en la memoria dedicada. La memoria se usa para el programa APF en sí y para el almacenamiento de datos, y el chipset no debe borrarla ni escribirla, excepto a través de los métodos HAL de APF. El código de bytes de APF usa el almacenamiento de datos para almacenar contadores de paquetes aceptados y descartados. Puedes leer la región de datos desde el framework de Android. Las instrucciones de APF son eficientes en cuanto a la memoria, pero maximizar su potencial de ahorro de energía y funcionalidad exige reglas de filtrado complejas y dinámicas. Esta complejidad requiere una parte dedicada de la memoria en el chipset. El requisito mínimo de memoria para APFv4 es de 1,024 bytes, mientras que APFv6 requiere 2,048 bytes. Sin embargo, te recomendamos que asignes 4,096 bytes para APFv6 para verificar el rendimiento óptimo. El intérprete de APF debe compilarse en el firmware. Los intérpretes de APFv4 y APFv6 están optimizados para el tamaño del código. En la arquitectura arm32, el intérprete de APFv4 compilado es de alrededor de 1.8 KB, mientras que el intérprete de APFv6 más complejo, con funciones agregadas (por ejemplo, compatibilidad integrada con suma de comprobación y código de descompresión de DNS integrado), es de aproximadamente 4 KB.

Los filtros de APF pueden funcionar junto con otros filtros específicos del proveedor del chipset dentro del firmware. Puedes elegir ejecutar tu lógica de filtrado antes o después del proceso de filtrado de APF. Si se descarta un paquete antes de llegar al filtro de APF, el filtro de APF no lo procesa.

Para verificar la funcionalidad correcta del filtro de APF, cuando APF esté activado, verifica que el firmware proporcione al filtro de APF acceso a todo el paquete, no solo al encabezado.

Ejemplos de programas APF

ApfTest y ApfFilterTest contienen programas de prueba de muestra que ilustran cómo funciona cada filtro de APF. Para estudiar el programa generado real, modifica el caso de prueba para imprimir el programa como una cadena hexadecimal.

La carpeta testdata contiene programas APFv4 de muestra para filtros RA de APF. La carpeta samples contiene utilidades de Python que generan programas de descarga de APFv6. Para obtener más detalles, consulta la documentación en los archivos de utilidad de Python.

Depurar APF

Para verificar si APF está habilitado en tu dispositivo, muestra el programa actual, muestra los contadores actuales y ejecuta el comando adb shell dumpsys network_stack. El siguiente es un ejemplo de este comando:

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

El resultado de este ejemplo de comando adb shell dumpsys network_stack incluye lo siguiente:

  • ApfCapabilities{version: 4, maxSize: 4096, format: 1}: Esto significa que los chips de Wi-Fi admiten APF (versión 4).
  • Last program: Esta sección es el programa APF binario instalado más reciente en formato de cadena hexadecimal.
  • APF packet counters: En esta sección, se muestra cuántos paquetes pasa o descarta APF y los motivos específicos.

Para decodificar y desensamblar el código en lenguaje ensamblador legible por humanos, usa la apf_disassembler herramienta. Para compilar el objeto binario ejecutable, ejecuta el comando m apf_disassembler. El siguiente es un ejemplo de cómo usar la herramienta 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
......

Para verificar los resultados de APF sin conexión, usa la apf_run herramienta. Para compilar el objeto binario ejecutable, ejecuta el comando m apf_run. La herramienta apf_run admite intérpretes de APFv4 y APFv6.

El siguiente es el manual del comando apf_run. De forma predeterminada, el comando apf_run se ejecuta en el intérprete de APFv4. Si pasas el argumento --v6 a apf_run, se ejecutará en el intérprete de APFv6. Todos los demás argumentos se pueden usar para APFv4 y 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.

Aquí tienes un ejemplo para pasar un paquete a APF y verificar si se puede descartar o pasar.

Para proporcionar la presentación de cadena binaria hexadecimal del paquete sin procesar, usa la opción --packet. Para proporcionar la cadena binaria hexadecimal de la región de datos, que es usada para almacenar el contador de APF, usa la --data opción. Debido a que cada contador tiene 4 bytes de longitud, las regiones de datos deben ser lo suficientemente largas para garantizar que no se produzca un desbordamiento del búfer.

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

Para verificar los resultados de APF en el archivo pcap que tomó tcpdump, usa el comando apf_run de la siguiente manera:

out/host/linux-x86/bin/apf_run --program 6bfcb03a01b8120c6b989401df06006b947c01d888a27c01d388a47c01ce88b87c01c988cd7c01c488e17c01bf88e384004408066a0e6bdca401a5000600010800060412147a1e016bd884019900021a1c6b907c01960000686bd4a401820006ffffffffffff6a266bc0a4017b0004c0a82b056bf874017084005f08000a17821f1112149c00181fffab0d2a108211446a3239a20506fabe589435936bf47401470a1e52f06bb07c014200e06bb81a1e7e00000135ffffffff6bb47e0000012ac0a82bff6be868a401160006ffffffffffff6bbc7401176bf074010c7c001086dd686bd0a2fb06ffffffffffff6bcc72fd0a147a0b3a6b9c0a267af1ff6be072e70a366bac7ae6858218886a26a2040fff02000000000000000000000000006ba872cbaa0e82be8eaa0f8c00b7025868a2a40ffabe5894359352a9874d08aa86dd606a12a2792600583afffe80000000000000f7d4e8ccd81ddb43fe80000000000000f8be58fffe94359386006a3aa272024108123c94006b02586a3ea25e0800000000000000006a56a25504030440c01a5a94004e02581a5e94004702586a62a23e04000000006a66a229102409891f9a26ae6d00000000000000006a76a22004190300001a7a94001902586a7ea204102409891f9a26ae6dba98e781ca9ef9ba6bc872086be4b03a01b87206b03a01b87201 --pcap apf.pcap --data 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
37 packets dropped
1733 packets passed
Data: 00000000000000000000000000000000000000000200000005000000000000000000000002000000000000001b000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000689000000000000003c00000000000000000000000000000000000006ea

Para probar las capacidades de transmisión de APFv6, usa el comando apf_run de la siguiente manera:

$ 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

Cuando usas el parámetro --trace, la herramienta apf_run proporciona un resultado detallado de cada paso en la ejecución del intérprete, lo que es útil para la depuración. En este ejemplo, ingresas un paquete de consulta ARP en el programa APF. El resultado muestra que se descarta la consulta ARP, pero se genera un paquete de respuesta. Los detalles de este paquete generado se muestran en la sección transmitted packet.

Problemas comunes de integración

En esta sección, se destacan varios problemas comunes que se encuentran durante la integración de APF:

  • Borrado inesperado de la región de datos: La memoria de APF debe estar completamente dedicada a APF; solo el código del intérprete o el código del framework (a través de la API de HAL) pueden modificar la región de memoria de APF.
  • Problemas de instalación con programas APF de X bytes (X <= maxLen): El firmware debe admitir la lectura o escritura de cualquier longitud de programa hasta maxLen sin fallas, bloqueos ni truncamiento. Las escrituras no deben alterar ningún byte entre X y maxLen.
  • Implementación de APF en el código del controlador: APF solo debe implementarse dentro del firmware, no del código del controlador. De lo contrario, no hay beneficios de ahorro de energía porque la CPU debe activarse para procesar el paquete.
  • Valores filter_age o filter_age_16384th incorrectos: Los filter_age (APFv4) y filter_age_16384th (APFv6) deben pasarse correctamente a las funciones accept_packet() y apf_run(). Para obtener detalles sobre el cálculo de filter_age_16384th, consulta la documentación en apf_interpreter.h.
  • APF no habilitado cuando es necesario: APF debe habilitarse cuando la pantalla está apagada y el vínculo Wi-Fi está inactivo o el tráfico es inferior a 10 Mbps.
  • Paquetes truncados pasados a accept_packet() o apf_run(): Todos los paquetes de transmisión, multidifusión y unidifusión pasados a accept_packet() o apf_run() deben estar completos. No es válido pasar paquetes truncados a APF.

Pruebas de APF

A partir de Android 15, Android proporciona casos de prueba de Compatibility Test Suite (CTS) de un solo dispositivo y de varios dispositivos para la integración del filtro de APF y el intérprete de APF para verificar la funcionalidad correcta de APF. A continuación, se detalla el propósito de cada caso de prueba:

  • Prueba de integración de ApfFilter y apf_interpreter: Verifica que ApfFilter genere el código de bytes correcto y que apf_interpreter ejecute el código correctamente para producir los resultados esperados.
  • **CTS de un solo dispositivo de APF**: Usa un solo dispositivo para probar la funcionalidad de APF en el chipset de Wi-Fi. Confirma lo siguiente:
    • APF se activa cuando la pantalla está apagada y el tráfico de Wi-Fi es inferior a 10 Mbps.
    • Las capacidades de APF se declaran correctamente.
    • Las operaciones de lectura y escritura en la región de memoria de APF se realizan correctamente, y la región de memoria no se modifica de forma inesperada.
    • Los argumentos se pasan correctamente a accept_packet() o apf_run().
    • El firmware integrado con APFv4/APFv6 puede descartar paquetes.
    • El firmware integrado con APFv6 puede responder a los paquetes.
  • CTS de varios dispositivos de APF: Emplea dos dispositivos (un emisor y un receptor) para probar el comportamiento de filtrado de APF. Se generan varios tipos de paquetes en el lado del emisor, y la prueba confirma si se descartan, pasan o responden correctamente según las reglas configuradas en ApfFilter para verificar la funcionalidad correcta de APF.

Instrucciones adicionales para la prueba de integración

Además, te recomendamos que incorpores pruebas de APF en tus conjuntos de pruebas de integración de Wi-Fi de firmware.

Integrar las pruebas de APF en los conjuntos de pruebas de integración de Wi-Fi de firmware es fundamental para verificar la funcionalidad adecuada de APF en situaciones complejas de conexión Wi-Fi, como situaciones de conexión Wi-Fi de tipo make-before-break o roaming. En la siguiente sección, se pueden encontrar instrucciones detalladas para realizar pruebas de integración.

Requisitos previos

Cuando realices pruebas de integración, haz lo siguiente:

  • APF debe estar habilitado en todos los casos de prueba de integración (por ejemplo, roaming, make-before-break).
  • Al comienzo de cada prueba, borra la memoria de APF.
  • Instala o vuelve a instalar programas APF cada 5 minutos durante la prueba.

Situaciones de prueba

APF debe estar activo durante las pruebas de integración. En este documento, se proporcionan dos programas APF que puedes instalar durante las pruebas. Los programas están en formato de cadena hexadecimal, y debes convertir la cadena hexadecimal en binaria y, luego, instalar los programas en el firmware para que apf_interpreter pueda ejecutarlos. Durante la prueba de integración, debes enviar paquetes que se espera que activen la lógica de filtrado en el programa 1 y el programa 2.

Programa 1 de APF

Cuando la pantalla del dispositivo esté encendida, instala el programa 1 de APF. Este programa puede descartar paquetes inofensivos que no afectan la funcionalidad del dispositivo. Estos paquetes se usan para probar si APF filtra correctamente el tráfico de red.

La lógica del programa 1 de APF es la siguiente:

  1. Descartar y aumentar el contador:
    1. Valores de EtherType: 0x88A2, 0x88A4, 0x88B8, 0x88CD, 0x88E1, 0x88E3
    2. Paquetes de detección o solicitud de DHCP de IPv4
    3. Paquetes RS
  2. Pasar y aumentar el contador: Todos los demás paquetes.

Los códigos de bytes del programa 1 de APF son los siguientes:

6BF0B03A01B86BF8AA0FB86BF4AA09B8120C6BEC7C005D88A27C005888A47C005388B87C004E88CD7C004988E17C004488E3120C84002008001A1A821B001A1E8600000010FFFFFFFF0A17820B11AB0D2A108204436BE8721D120C84000E86DD0A1482093A0A368204856BE072086BDCB03A01B87206B03A01B87201
Programa 2 de APF

Cuando la pantalla del dispositivo esté apagada, instala el programa 2 de APF. Este programa filtra todos los paquetes que filtra el programa 1 de APF, así como los paquetes de solicitud de ping. Para verificar que el programa 2 de APF esté instalado correctamente, envía paquetes de ping al dispositivo en prueba.

La lógica del programa 2 de APF es la siguiente:

  1. Descartar y aumentar el contador:
    1. Valores de EtherType: 0x88A2, 0x88A4, 0x88B8, 0x88CD, 0x88E1, 0x88E3
    2. Paquetes de detección o solicitud de DHCP de IPv4
    3. Paquetes RS
  2. Descartar y aumentar el contador: Paquetes de solicitud de ping ICMP
  3. Pasar y aumentar el contador: Todos los demás paquetes

Los códigos de bytes del programa 2 de APF son los siguientes:

6BF0B03A01B86BF8AA0FB86BF4AA09B8120C6BEC7C007488A27C006F88A47C006A88B87C006588CD7C006088E17C005B88E3120C84002008001A1A821B001A1E8600000010FFFFFFFF0A17820B11AB0D2A108204436BE87234120C84000E86DD0A1482093A0A368204856BE0721F120C84001008000A17820B01AB0D220E8204086BE472086BDCB03A01B87206B03A01B87201
Verificación de datos

Para verificar que el programa APF se ejecute y pase o descarte paquetes correctamente, haz lo siguiente:

  • Recupera y verifica la región de datos de APF cada 5 minutos.
  • No borres el contador.
  • Genera paquetes de prueba para activar cada regla de filtro.
  • Verifica los aumentos del contador con estas ubicaciones de memoria:

    Nombre del contador Ubicación de la memoria
    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]

Pseudocódigo para el programa 1 de APF y el programa 2 de APF

En el siguiente pseudocódigo, se explica la lógica del programa 1 de APF y el programa 2 de APF en detalle:

// 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