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 hastamaxLen
sin fallas, fallas ni truncamientos. Las operaciones de escritura no deben alterar ningún byte entreX
ymaxLen
. - 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
ofilter_age_16384th
: Los valores defilter_age
(APFv4) yfilter_age_16384th
(APFv6) se deben pasar correctamente a las funcionesaccept_packet()
yapf_run()
. Para obtener detalles sobre el cálculo defilter_age_16384th
, consulta la documentación deapf_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()
oapf_run()
: Todos los paquetes unicast, de transmisión y multicast que se pasan aaccept_packet()
oapf_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
yapf_interpreter
: Verifica queApfFilter
genere el código de bytes correcto y queapf_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()
oapf_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:
- Disminuye y aumenta el contador:
- Valores de EtherType:
0x88A2
,0x88A4
,0x88B8
,0x88CD
,0x88E1
y0x88E3
- Paquetes de detección o solicitud de DHCP IPv4
- Paquetes RS
- Valores de EtherType:
- 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:
- Disminuye y aumenta el contador:
- Valores de EtherType:
0x88A2
,0x88A4
,0x88B8
,0x88CD
,0x88E1
y0x88E3
- Paquetes de detección o solicitud de DHCP IPv4
- Paquetes RS
- Valores de EtherType:
- Eliminación y aumento del contador: paquetes de solicitud de ping ICMP
- 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