PORT HOTPLUG FRAMEWORK
端口熱插拔框架為DPDK應用程序提供在運行時附加和分離端口的能力。由于該框架依賴于PMD實現,PMD無法處理的端口超出了該框架的范圍。此外,在從DPDK應用程序分離端口后,該框架不提供從系統中移除設備的方法。對于由物理網卡支持的端口,內核需要支持PCI熱插拔功能。
26.1 概述
端口熱插拔框架的基本要求包括:
- 使用端口熱插拔框架的DPDK應用程序必須管理自己的端口。端口熱插拔框架的實現允許DPDK應用程序管理端口。例如,當DPDK應用程序調用端口附加函數時,將返回已附加的端口號。DPDK應用程序還可以通過端口號分離端口。
- 附加或分離物理設備端口需要內核支持。要附加新的物理設備端口,首先設備將在內核中被用戶空間驅動I/O框架識別。然后DPDK應用程序可以調用端口熱插拔函數來附加端口。對于分離,步驟相反。
- 分離之前,端口必須停止和關閉。DPDK應用程序在分離端口之前必須調用
rte_eth_dev_stop()
和rte_eth_dev_close()
API。這些函數將啟動PMD的最終化序列。 - 該框架不影響傳統的DPDK應用程序行為。如果未調用端口熱插拔函數,則所有傳統的DPDK應用程序仍可在不進行修改的情況下正常工作。
26.2 端口熱插拔API概述
- 附加端口
rte_eth_dev_attach()
API將端口附加到DPDK應用程序,并返回已附加的端口號。在調用API之前,設備應該被用戶空間驅動I/O框架識別。該API接收類似“0000:01:00.0”這樣的PCI地址或者類似“eth_pcap0,iface=eth0”這樣的虛擬設備名稱。對于虛擬設備名稱,格式與DPDK的一般“–vdev”選項相同。 - 分離端口
rte_eth_dev_detach()
API從DPDK應用程序分離端口,并返回分離設備的PCI地址或設備的虛擬設備名稱。
26.3 參考
“testpmd”支持端口熱插拔框架。
26.4 限制
- 端口熱插拔API不具備線程安全性。
- 該框架僅在Linux下可用,不支持BSD。
- 要分離端口,端口應由igb_uio管理的設備支持。不支持VFIO。
- 并非所有PMD都支持分離功能。要了解PMD是否支持分離,請搜索PMD實現中的“RTE_PCI_DRV_DETACHABLE”標志。如果PMD中定義了該標志,則支持分離功能。
SOURCE ORGANIZATION
此部分描述了DPDK框架中源代碼的組織結構。
27.1 Makefiles 和 Config
注意:在下面的描述中,RTE_SDK 是一個環境變量,指向解壓縮tar包的基本目錄。請參閱構建系統提供的有用變量的描述,了解其他變量的說明。
DPDK庫和應用程序提供的 Makefiles 位于 $(RTE_SDK)/mk。
Config 模板位于 $(RTE_SDK)/config。這些模板描述了每個目標啟用的選項。配置文件還包含許多DPDK庫的可啟用和禁用項,包括調試選項。用戶應查看配置文件,并熟悉其中的選項。配置文件還用于創建一個頭文件,該頭文件將位于新的構建目錄中。
27.2 Libraries
庫位于 $(RTE_SDK)/lib 的子目錄中。按照慣例,我們將提供應用程序接口(API)的代碼稱為庫。通常,它會生成一個存檔文件(.a),但內核模塊也應該放在同一個目錄下。
lib 目錄包含:
lib
+-- librte_cmdline # command line interface helper
+-- librte_distributor # packet distributor
+-- librte_eal # environment abstraction layer
+-- librte_ether # generic interface to poll mode driver
+-- librte_hash # hash library
+-- librte_ip_frag # IP fragmentation library
+-- librte_ivshmem # QEMU IVSHMEM library
+-- librte_kni # kernel NIC interface
+-- librte_kvargs # argument parsing library
+-- librte_lpm # longest prefix match library
+-- librte_malloc # malloc-like functions
+-- librte_mbuf # packet and control mbuf manipulation library
+-- librte_mempool # memory pool manager (fixedsized objects)
+-- librte_meter # QoS metering library
+-- librte_net # various IP-related headers
+-- librte_pmd_bond # bonding poll mode driver
+-- librte_pmd_e1000 # 1GbE poll mode drivers (igb and em)
+-- librte_pmd_fm10k # Host interface PMD driver for FM10000 Series
+-- librte_pmd_ixgbe # 10GbE poll mode driver
+-- librte_pmd_i40e # 40GbE poll mode driver
+-- librte_pmd_mlx4 # Mellanox ConnectX-3 poll mode driver
+-- librte_pmd_pcap # PCAP poll mode driver
+-- librte_pmd_ring # ring poll mode driver
+-- librte_pmd_virtio # virtio poll mode driver
+-- librte_pmd_vmxnet3 # VMXNET3 poll mode driver
+-- librte_pmd_xenvirt # Xen virtio poll mode driver
+-- librte_power # power management library
+-- librte_ring # software rings (act as lockless FIFOs)
+-- librte_sched # QoS scheduler and dropper library
+-- librte_timer # timer library
27.3 Applications
應用程序是包含 main() 函數的源代碼。它們位于 $(RTE_SDK)/app 和 $(RTE_SDK)/examples 目錄中。
app 目錄包含用于測試DPDK的示例應用程序(自動測試)。
examples 目錄包含展示如何使用庫的示例應用程序。
app
+-- chkincs # test prog to check include depends
+-- test # autotests, to validate DPDK features
+-- test-pmd # test and bench poll mode driver examples
examples
+-- cmdline # Example of using cmdline library
+-- dpdk_qat # Example showing integration with Intel QuickAssist
+-- exception_path # Sending packets to and from Linux Ethernet device (TAP)
+-- helloworld # Helloworld basic example
+-- ip_reassembly # Example showing IP Reassembly
+-- ip_fragmentation # Example showing IPv4 Fragmentation
+-- ipv4_multicast # Example showing IPv4 Multicast
+-- kni # Kernel NIC Interface example
+-- l2fwd # L2 Forwarding example with and without SR-IOV
+-- l3fwd # L3 Forwarding example
+-- l3fwd-power # L3 Forwarding example with power management
+-- l3fwd-vf # L3 Forwarding example with SR-IOV
+-- link_status_interrupt # Link status change interrupt example
+-- load_balancer # Load balancing across multiple cores/sockets
+-- multi_process # Example applications with multiple DPDK processes
+-- qos_meter # QoS metering example
+-- qos_sched # QoS scheduler and dropper example
+-- timer # Example of using librte_timer library
+-- vmdq_dcb # Intel 82599 Ethernet Controller VMDQ and DCB receiving
+-- vmdq # Example of VMDQ receiving
+-- vhost # Example of userspace vhost and switch
注意:實際的 examples 目錄可能包含除上述示例之外的其他示例應用程序。請查看最新的DPDK源文件以了解詳情。
DEVELOPMENT KIT BUILD SYSTEM
DPDK需要一個構建系統來進行編譯等活動。本部分描述了DPDK框架中使用的約束和機制。
該框架有兩個用例:
? 編譯DPDK庫和示例應用程序;該框架生成特定的二進制庫、包含文件和示例應用程序。
? 使用已安裝的二進制DPDK,編譯外部應用程序或庫。
28.1 構建開發套件二進制
以下提供了如何構建DPDK二進制的詳細信息。
28.1.1 構建目錄概念
在安裝后,會創建一個構建目錄結構。每個構建目錄包含包含文件、庫和應用程序:
~/DPDK$ ls
app MAINTAINERS
config Makefile
COPYRIGHT mk
doc scripts
examples lib
tools x86_64-native-linuxapp-gcc
x86_64-native-linuxapp-icc i686-native-linuxapp-gcc
i686-native-linuxapp-icc
...
~/DEV/DPDK$ ls i686-native-linuxapp-gcc
app build hostapp include kmod lib Makefile
~/DEV/DPDK$ ls i686-native-linuxapp-gcc/app/
cmdline_test dump_cfg test testpmd
cmdline_test.map dump_cfg.map test.map
testpmd.map
~/DEV/DPDK$ ls i686-native-linuxapp-gcc/lib/
libethdev.a librte_hash.a librte_mbuf.a librte_pmd_ixgbe.a
librte_cmdline.a librte_lpm.a librte_mempool.a librte_ring.a
librte_eal.a librte_malloc.a librte_pmd_e1000.a librte_timer.a
~/DEV/DPDK$ ls i686-native-linuxapp-gcc/include/
arch rte_cpuflags.h rte_memcpy.h
cmdline_cirbuf.h rte_cycles.h rte_memory.h
cmdline.h rte_debug.h rte_mempool.h
cmdline_parse_etheraddr.h rte_eal.h rte_memzone.h
cmdline_parse.h rte_errno.h rte_pci_dev_ids.h
cmdline_parse_ipaddr.h rte_ethdev.h rte_pci.h
cmdline_parse_num.h rte_ether.h rte_per_lcore.h
cmdline_parse_portlist.h rte_fbk_hash.h rte_prefetch.h
cmdline_parse_string.h rte_hash_crc.h rte_random.h
cmdline_rdline.h rte_hash.h rte_ring.h
cmdline_socket.h rte_interrupts.h rte_rwlock.h
cmdline_vt100.h rte_ip.h rte_sctp.h
exec-env rte_jhash.h rte_spinlock.h
rte_alarm.h rte_launch.h rte_string_fns.h
rte_atomic.h rte_lcore.h rte_tailq.h
rte_branch_prediction.h rte_log.h rte_tcp.h
rte_byteorder.h rte_lpm.h rte_timer.h
rte_common.h rte_malloc.h rte_udp.h
rte_config.h rte_mbuf.h
構建目錄特定于配置,包括架構 + 執行環境 + 工具鏈。可以有多個構建目錄共享相同的源文件,但具有不同的配置。
例如,要使用默認配置模板config/defconfig_x86_64-linuxapp創建一個名為my_sdk_build_dir的新構建目錄,可以執行以下操作:
cd ${RTE_SDK}
make config T=x86_64-native-linuxapp-gcc O=my_sdk_build_dir
這將創建一個新的 my_sdk_build_dir 目錄。 之后,我們可以通過執行以下操作進行編譯:
cd my_sdk_build_dir
make
這相當于:
make O=my_sdk_build_dir
my_sdk_build_dir 的內容是:
28.2 編譯外部應用程序
由于DPDK本質上是一個開發套件,最終用戶的首要目標將是使用此SDK創建應用程序。要編譯一個應用程序,用戶必須設置 RTE_SDK 和 RTE_TARGET 環境變量。
export RTE_SDK=/opt/DPDK
export RTE_TARGET=x86_64-native-linuxapp-gcc
cd /path/to/my_app
對于新應用程序,用戶必須創建自己的Makefile,其中包含一些.mk文件,如 ${RTE_SDK}/mk/rte.vars.mk 和 ${RTE_SDK}/mk/rte.app.mk。這在"構建您自己的應用程序"中有描述。
根據在Makefile中定義的或作為環境變量定義的選擇的目標(架構、機器、執行環境、工具鏈),應用程序和庫將使用適當的.h文件進行編譯,并鏈接適當的.a文件。這些文件位于 ${RTE_SDK}/arch-machine-execenv-toolchain 中,內部由 ${RTE_BIN_SDK} 引用。
要編譯他們的應用程序,用戶只需調用 make。編譯結果將位于 /path/to/my_app/build 目錄中。
示例應用程序位于 examples 目錄中。
28.3 Makefile描述
28.3.1 DPDK Makefile 的通用規則
在DPDK中,Makefiles 總是遵循相同的方案:
- 在開頭包含 $(RTE_SDK)/mk/rte.vars.mk。
- 定義 RTE 構建系統的特定變量。
- 包含特定的 $(RTE_SDK)/mk/rte.XYZ.mk,其中 XYZ 可以是 app、lib、extapp、extlib、obj、gnuconfigure 等,取決于您想構建的對象類型。請參見下面的Makefile類型。
- 包含用戶定義的規則和變量。
以下是一個非常簡單的外部應用程序Makefile示例:
include $(RTE_SDK)/mk/rte.vars.mk
# binary name
APP = helloworld
# all source are stored in SRCS-y
SRCS-y := main.c
CFLAGS += -O3
CFLAGS += $(WERROR_FLAGS)
include $(RTE_SDK)/mk/rte.extapp.mk
28.3.2 Makefile 類型
根據用戶Makefile末尾包含的 .mk 文件不同,Makefile 將具有不同的作用。請注意,不可能在同一個Makefile中構建庫和應用程序。對此,用戶必須創建兩個單獨的Makefile,可能位于兩個不同的目錄中。
無論如何,用戶Makefile中必須盡快包含 rte.vars.mk 文件。
應用程序
這些Makefiles生成二進制應用程序。
? rte.app.mk:在開發套件框架中的應用程序
? rte.extapp.mk:外部應用程序
? rte.hostapp.mk:開發套件框架中的主機應用程序
庫
生成 .a 庫。
? rte.lib.mk:開發套件框架中的庫
? rte.extlib.mk:外部庫
? rte.hostlib.mk:開發套件框架中的主機庫
安裝
? rte.install.mk:不構建任何內容,僅用于在安裝目錄中創建鏈接或復制文件。這對包含開發套件框架中的文件很有用。
內核模塊
? rte.module.mk:在開發套件框架中構建內核模塊。
對象
? rte.obj.mk:對象聚合(將多個 .o 合并為一個)在開發套件框架中。
? rte.extobj.mk:對象聚合(將多個 .o 合并為一個)在開發套件框架外部。
其他
? rte.doc.mk:開發套件框架中的文檔
? rte.gnuconfigure.mk:構建基于 configure 的應用程序。
? rte.subdir.mk:在開發套件框架中構建多個目錄。
28.3.3 構建系統提供的有用變量
? RTE_SDK:DPDK源文件的絕對路徑。在編譯開發套件時,該變量由框架自動設置。如果編譯外部應用程序,則必須由用戶定義為環境變量。
? RTE_SRCDIR:源文件根目錄的路徑。在編譯開發套件時,RTE_SRCDIR = RTE_SDK。在編譯外部應用程序時,該變量指向外部應用程序源文件的根目錄。
? RTE_OUTPUT:寫入輸出文件的路徑。通常是 $(RTE_SRCDIR)/build,但可以通過 make 命令行中的 O= 選項進行覆蓋。
? RTE_TARGET:標識正在構建的目標的字符串。格式為架構-機器-執行環境-工具鏈。在編譯SDK時,目標由配置文件(.config)的構建系統推導出來。在構建外部應用程序時,用戶必須在Makefile中或作為環境變量指定。
? RTE_SDK_BIN:引用 ( R T E S D K ) / (RTE_SDK)/ (RTES?DK)/(RTE_TARGET)。
? RTE_ARCH:定義架構(i686、x86_64)。與 CONFIG_RTE_ARCH 相同,但字符串周圍沒有雙引號。
? RTE_MACHINE:定義機器。與 CONFIG_RTE_MACHINE 相同,但字符串周圍沒有雙引號。
? RTE_TOOLCHAIN:定義工具鏈(gcc、icc)。與 CONFIG_RTE_TOOLCHAIN 相同,但字符串周圍沒有雙引號。
? RTE_EXEC_ENV:定義執行環境(linuxapp)。與 CONFIG_RTE_EXEC_ENV 相同,但字符串周圍沒有雙引號。
? RTE_KERNELDIR:該變量包含用于編譯內核模塊的內核源文件的絕對路徑。內核頭文件必須與將在目標機器(運行應用程序的機器)上使用的頭文件相同。默認情況下,該變量設置為 /lib/modules/$(shell uname -r)/build,這在目標機器也是構建機器時是正確的。
28.3.4 只能在Makefile中設置/覆蓋的變量
- VPATH: 構建系統將搜索源文件的路徑列表。默認情況下,RTE_SRCDIR 將包含在 VPATH 中。
- CFLAGS: 用于C編譯的標志。用戶應該使用 += 來追加此變量中的數據。
- LDFLAGS: 用于鏈接的標志。用戶應該使用 += 來追加此變量中的數據。
- ASFLAGS: 用于匯編的標志。用戶應該使用 += 來追加此變量中的數據。
- CPPFLAGS: 用于給C預處理器傳遞標志(僅在匯編 .S 文件時有用)。用戶應該使用 += 來追加此變量中的數據。
- LDLIBS: 在應用程序中,要鏈接的庫列表(例如,-L /path/to/libfoo -lfoo)。用戶應該使用 += 來追加此變量中的數據。
- SRC-y: 應用程序、庫或對象Makefile中源文件的列表(.c、.S 或 .o,如果源文件是二進制文件)。這些源文件必須從 VPATH 中獲取。
- INSTALL-y-$(INSTPATH): 要安裝到 $(INSTPATH) 的文件列表。這些文件必須從 VPATH 中獲取,并將被復制到 ( R T E O U T P U T ) / (RTE_OUTPUT)/ (RTEO?UTPUT)/(INSTPATH)。幾乎可以在任何 RTE Makefile 中使用。
- SYMLINK-y-$(INSTPATH): 要安裝到 $(INSTPATH) 的文件列表。這些文件必須從 VPATH 中獲取,并將以符號鏈接的方式鏈接到 ( R T E O U T P U T ) / (RTE_OUTPUT)/ (RTEO?UTPUT)/(INSTPATH)。幾乎可以在任何 DPDK Makefile 中使用。
- PREBUILD: 在主要構建之前執行的先決條件操作的列表。用戶應該使用 += 來追加此變量中的數據。
- POSTBUILD: 在主要構建之后執行的操作的列表。用戶應該使用 += 來追加此變量中的數據。
- PREINSTALL: 在安裝之前執行的先決條件操作的列表。用戶應該使用 += 來追加此變量中的數據。
- POSTINSTALL: 在安裝之后執行的操作的列表。用戶應該使用 += 來追加此變量中的數據。
- PRECLEAN: 在清理之前執行的先決條件操作的列表。用戶應該使用 += 來追加此變量中的數據。
- POSTCLEAN: 在清理之后執行的操作的列表。用戶應該使用 += 來追加此變量中的數據。
- DEPDIR-y: 僅在開發套件框架中使用,指定當前目錄的構建是否依賴于另一個目錄的構建。這是為了正確支持并行構建。
28.3.5 只能由用戶在命令行中設置/覆蓋的變量
一些變量可用于配置構建系統的行為。這些變量在“Development Kit Root Makefile Help”和“External Application/Library Makefile Help”中有文檔記錄。
- WERROR_CFLAGS: 默認情況下,此變量設置為取決于編譯器的特定值。鼓勵用戶按照以下方式使用此變量:
這避免了根據編譯器(icc 或 gcc)使用不同情況。此外,此變量可以從命令行覆蓋,以便在測試目的時繞過標志。CFLAGS += $(WERROR_CFLAGS)
28.3.6 可在Makefile或命令行中設置/覆蓋的變量
- CFLAGS_my_file.o: 用于 my_file.c 的 C 編譯的特定標志。
- LDFLAGS_my_app: 在鏈接 my_app 時添加的特定標志。
- NO_AUTOLIBS: 如果設置,框架提供的庫將不會自動包含在 LDLIBS 變量中。
- EXTRA_CFLAGS: 在編譯時將此變量的內容追加到 CFLAGS 之后。
- EXTRA_LDFLAGS: 在鏈接時將此變量的內容追加到 LDFLAGS 之后。
- EXTRA_ASFLAGS: 在匯編時將此變量的內容追加到 ASFLAGS 之后。
- EXTRA_CPPFLAGS: 在匯編文件上使用 C 預處理器時將此變量的內容追加到 CPPFLAGS 之后。
29.1 配置目標
配置目標需要指定目標的名稱,使用 T=mytarget 參數是必需的。可用的目標列表位于 $(RTE_SDK)/config(去掉 defconfig_ 前綴)。
配置目標還支持指定輸出目錄的名稱,使用 O=mybuilddir。這是一個可選參數,默認輸出目錄是 build。
- Config
創建一個構建目錄,并從模板生成配置。在新的構建目錄中也創建一個 Makefile。
示例:make config O=mybuild T=x86_64-native-linuxapp-gcc
29.2 構建目標
構建目標支持指定輸出目錄的名稱,使用 O=mybuilddir。默認輸出目錄是 build。
-
all, build 或僅 make
在之前由 make config 創建的輸出目錄中構建 DPDK。
示例:make O=mybuild
-
clean
清除使用 make build 創建的所有對象。
示例:make clean O=mybuild
-
%_sub
僅構建一個子目錄,而不管理其他目錄的依賴關系。
示例:make lib/librte_eal_sub O=mybuild
-
%_clean
僅清除一個子目錄。
示例:make lib/librte_eal_clean O=mybuild
29.3 安裝目標
-
Install
構建 DPDK 二進制文件。實際上,這會將每個支持的目標構建到單獨的目錄中。每個目錄的名稱是目標的名稱。可以選擇性地使用 T=mytarget 指定要安裝的目標名稱。目標名稱可以包含通配符 * 字符。可用的目標列表位于 $(RTE_SDK)/config(刪除 defconfig_ 前綴)。
示例:make install T=x86_64-*
-
Uninstall
移除已安裝的目標目錄。
29.4 測試目標
-
test
啟動指定使用 O=mybuilddir 的構建目錄的自動測試。這是可選的,默認輸出目錄是 build。
示例:make test O=mybuild
-
testall
啟動所有已安裝目標目錄(在 make install 之后)的自動測試。可以選擇性地使用 T=mytarget 指定要測試的目標名稱。目標名稱可以包含通配符 * 字符。可用的目標列表位于 $(RTE_SDK)/config(刪除 defconfig_ 前綴)。
示例:make testall, make testall T=x86_64-*
29.5 文檔目標
- doc
生成 Doxygen 文檔(API、html 和 pdf)。 - doc-api-html
生成 html 格式的 Doxygen API 文檔。 - doc-guides-html
生成 html 格式的指南文檔。 - doc-guides-pdf
生成 pdf 格式的指南文檔。
29.6 依賴目標
-
depdirs
此目標在 make config 時隱式調用。通常情況下,除非在 Makefiles 中更新了 DEPDIRS-y 變量,否則無需用戶調用它。它將生成文件 $(RTE_OUTPUT)/.depdirs。
示例:make depdirs O=mybuild
-
depgraph
此命令生成依賴關系的 dot 圖。它可以用于調試循環依賴問題,或者只是了解依賴關系。
示例:make depgraph O=mybuild > /tmp/graph.dot && dotty /tmp/graph.dot
29.7 其他目標
- help
顯示此幫助信息。
29.8 其他有用的命令行變量
以下變量可以在命令行上指定:
- V=
啟用詳細構建(顯示完整的編譯命令行和一些中間命令)。 - D=
啟用依賴項調試。這提供了一些有關為何構建或不構建目標的有用信息。 - EXTRA_CFLAGS=, EXTRA_LDFLAGS=, EXTRA_ASFLAGS=, EXTRA_CPPFLAGS=
追加特定的編譯、鏈接或匯編標志。 - CROSS=
指定一個交叉工具鏈頭部,它將作為前綴用于所有 gcc/binutils 應用程序。這僅在使用 gcc 時有效。
29.9 在構建目錄中使用 Make
在 SDK 根目錄 $(RTE_SDK) 中調用了上述所有目標。可以在構建目錄內部運行相同的 Makefile 目標。例如,以下命令:
cd $(RTE_SDK)
make config O=mybuild T=x86_64-native-linuxapp-gcc
make O=mybuild
等同于:
cd $(RTE_SDK)
make config O=mybuild T=x86_64-native-linuxapp-gcc
cd mybuild
# 現在不需要再指定 O= now
make
29.10 編譯調試版本
要在 DPDK 和示例應用程序中包含調試信息并將優化級別設置為 0 進行編譯,應在編譯之前設置 EXTRA_CFLAGS 環境變量,如下所示:
export EXTRA_CFLAGS='-O0 -g'
然后可以以通常的方式編譯 DPDK 以及任何用戶或示例應用程序。例如:
make install T=x86_64-native-linuxapp-gcc
make -C examples/<theapp>
擴展 DPDK
本章描述了開發人員如何擴展 DPDK 以提供新的庫、新的目標或支持新的目標。
30.1 示例:添加一個新庫 libfoo
要向 DPDK 中添加新庫,請按照以下步驟進行:
- 添加新的配置選項:
for f in config/*; do \echo CONFIG_RTE_LIBFOO=y >> $f; done
1、創建帶有源代碼的新目錄:
mkdir ${RTE_SDK}/lib/libfoo
touch ${RTE_SDK}/lib/libfoo/foo.c
touch ${RTE_SDK}/lib/libfoo/foo.h
2、在 libfoo 中添加 foo() 函數:
void foo(void)
{
}
在 foo.h 中聲明:
extern void foo(void);
3、更新 lib/Makefile:
vi ${RTE_SDK}/lib/Makefile
添加:
DIRS-$(CONFIG_RTE_LIBFOO) += libfoo
4、為此庫創建新的 Makefile(從 mempool Makefile 派生):
cp ${RTE_SDK}/lib/librte_mempool/Makefile ${RTE_SDK}/lib/libfoo/
vi ${RTE_SDK}/lib/libfoo/Makefile
替換:
librte_mempool -> libfoo
rte_mempool -> foo
5、更新 mk/DPDK.app.mk:
如果啟用了該選項,則在 LDLIBS 變量中添加 -lfoo。這將在鏈接 DPDK 應用程序時自動包含此標志。
6、使用新庫構建 DPDK:
cd ${RTE_SDK}
make config T=x86_64-native-linuxapp-gcc
make
7、檢查庫的安裝情況:
ls build/lib
ls build/include
30.1.1 示例:在測試應用程序中使用 libfoo
測試應用程序用于驗證 DPDK 的所有功能。一旦您添加了一個庫,就應該在測試應用程序中添加一個新的測試用例。
- 應添加一個新的 test_foo.c 文件,其中包括 foo.h 并從 test_foo() 中調用 foo() 函數。當測試通過時,test_foo() 函數應返回 0。
- Makefile、test.h 和 commands.c 也必須進行更新,以處理新的測試用例。
- 測試報告生成:autotest.py 是一個用于生成測試報告的腳本,位于 ${RTE_SDK}/doc/rst/test_report/autotests 目錄中。還需要更新此腳本。如果 libfoo 屬于新的測試系列,則必須更新 ${RTE_SDK}/doc/rst/test_report/test_report.rst 中的鏈接。
- 使用更新后的測試應用程序構建 DPDK(以下僅顯示特定目標):
cd ${RTE_SDK}
make config T=x86_64-native-linuxapp-gcc
make
構建你自己的應用程序
31.1 在開發工具包目錄中編譯示例應用程序
當編譯示例應用程序(例如,hello world)時,必須導出以下變量:RTE_SDK 和 RTE_TARGET。
~/DPDK$ cd examples/helloworld/
~/DPDK/examples/helloworld$ export RTE_SDK=/home/user/DPDK
~/DPDK/examples/helloworld$ export RTE_TARGET=x86_64-native-linuxapp-gcc
~/DPDK/examples/helloworld$ make
CC main.o
LD helloworld
INSTALL-APP helloworld
INSTALL-MAP helloworld.map
默認情況下,二進制文件生成在 build 目錄下:
~/DPDK/examples/helloworld$ ls build/app
helloworld helloworld.map
31.2 在開發工具包之外構建你自己的應用程序
將示例應用程序(Hello World)復制到一個新目錄,作為開發的起點:
~$ cp -r DPDK/examples/helloworld my_rte_app
~$ cd my_rte_app/
~/my_rte_app$ export RTE_SDK=/home/user/DPDK
~/my_rte_app$ export RTE_TARGET=x86_64-native-linuxapp-gcc
~/my_rte_app$ make
CC main.o
LD helloworld
INSTALL-APP helloworld
INSTALL-MAP helloworld.map
自定義 Makefile
31.3.1 應用程序 Makefile
提供的 Hello World 示例應用程序的默認 Makefile 是一個很好的起點。
它包含以下內容:
在開頭包含了 $(RTE_SDK)/mk/rte.vars.mk
在結尾包含了 $(RTE_SDK)/mk/rte.extapp.mk
用戶需要定義一些變量:
APP:包含應用程序的名稱。
SRCS-y:源文件列表(.c,.S)。
31.3.2 庫 Makefile
同樣也可以以相同的方式構建一個庫:
在開頭包含 $(RTE_SDK)/mk/rte.vars.mk。
在結尾包含 $(RTE_SDK)/mk/rte.extlib.mk。
唯一的區別是 APP 應該替換為 LIB,其中包含庫的名稱。例如,libfoo.a。
31.3.3 自定義 Makefile 操作
一些變量可以被定義來自定義 Makefile 操作。以下是最常見的變量。有關詳細信息,請參閱“開發工具包構建系統”章節中的“Makefile 描述”部分。
- VPATH:構建系統搜索源文件的路徑列表。默認情況下,RTE_SRCDIR 將包含在 VPATH 中。
- CFLAGS_my_file.o:對 my_file.c 進行 C 編譯的特定標志。
- CFLAGS:用于 C 編譯的標志。
- LDFLAGS:用于鏈接的標志。
- CPPFLAGS:用于向 C 預處理器提供標志的標志(僅在匯編 .S 文件時有用)。
- LDLIBS:要鏈接的庫列表(例如,-L /path/to/libfoo - lfoo)。
- NO_AUTOLIBS:如果設置,則框架提供的庫不會自動包含在 LDLIBS 變量中。
請根據需要自行添加翻譯或額外說明。
外部應用程序/庫的 Makefile 幫助
外部應用程序或庫應包含來自 RTE_SDK 中的特定 Makefile,位于 mk 目錄中。這些 Makefile 是:
- ${RTE_SDK}/mk/rte.extapp.mk:構建應用程序
- ${RTE_SDK}/mk/rte.extlib.mk:構建靜態庫
- ${RTE_SDK}/mk/rte.extobj.mk:構建對象(.o)
32.1 先決條件
必須定義以下變量:
- ${RTE_SDK}:指向 DPDK 的根目錄。
- ${RTE_TARGET}:引用用于編譯的目標(例如,x86_64-native-linuxapp-gcc)。
32.2 構建目標
構建目標支持指定輸出目錄的名稱,使用 O=mybuilddir。這是可選的;默認輸出目錄為 build。
- all,“nothing”(僅表示 make)
在指定的輸出目錄中構建應用程序或庫。
示例:
make O=mybuild
- clean
清理使用 make build 創建的所有對象。
示例:
make clean O=mybuild
32.3 幫助目標
- help
顯示此幫助信息。
32.4 其他有用的命令行變量
以下變量可以在命令行指定:
- S=
指定源文件所在的目錄。默認情況下,它是當前目錄。 - M=
指定一旦創建輸出目錄后要調用的 Makefile。默認情況下,它使用 $(S)/Makefile。 - V=
啟用詳細構建(顯示完整的編譯命令行和一些中間命令)。 - D=
啟用依賴關系調試。這提供了一些關于為什么需要重建目標的有用信息。
EXTRA_CFLAGS=、EXTRA_LDFLAGS=、EXTRA_ASFLAGS=、EXTRA_CPPFLAGS=
追加特定的編譯、鏈接或匯編標志。 - CROSS=
指定一個用于所有 gcc/binutils 應用程序的交叉工具鏈標頭。這僅在使用 gcc 時有效。
32.5 從其他目錄運行 Make
可以通過指定輸出目錄和源目錄來從另一個目錄運行 Makefile。例如:
export RTE_SDK=/path/to/DPDK
export RTE_TARGET=x86_64-native-linuxapp-icc
make -f /path/to/my_app/Makefile S=/path/to/my_app O=/path/to/build_dir
33.1 引言
以下部分描述了 DPDK 中使用的優化以及新應用程序應考慮的優化方法。
它們還強調了在使用 DPDK 開發應用程序時應該和不應該使用的對性能影響較大的編碼技術。
最后,它們介紹了使用英特爾的性能分析器進行應用程序分析以優化軟件的方法。
編寫高效代碼
本章提供了一些使用 DPDK 開發高效代碼的技巧。欲獲取更多通用信息,請參考英特爾? 64 和 IA-32 架構優化參考手冊,這是編寫高效代碼的寶貴參考資料。
34.1 內存
本節描述了在 DPDK 環境中開發應用程序時的一些關鍵內存注意事項。
34.1.1 內存拷貝:在數據平面不要使用libc
在 DPDK 中通過 Linux* 應用環境可以使用許多 libc 函數,這可以簡化應用程序的移植和配置平面的開發。然而,許多這些函數并非為性能而設計。像 memcpy() 或 strcpy() 這樣的函數不應該在數據平面中使用。對于拷貝小結構體,最好使用編譯器可以優化的更簡單的技術。建議參考英特爾出版的 VTune? Performance Analyzer Essentials 出版物獲取建議。
對于頻繁調用的特定函數,最好提供一個自制的經過優化的函數,應該聲明為 static inline。
DPDK API 提供了一個經過優化的 rte_memcpy() 函數。
34.1.2 內存分配
libc 的其他函數,如 malloc(),提供了一種靈活的方式來分配和釋放內存。在某些情況下,使用動態分配是必要的,但不建議在數據平面中使用類似 malloc 的函數,因為管理碎片化的堆可能成本高昂,而且分配器可能沒有針對并行分配進行優化。
如果確實需要在數據平面中進行動態分配,最好使用固定大小對象的內存池。這個 API 由 librte_mempool 提供。這個數據結構提供了一些增加性能的服務,如對象的內存對齊、無鎖訪問對象、NUMA 感知、批量獲取/放置和每個 lcore 的緩存。rte_malloc() 函數使用了與內存池類似的概念。
34.1.3 并發訪問相同的內存區域
多個 lcore 對同一內存區域的讀寫訪問操作可能會產生大量數據緩存未命中,這是非常昂貴的。通常可以使用每個 lcore 變量,例如統計數據。針對此問題至少有兩種解決方案:
- 使用 RTE_PER_LCORE 變量。請注意,在這種情況下,lcore X 上的數據對于 lcore Y 不可用。
- 使用結構體表(每個 lcore 一個)。在這種情況下,每個結構體必須緩存對齊。
如果同一緩存行中沒有讀寫變量,那么只讀變量可以在多個 lcore 之間共享而不會造成性能損失。
34.1.4 NUMA
在 NUMA 系統上,最好訪問本地內存,因為遠程內存訪問速度較慢。在 DPDK 中,memzone、ring、rte_malloc 和 mempool API 提供了在特定套接字上創建池的方法。
有時,復制數據以優化速度可能是個好主意。對于經常訪問的只讀變量,把它們僅保留在一個套接字中應該不是問題,因為數據將存在于緩存中。
34.1.5 跨內存通道分配
現代內存控制器具有多個內存通道,可以并行加載或存儲數據。根據內存控制器及其配置,內存分布在通道上的方式各不相同。每個通道都有帶寬限制,這意味著如果所有內存訪問操作都只在第一個通道上進行,可能會存在潛在的瓶頸。
默認情況下,內存池庫將對象的地址分布在內存通道之間。
34.2 lcore 之間的通信
為了在 lcore 之間提供基于消息的通信,建議使用 DPDK ring API,它提供了無鎖環實現。
這個環支持批量和突發訪問,意味著可以使用一個昂貴的原子操作從環中讀取多個元素(參見第 5 章“環庫”)。使用批量訪問操作可以極大地提高性能。
出隊消息的代碼算法可能類似于以下內容:
#define MAX_BULK 32
while (1) {/* Process as many elements as can be dequeued. */count = rte_ring_dequeue_burst(ring, obj_table, MAX_BULK);if (unlikely(count == 0))continue;my_process_bulk(obj_table, count);
}
34.3 PMD 驅動程序
DPDK Poll Mode Driver(PMD)也能以批量/突發模式工作,允許在發送或接收函數的每次調用中對一些代碼進行因式分解。
避免部分寫入。當 PCI 設備通過 DMA 寫入系統內存時,如果寫操作是在完整的緩存行上而不是部分緩存行上,成本就會較低。在 PMD 代碼中,已經采取了盡可能避免部分寫入的措施。
34.3.1 降低數據包延遲
傳統上,吞吐量和延遲之間存在權衡。一個應用程序可以調整以實現高吞吐量,但平均數據包的端到端延遲通常會增加。同樣地,該應用程序可以調整以實現平均較低的端到端延遲,但代價是較低的吞吐量。
為了實現更高的吞吐量,DPDK 試圖通過批量處理每個數據包的成本來聚合。以 testpmd 應用程序為例,可以在命令行上將批量大小設置為 16(也是默認值)。這允許應用程序一次從 PMD 請求 16 個數據包。然后,testpmd 應用程序立即嘗試傳輸所有接收到的數據包,即在本例中為所有 16 個數據包。
在網絡端口的相應 TX 隊列的尾指針更新之前,數據包不會被傳輸。在調整以實現高吞吐量時,這種行為是可取的,因為對 RX 和 TX 隊列的尾指針更新的成本可以分攤到 16 個數據包上,有效地隱藏了相對較慢的 MMIO 寫入 PCIe* 設備的成本。然而,當調整以實現低延遲時,這并不理想,因為第一個接收到的數據包必須等待其他 15 個數據包也被接收。在所有 16 個數據包都被傳輸進行處理之前,它無法被傳輸,因為網卡在 TX 尾指針更新之前不知道傳輸數據包。
為了在系統負載較重的情況下始終實現低延遲,應用程序開發人員應避免批量處理數據包。testpmd 應用程序可以從命令行配置為使用批量值為 1。這將允許一次處理一個數據包,提供較低的延遲,但代價是較低的吞吐量。
34.4 鎖和原子操作
原子操作意味著在指令之前添加一個鎖前綴,導致處理器在執行下一條指令期間斷言 LOCK# 信號。在多核環境中,這對性能有很大影響。
通過避免在數據平面中使用鎖機制可以提高性能。通常可以用其他解決方案代替,比如每個 lcore 變量。此外,某些鎖定技術比其他技術更高效。例如,讀-拷貝-更新(RCU)算法經常可以取代簡單的讀寫鎖。
34.5 編碼注意事項
34.5.1 內聯函數
小函數可以在頭文件中聲明為 static inline。這避免了調用指令的成本(以及相關的上下文保存)。然而,這種技術并不總是高效的;它取決于許多因素,包括編譯器。
34.5.2 分支預測
英特爾? C/C++ 編譯器(icc)/gcc 內置的輔助函數 likely() 和 unlikely() 允許開發人員指示代碼分支可能被執行或不會被執行。例如:
if (likely(x > 1))
do_stuff();
34.6 設置目標CPU類型
DPDK通過DPDK配置文件中的CONFIG_RTE_MACHINE選項支持針對CPU微架構的特定優化。優化程度取決于編譯器針對特定微架構的優化能力,因此盡可能使用最新的編譯器版本是可取的。
如果編譯器版本不支持特定的功能集(例如Intel? AVX指令集),則構建過程會優雅地降級到編譯器支持的最新功能集。
由于構建和運行時目標可能不相同,因此生成的二進制文件還包含一個在main()函數之前運行的平臺檢查,檢查當前機器是否適合運行該二進制文件。
除了編譯器優化之外,一組預處理器定義會自動添加到構建過程中(不考慮編譯器版本)。這些定義對應于目標CPU應該能夠支持的指令集。例如,為任何支持SSE4.2的處理器編譯的二進制文件將定義RTE_MACHINE_CPUFLAG_SSE4_2,從而為不同平臺啟用編譯時代碼路徑選擇。
對應用程序進行性能分析
英特爾處理器提供性能計數器來監視事件。英特爾提供的一些工具可用于對應用程序進行性能分析和基準測試。參閱英特爾出版的《VTune性能分析器Essentials》獲取更多信息。
對于DPDK應用程序,這僅限于Linux*應用程序環境中進行。
通過事件計數器應該監控的主要情況包括:
- 緩存未命中
- 分支錯誤預測
- DTLB未命中
- 長延遲指令和異常
有關應用程序分析的詳細信息,請參閱英特爾性能分析指南。
術語表
- ACL: 訪問控制列表 (Access Control List)
- API: 應用程序編程接口 (Application Programming Interface)
- ASLR: Linux* 內核地址空間布局隨機化 (Linux* kernel Address-Space Layout Randomization)
- BSD: 伯克利軟件發行版 (Berkeley Software Distribution)
- Clr: 清除 (Clear)
- CIDR: 無類域間路由 (Classless Inter-Domain Routing)
- Control Plane: 控制平面,涉及數據包路由和提供起點或終點。
- Core: 核心,如果處理器支持超線程,則一個核心可能包含多個邏輯核心或線程。
- Core Components: DPDK 提供的一組庫,包括 eal、ring、mempool、mbuf、timers 等。
- CPU: 中央處理器 (Central Processing Unit)
- CRC: 循環冗余校驗 (Cyclic Redundancy Check)
- ctrlmbuf: 攜帶控制數據的 mbuf。
- Data Plane: 與控制平面相對應,在網絡架構中用于轉發數據包的層。這些層必須高度優化以獲得良好性能。
- DIMM: 雙列直插內存模塊 (Dual In-line Memory Module)
- Doxygen: DPDK 中用于生成 API 參考的文檔生成器。
- DPDK: 數據平面開發工具包 (Data Plane Development Kit)
- DRAM: 動態隨機存取存儲器 (Dynamic Random Access Memory)
- EAL: 環境抽象層 (Environment Abstraction Layer),為應用程序和庫隱藏環境細節的通用接口。提供的服務包括:開發工具包加載和啟動、核心親和/分配過程、系統內存分配/描述、PCI 總線訪問、分區間通信。
- FIFO: 先進先出 (First In First Out)
- FPGA: 現場可編程門陣列 (Field Programmable Gate Array)
- GbE: 千兆以太網 (Gigabit Ethernet)
- HW: 硬件 (Hardware)
- HPET: 高精度事件定時器 (High Precision Event Timer),在 x86 平臺上提供精確的時間參考。
- ID: 標識符 (Identifier)
- IOCTL: 輸入/輸出控制 (Input/Output Control)
- I/O: 輸入/輸出 (Input/Output)
- IP: 互聯網協議 (Internet Protocol)
- IPv4: 互聯網協議版本 4 (Internet Protocol version 4)
- IPv6: 互聯網協議版本 6 (Internet Protocol version 6)
- lcore: 處理器的邏輯執行單元,有時稱為硬件線程。
- KNI: 內核網絡接口 (Kernel Network Interface)
- L1: 第一層 (Layer 1)
- L2: 第二層 (Layer 2)
- L3: 第三層 (Layer 3)
- L4: 第四層 (Layer 4)
- LAN: 局域網 (Local Area Network)
- LPM: 最長前綴匹配 (Longest Prefix Match)
- master lcore: 執行主()函數并啟動其他 lcore 的執行單元。
- mbuf: 一種用于內部攜帶消息(主要是網絡數據包)的數據結構。名稱來源于 BSD 棧。要了解數據包緩沖區或 mbuf 的概念,請參閱《TCP/IP 詳解》第 2 卷:實現。
- MESI: 修改(Modified)、互斥(Exclusive)、共享(Shared)、失效(Invalid)(CPU 緩存一致性協議)
- MTU: 最大傳輸單元 (Maximum Transfer Unit)
- NIC: 網絡接口卡 (Network Interface Card)
- OOO: 指令在 CPU 流水線內的亂序執行 (Out Of Order)
- NUMA: 非一致性內存訪問 (Non-uniform Memory Access)
- PCI: 外設連接接口 (Peripheral Connect Interface)
- PHY: OSI 模型的物理層的縮寫。
- pktmbuf: 攜帶網絡數據包的 mbuf。
- PMD: 輪詢模式驅動程序 (Poll Mode Driver)
- QoS: 服務質量 (Quality of Service)
- RCU: 讀-拷貝-更新算法 (Read-Copy-Update),用于替代簡單讀寫鎖。
- Rd: 讀取 (Read)
- RED: 隨機早期檢測 (Random Early Detection)
- RSS: 接收端縮放 (Receive Side Scaling)
- RTE: 運行時環境 (Run Time Environment),為快速數據包處理提供了一個快速簡單的框架,作為 Linux* 應用程序的輕量環境,并使用輪詢模式驅動程序(PMD)來提高速度。
- Rx: 接收 (Reception)
- Slave lcore: 不是主 lcore 的任何 lcore。
- Socket: 物理 CPU,包含多個核心。
- SLA: 服務等級協議 (Service Level Agreement)
- srTCM: 單速三色標記 (Single Rate Three Color Marking)
- SRTD: 調度器往返延遲 (Scheduler Round Trip Delay)
- SW: 軟件 (Software)
- Target: 在 DPDK 中,目標是架構、機器、執行環境和工具鏈的組合。例如:i686-native-linuxapp-gcc。
- TCP: 傳輸控制協議 (Transmission Control Protocol)
- TC: 流量類別 (Traffic Class)
- TLB: 轉換查找緩沖區 (Translation Lookaside Buffer)
- TLS: 線程本地存儲 (Thread Local Storage)
- trTCM: 雙速三色標記 (Two Rate Three Color Marking)
- TSC: 時間戳計數器 (Time Stamp Counter)
- Tx: 傳輸 (Transmission)
- TUN/TAP: TUN 和 TAP 是虛擬網絡內核設備。
- VLAN: 虛擬局域網 (Virtual Local Area Network)
- Wr: 寫入 (Write)
- WRED: 加權隨機早期檢測 (Weighted Random Early Detection)
- WRR: 加權輪詢 (Weighted Round Robin)
術語表(續)
- Figures
- Fig. 2.1: 核心組件架構
- Fig. 3.1: 在Linux應用程序環境中的EAL初始化
- Fig. 4.1: malloc堆和malloc庫中的malloc元素示例
- Fig. 5.1: 環形結構
- Fig. 5.2: 入隊第一步
- Fig. 5.3: 入隊第二步
- Fig. 5.4: 入隊最后一步
- Fig. 5.5: 出隊最后一步
- Fig. 5.6: 出隊第二步
- Fig. 5.7: 出隊最后一步
- Fig. 5.8: 多消費者入隊第一步
- Fig. 5.9: 多消費者入隊第二步
- Fig. 5.10: 多消費者入隊第三步
- Fig. 5.11: 多消費者入隊第四步
- Fig. 5.12: 多消費者入隊最后一步
- Fig. 5.13: 32位模數索引 - 示例1
- Fig. 5.14: 32位模數索引 - 示例2
- Fig. 6.1: 兩個通道和四排DIMM示例
- Fig. 6.2: 三個通道和兩個雙排DIMM示例
- Fig. 6.3: 存儲器中的mempool及其關聯的環
術語表(續)
-
Figures
- Fig. 7.1: 一個片段的mbuf
- Fig. 7.2: 三個片段的mbuf
- Fig. 18.1: DPDK多進程示例應用程序中的內存共享
- Fig. 19.1: DPDK KNI應用程序的組件
- Fig. 19.2: 通過mbufs進行的KNI數據包流
- Fig. 19.3: vHost-net架構概覽
- Fig. 19.4: KNI流量流向
- Fig. 21.1: 具有QoS支持的復雜數據包處理流水線
- Fig. 21.2: 分層調度器塊內部結構圖
- Fig. 21.3: 每個端口的調度層次結構
- Fig. 21.4: 每個端口的內部數據結構
- Fig. 21.5: 分層調度器Enqueue操作的預取管道
- Fig. 21.6: 分層調度器Dequeue操作的管道預取狀態機
- Fig. 21.7: DPDK Dropper的高級塊圖
- Fig. 21.8: Dropper的流程
- Fig. 21.9: Dropper中的數據流示例
- Fig. 21.10: 給定RED配置的數據包丟失概率
- Fig. 21.11: 使用因子1(藍曲線)和因子2(紅曲線)計算的初始丟包概率和實際丟包概率
-
Tables
- Table 21.1: 實施QoS的數據包處理流水線
- Table 21.2: 數據包處理流水線使用的基礎結構塊
- Table 21.3: 端口調度層次結構
- Table 21.4: 每個端口的調度器內部數據結構
- Table 21.5: 以太網幀開銷字段
- Table 21.6: 令牌桶通用操作
- Table 21.7: 令牌桶通用參數
- Table 21.8: 令牌桶持久數據結構
- Table 21.9: 令牌桶操作
- Table 21.10: Subport/Pipe流量類別上限執行持久數據結構
- Table 21.11: Subport/Pipe流量類別上限執行操作
- Table 21.12: 加權輪詢(WRR)
- Table 21.13: Subport流量類別過訂閱
- Table 21.14: 每個流量類別上限執行周期開始時從子端口級別到成員Pipe的水印傳播
- Table 21.15: 水印計算
- Table 21.16: RED配置參數
- Table 21.17: 替代方法的相對性能
- Table 21.18: 對應于RED配置文件的RED配置
術語表(續)
-
Figures
- Fig. 24.1: 網絡處理流水線示例,其中輸入端口0和1通過表0和1連接到輸出端口0、1和2
- Fig. 24.2: 數據包處理上下文中哈希表操作的步驟序列
- Fig. 24.3: 可配置鍵大小哈希表的數據結構
- Fig. 24.4: 關鍵查找操作的桶搜索流水線(可配置鍵大小哈希表)
- Fig. 24.5: 8字節鍵哈希表的數據結構
- Fig. 24.6: 16字節鍵哈希表的數據結構
-
Tables
- Table 24.1: 端口類型
- Table 24.2: 20端口抽象接口
- Table 24.3: 表類型
- Table 24.5: 適用于所有哈希表類型的通用配置參數
- Table 24.6: 適用于可擴展桶哈希表的特定配置參數
- Table 24.7: 適用于預計算鍵簽名哈希表的特定配置參數
- Table 24.8: 用于可配置鍵大小哈希表的主要大型數據結構(數組)
- Table 24.9: 桶數組條目的字段描述(可配置鍵大小哈希表)
- Table 24.10: 桶搜索流水線階段描述(可配置鍵大小哈希表)
- Table 24.11: Match、Match_Many和Match_Pos的查找表
- Table 24.12: Match、Match_Many和Match_Pos的折疊查找表
- Table 24.13: 用于8字節和16字節鍵大小哈希表的主要大型數據結構(數組)
- Table 24.14: 桶數組條目的字段描述(8字節和16字節鍵哈希表)
- Table 24.15: 桶搜索流水線階段描述(8字節和16字節鍵哈希表)
- Table 24.16: 下一跳操作(已保留)
- Table 24.17: 用戶動作示例