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, a la vez que permite que el framework de Android cambie las reglas de filtrado durante el tiempo de ejecución según las condiciones de la red.

Descripción general de APF

El APF consta de dos componentes principales:

  • El intérprete de APF se ejecuta en hardware de red (por lo general, el chipset 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 aceptarlos, descartarlos o responderlos.
  • El código de generación de programas de APF se ejecuta en la CPU principal. El código crea y actualiza los programas de APF según el estado de la red y del dispositivo.

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

Se implementaron varios filtros de APF. Por ejemplo, el APF incluye filtros para descartar los tipos de Ethernet no permitidos, filtrar los paquetes de anuncio de router (RA) IPv6, filtrar el tráfico multicast y de transmisión si no se mantiene el bloqueo multicast, descartar los paquetes de DHCP para otros hosts y descartar los paquetes de protocolo de resolución de direcciones (ARP) y de 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 otro modo, requerirían que la CPU se active para responder, como las consultas de ARP y NS. La lista completa de filtros se define en ApfFilter.

Debido a que el código de generación de programas de APF forma parte del módulo de pila de red, puedes usar las [actualizaciones de Mainline mensuales 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: Esta versión, que se introdujo en Android 15, admite el filtrado de paquetes, incluye contadores para la depuración y las métricas, y admite la transmisión de paquetes.
  • APFv4: Se introdujo en Android 10. Esta versión admite el filtrado de paquetes y, además, incluye contadores para la depuración y las métricas.
  • APFv2: Esta versión, que se introdujo en Android 7, 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 a apf_run() en APFv6 para determinar si se debe descartar el paquete (valor que se muestra como cero) o pasarlo al procesador de la app (valor que no es cero). Si se necesita transmitir un paquete, apf_run() también muestra cero porque su paquete no se necesita pasar al procesador de la app. Si el firmware admite APFv6, debe implementar las APIs de 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 son de 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 intercalan directamente dentro de apf_interpreter.c para APFv6.

El APF se basa en la memoria dedicada. La memoria se usa tanto para el programa de APF como para el almacenamiento de datos, y el chipset no debe borrarla ni escribirla, excepto a través de los métodos de HAL de APF. El código de bytes de APF usa el almacenamiento de datos para almacenar contadores de paquetes aceptados y descartados. La región de datos se puede leer desde el framework de Android. Las instrucciones de APF son eficientes en términos de memoria, pero maximizar su potencial de ahorro de energía y funcionalidad requiere reglas de filtrado complejas y dinámicas. Esta complejidad requiere una parte dedicada de la memoria del 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 4096 bytes para APFv6 para garantizar un rendimiento óptimo. El intérprete de APF se debe compilar 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 compilado de APFv4 es de alrededor de 1.8 KB, mientras que el intérprete más complejo de APFv6, con funciones agregadas (por ejemplo, compatibilidad con sumas de comprobación nativas y código de descompresión de DNS nativo), es de aproximadamente 4 KB.

Los filtros de APF pueden funcionar junto con otros filtros específicos del proveedor del chipset dentro del firmware. Los proveedores de conjuntos de chips pueden elegir ejecutar su 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, este no lo procesará.

Para garantizar la funcionalidad correcta del filtro de APF, cuando este está activado, el firmware debe proporcionarle acceso al paquete completo, no solo al encabezado, cuando está habilitado.

Ejemplos de programas de 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 imprimirlo como una cadena hexadecimal.

La carpeta testdata contiene programas APFv4 de muestra para filtros de 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.

Cómo depurar APF

Para verificar si la APF está habilitada en el 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 Wi-Fi admiten APF (versión 4).
  • Last program: Esta sección es el programa binario de APF 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 desarmar el código en lenguaje ensamblador legible por humanos, usa la herramienta apf_disassembler. 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 herramienta apf_run. Para compilar el objeto binario ejecutable, ejecuta el comando m apf_run. La herramienta apf_run admite intérpretes 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 APFv4. Pasar el argumento --v6 a apf_run le permite ejecutarse 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.

Este es un ejemplo para pasar un paquete al APF para 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 se usa para almacenar el contador de APF, usa --data option. 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 toma 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, ingresamos un paquete de consulta de ARP en el programa APF. El resultado muestra que se descarta la consulta de 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 de APF de X bytes (X <= maxLen): El firmware debe admitir la lectura o escritura de cualquier longitud de programa de hasta maxLen sin fallas, fallas ni truncamientos. Las operaciones de escritura no deben alterar ningún byte entre X y maxLen.
  • Implementación de APF en el código del controlador: El APF solo debe implementarse dentro del firmware, no en el 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 incorrectos de filter_age o filter_age_16384th: Los valores de filter_age (APFv4) y filter_age_16384th (APFv6) se deben pasar correctamente a las funciones accept_packet() y apf_run(). Para obtener detalles sobre el cálculo de filter_age_16384th, consulta la documentación de apf_interpreter.h.
  • APF no está habilitado cuando es necesario: El APF debe estar habilitado cuando la pantalla está apagada y el vínculo Wi-Fi está inactivo o el tráfico es inferior a 10 Mbps.
  • Paquetes truncados que se pasan a accept_packet() o apf_run(): Todos los paquetes unicast, de transmisión y multicast que se pasan 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 CTS para un solo dispositivo y varios dispositivos para la integración del filtro y el intérprete de APF para garantizar 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:
    • El 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 declararon 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 en APFv4/APFv6 puede descartar paquetes.
    • El firmware integrado en APFv6 puede responder a los paquetes.
  • CTS multidispositivo de APF: Emplea dos dispositivos (un remitente y un receptor) para probar el comportamiento de filtrado de APF. Se generan varios tipos de paquetes en el lado del remitente, y la prueba confirma si se descartan, pasan o responden correctamente según las reglas configuradas en ApfFilter.

Instrucciones adicionales para la prueba de integración

Además, recomendamos encarecidamente que los proveedores de chipsets incorporen las pruebas de APF en sus propios paquetes de pruebas de integración de Wi-Fi de firmware.

La integración de las pruebas de APF en los paquetes de pruebas de integración de Wi-Fi del 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 conexión antes de la interrupción o de roaming. Puedes encontrar instrucciones detalladas sobre cómo realizar pruebas de integración en la siguiente sección.

Requisitos previos

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

  • El 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 reinstala los programas de APF cada 5 minutos durante la prueba.

Situaciones de prueba

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

Programa de APF 1

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 el APF filtra correctamente el tráfico de red.

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

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

Los códigos de 1 byte del programa 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. Disminuye y aumenta el contador:
    1. Valores de EtherType: 0x88A2, 0x88A4, 0x88B8, 0x88CD, 0x88E1 y 0x88E3
    2. Paquetes de detección o solicitud de DHCP IPv4
    3. Paquetes RS
  2. Eliminación y aumento del contador: paquetes de solicitud de ping ICMP
  3. Pasar y aumentar el contador: Todos los demás paquetes

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

6BF0B03A01B86BF8AA0FB86BF4AA09B8120C6BEC7C007488A27C006F88A47C006A88B87C006588CD7C006088E17C005B88E3120C84002008001A1A821B001A1E8600000010FFFFFFFF0A17820B11AB0D2A108204436BE87234120C84000E86DD0A1482093A0A368204856BE0721F120C84001008000A17820B01AB0D220E8204086BE472086BDCB03A01B87206B03A01B87201
Verificación de datos

Para verificar que se ejecute el programa de APF y que los paquetes se pasen o se descarten 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 incrementos del contador con las siguientes 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 y el programa 2 de APF

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

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