Android 数据包过滤器 (APF) 让框架可以在运行时控制硬件数据包过滤逻辑。这样系统便可以在硬件中丢弃数据包来节省电量,同时允许 Android 框架根据网络状况在运行时更改过滤规则。
APF 概览
APF 由两个主要组件组成
- APF 解释器在网络硬件(通常为无线网络芯片组)上运行。APF 解释器在硬件接收的数据包上运行 APF 字节码,并决定是接受、丢弃还是回复这些数据包。
- APF 程序生成代码在主 CPU 上运行。该代码根据网络和设备状态创建和更新 APF 程序。
无线网络 HAL 方法允许 Android 框架安装 APF 程序字节码并读取当前计数器。网络堆栈主线模块可以在 APF 运行时随时更新 APF 程序字节码。
已实施多个 APF 过滤器。例如,APF 包括用于丢弃不允许的以太网类型、过滤 IPv6 路由器通告 (RA) 数据包、在未持有多播锁定的情况下过滤多播和广播流量、丢弃其他主机的 DHCP 数据包以及丢弃未经请求的地址解析协议 (ARP) 和邻居发现 (ND) 数据包的过滤器。如果固件支持 APFv6,ApfFilter
还会生成规则来回复常见的程序包类型,否则这些类型将需要 CPU 唤醒才能响应,例如 ARP 查询和 NS 查询。过滤器的完整列表在 ApfFilter
中定义。
由于 APF 程序生成代码是网络堆栈模块的一部分,因此您可以使用每月 [主线更新] 来添加新过滤器和更新过滤逻辑。
APF 修订版本
以下列表描述了 APF 的修订历史记录
- APFv6:此版本在 Android 15 中推出,支持数据包过滤,包括用于调试和指标的计数器,并支持数据包传输。
- APFv4:此版本在 Android 10 中推出,支持数据包过滤,并包括用于调试和指标的计数器。
- APFv2:此版本在 Android 7 中推出,支持数据包过滤。
APF 集成
APF 解释器和硬件之间的 APF API 在 apf_interpreter.h
中定义(APFv4、APFv6)。无线网络固件代码在 APFv4 中调用 accept_packet()
或在 APFv6 中调用 apf_run()
,以确定是否应丢弃(零返回值)数据包或将其传递到应用处理器(非零返回值)。如果需要传输数据包,apf_run()
也会返回零,因为其数据包不需要传递到应用处理器。如果固件支持 APFv6,则必须实现 apf_allocate_buffer()
和 apf_transmit_buffer()
API。APF 解释器在数据包传输逻辑期间调用这两个 API。APF 指令是可变长度的。每个指令的长度至少为 1 字节。APF 指令代码在 apf.h
中为 APFv4 定义,并直接在 apf_interpreter.c
中为 APFv6 内联。
APF 依赖于专用内存。该内存既用于 APF 程序本身,也用于数据存储,并且除非通过 APF HAL 方法,否则芯片组不得清除或写入该内存。APF 字节码使用数据存储来存储已接受和丢弃数据包的计数器。可以从 Android 框架读取数据区域。APF 指令具有内存效率,但要最大限度地发挥其节能和功能潜力,则需要复杂的动态过滤规则。这种复杂性需要芯片组上的一块专用内存。APFv4 的最小内存要求为 1024 字节,而 APFv6 则需要 2048 字节。但是,我们强烈建议为 APFv6 分配 4096 字节,以确保最佳性能。APF 解释器必须编译到固件中。APFv4 和 APFv6 解释器都针对代码大小进行了优化。在 arm32 架构下,编译后的 APFv4 解释器约为 1.8 KB,而更复杂的 APFv6 解释器(具有新增功能,例如,原生校验和支持和原生 DNS 解压缩代码)约为 4 KB。
APF 过滤器可以与固件内的其他芯片组供应商特定的过滤器协同工作。芯片组供应商可以选择在 APF 过滤过程之前或之后运行其过滤逻辑。如果数据包在到达 APF 过滤器之前被丢弃,则 APF 过滤器不会处理该数据包。
为了确保 APF 过滤器的功能正确,当 APF 开启时,固件必须为 APF 过滤器提供对整个数据包的访问权限,而不仅仅是标头,当 APF 启用时。
APF 程序示例
ApfTest
和 ApfFilterTest
包含示例测试程序,这些程序说明了每个 APF 过滤器的工作原理。要研究实际生成的程序,请修改测试用例以将程序打印为十六进制字符串。
testdata
文件夹包含用于 APF RA 过滤器的示例 APFv4 程序。samples
文件夹包含生成 APFv6 卸载程序的 Python 实用程序。有关更多详细信息,请参阅 Python 实用程序文件中的文档。
调试 APF
要检查设备上是否启用了 APF,请显示当前程序、显示当前计数器,并运行 adb shell dumpsys network_stack
命令。以下是此命令的示例
adb shell dumpsys network_stack
......
IpClient.wlan0 APF dump:
Capabilities: ApfCapabilities{version: 4, maxSize: 4096, format: 1}
......
Last program:
6bfcb03a01b8120c6b9494026506006b907c025e88a27c025988a47c025488b87c024f88cd7c024a88e17c024588e384004408066a0e6bdca4022b000600010800060412147a1e016bd884021f00021a1c6b8c7c021c0000686bd4a402080006ffffffffffff6a266bbca402010004c0a801eb6bf87401f6120c84005f08000a17821f1112149c00181fffab0d2a108211446a3239a20506c2fc393057dd6bf47401cb0a1e52f06bac7c01c600e06bb41a1e7e000001b9ffffffff6bb07e000001aec0a801ff6be868a4019a0006ffffffffffff6bb874019b6bf07401907c001386dd686bd0a4017d0006ffffffffffff6bc874017e0a147a0e3a6b980a267c017000ff6be07401650a366ba87c016200858219886a26a2050fff02000000000000000000000000006ba4740146aa0e84013700e6aa0f8c0130006068a4011b000f33330000000184c9b26aed4c86dd606a12a2f02600b03afffe8000000000000086c9b2fffe6aed4cff02000000000000000000000000000186006a3aa2e9024000123c92e4606a3ea2d70800000000000000006a56a2ce04030440c01a5a92c9601a5e92c4606a62a2bb04000000006a66a2a6102401fa00049c048400000000000000006a76a29d04030440c01a7a9298601a7e9293606c0082a28904000000006c0086a27310fdfd9ed67950000400000000000000006c0096a2690418033c001a9a9264606c009ea24e102401fa00049c048000000000000000006c00aea24404180330001ab2923f606c00b6a22910fdfd9ed67950000000000000000000006c00c6a21f04190300001aca921a606c00cea20410fdfd9ed67950000400000000000000016bc472086be4b03a01b87206b03a01b87201
APF packet counters:
TOTAL_PACKETS: 469
PASSED_DHCP: 4
PASSED_IPV4: 65
PASSED_IPV6_NON_ICMP: 64
PASSED_IPV4_UNICAST: 64
PASSED_IPV6_ICMP: 223
PASSED_IPV6_UNICAST_NON_ICMP: 6
PASSED_ARP_UNICAST_REPLY: 4
PASSED_NON_IP_UNICAST: 1
DROPPED_RA: 4
DROPPED_IPV4_BROADCAST_ADDR: 7
DROPPED_IPV4_BROADCAST_NET: 27
此示例 adb shell dumpsys network_stack
命令的输出包括以下内容
ApfCapabilities{version: 4, maxSize: 4096, format: 1}
:这意味着 Wi-Fi 芯片支持 APF(版本 4)。Last program
:此部分是以十六进制字符串格式表示的最新安装的 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
要针对 tcpdump 捕获的 pcap 文件检查 APF 结果,请按如下方式使用 apf_run
命令
out/host/linux-x86/bin/apf_run --program 6bfcb03a01b8120c6b989401df06006b947c01d888a27c01d388a47c01ce88b87c01c988cd7c01c488e17c01bf88e384004408066a0e6bdca401a5000600010800060412147a1e016bd884019900021a1c6b907c01960000686bd4a401820006ffffffffffff6a266bc0a4017b0004c0a82b056bf874017084005f08000a17821f1112149c00181fffab0d2a108211446a3239a20506fabe589435936bf47401470a1e52f06bb07c014200e06bb81a1e7e00000135ffffffff6bb47e0000012ac0a82bff6be868a401160006ffffffffffff6bbc7401176bf074010c7c001086dd686bd0a2fb06ffffffffffff6bcc72fd0a147a0b3a6b9c0a267af1ff6be072e70a366bac7ae6858218886a26a2040fff02000000000000000000000000006ba872cbaa0e82be8eaa0f8c00b7025868a2a40ffabe5894359352a9874d08aa86dd606a12a2792600583afffe80000000000000f7d4e8ccd81ddb43fe80000000000000f8be58fffe94359386006a3aa272024108123c94006b02586a3ea25e0800000000000000006a56a25504030440c01a5a94004e02581a5e94004702586a62a23e04000000006a66a229102409891f9a26ae6d00000000000000006a76a22004190300001a7a94001902586a7ea204102409891f9a26ae6dba98e781ca9ef9ba6bc872086be4b03a01b87206b03a01b87201 --pcap apf.pcap --data 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
37 packets dropped
1733 packets passed
Data: 00000000000000000000000000000000000000000200000005000000000000000000000002000000000000001b000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000689000000000000003c00000000000000000000000000000000000006ea
要测试 APFv6 传输功能,请按如下方式使用 apf_run
命令
$ apf_run --program 75001001020304050608060001080006040002AA300E3CAA0FBA06AA09BA07AA08BA086A01BA09120C84006F08066A0EA30206000108000604032B12147A27017A020203301A1C820200032D68A30206FFFFFFFFFFFF020E1A267E000000020A000001032C020B1A267E000000020A000001032CAB24003CCA0606CB0306CB090ACB0306C60A000001CA0606CA1C04AA 0A3A12AA1AAA25FFFF032F020D120C84001708000A1782100612149C00091FFFAB0D2A10820207032A02117C000E86DD68A30206FFFFFFFFFFFF021603190A1482020002187A023A02120A36820285031F8216886A26A2020FFF020000000000000000000000000003200214 --packet FFFFFFFFFFFF112233445566080600010800060400011122334455660A0000020000000000000A0000 01 --data 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 --age 0 --v6 --trace R0 R1 PC Instruction
------------------------------------------------- 0 0 0: data 16, 01020304050608060001080006040002 0 0 19: debugbuf size=3644 0 0 23: ldm r0, m[15] 0 0 25: stdw counter=6, r0 0 0 27: ldm r0, m[9] 0 0 29: stdw counter=7, r0 0 0 31: ldm r0, m[8] 134d811 0 33: stdw counter=8, r0 134d811 0 35: li r0, 1 1 0 37: stdw counter=9, r0 1 0 39: ldh r0, [12] 806 0 41: jne r0, 0x806, 157 806 0 46: li r0, 14 e 0 48: jbseq r0, 0x6, 59, 000108000604 e 0 59: ldh r0, [20] 1 0 61: jeq r0, 0x1, 103 1 0 103: ldw r0, [38] a000001 0 105: jeq r0, 0xa000001, 116 a000001 0 116: allocate 60 a000001 0 120: pktcopy src=6, len=6 a000001 0 123: datacopy src=3, len=6 a000001 0 126: datacopy src=9, len=10 a000001 0 129: datacopy src=3, len=6 a000001 0 132: write 0x0a000001 a000001 0 137: pktcopy src=6, len=6 a000001 0 140: pktcopy src=28, len=4 a000001 0 143: ldm r0, m[10] 2a 0 145: add r0, 18 3c 0 147: stm r0, m[10] 3c 0 149: transmit ip_ofs=255 3c 0 153: drop counter=47 Packet dropped Data: 00000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000100000011d8340100000000000000000000000000000000000000000100000078563412 transmitted packet: 112233445566010203040506080600010800060400020102030405060a0000011122334455660a000002000000000000000000000000000000000000
当您使用 --trace
参数时,apf_run
工具会提供解释器执行中每个步骤的详细输出,这有助于调试。在此示例中,我们将 ARP 查询数据包输入到 APF 程序中。输出显示 ARP 查询被丢弃,但生成了回复数据包。“transmitted packet
”部分显示了此生成的数据包的详细信息。
常见集成问题
本节重点介绍 APF 集成期间遇到的一些常见问题
- 意外的数据区域清除:APF 内存必须完全专用于 APF;只有解释器代码或框架代码(通过 HAL API)才允许修改 APF 内存区域。
- X 字节(X <=
maxLen
)的 APF 程序安装问题:固件必须支持读取或写入任何程序长度(最大为maxLen
),而不会发生故障、崩溃或截断。写入不得更改X
和maxLen
之间的任何字节。 - 驱动程序代码中的 APF 实现:APF 应仅在固件中实现,而不能在驱动程序代码中实现。否则,不会有任何节能优势,因为 CPU 需要唤醒以处理数据包。
- 不正确的
filter_age
或filter_age_16384th
值:filter_age
(APFv4) 和filter_age_16384th
(APFv6) 值必须正确传递给accept_packet()
和apf_run()
函数。有关计算filter_age_16384th
的详细信息,请参阅apf_interpreter.h
中的文档。 - 未在需要时启用 APF:当屏幕关闭且 Wi-Fi 链路空闲或流量低于 10 Mbps 时,必须启用 APF。
- 传递给
accept_packet()
或apf_run()
的截断数据包:传递给accept_packet()
或apf_run()
的所有单播、广播和多播数据包都必须是完整的。将截断的数据包传递到 APF 无效。
APF 测试
从 Android 15 开始,Android 提供了针对 APF 过滤器和 APF 解释器集成的单设备和多设备 CTS 测试用例,以确保 APF 功能正确。以下是每个测试用例的目的细分
ApfFilter
和apf_interpreter
集成测试:验证ApfFilter
生成正确的字节码,并且apf_interpreter
正确执行代码以产生预期的结果。- APF 单设备 CTS:使用单个设备测试 Wi-Fi 芯片组上的 APF 功能。确认
- 当屏幕关闭且 Wi-Fi 流量低于 10 Mbps 时,APF 会开启。
- APF 功能已正确声明。
- 对 APF 内存区域的读取和写入操作成功,并且内存区域未被意外修改。
- 参数已正确传递给
accept_packet()
或apf_run()
。 - 与 APFv4/APFv6 集成的固件可以丢弃数据包。
- 与 APFv6 集成的固件可以回复数据包。
- APF 多设备 CTS:使用两个设备(一个发送方,一个接收方)来测试 APF 的过滤行为。在发送方生成各种类型的数据包,并且测试确认是否根据
ApfFilter
中配置的规则正确丢弃、传递或回复这些数据包。
其他集成测试说明
此外,我们强烈建议芯片组供应商将 APF 测试纳入其自己的固件 Wi-Fi 集成测试套件中。
将 APF 测试集成到固件 Wi-Fi 集成测试套件中对于验证复杂 Wi-Fi 连接场景(例如先断后连或 Wi-Fi 漫游连接场景)中的 APF 功能是否正常至关重要。有关如何执行集成测试的详细说明,请参见以下部分。
先决条件
执行集成测试时,请执行以下操作
- 在所有集成测试用例(例如,漫游、先断后连)中,必须启用 APF。
- 在每个测试开始时,清除 APF 内存。
- 在测试期间,每 5 分钟安装或重新安装 APF 程序。
测试场景
APF 必须在整个集成测试中处于活动状态。本文档中提供了两个 APF 程序,可以在测试期间安装。这些程序采用十六进制字符串格式,测试人员必须将十六进制字符串转换为二进制文件并将其安装到固件中,以便程序可以由 apf_interpreter
执行。在集成测试期间,测试人员应发送预期会触发程序 1 和程序 2 中过滤逻辑的数据包。
APF 程序 1
当设备屏幕开启时,安装APF 程序 1。此程序可以丢弃不会影响设备功能的无害数据包。这些数据包用于测试 APF 是否正确过滤网络流量。
APF 程序 1 逻辑如下
- 丢弃并递增计数器
- EtherType 值:
0x88A2
、0x88A4
、0x88B8
、0x88CD
、0x88E1
、0x88E3
- IPv4 DHCP 发现或请求数据包
- RS 数据包
- EtherType 值:
- 传递并递增计数器:所有其他数据包。
APF 程序 1 字节码如下
6BF0B03A01B86BF8AA0FB86BF4AA09B8120C6BEC7C005D88A27C005888A47C005388B87C004E88CD7C004988E17C004488E3120C84002008001A1A821B001A1E8600000010FFFFFFFF0A17820B11AB0D2A108204436BE8721D120C84000E86DD0A1482093A0A368204856BE072086BDCB03A01B87206B03A01B87201
APF 程序 2
当设备屏幕关闭时,安装APF 程序 2。此程序过滤掉APF 程序 1 过滤的所有数据包以及 ping 请求数据包。要验证APF 程序 2 是否已正确安装,请将 ping 数据包发送到被测设备。
APF 程序 2 逻辑如下
- 丢弃并递增计数器
- EtherType 值:
0x88A2
、0x88A4
、0x88B8
、0x88CD
、0x88E1
、0x88E3
- IPv4 DHCP 发现或请求数据包
- RS 数据包
- EtherType 值:
- 丢弃并递增计数器:ICMP ping 请求数据包
- 传递并递增计数器:所有其他数据包
APF 程序 2 字节码如下
6BF0B03A01B86BF8AA0FB86BF4AA09B8120C6BEC7C007488A27C006F88A47C006A88B87C006588CD7C006088E17C005B88E3120C84002008001A1A821B001A1E8600000010FFFFFFFF0A17820B11AB0D2A108204436BE87234120C84000E86DD0A1482093A0A368204856BE0721F120C84001008000A17820B01AB0D220E8204086BE472086BDCB03A01B87206B03A01B87201
数据验证
要验证 APF 程序是否已执行并且数据包是否已正确传递或丢弃,请执行以下操作
- 每 5 分钟获取并验证 APF 数据区域。
- 不要清除计数器。
- 生成测试数据包以触发每个过滤器规则。
使用以下内存位置验证计数器递增
计数器名称 内存位置 DROPPED_ETHERTYPE_DENYLISTED
[ApfRamSize - 20, ApfRamSize - 16] DROPPED_DHCP_REQUEST_DISCOVERY
[ApfRamSize - 24, ApfRamSize - 20] DROPPED_ICMP4_ECHO_REQUEST
[ApfRamSize - 28, ApfRamSize - 24] DROPPED_RS
[ApfRamSize - 32, ApfRamSize - 28] PASSED_PACKET
[ApfRamSize - 36, ApfRamSize - 32]
APF 程序 1 和 APF 程序 2 的伪代码
以下伪代码详细解释了 APF 程序 1 和 APF 程序 2 的逻辑
// ethertype filter
If the ethertype in [0x88A2, 0x88A4, 0x88B8, 0x88CD, 0x88E1, 0x88E3]:
drop packet and increase counter: DROPPED_ETHERTYPE_DENYLISTED
// dhcp discover/request filter
if ethertype != ETH_P_IP:
skip the filter
if ipv4_src_addr != 0.0.0.0:
skip the filter
if ipv4_dst_addr != 255.255.255.255
skip the filter
if not UDP packet:
skip the filter
if UDP src port is not dhcp request port:
skip the filter
else:
drop the packet and increase the counter: DROPPED_DHCP_REQUEST_DISCOVERY
// Router Solicitation filter:
if ethertype != ETH_P_IPV6:
skip the filter
if not ICMP6 packet:
skip the filter
if ICMP6 type is not a Router Solicitation:
skip the filter
else:
drop the packet and increase the counter: DROPPED_RS
// IPv4 ping filter (only included in Program 2)
if ethertype != ETH_P_IP:
skip the filter
if it ipv4 protocol is not ICMP:
skip the filter
if port is not a ping request port
skip the filter
else:
drop the packet and increase the counter: DROPPED_ICMP4_ECHO_REQUEST
pass the packet and increase: PASSED_PACKET