Android 封包篩選器 (APF) 可讓架構在執行階段控管硬體封包篩選邏輯。這樣一來,系統就能在硬體中捨棄封包,藉此節省電力,同時允許 Android 架構根據網路狀況,在執行階段變更篩選規則。
APF 總覽
APF 包含兩個主要元件:
- APF 解譯器會在網路硬體 (通常是 Wi-Fi 晶片組) 上執行。APF 解譯器會在硬體收到的封包上執行 APF 位元組碼,並決定是否接受、捨棄或回覆這些封包。
- APF 程式產生程式碼會在主要 CPU 上執行。程式碼會根據網路和裝置狀態建立及更新 APF 程式。
Android 架構可透過 Wi-Fi HAL 方法安裝 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)。Wi-Fi 韌體程式碼會呼叫 APFv4 中的 accept_packet()
或 APFv6 中的 apf_run()
,判斷是否應捨棄封包 (傳回值為零),或將封包傳遞至應用程式處理器 (傳回值為非零)。如果封包需要傳輸,apf_run()
也會傳回零,因為封包不需要傳遞至應用程式處理器。如果韌體支援 APFv6,則必須實作 apf_allocate_buffer()
和 apf_transmit_buffer()
API。APF 解譯器會在封包傳輸邏輯期間呼叫這兩個 API。APF 指令的長度不一。每項指令的長度至少為 1 個位元組。APF 指令代碼定義於 APFv4 的 apf.h
,並直接內嵌於 APFv6 的 apf_interpreter.c
。
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 程式範例
ApfTest
和
ApfFilterTest
包含範例測試程式,說明各個 APF 篩選器如何運作。如要研究實際產生的程式,請修改測試案例,將程式列印為十六進位字串。
testdata
資料夾包含 APF RA 篩選器的範例 APFv4 程式。「samples
」資料夾包含 Python 公用程式,可產生 APFv6 卸載程式。詳情請參閱 Python 公用程式檔案中的說明文件。
偵錯 APF
如要檢查裝置是否已啟用 APF,請顯示目前的程式、顯示目前的計數器,然後執行 adb shell dumpsys network_stack
指令。以下是這個指令的範例:
adb shell dumpsys network_stack
......
IpClient.wlan0 APF dump:
Capabilities: ApfCapabilities{version: 4, maxSize: 4096, format: 1}
......
Last program:
6bfcb03a01b8120c6b9494026506006b907c025e88a27c025988a47c025488b87c024f88cd7c024a88e17c024588e384004408066a0e6bdca4022b000600010800060412147a1e016bd884021f00021a1c6b8c7c021c0000686bd4a402080006ffffffffffff6a266bbca402010004c0a801eb6bf87401f6120c84005f08000a17821f1112149c00181fffab0d2a108211446a3239a20506c2fc393057dd6bf47401cb0a1e52f06bac7c01c600e06bb41a1e7e000001b9ffffffff6bb07e000001aec0a801ff6be868a4019a0006ffffffffffff6bb874019b6bf07401907c001386dd686bd0a4017d0006ffffffffffff6bc874017e0a147a0e3a6b980a267c017000ff6be07401650a366ba87c016200858219886a26a2050fff02000000000000000000000000006ba4740146aa0e84013700e6aa0f8c0130006068a4011b000f33330000000184c9b26aed4c86dd606a12a2f02600b03afffe8000000000000086c9b2fffe6aed4cff02000000000000000000000000000186006a3aa2e9024000123c92e4606a3ea2d70800000000000000006a56a2ce04030440c01a5a92c9601a5e92c4606a62a2bb04000000006a66a2a6102401fa00049c048400000000000000006a76a29d04030440c01a7a9298601a7e9293606c0082a28904000000006c0086a27310fdfd9ed67950000400000000000000006c0096a2690418033c001a9a9264606c009ea24e102401fa00049c048000000000000000006c00aea24404180330001ab2923f606c00b6a22910fdfd9ed67950000000000000000000006c00c6a21f04190300001aca921a606c00cea20410fdfd9ed67950000400000000000000016bc472086be4b03a01b87206b03a01b87201
APF packet counters:
TOTAL_PACKETS: 469
PASSED_DHCP: 4
PASSED_IPV4: 65
PASSED_IPV6_NON_ICMP: 64
PASSED_IPV4_UNICAST: 64
PASSED_IPV6_ICMP: 223
PASSED_IPV6_UNICAST_NON_ICMP: 6
PASSED_ARP_UNICAST_REPLY: 4
PASSED_NON_IP_UNICAST: 1
DROPPED_RA: 4
DROPPED_IPV4_BROADCAST_ADDR: 7
DROPPED_IPV4_BROADCAST_NET: 27
這個 adb shell dumpsys network_stack
指令的輸出內容包括:
ApfCapabilities{version: 4, maxSize: 4096, format: 1}
:這表示 Wi-Fi 晶片支援 APF (第 4 版)。Last program
:這個部分是最新安裝的 APF 程式二進位檔,格式為十六進位字串。APF packet counters
:這個部分會顯示 APF 傳遞或捨棄的封包數量,以及具體原因。
如要將程式碼解碼並拆解為人類可讀的組語,請使用 apf_disassembler
工具。如要編譯可執行的二進位檔,請執行 m apf_disassembler
指令。
以下範例說明如何使用 apf_disassembler
工具:
echo "6bfcb03a01b8120c6b949401e906006b907c01e288a27c01dd88a47c01d888b87c01d388cd7c01ce88e17c01c988e384004008066a0e6bdca401af000600010800060412147a1e016bd88401a300021a1c6b8c7c01a00000686bd4a4018c0006ffffffffffff1a266bc07c018900006bf874017e120c84005408000a17821f1112149c00181fffab0d2a108211446a3239a205065a56483ac3146bf47401530a1e52f06bac7c014e00e06bb41a1e7e00000141ffffffff6be868a4012d0006ffffffffffff6bb874012e6bf07401237c001386dd686bd0a401100006ffffffffffff6bc87401110a147a0d3a6b980a267c010300ff6be072f90a366ba87af8858218886a26a2040fff02000000000000000000000000006ba472ddaa0e82d0aeaa0f8c00c9025868a2b60f5a56483ac3140c8126f3895186dd606a12a28b2600783afffe8000000000000002005efffe00026fff02000000000000000000000000000186006a3aa284024000123c94007d02586a3ea2700800000000000000006a56a26704190500001a5a94006002586a5ea23b2020014860486000000000000000006464200148604860000000000000000000646a7ea23204030440c01a8294002b02581a8694002402586c008aa21a04000000006c008ea204102a0079e10abcf60500000000000000006bc472086be4b03a01b87206b03a01b87201" | out/host/linux-x86/bin/apf_disassembler
0: li r1, -4
2: lddw r0, [r1+0]
3: add r0, 1
5: stdw r0, [r1+0]
6: ldh r0, [12]
8: li r1, -108
10: jlt r0, 0x600, 504
15: li r1, -112
17: jeq r0, 0x88a2, 504
22: jeq r0, 0x88a4, 504
27: jeq r0, 0x88b8, 504
32: jeq r0, 0x88cd, 504
37: jeq r0, 0x88e1, 504
42: jeq r0, 0x88e3, 504
47: jne r0, 0x806, 116
......
如要在離線狀態下查看 APF 結果,請使用 apf_run
工具。如要編譯可執行的二進位檔,請執行 m apf_run
指令。apf_run
工具支援 APFv4 和 APFv6 解譯器。
以下是 apf_run
指令的手冊。根據預設,apf_run
指令會在 APFv4 解譯器中執行。將 --v6
引數傳遞至 apf_run
,即可針對 APFv6 解譯器執行該引數。所有其他引數都可用於 APFv4 和 APFv6。
apf_run --help
Usage: apf_run --program <program> --pcap <file>|--packet <packet> [--data <content>] [--age <number>] [--trace]
--program APF program, in hex.
--pcap Pcap file to run through program.
--packet Packet to run through program.
--data Data memory contents, in hex.
--age Age of program in seconds (default: 0).
--trace Enable APF interpreter debug tracing
--v6 Use APF v6
-c, --cnt Print the APF counters
-h, --help Show this message.
以下範例會將一個封包傳遞至 APF,檢查封包是否可以捨棄或傳遞。
如要提供原始封包的十六進位二進位字串表示法,請使用 --packet
選項。如要提供資料地區的十六進位二進位字串 (用於儲存 APF 計數器),請使用 --data option
。由於每個計數器長度為 4 個位元組,資料區域必須夠長,才能確保不會發生緩衝區溢位。
out/host/linux-x86/bin/apf_run --program 6bfcb03a01b8120c6b9494010c06006b907c010588a27c010088a47c00fb88b87c00f688cd7c00f188e17c00ec88e384003908066a0e6bdca2d40600010800060412147a18016bd882ca021a1c6b8c7ac900686bd4a2b706ffffffffffff6a266bbca2b204c0a814656bf872a8120c84005808000a17821e1112149c00171fffab0d2a108210446a3239a204064651dbcc88ff6bf4727e0a1e52f06bac7a7be06bb41a1e7e0000006effffffff6bb07e00000063c0a814ff6be868a25106ffffffffffff6bb872536bf072497c001086dd686bd0a23806ffffffffffff6bc8723a0a147a0b3a6b980a267a2eff6be072240a366ba87a23858218886a26a2040fff02000000000000000000000000006ba472086be4b03a01b87206b03a01b87201 --packet 5ebcd79a8f0dc244efaab81408060001080006040002c244efaab814c0a8ca1e5ebcd79a8f0d --data 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Packet passed
Data: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000001
如要根據 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 記憶體區域。
- APF 程式安裝問題 (X 位元組,X <=
maxLen
): 韌體必須支援讀取或寫入任何長度 (最多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 提供單一裝置和多裝置 CTS 測試案例,適用於 APF 篩選器和 APF 解譯器整合,確保 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 已正確安裝,請將連線偵測封包傳送至受測裝置。
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