@ -29,11 +29,6 @@ UA编程主要处理硬件送到指定软件的分组数据;
寄存器访问控制编程主要是对硬件各寄存器资源的访问控制。
对硬件规则的读写与对硬件其他寄存器的读写需要了解FAST架构的虚拟地址空间定义。
\subsection { FAST软件获取}
\label { subsec:app:fast_ get-soft}
FAST的软硬件代码和相关工具下载请查看文章结尾的百度网盘链接。
\subsection { FAST代码结构}
\subsubsection { 目录结构}
@ -42,8 +37,8 @@ FAST的软硬件代码和相关工具下载请查看文章结尾的百度网盘
\begin { table} [!ht]
\small
\centering
\caption { 以太网帧格式 }
\label { tab:c:wireshark_ eth-format }
\caption { FAST代码目录结构 }
\label { tab:a:fast_ dir-structure }
\begin { tabular} { |c|c|c|} \hline
\heiti 序号 & \heiti 目录名称 & \heiti 说明\\ \hline
1 & include & 开发所用头文件目录\\ \hline
@ -57,23 +52,31 @@ FAST的软硬件代码和相关工具下载请查看文章结尾的百度网盘
\subsubsection { 头文件}
\begin { enumerate}
\item Fast\_ vaddr.h: FAST平台硬件资源访问对应的虚拟地址空间定义
\item Fast\_ type.h: FAST平台所用数据类型定义
\item Fast\_ err.h: FAST平台错误号定义
\item Fast\_ struct.h: FAST平台数据结构类型定义
\item Fast.h: FAST平台所有开发函数定义, 包含上述所有头文件
\item 其他:不同平台的适配头文件
\item \textbf { fast\_ vaddr.h: } FAST平台硬件资源访问对应的虚拟地址空间定义;
\item \textbf { fast\_ type.h: } FAST平台所用数据类型定义;
\item \textbf { fast\_ err.h: } FAST平台错误号定义;
\item \textbf { fast\_ struct.h: } FAST平台数据结构类型定义;
\item \textbf { fast.h: } FAST平台所有开发函数定义, 包含上述所有头文件;
\item \textbf { 其他:} 不同平台的适配头文件。
\end { enumerate}
\subsubsection { 库文件}
\begin { enumerate}
\item \textbf { libreg: } libreg主要是用来实现对硬件寄存器读写动作的封装, 底层支持标准PCIe设备的寄存器读写和NetMagic08使用NMAC方式的寄存器读写。在FAST平台所有对硬件的寄存器读写全部封装为统一的接口函数, 主要包括硬件资源初始化、寄存器读和寄存器写等函数。用户只需要根据此接口函数读写寄存器即可, 底层具体实现用户可以不用关心;
\item \textbf { librule: } librule主要是实现对硬件流表规则的软件抽象与具体实现, 该规则库实现了一种与硬件对应的流表字段序列, 仅是一种参考实现。用户可根据硬件查表关键字来重新定义规则字段序列, 但必须要求硬件字段序列与软件字段序列一一对应, 包括比特位宽与大小端定义。该库封装了规则的基本操作函数, 如初始化规则、添加规则、修改规则和删除规则;
\item \textbf { libua: } libua主要是用来支持多用户对不同特征流的处理开发和同一特征流在不同用户进程段流水处理开发。该库的主要功能是使用规则配置的方式设置与用户关联的特征流属性, 并提供用户接收与发送该属性特征流的开发接口, 实现用户对特征流的接收、处理与发送操作。该库主要封装了UA的初始化函数、流处理回调函数、分组发送函数等。
\end { enumerate}
\subsubsection { 开发示例}
开发示例提供了一个基于FAST架构的2层交换机实例,
综合使用了libreg和libua两个库实现了一个全软件的2层交换机功能。
开发示例提供了一个基于FAST架构的二 层交换机实例,
综合使用了libreg和libua两个库实现了一个全软件的二 层交换机功能。
\begin { enumerate}
\item L 2switch
L 2switch是基于FAST架构开发一个2层以太网交换机原型,
\item l 2switch
l 2switch是基于FAST架构开发一个2层以太网交换机原型,
通过对流表默认规则的设置, 将硬件所有的分组重定向到UA程序,
然后在UA的分组处理回调函数中实现对分组的2层交换,
然后将分组从指定端口发送或泛洪发送。
@ -94,263 +97,52 @@ FAST的软硬件代码和相关工具下载请查看文章结尾的百度网盘
示例程序的另一种表现就是FAST提供的一些小工具, 包括单独的寄存器读写命令、规则输出命令、端口状态显示命令和端口分组计数命令。
\begin { enumerate}
\item R eg\_ rw
\item r eg\_ rw
该工具主要是使用libreg库实现一个对用户指定的寄存器进行读写访问操作, 展示了用户如何调用libreg的相关库函数进行寄存器访问操作的方法。
\item R ule\_ hw
\item r ule\_ hw
该工具主要是使用libreg库和librule库实现对硬件流表的获取并分组输出操作, 展示了用户如何调用librule库的相关库函数进行规则操作。该工具目前只使用了硬件规则的读取操作, 更多规则的功能操作可参考综合测试程序
\item P ort\_ status
该工具主要是使用libreg库和librule库实现对硬件流表的获取并分组输出操作, 展示了用户如何调用librule库的相关库函数进行规则操作。该工具目前只使用了硬件规则的读取操作, 更多规则的功能操作可参考综合测试程序。
\item p ort\_ status
该工具主要使用libreg库实现了对各端口的协商状态、链路状态等寄存器的访问并进行各状态值的解释。主要展示了不同端口状态的寄存器地址如何计算, 各状态寄存器值返回如何解释, 示例代码中包含了目前支持的所有状态寄存器及对应功能说明
\item P ort\_ counts
该工具主要使用libreg库实现了对各端口的协商状态、链路状态等寄存器的访问并进行各状态值的解释。主要展示了不同端口状态的寄存器地址如何计算, 各状态寄存器值返回如何解释, 示例代码中包含了目前支持的所有状态寄存器及对应功能说明。
\item p ort\_ counts
该工具主要使用libreg库实现了对各端口分组计数的统计显示, 主要展示了不同功能计数统计的寄存器虚拟地址空间定义, 各端口对应功能寄存器的计算方法。示例代码中包含了目前支持的所有功能计数统计寄存器定义与说明
该工具主要使用libreg库实现了对各端口分组计数的统计显示, 主要展示了不同功能计数统计的寄存器虚拟地址空间定义, 各端口对应功能寄存器的计算方法。示例代码中包含了目前支持的所有功能计数统计寄存器定义与说明。
\end { enumerate}
\subsubsection { 综合测试}
综合测试程序包含了libreg、librule和libua库的综合开发示例功能。
首先,用户可以通过此程序了解各功能库的主要使用函数及调用顺序;
其次,用户可以通过此程序的编译参数了解不同功能库如何添加对应库功能支持
其次,用户可以通过此程序的编译参数了解不同功能库如何添加对应库功能支持。
subsection{ FAST代码运行}
\ subsection{ FAST代码运行}
\subsubsection { 软硬件环境}
FAST平台由湖南新实网络科技有限公司提供销售、售后与技术支持。
该平台可通过采购或免费申请试用获取, 用户拿到FAST平台后,
默认系统环境均已支持FAST硬件基础版本与FAST软件基础版本。
FAST硬件基础版本是指基于FAST的标准5组 流水线功能;
FAST硬件基础版本是指基于FAST的标准5级 流水线功能;
FAST软件基础版本是指FAST- XXX软件版本。
如果用户只需要了解软件功能, 可以不用FAST设备,
FAST软件可在通用Linux系统中进行编译与测试,
没有硬件平台的软件代码,不能进行硬件寄存器读写、规则配置与报文收发功能。
\subsubsection { 代码获取}
参考第\ref { subsec:app:fast_ get-soft} 节
\subsubsection { 代码编译}
\begin { enumerate}
\item 解压代码
\begin { code} [console]
openbox@OpenBox~/hnxs$ tar – zxf fast - 0 . 4 . 5 .tar.gz
openbox@OpenBox~/hnxs$ cd fast - 0 . 4 . 5
openbox@OpenBox~/hnxs/fast-0.4.5$ ls
aclocal.m4 config.guess config.sub include ltmain.sh NEWS
app config.h configure INSTALL Makefile README
AUTHORS config.h.in configure.ac install-sh Makefile.am src
ChangeLog config.log COPYING lib Makefile.in stamp-h1
compile config.status depcomp libtool missing tools
openbox@OpenBox~/hnxs$ tar – zxf fast - 0 . 4 . 5 .tar.gz
\end { code}
\item 配置环境
\begin { code} [console]
openbox@OpenBox~/hnxs/fast-0.4.5$ . / configure
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... gawk
checking whether make sets $ ( MAKE ) ... yes
checking whether make supports nested variables... yes
checking whether make supports nested variables... (cached) yes
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables...
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking whether gcc understands -c and -o together... yes
checking for style of include used by make... GNU
checking dependency style of gcc... gcc3
checking whether NLS is requested... yes
checking for intltool >= 0.35.0... 0.50.2 found
checking for intltool-update... /usr/bin/intltool-update
checking for intltool-merge... /usr/bin/intltool-merge
checking for intltool-extract... /usr/bin/intltool-extract
checking for xgettext... /usr/bin/xgettext
checking for msgmerge... /usr/bin/msgmerge
checking for msgfmt... /usr/bin/msgfmt
checking for gmsgfmt... /usr/bin/msgfmt
checking for perl... /usr/bin/perl
checking for perl >= 5.8.1... 5.18.2
checking for XML::Parser... ok
checking how to run the C preprocessor... gcc -E
checking for grep that handles long lines and -e... /bin/grep
checking for egrep... /bin/grep -E
checking for ANSI C header files... yes
checking for sys/types.h... yes
checking for sys/stat.h... yes
checking for stdlib.h... yes
checking for string.h... yes
checking for memory.h... yes
checking for strings.h... yes
checking for inttypes.h... yes
checking for stdint.h... yes
checking for unistd.h... yes
checking locale.h usability... yes
checking locale.h presence... yes
checking for locale.h... yes
checking for LC_ MESSAGES... yes
checking libintl.h usability... yes
checking libintl.h presence... yes
checking for libintl.h... yes
checking for ngettext in libc... yes
checking for dgettext in libc... yes
checking for bind_ textdomain_ codeset... yes
checking for msgfmt... (cached) /usr/bin/msgfmt
checking for dcgettext... yes
checking if msgfmt accepts -c... yes
checking for gmsgfmt... (cached) /usr/bin/msgfmt
checking for xgettext... (cached) /usr/bin/xgettext
checking build system type... x86_ 64-unknown-linux-gnu
checking host system type... x86_ 64-unknown-linux-gnu
checking how to print strings... printf
checking for a sed that does not truncate output... /bin/sed
checking for fgrep... /bin/grep -F
checking for ld used by gcc... /usr/bin/ld
checking if the linker (/usr/bin/ld) is GNU ld... yes
checking for BSD- or MS-compatible name lister (nm)... /usr/bin/nm -B
checking the name lister (/usr/bin/nm -B) interface... BSD nm
checking whether ln -s works... yes
checking the maximum length of command line arguments... 1572864
checking whether the shell understands some XSI constructs... yes
checking whether the shell understands "+="... yes
checking how to convert x86_ 64-unknown-linux-gnu file names to x86_ 64-unknown-linux-gnu format... func_ convert_ file_ noop
checking how to convert x86_ 64-unknown-linux-gnu file names to toolchain format... func_ convert_ file_ noop
checking for /usr/bin/ld option to reload object files... -r
checking for objdump... objdump
checking how to recognize dependent libraries... pass_ all
checking for dlltool... no
checking how to associate runtime and link libraries... printf % s\n
checking for ar... ar
checking for archiver @FILE support... @
checking for strip... strip
checking for ranlib... ranlib
checking command to parse /usr/bin/nm -B output from gcc object... ok
checking for sysroot... no
checking for mt... mt
checking if mt is a manifest tool... no
checking for dlfcn.h... yes
checking for objdir... .libs
checking if gcc supports -fno-rtti -fno-exceptions... no
checking for gcc option to produce PIC... -fPIC -DPIC
checking if gcc PIC flag -fPIC -DPIC works... yes
checking if gcc static flag -static works... yes
checking if gcc supports -c -o file.o... yes
checking if gcc supports -c -o file.o... (cached) yes
checking whether the gcc linker (/usr/bin/ld -m elf_ x86_ 64) supports shared libraries... yes
checking whether -lc should be explicitly linked in... no
checking dynamic linker characteristics... GNU/Linux ld.so
checking how to hardcode library paths into programs... immediate
checking whether stripping libraries is possible... yes
checking if libtool supports shared libraries... yes
checking whether to build shared libraries... yes
checking whether to build static libraries... yes
checking that generated files are newer than configure... done
configure: creating ./config.status
config.status: creating Makefile
config.status: creating include/Makefile
config.status: creating libreg/Makefile
config.status: creating libua/Makefile
config.status: creating librule/Makefile
config.status: creating po/Makefile.in
config.status: creating src/Makefile
config.status: creating tools/Makefile
config.status: creating tools/port_ counts/Makefile
config.status: creating tools/port_ status/Makefile
config.status: creating tools/rule/Makefile
config.status: creating tools/reg_ rw/Makefile
config.status: creating tools/debug/Makefile
config.status: creating examples/Makefile
config.status: creating examples/l2switch/Makefile
config.status: creating config.h
config.status: executing depfiles commands
config.status: executing default-1 commands
config.status: executing libtool commands
config.status: executing po/stamp-it commands
openbox@OpenBox~/hnxs/fast-0.4.5$ . / configure
\end { code}
\item 编译
\begin { code} [console]
openbox@OpenBox~/hnxs/fast-0.4.5$ make
make all-recursive
make[1]: 正在进入目录 `/home/openbox/hnxs/fast-0.4.5'
Making all in include
make[2]: 正在进入目录 `/home/openbox/hnxs/fast-0.4.5/include'
make[2]: 没有什么可以做的为 `all'。
make[2]:正在离开目录 `/home/openbox/hnxs/fast-0.4.5/include'
Making all in libreg
make[2]: 正在进入目录 `/home/openbox/hnxs/fast-0.4.5/libreg'
CC main_ libreg.o
AR libreg.a
make[2]:正在离开目录 `/home/openbox/hnxs/fast-0.4.5/libreg'
Making all in libua
make[2]: 正在进入目录 `/home/openbox/hnxs/fast-0.4.5/libua'
CC main_ libua.o
AR libua.a
make[2]:正在离开目录 `/home/openbox/hnxs/fast-0.4.5/libua'
Making all in librule
make[2]: 正在进入目录 `/home/openbox/hnxs/fast-0.4.5/librule'
CC main_ librule.o
AR librule.a
make[2]:正在离开目录 `/home/openbox/hnxs/fast-0.4.5/librule'
Making all in tools
make[2]: 正在进入目录 `/home/openbox/hnxs/fast-0.4.5/tools'
Making all in port_ counts
make[3]: 正在进入目录 `/home/openbox/hnxs/fast-0.4.5/tools/port_ counts'
CC main_ port_ counts.o
CCLD port_ counts
make[3]:正在离开目录 `/home/openbox/hnxs/fast-0.4.5/tools/port_ counts'
Making all in port_ status
make[3]: 正在进入目录 `/home/openbox/hnxs/fast-0.4.5/tools/port_ status'
CC main_ port_ status.o
CCLD port_ status
make[3]:正在离开目录 `/home/openbox/hnxs/fast-0.4.5/tools/port_ status'
Making all in rule
make[3]: 正在进入目录 `/home/openbox/hnxs/fast-0.4.5/tools/rule'
CC main_ rule.o
CCLD rule
make[3]:正在离开目录 `/home/openbox/hnxs/fast-0.4.5/tools/rule'
Making all in reg_ rw
make[3]: 正在进入目录 `/home/openbox/hnxs/fast-0.4.5/tools/reg_ rw'
CC main_ reg_ rw.o
CCLD reg_ rw
make[3]:正在离开目录 `/home/openbox/hnxs/fast-0.4.5/tools/reg_ rw'
Making all in debug
make[3]: 正在进入目录 `/home/openbox/hnxs/fast-0.4.5/tools/debug'
CC main_ debug.o
CCLD debug
make[3]:正在离开目录 `/home/openbox/hnxs/fast-0.4.5/tools/debug'
make[3]: 正在进入目录 `/home/openbox/hnxs/fast-0.4.5/tools'
make[3]: 没有什么可以做的为 `all-am'。
make[3]:正在离开目录 `/home/openbox/hnxs/fast-0.4.5/tools'
make[2]:正在离开目录 `/home/openbox/hnxs/fast-0.4.5/tools'
Making all in po
make[2]: 正在进入目录 `/home/openbox/hnxs/fast-0.4.5/po'
make[2]: 没有什么可以做的为 `all'。
make[2]:正在离开目录 `/home/openbox/hnxs/fast-0.4.5/po'
Making all in src
make[2]: 正在进入目录 `/home/openbox/hnxs/fast-0.4.5/src'
CC fast-main.o
CCLD fast
make[2]:正在离开目录 `/home/openbox/hnxs/fast-0.4.5/src'
Making all in examples
make[2]: 正在进入目录 `/home/openbox/hnxs/fast-0.4.5/examples'
Making all in l2switch
make[3]: 正在进入目录 `/home/openbox/hnxs/fast-0.4.5/examples/l2switch'
CC main_ l2switch.o
CCLD l2switch
make[3]:正在离开目录 `/home/openbox/hnxs/fast-0.4.5/examples/l2switch'
make[3]: 正在进入目录 `/home/openbox/hnxs/fast-0.4.5/examples'
make[3]: 没有什么可以做的为 `all-am'。
make[3]:正在离开目录 `/home/openbox/hnxs/fast-0.4.5/examples'
make[2]:正在离开目录 `/home/openbox/hnxs/fast-0.4.5/examples'
make[2]: 正在进入目录 `/home/openbox/hnxs/fast-0.4.5'
make[2]: 没有什么可以做的为 `all-am'。
make[2]:正在离开目录 `/home/openbox/hnxs/fast-0.4.5'
make[1]:正在离开目录 `/home/openbox/hnxs/fast-0.4.5'
openbox@OpenBox~/hnxs/fast-0.4.5$ make
\end { code}
\end { enumerate}
@ -366,144 +158,40 @@ FAST软件可在通用Linux系统中进行编译与测试,
\subsubsection { UM数据结构}
\begin { code} [c]
struct um_ metadata{
#if defined(_ _ LITTLE_ ENDIAN) /*INTER*/
#ifdef FAST_ 10
u64 ts:32, /**< @brief 报文接收的时间戳 @note 如果用户需要使用表示更大的时间, 建议存储在第二拍数据中( user[2]字段)*/
ts2:12,
flowID:14, /**< @brief 流ID号*/
priority:3, /**< @brief 报文优先级*/
discard:1, /**< @brief 指示报文是否丢弃 @note 默认为0, 表示不丢弃, 置1时表示丢弃*/
pktdst:1, /**< @brief 报文的输出目的方向 @note 0表示输出到网络端口, 1表示输出到CPU*/
pktsrc:1; /**< @brief 报文的输入源方向 @note 0表示网络端口输入, 1表示从CPU输入*/
u64 outport:16, /**< @brief 报文输出端口号 @note 以bitmap形式表示, 1表示从0号端口输出; 8表示从3号端口输出*/
seq:12, /**< @brief 报文接收时的序列号 @note 每个端口独立维护一个编号*/
dstmid:8, /**< @brief 报文下次处理的目的模块编号*/
srcmid:8, /**< @brief 报文上次处理时的模块编号*/
len:12, /**< @brief 报文长度 @note 最大可表示4095字节, 但FAST平台报文缓存区最大为2048, 完整以太网报文的MTU不要超过1500*/
inport:4, /**< @brief 输入端口号 @note 取值: 0——15, 最多表示16个输入端口*/
ttl:4; /**< @brief 报文通过模块的TTL值, 每过一个处理模块减1*/
#elif FAST_ 20
u64 ts:32, /**< @brief 时间戳*/
reserve:17, /**< @brief 保留*/
pktsrc:1, /**< @brief 分组的来源, 0为网络接口输入, 1为CPU输入, 此比特位在进入硬件时会交换到pkttype位置, 保留位为18位*/
flowID:14; /**< @brief 流ID*/
u64 seq:8, /**< @brief 分组接收序列号*/
pst:8, /**< @brief 标准协议类型(参考硬件定义)*/
dstmid:8, /**< @brief 下一个处理分组的模块ID*/
srcmid:8, /**< @brief 最近一次处理分组的模块ID*/
len:12, /**< @brief 报文长度*/
discard:1, /**< @brief 丢弃位*/
priority:3, /**< @brief 分组优先级*/
outport:6, /**< @brief 单播: 分组输出端口ID, 组播/泛洪:组播/泛洪表地址索引*/
outtype:2, /**< @brief 输出类型, 00: 单播, 01: 组播, 10: 泛洪, 11: 从输入接口输出*/
inport:6, /**< @brief 分组的输入端口号*/
pktdst:1, /**< @brief 分组目的, 0为网络接口输出, 1为送CPU*/
pkttype:1; /**< @brief 报文类型, 0: 数据报文, 1: 控制报文。硬件识别报文类别后, 会将pktsrc位交换到此, 恢复硬件数据格式*/
#endif
u64 user[2]; /**< @brief 用户自定义metadata数据格式与内容 @remarks 此字段由可用户改写, 但需要保证数据大小严格限定在16字节*/
#elif defined(_ _ BIG_ ENDIAN) /**/
#error "(_ _ BIG_ ENDIAN)Please fix <asm/byteorder.h>"
#else
#error "Please fix <asm/byteorder.h>"
#endif
} ;
u64 ts:32, /**< @brief 时间戳*/
reserve:17, /**< @brief 保留*/
pktsrc:1, /**< @brief 分组的来源, 0为网络接口输入, 1为CPU输入*/
flowID:14; /**< @brief 流ID*/
u64 seq:8, /**< @brief 分组接收序列号*/
pst:8, /**< @brief 标准协议类型(参考硬件定义)*/
dstmid:8, /**< @brief 下一个处理分组的模块ID*/
srcmid:8, /**< @brief 最近一次处理分组的模块ID*/
len:12, /**< @brief 报文长度*/
discard:1, /**< @brief 丢弃位*/
priority:3, /**< @brief 分组优先级*/
outport:6, /**< @brief 单播: 分组输出端口ID, 组播/泛洪:组播/泛洪表地址索引*/
outtype:2, /**< @brief 输出类型, 00: 单播, 01: 组播, 10: 泛洪, 11: 从输入接口输出*/
inport:6, /**< @brief 分组的输入端口号*/
pktdst:1, /**< @brief 分组目的, 0为网络接口输出, 1为送CPU*/
pkttype:1; /**< @brief 报文类型, 0: 数据报文, 1: 控制报文。硬件识别报文类别后, 会将pktsrc位交换到此, 恢复硬件数据格式*/
u64 user[2]; /**< @brief 用户自定义metadata数据格式与内容 @remarks 此字段由可用户改写, 但需要保证数据大小严格限定在16字节*/
} ;
\end { code}
\subsubsection { FAST报文数据结构}
\begin { code} [c]
struct fast_ packet
{
union
{
struct um_ metadata um; /**< @brief UM模块数据格式定义 @see ::um_ metadata */
struct ctl_ metadata cm; /**< 控制报文格式定义*/
struct common_ metadata md; /**< 公共控制信息, 报文类型( 0: 数据, 1: 控制) */
} ;
#ifdef OPENBOX_ S28
u16 flag; /**< @brief 2字节对齐标志, 主要是为了IP地址的对齐 @note 此标志在内核会用来标记是一个FAST类型报文, 建议用户不使用些字段*/
#endif
u8 data[1514]; /**< @brief 完整以太网报文数据, 暂时不含CRC数据*/
} ;
\end { code}
\subsubsection { 流关键字数据结构}
\begin { code} [c]
struct flow /*2017/06/01开始启用, 支持IPv6*/
struct fast_ packet
{
union
{
u8 dmac[ETH_ ALEN]; /**< @brief Ethernet source address. */
u8 smac[ETH_ ALEN]; /**< @brief Ethernet destination address. */
u16 tci; /**< @brief 0 if no VLAN, VLAN_ TAG_ PRESENT set otherwise. */
u16 type; /**< @brief Ethernet frame type. */
//eth-16;
u8 proto; /**< @brief IP protocol or lower 8 bits of ARP opcode. */
u8 tos; /**< @brief IP ToS. */
u8 ttl; /**< @brief IP TTL/hop limit. */
u8 port:6, /**< @brief Input Port*/
frag:2; /**< @brief One of OVS_ FRAG_ TYPE_ *. */
//ip=16+4;
union {
struct {
u32 src; /**< @brief IP source address. */
u32 dst; /**< @brief IP destination address. */
//addr;
union {
struct {
u16 sport; /**< @brief TCP/UDP/SCTP source port. */
u16 dport; /**< @brief TCP/UDP/SCTP destination port. */
u16 flags; /**< @brief TCP flags. */
} tp; /**< @brief IPv4的传输层端口与标志信息*/
struct {
u8 sha[ETH_ ALEN]; /**< @brief ARP source hardware address. */
u8 tha[ETH_ ALEN]; /**< @brief ARP target hardware address. */
} arp; /**< @brief ARP的MAC地址信息*/
} ; /**< @brief IPv4传输层信息与ARP信息共用体, 二者互斥存在*/
} ipv4; /**< @brief IPv4协议相关字段*/
struct {
struct in6_ addr src; /**< @brief IPv6 source address. */
struct in6_ addr dst; /**< @brief IPv6 destination address. */
//addr;
u32 label; /**< @brief IPv6 flow label. */
union {
struct {
u16 sport; /**< @brief TCP/UDP/SCTP source port. */
u16 dport; /**< @brief TCP/UDP/SCTP destination port. */
u16 flags; /**< @brief TCP flags. */
} tp; /**< @brief IPv6的传输层端口与标志信息*/
/*512位宽表项不够, 暂不使用ND协议中的targetIP!!!为方便以后扩展,将其移至末尾*/
#if 0
struct {
u8 sll[ETH_ ALEN]; /**< @brief ND source link layer address. */
u8 tll[ETH_ ALEN]; /**< @brief ND target link layer address. */
struct in6_ xaddr target; /**< @brief ND target address. */
} nd;
#endif
} ; /**< @brief IPv6传输层信息与ND信息共用体, 二者互斥存在*/
u16 nil;
} ipv6; /**< @brief IPv6协议相关字段*/
} ;
} ;
\end { code}
\subsubsection { 流数据结构}
\begin { code} [c]
struct fast_ rule{
struct flow key; /**< @brief 规则内容存储结构 @see ::flow*/
struct flow mask; /**< @brief 规则掩码设置结构,与key一一对应 @see ::flow*/
u32 priority; /**< @brief 规则的优先级设置*/
u32 valid; /**< @brief 规则的有效标志设置,要删除一条规则只需要将此标记置0,并更新到硬件*/
u32 action; /**< @brief 规则所对应的执行动作, 动作由两部分组成, 高4位为ACTION枚举类型, 低28位不此类型对应的值 @see ::ACTION*/
/*此前数据必须要写入到硬件*/
u32 flow_ stats_ len; /**< @brief 流表信息长度*/
u64 *flow_ stats_ info; /**< @brief 流表信息存储指针位置*/
#ifdef OPENBOX_ S4
u32 *tmp; /*在S4系统中, 上面变量指针大小为32*/
#endif
u64 cookie; /**< @brief 用来存储流的cookie信息, 软件使用*/
u64 cookie_ mask; /**< @brief 用来存储流cookie的掩码信息, 软件使用*/
u32 md5[4]; /**< @brief MD5值 @note 用来区分规则的唯一性,软件生成规则时即会判断是否规则重复*/
u32 pad[18]; /**< @brief 总长256B, 此为确保数据结构大小做的填充*/
struct um_ metadata um; /**< @brief UM模块数据格式定义 @see ::um_ metadata */
struct ctl_ metadata cm; /**< 控制报文格式定义*/
struct common_ metadata md; /**< 公共控制信息, 报文类型( 0: 数据, 1: 控制) */
} ;
#ifdef OPENBOX_ S28
u16 flag; /**< @brief 2字节对齐标志, 主要是为了IP地址的对齐*/
#endif
u8 data[1514]; /**< @brief 完整以太网报文数据, 暂时不含CRC数据*/
} ;
\end { code}
\subsection { FAST开发函数}
@ -511,6 +199,7 @@ FAST软件可在通用Linux系统中进行编译与测试,
\subsubsection { 硬件资源与寄存器}
\begin { enumerate}
\item int fast\_ init\_ hw(u64 addr,u64 len);
硬件资源初始化。所有涉及到需要操作硬件寄存器、流表和动作等均需要先调用此函数,
实例化硬件资源,使软件具体访问硬件的能力。
@ -523,6 +212,7 @@ FAST软件可在通用Linux系统中进行编译与测试,
返回值: 0表示硬件资源实例化正常, 非零表示失败,
如果失败将无法对硬件进行任何操作,程序将自动退出。
\item void fast\_ distroy\_ hw(void);
硬件资源销毁。PCIe设备主要是撤销对硬件资源的映射,
OpenBox-S4主要是对设备发送关闭报文。
一般情况下,用户程序退出时应该调用此函数,释放资源。
@ -530,6 +220,7 @@ FAST软件可在通用Linux系统中进行编译与测试,
即使用户不调用此函数,当程序正常退出时,系统也能正常回收资源,
不影响程序再次运行使用。
\item u64 fast\_ reg\_ rd(u64 regaddr);
寄存器读函数。读取用户指定寄存器位置的值返回。
该函数内部会根据平台的不同使用不同的方法去访问硬件寄存器。
PCIe的平台以正常寄存器方式访问, 而NetMagic~08需要使用NMAC报文进行交互获取。
@ -544,7 +235,8 @@ FAST软件可在通用Linux系统中进行编译与测试,
返回值: 返回该寄存器对应的值。该值的位宽是64位,
在所有FAST平台寄存器的位宽均为64位。
\item void fast\_ reg\_ wr(u64 regaddr,u64 regvalue);
\item void fast\_ reg\_ wr(u64 regaddr,u64 regvalue)。
寄存器写函数。将指定值写对硬件对应的寄存器位置。
该函数内部会根据平台的不同使用不同的方法去操作硬件寄存器。
PCIe的平台以正常寄存器方式访问, 而NetMagic~08需要使用NMAC报文进行交互获取。
@ -560,9 +252,11 @@ FAST软件可在通用Linux系统中进行编译与测试,
参数: regvalue, 表示要写入上述参数寄存器位置的值。该值的位宽为64位。
\end { enumerate}
\subsubsection { 流表操作}
\begin { enumerate}
\item void init\_ rule(u32 default\_ action);
初始化规则。初始化规则函数的主要功能是在软件分配软件规则空间,
将硬件规则空间清零,设置硬件规则的默认动作。
该函数只在进行流表操作的应用中进行调用,而且只能被调用一次。
@ -576,141 +270,71 @@ FAST软件可在通用Linux系统中进行编译与测试,
流表可以为空,但默认动作必须要有。详细的动作含义可以参考动作说明。
\item int fast\_ add\_ rule(struct fast\_ rule *rule);
添加一条规则。添加规则函数,先将用户的规则添加在软件流表中,
经过各种比较判断后,看是否能正常添加,有无冲突或是否存在,
如果可以正常添加,则先将规则存储在软件,
然后将此条软件规则数据通过寄存器方式下发到硬件对应规则的存储位置。
参数: rule, 规则对象, 内部具体字段参考流规则数据结构定义
参数: rule, 规则对象, 内部具体字段参考流规则数据结构定义。
返回值:返回当前添加规则成功后此条规则所在的索引号
返回值:返回当前添加规则成功后此条规则所在的索引号。
\item int fast\_ modify\_ rule(struct fast\_ rule *rule,int idx);
修改一条已经存在的规则。此函数主要是用来修改已经存在的规则,
对其关键字、掩码、动作和优先级等进行修改。
该函数的索引值参数如果指向一条空规则,其操作流程将类似于添加规则函数。
参数: rule, 新规则对象, 内部具体字段参考流规则数据结构定义
参数: rule, 新规则对象, 内部具体字段参考流规则数据结构定义。
参数: idx, 旧规则所在索引号
参数: idx, 旧规则所在索引号。
返回值: 返回输入参数的idx值说明操作成功, 其他值说明操作失败
\item int fast\_ del\_ rule(int idx);
删除一条已经存储的规则,或将一条规则置为无效。
只需要提供规则所在的索引号,软件可通过索引号定位到对应硬件存储规则位置,
将规则的有效位置为无效,实现一条规则的删除。
删除硬件成功后,将其对应的软件规则进行清除。
参数: idx, 删除规则所在索引号
参数: idx, 删除规则所在索引号。
返回值: 返回输入参数的idx值说明操作成功, 其他值说明操作失败
返回值: 返回输入参数的idx值说明操作成功, 其他值说明操作失败。
\item int read\_ hw\_ rule(struct fast\_ rule *rule,int index);
读取一条硬件规则。将存储在硬件规则内对应索引的数据读取出来,
还原为一条软件规则数据,存储在用户提供的指针位置。
参数: rule, 将要存储规则的内存指针
参数: rule, 将要存储规则的内存指针。
参数: idx, 将要读取规则所在硬件的索引号
参数: idx, 将要读取规则所在硬件的索引号。
返回值: 返回输入参数的idx值说明操作成功, 其他值说明操作失败
\item void print\_ hw\_ rule(void);
返回值: 返回输入参数的idx值说明操作成功, 其他值说明操作失败。
\item void print\_ hw\_ rule(void)。
打印硬件所有规则信息。此函数是上一个读取硬件规则条目信息的集合操作,
将所有硬件流规则信息一一读出,并打印输出在屏幕上。
\end { enumerate}
\subsubsection { UA编程}
\begin { enumerate}
\item int fast\_ ua\_ init(int mid,fast\_ ua\_ recv\_ callback callback);
UA编程初始化函数。
\item void fast\_ ua\_ destroy(void);
UA编程注销函数。
\item int fast\_ ua\_ send(struct fast\_ packet *pkt,int pkt\_ len);
UA程序发送报文函数
\item void fast\_ ua\_ recv();
\item void fast\_ ua\_ recv()。
启动UA接收用户特征流程序函数
\end { enumerate}
\subsection { FAST虚拟地址空间定义}
\subsubsection { debug um}
\begin { code} [c]
#define FAST_ DEBUG_ UM_ DC FAST_ HW_ UM+0x0000
#define FAST_ DEBUG_ UM_ GPP FAST_ HW_ UM+0x2000
#define FAST_ DEBUG_ UM_ GKE FAST_ HW_ UM+0x4000
#define FAST_ DEBUG_ UM_ GME FAST_ HW_ UM+0x6000
#define FAST_ DEBUG_ UM_ GAC FAST_ HW_ UM+0x8400
#define FAST_ DEBUG_ UM_ GOE FAST_ HW_ UM+0xA000
/*GPP模块*/
#define FAST_ DEBUG_ GPP_ GPP_ STATUS FAST_ DEBUG_ UM_ GPP+0x00
#define FAST_ DEBUG_ GPP_ IN_ GPP_ DATA_ COUNT FAST_ DEBUG_ UM_ GPP+0x08
#define FAST_ DEBUG_ GPP_ OUT_ GPP_ MD_ COUNT FAST_ DEBUG_ UM_ GPP+0x10
#define FAST_ DEBUG_ GPP_ OUT_ GPP_ PHY_ COUNT FAST_ DEBUG_ UM_ GPP+0x18
#define FAST_ DEBUG_ GPP_ OUT_ GPP_ CACHE_ COUNT FAST_ DEBUG_ UM_ GPP+0x20
/*GKE模块*/
#define FAST_ DEBUG_ GKE_ GKE_ STATUS FAST_ DEBUG_ UM_ GKE+0x00
#define FAST_ DEBUG_ GKE_ IN_ GKE_ MD_ COUNT FAST_ DEBUG_ UM_ GKE+0x08
#define FAST_ DEBUG_ GKE_ IN_ GKE_ PHY_ COUNT FAST_ DEBUG_ UM_ GKE+0x10
#define FAST_ DEBUG_ GKE_ OUT_ GKE_ MD_ COUNT FAST_ DEBUG_ UM_ GKE+0x18
#define FAST_ DEBUG_ GKE_ OUT_ GKE_ PHY_ COUNT FAST_ DEBUG_ UM_ GKE+0x20
#define FAST_ DEBUG_ GKE_ OUT_ GKE_ KEY_ COUNT FAST_ DEBUG_ UM_ GKE+0x28
/*GME*/
#define FAST_ DEBUG_ GME_ GME_ STATUS FAST_ DEBUG_ UM_ GME+0x00
#define FAST_ DEBUG_ GME_ IN_ GME_ MD_ COUNT FAST_ DEBUG_ UM_ GME+0x08
#define FAST_ DEBUG_ GME_ IN_ GME_ PHY_ COUNT FAST_ DEBUG_ UM_ GME+0x10
#define FAST_ DEBUG_ GME_ IN_ GME_ KEY_ COUNT FAST_ DEBUG_ UM_ GME+0x18
#define FAST_ DEBUG_ GME_ IN_ GME_ INDEX_ COUNT FAST_ DEBUG_ UM_ GME+0x20
#define FAST_ DEBUG_ GME_ OUT_ GME_ MD_ COUNT FAST_ DEBUG_ UM_ GME+0x28
#define FAST_ DEBUG_ GME_ OUT_ GME_ PHY_ COUNT FAST_ DEBUG_ UM_ GME+0x30
#define FAST_ DEBUG_ GME_ OUT_ GME_ KEY_ COUNT FAST_ DEBUG_ UM_ GME+0x38
/*GAC*/
#define FAST_ DEBUG_ GAC_ GAC_ STATUS FAST_ DEBUG_ UM_ GAC+0x00
#define FAST_ DEBUG_ GAC_ IN_ GAC_ DATA_ COUNT FAST_ DEBUG_ UM_ GAC+0x08
#define FAST_ DEBUG_ GAC_ IN_ GAC_ MD_ COUNT FAST_ DEBUG_ UM_ GAC+0x10
#define FAST_ DEBUG_ GAC_ IN_ GAC_ PHY_ COUNT FAST_ DEBUG_ UM_ GAC+0x18
#define FAST_ DEBUG_ GAC_ OUT_ GAC_ DATA_ COUNT FAST_ DEBUG_ UM_ GAC+0x20
#define FAST_ DEBUG_ GAC_ OUT_ GAC_ PHY_ COUNT FAST_ DEBUG_ UM_ GAC+0x28
/*GOE*/
#define FAST_ DEBUG_ GOE_ GOE_ STATUS FAST_ DEBUG_ UM_ GOE+0x00
#define FAST_ DEBUG_ GOE_ IN_ GOE_ DATA_ COUNT FAST_ DEBUG_ UM_ GOE+0x08
#define FAST_ DEBUG_ GOE_ IN_ GOE_ PHY_ COUNT FAST_ DEBUG_ UM_ GOE+0x10
#define FAST_ DEBUG_ GOE_ OUT_ GOE_ DATA_ COUNT FAST_ DEBUG_ UM_ GOE+0x18
#define FAST_ DEBUG_ DC_ DATA_ CACHE_ STATUS FAST_ DEBUG_ UM_ DC+0x00
#define FAST_ DEBUG_ DC_ IN_ DATA_ CACHE_ COUNT FAST_ DEBUG_ UM_ DC+0x08
#define FAST_ DEBUG_ DC_ OUT_ DATA_ CACHE_ COUNT FAST_ DEBUG_ UM_ DC+0x10
\end { code}
\subsubsection { 端口计数}
\begin { code} [c]
#define FAST_ COUNTS_ RECV_ BYTE_ L 0x200 /**< 计数寄存器:成功接收字节数低位计数*/
#define FAST_ COUNTS_ RECV_ BYTE_ H 0x204 /**< 计数寄存器:成功接收字节数高位计数*/
#define FAST_ COUNTS_ SEND_ BYTE_ L 0x208 /**< 计数寄存器:成功发送字节数低位计数*/
#define FAST_ COUNTS_ SEND_ BYTE_ H 0x20C /**< 计数寄存器:成功发送字节数高位计数*/
#define FAST_ COUNTS_ RECV_ PKT_ L 0x290 /**< 计数寄存器:接收成功的计数*/
#define FAST_ COUNTS_ RECV_ PKT_ H 0x294 /**< 计数寄存器:接收成功的计数*/
#define FAST_ COUNTS_ SEND_ PKT_ L 0x2D8 /**< 计数寄存器:发送成功的计数*/
#define FAST_ COUNTS_ SEND_ PKT_ H 0x2DC /**< 计数寄存器:发送成功的计数*/
\end { code}
\subsubsection { 硬件流表}
\begin { code} [c]
#define FAST_ OFP_ FLOW_ STATS_ PKTS 0x8B000 /*流表报文计数*/
#define FAST_ OFP_ FLOW_ STATS_ BYTES 0x8B800 /*流表字节计数*/
\end { code}
\subsubsection { 硬件动作}
\begin { code} [c]
#define BASE_ ADDR 0x43C00000 /**< 硬件资源起始地址*/
#define REG_ LEN 0x01000000 /**< 硬件资源可用空间*/
#define FAST_ ACTION_ REG_ ADDR 0x88000 /**< 写动作寄存器*/
#define FAST_ DEFAULT_ RULE_ ADDR 0x1F8 /**< 默认动作(匹配不到规则时执行默认动作)地址*/
\end { code}
\subsection { FAST开发流程}
基于FAST的软件代码开发有三种方式:
第一种是基于FAS的源代码进行修改, 整个代码结构不变,
第一种是基于FAST的源代码进行修改, 整个代码结构不变,
可以直接使用原工程中的所有Makefile文件,
修改完成后, 直接make即可得到用户所需要的可执行文件;
第二种是用户根据自己需要,选择需要的开发库与头文件,
@ -720,10 +344,10 @@ FAST软件可在通用Linux系统中进行编译与测试,
\subsubsection { 修改源码开发}
\begin { enumerate}
\item 已 FAST的rule\_ rw工具作为修改示例,
修改fast/tools/rule\_ rw/目录下main\_ rule.c文件
\item 以 FAST的rule\_ rw工具作为修改示例,
修改fast/tools/rule\_ rw/目录下main\_ rule.c文件;
\item 修改main\_ rule\_ test函数,
将两个端口互转硬件规则改为根据以太网类型来转发
将两个端口互转硬件规则改为根据以太网类型来转发。
\begin { code} [c]
void main_ rule_ test(int argc,char *argv[])
{
@ -735,20 +359,7 @@ FAST软件可在通用Linux系统中进行编译与测试,
p1 = atoi(argv[1]);
p2 = atoi(argv[2]);
}
else if(argc == 4)
{
p1 = atoi(argv[1]);
p2 = atoi(argv[2]);
idx1 = atoi(argv[3]);
}
else if(argc == 5)
{
p1 = atoi(argv[1]);
p2 = atoi(argv[2]);
idx1 = atoi(argv[3]);
idx2 = atoi(argv[4]);
}
//给规则的各字段赋值
rule[i].key.type = htole16(0x0800); //以太网类型
rule[i].key.port = p1;
@ -760,11 +371,7 @@ FAST软件可在通用Linux系统中进行编译与测试,
rule[i].mask.type = 0xFFFF;
rule[i].mask.port = 0x3F;/*6bit*/
//fast_ add_ rule(& rule[i]);
//fast_ modify_ rule(& rule[i],0);
i++;
rule[i].key.type = htole16(0x0800);
rule[i].key.port = p2;
rule[i].priority =0xB;
@ -775,40 +382,17 @@ FAST软件可在通用Linux系统中进行编译与测试,
rule[i].mask.type = 0xFFFF;
rule[i].mask.port = 0x3F;
//fast_ add_ rule(& rule[i]);
//fast_ modify_ rule(& rule[i],1);
if(argc == 3 || argc == 1)
{
fast_ modify_ rule(& rule[i-1],idx1);
fast_ modify_ rule(& rule[i],idx2);
printf("Row[% d],Port[% d]----->Port[% d]\n ",idx1,p1,p2);
printf("Row[% d],Port[% d]----->Port[% d]\n ",idx2,p2,p1);
}
else if(argc == 4)
{
p1 = atoi(argv[1]);
p2 = atoi(argv[2]);
idx1 = atoi(argv[3]);
fast_ modify_ rule(& rule[i-1],idx1);
printf("Row[% d],Port[% d]----->Port[% d]\n ",idx1,p1,p2);
}
else if(argc == 5)
if(argc == 3)
{
p1 = atoi(argv[1]);
p2 = atoi(argv[2]);
idx1 = atoi(argv[3]);
idx2 = atoi(argv[4]);
fast_ modify_ rule(& rule[i-1],idx1);
fast_ modify_ rule(& rule[i],idx2);
printf("Row[% d],Port[% d]----->Port[% d]\n ",idx1,p1,p2);
printf("Row[% d],Port[% d]----->Port[% d]\n ",idx2,p2,p1);
}
}
}
\end { code}
修改保存退出, 打开命令终端, 跳到fast目录下, 执行交叉编译
修改保存退出, 打开命令终端, 跳到fast目录下, 执行交叉编译。
\begin { code} [console]
# cd fast-0.4.5
@ -816,21 +400,17 @@ FAST软件可在通用Linux系统中进行编译与测试,
\end { code}
编译完成后将把tools/rule\_ hw目录下rule\_ hw工具放到OpenBox-S4设备,
执行修改过的rule\_ hw工具
执行修改过的rule\_ hw工具。
\begin { code} [console]
# ./rule_ hw 0 1
\end { code}
\end { enumerate}
\subsubsection { 新增代码开发}
用户基于FAST架构代码增加自己的软件代码,
建议按照完整项目工程管理的方法进行,
使用Anjuta开发软件进行修改和配置,
具体请参考《OpenBox-S4开发环境搭建手册》第三章anjuta 部署fast源代码。
\subsubsection { 交叉编译代码}
OpenBox-S4平台为ARM嵌入式平台,
所运行软件需要通过交叉编译后才可放入平台运行。
软件代码的交叉编译请参考《OpenBox-S4开发环境搭建手册》第二章的2.4节测试交叉编译。
\subsubsection { 编译代码}
在fast代码的根目录执行编译命令。
\begin { code} [console]
# make clean
# make
\end { code}