修改了第4单元,第5单元,附录B和附录C,更新了一些图

merge-requests/5/head
XDL 4 years ago
parent 3eaa514362
commit 57d1cb4903

@ -29,11 +29,6 @@ UA编程主要处理硬件送到指定软件的分组数据
寄存器访问控制编程主要是对硬件各寄存器资源的访问控制。
对硬件规则的读写与对硬件其他寄存器的读写需要了解FAST架构的虚拟地址空间定义。
\subsection{FAST软件获取}
\label{subsec:app:fast_get-soft}
FAST的软硬件代码和相关工具下载请查看文章结尾的百度网盘链接。
\subsection{FAST代码结构}
\subsubsection{目录结构}
@ -42,7 +37,7 @@ FAST的软硬件代码和相关工具下载请查看文章结尾的百度网盘
\begin{table}[!ht]
\small
\centering
\caption{以太网帧格式}
\caption{代码目录结构}
\label{tab:c:wireshark_eth-format}
\begin{tabular}{|c|c|c|} \hline
\heiti 序号 & \heiti 目录名称 & \heiti 说明\\ \hline
@ -57,23 +52,31 @@ FAST的软硬件代码和相关工具下载请查看文章结尾的百度网盘
\subsubsection{头文件}
\begin{enumerate}
\item Fast\_vaddr.hFAST平台硬件资源访问对应的虚拟地址空间定义
\item Fast\_type.hFAST平台所用数据类型定义
\item Fast\_err.hFAST平台错误号定义
\item Fast\_struct.hFAST平台数据结构类型定义
\item Fast.hFAST平台所有开发函数定义包含上述所有头文件
\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 L2switch
\item l2switch
L2switch是基于FAST架构开发一个2层以太网交换机原型
l2switch是基于FAST架构开发一个2层以太网交换机原型
通过对流表默认规则的设置将硬件所有的分组重定向到UA程序
然后在UA的分组处理回调函数中实现对分组的2层交换
然后将分组从指定端口发送或泛洪发送。
@ -94,16 +97,16 @@ FAST的软硬件代码和相关工具下载请查看文章结尾的百度网盘
示例程序的另一种表现就是FAST提供的一些小工具包括单独的寄存器读写命令、规则输出命令、端口状态显示命令和端口分组计数命令。
\begin{enumerate}
\item Reg\_rw
\item reg\_rw
该工具主要是使用libreg库实现一个对用户指定的寄存器进行读写访问操作展示了用户如何调用libreg的相关库函数进行寄存器访问操作的方法。
\item Rule\_hw
\item rule\_hw
该工具主要是使用libreg库和librule库实现对硬件流表的获取并分组输出操作展示了用户如何调用librule库的相关库函数进行规则操作。该工具目前只使用了硬件规则的读取操作更多规则的功能操作可参考综合测试程序
\item Port\_status
\item port\_status
该工具主要使用libreg库实现了对各端口的协商状态、链路状态等寄存器的访问并进行各状态值的解释。主要展示了不同端口状态的寄存器地址如何计算各状态寄存器值返回如何解释示例代码中包含了目前支持的所有状态寄存器及对应功能说明
\item Port\_counts
\item port\_counts
该工具主要使用libreg库实现了对各端口分组计数的统计显示主要展示了不同功能计数统计的寄存器虚拟地址空间定义各端口对应功能寄存器的计算方法。示例代码中包含了目前支持的所有功能计数统计寄存器定义与说明
\end{enumerate}
@ -112,12 +115,11 @@ FAST的软硬件代码和相关工具下载请查看文章结尾的百度网盘
综合测试程序包含了libreg、librule和libua库的综合开发示例功能。
首先,用户可以通过此程序了解各功能库的主要使用函数及调用顺序;
其次,用户可以通过此程序的编译参数了解不同功能库如何添加对应库功能支持
其次,用户可以通过此程序的编译参数了解不同功能库如何添加对应库功能支持
subsection{FAST代码运行}
\subsection{FAST代码运行}
\subsubsection{软硬件环境}
FAST平台由湖南新实网络科技有限公司提供销售、售后与技术支持。
该平台可通过采购或免费申请试用获取用户拿到FAST平台后
默认系统环境均已支持FAST硬件基础版本与FAST软件基础版本。
FAST硬件基础版本是指基于FAST的标准5组流水线功能
@ -127,230 +129,20 @@ FAST软件基础版本是指FASTXXX软件版本。
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
\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
\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'
\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
struct fast_packet
{
union
{
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*/
{
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,19 +359,6 @@ 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); //以太网类型
@ -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,31 +382,8 @@ 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);
@ -808,7 +392,7 @@ FAST软件可在通用Linux系统中进行编译与测试
}
\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}

@ -5,454 +5,324 @@
\subsection{FAST简介}
针对近年来关于工业控制网络创新技术、创新网络结构、
时间敏感网络、SDN网络、FPGA硬件加速技术及下一代网络技术的研究需求
由国防科大与湖南新实共同发起的开源项目
——FASTFPGA Accelerated Switcing plaTform于2016年创建。
FAST平台的架构是一种通用多核CPU加FPGA形态的网络处理架构
该平台架构主要由硬件逻辑和软件逻辑两部分组成,
实现软硬件耦合通信与支持软硬件可编程的网络创新实验系统。
其中硬件包括平台相关的数据IO和FAST硬件逻辑。
软件部分包括通用操作系统与FAST软件逻辑。
FAST软件逻辑包括FAST软件开发环境和FAST UA程序。
在FAST平台不仅支持FAST的UA编程开发同时也支持通用APP的运行。
针对近年来关于工业控制网络创新技术、创新网络结构、时间敏感网络、SDN网络、FPGA硬件加速技术及下一代网络技术的研究需求由国防科大与湖南新实共同发起的开源项目——FASTFPGA Accelerated Switcing plaTform于2016年创建。截止到目前该开源项目已经服务全国多所高校和科研院所的网络实验建设和科研项目。
FAST平台的架构是一种通用多核CPU加FPGA形态的网络处理架构该平台架构主要由硬件逻辑和软件逻辑两部分组成实现软硬件耦合通信与支持软硬件可编程的网络创新实验系统。其中硬件包括平台相关的数据IO和FAST硬件逻辑。软件部分包括通用操作系统与FAST软件逻辑。FAST软件逻辑包括软件开发环境和UA程序。该平台不仅支持FAST的UA编程开发同时也支持通用APP的开发与运行。
\subsection{设备简介}
OpenBox-S4是一款软硬件全可编程网络实验平台
基于多核CPU加FPGA异构模型的FAST处理架构实现
软件在CPU上使用C语言编程硬件在FPGA芯片上使用Verilog语言编程。
全系统根据FAST架构搭建其软硬件基础运行环境
内部软硬件用户逻辑支持所有FAST架构开发的应用、
标准的网络协议栈与通用网络应用。
平台软硬件逻辑代码开源免费,支持用户二次开发。
OpenBox-S4是一款软硬件全功能可编程网络实验平台的具体型号产品该产品基于多核CPU加FPGA异构模型的FAST处理架构实现软件在CPU上使用C语言编程硬件在FPGA芯片上使用Verilog语言编程。全系统根据FAST架构搭建其软硬件基础运行环境内部软硬件用户逻辑支持所有FAST架构开发的应用、标准的网络协议栈与通用网络应用。平台软硬件逻辑代码开源免费支持用户二次开发。
\subsection{设备上电检测}
当我们拿到设备后,并不知道这个设备有没有故障。
所以在使用设备进行实验前,我们尽量简单并全面的对设备进行一次上电检测,
以确认设备是否没有故障。
用户拿到设备后,首先做个简单的上电测试,以确保硬件平台可以正常工作。
\subsubsection{设备外部接口及其配件说明}
\begin{enumerate}
\item 设备外部接口,如下图所示。
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f01}
\caption{正面外部接口}
\label{fig:a:ob_f01}
\end{figure}
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f02}
\caption{反面外部接口}
\label{fig:a:ob_f02}
\end{figure}
\item 12V-1A电源线如下图所示。
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f03}
\caption{设备电源线}
\label{fig:a:ob_f03}
\end{figure}
\item 串口线,如下图所示。
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f04}
\caption{设备串口线}
\label{fig:a:ob_f04}
\end{figure}
\item 设备烧录线,如下图所示。
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f05}
\caption{设备烧录线}
\label{fig:a:ob_f05}
\end{figure}
\item 设备外观与接口,正面如下图所示:
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f01}
\caption{正面外部接口}
\label{fig:a:ob_f01}
\end{figure}
\item 设备外观与接口,背面如下图所示:
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f02}
\caption{背面外部接口}
\label{fig:a:ob_f02}
\end{figure}
\item 12V-1A电源线如下图所示
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f03}
\caption{设备电源线}
\label{fig:a:ob_f03}
\end{figure}
\item 串口线,如下图所示:
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f04}
\caption{设备串口线}
\label{fig:a:ob_f04}
\end{figure}
\item 设备烧录线,如下图所示:
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f05}
\caption{设备烧录线}
\label{fig:a:ob_f05}
\end{figure}
\end{enumerate}
\subsubsection{检测准备}
\begin{enumerate}
\item 物品准备
\begin{table}[!htp]
\small
\centering
\caption{以太网帧格式}
\label{tab:c:wireshark_eth-format}
\begin{tabular}{|c|c|} \hline
\heiti 测试项 & \heiti 所需物品 \\ \hline
上电检测 & 一台设备及电源\\ \hline
串口检测 & 一台设备及电源、一台电脑、一个micro usb 串口线\\ \hline
管理网口MGMT & 一台设备及电源、一台电脑、一个网线\\ \hline
\end{tabular}
\end{table}
\item 物品准备
\begin{table}[!htp]
\small
\centering
\caption{以太网帧格式}
\label{tab:c:wireshark_eth-format}
\begin{tabular}{|c|c|} \hline
\heiti 测试项 & \heiti 所需物品 \\ \hline
上电检测 & 一台设备及电源\\ \hline
串口检测 & 一台设备及电源、一台电脑、一个micro usb 串口线\\ \hline
管理网口MGMT & 一台设备及电源、一台电脑、一个网线\\ \hline
\end{tabular}
\end{table}
\end{enumerate}
\subsubsection{上电检测}
\begin{enumerate}
\item 连接电源将电源开关拨到ON向右
\item 观察电源指示灯变化情况:
\item 电源开关拨到ON向右CFG电源指示灯会亮一下
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f06}
\caption{电源指示灯(刚接入电源)}
\label{fig:a:ob_f06}
\end{figure}
\item CFG电源指示灯过几秒后就灭了
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f07}
\caption{电源指示灯(系统配置)}
\label{fig:a:ob_f07}
\end{figure}
图 7 电源指示灯(系统配置)
\item 等待15秒左右RUN电源指示灯常亮。
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f08}
\caption{电源指示灯(系统运行)}
\label{fig:a:ob_f08}
\end{figure}
\item 连接电源将电源开关拨到ON向右
\item 观察电源指示灯变化情况;
\item 电源开关拨到ON向右CFG电源指示灯会亮一下
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f06}
\caption{电源指示灯(刚接入电源)}
\label{fig:a:ob_f06}
\end{figure}
\item CFG电源指示灯过几秒后就灭了
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f07}
\caption{电源指示灯(系统配置)}
\label{fig:a:ob_f07}
\end{figure}
电源指示灯(系统配置)
\item 等待15秒左右RUN电源指示灯常亮。
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f08}
\caption{电源指示灯(系统运行)}
\label{fig:a:ob_f08}
\end{figure}
\end{enumerate}
\subsubsection{串口检测}
\begin{enumerate}
\item 确保micro usb串口线正确连接到设备上并且设备已上电。
\item 确保调试电脑已按照《01\_常用软件的安装使用手册.pdf》
文档进行了PUTTY串口终端工具的安装。
\item 确保调试电脑已按照《01\_常用软件的安装使用手册.pdf》
文档进行了CP2102驱动的安装。
\item 在电脑的设备管理器查看设备的COM口数值。
如下图设备成的COM口数值为COM4不同的电脑显示的COM口数值会不同
\item 打开PUTTY工具界面。
\begin{enumerate}
\item 先点击左边“category”栏的 “serial”选项
\item 在“Serial line to connect to ”栏填写设备管理器中看到的COM数值
\item 在“Speed”栏填写串口的波特率为“115200”
\item 在 “Data bits”栏。填写数据位宽为“8”
\item 在“Flow control”栏选择“None”。
\item 如下所示调试电脑的COM数值为COM3所以“serial line”栏填写为“COM3”。
不同电脑的COM数值可能不同请填写实际的COM数值
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f09}
\caption{putty软件串口配置参数}
\label{fig:a:ob_f09}
\end{figure}
\end{enumerate}
\item 确保micro usb串口线连接到设备上并且设备已上电
\item 确保调试电脑已安装了PUTTY串口终端工具PUTTY软件包以及详细安装教程请自行搜索
\item 确保调试电脑已安装了CP2102驱动CP2102驱动包以及详细安装教程请自行搜索
\item 电脑的设备管理器查看设备的COM口数值。如下图设备的COM口数值为COM3不同的电脑显示的COM口数值会不同
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f09}
\caption{查看设备的COM口数值}
\label{fig:a:ob_f09}
\end{figure}
\item 打开PUTTY工具界面
\begin{enumerate}
\item 先点击右边“Connection type”位置的“serial”选项
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f10}
\caption{putty软件界面}
\label{fig:a:ob_f10}
\end{figure}
\item 点击左边“category”栏的 “serial”标签
\item 在“Serial line to connect to ”栏填写设备管理器中看到的COM数值
\item 在“Speed”栏填写串口的波特率为“115200”
\item 在 “Data bits”栏。填写数据位宽为“8”
\item 在“Flow control”栏选择“None”。
\item 如下所示调试电脑的COM数值为COM3所以“serial line”栏填写为“COM3”。
不同电脑的COM数值可能不同请填写实际的COM数值
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f11}
\caption{putty软件串口配置参数}
\label{fig:a:ob_f11}
\end{figure}
\end{enumerate}
\item 点击 “open” 进入设备系统则串口测试OK。
\end{enumerate}
\subsubsection{管理网口检测}
\begin{enumerate}
\item 使用一根网线将调试电脑与设备的obx0口连接。
\item
\item 设备的eth0网口的默认ip地址为192.168.50.5
所以需要将调试电脑的ip地址设置成与设备eth0网口的ip地址在同一个网段下
也就是192.168.50网段)。
\item 在调试电脑的 控制面板->网络和Internet->网络设备中。
点击以太网->属性->internet协议版本4TCP/IPV4进行ip地址的配置。如下所示。
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f10}
\caption{配置以太网的ip地址}
\label{fig:a:ob_f10}
\end{figure}
图 10 配置以太网的ip地址
\item 在调试电脑的 控制面板>系统和安全>Windows Defender 防火墙>自定义设置中。
关闭调试电脑的防火墙功能。
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f11}
\caption{关闭防火墙功能}
\label{fig:a:ob_f11}
\end{figure}
\item 在调试电脑的CMD终端下使用ping命令能正常与eth0网口通讯
则说明管理网络检测OK。
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f12}
\caption{ping 命令测试网络连通性}
\label{fig:a:ob_f12}
\end{figure}
\item 使用一根网线,将调试电脑与设备的管理网口连接;
\item 设备管理网口的默认ip地址为192.168.50.5所以需要将调试电脑的ip地址设置成与设备管理网口的ip地址在同一个网段下也就是192.168.50.0网段);
\item 在调试电脑的 控制面板->网络和Internet->网络设备中。点击以太网->属性->internet协议版本4TCP/IPV4进行ip地址的配置。如下所示:
\end{enumerate}
\subsection{搭建环境}
OpenBox-S4是一款软硬件全可编程网络实验平台
根据FAST架构搭建其软硬件基础运行环境
内部软硬件用户逻辑支持所有FAST架构开发的应用
是一款专业的网络实验与研究验证平台。
\subsubsection{连接二层交换拓扑}
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f12}
\caption{配置以太网的IP地址}
\label{fig:a:ob_f12}
\end{figure}
\item 在调试电脑的 控制面板>系统和安全>Windows Defender 防火墙>自定义设置中。关闭调试电脑的防火墙功能;
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f13}
\caption{二层交换连接拓扑示意图}
\label{fig:a:ob_f13}
\centering
\includegraphics[width=11cm]{f13}
\caption{关闭防火墙功能}
\label{fig:a:ob_f13}
\end{figure}
\item 在调试电脑的CMD终端下使用ping命令能正常与管理网口通讯则说明管理网络工作正常。
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f14}
\caption{ping命令测试网络连通性}
\label{fig:a:ob_f14}
\end{figure}
\end{enumerate}
其中PC1的IP地址设置为“192.168.1.20”PC2的IP地址设置为“192.168.1.21”
\subsubsection{在OpenBox-S4上运行二层交换程序}
\subsection{搭建环境}
\subsubsection{测试二层交换功能}
\begin{enumerate}
\item 搭建二层交换拓扑
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f14}
\caption{二层交换命令启动输出图}
\label{fig:a:ob_f14}
\centering
\includegraphics[width=11cm]{f15}
\caption{二层交换连接拓扑示意}
\label{fig:a:ob_f15}
\end{figure}
在串口登录界面或网络登录界面输入命令l2switch
其中主机A的IP地址设置为“192.168.1.111”主机B的IP地址设置为“192.168.1.119”。
\item 在OpenBox-S4上运行二层交换程序
 在串口登录界面或网络登录界面输入命令l2switch如下图所示
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f15}
\caption{二层交换命令运行输出图}
\label{fig:a:ob_f15}
\centering
\includegraphics[width=11cm]{f16}
\caption{二层交换命令启动输出图}
\label{fig:a:ob_f16}
\end{figure}
\subsubsection{在PC两端进行PING测试}
\item 在PC两端进行PING测试
在主机B的CMD (命令提示符) 程序中。输入并执行命令“ping 192.168.1.111 ”即可测试两台主机之间的联通性。测试结果如下所示:
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f16}
\caption{端主机PING通结果图}
\label{fig:a:ob_f16}
\centering
\includegraphics[width=11cm]{f17}
\caption{端主机PING通结果图(二层交换)}
\label{fig:a:ob_f17}
\end{figure}
\subsection{常用软件安装与使用}
\subsubsection{Wireshark抓包工具的安装使用}
\begin{enumerate}
\item 安装教程
\begin{enumerate}
\item 进入“\\06\_软件包及工具\\抓包工具”目录。
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f17}
\caption{Wireshark安装包路径}
\label{fig:a:ob_f17}
\end{figure}
\item 鼠标双击Wireshark-win64-3.2.5.exe文件
进入到下图中的安装界面。直接点击“agree”进行下一步。
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f18}
\caption{Wireshark许可协议}
\label{fig:a:ob_f18}
\end{figure}
\item 选择软件的安装路径。
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f19}
\caption{更改Wireshark安装路径}
\label{fig:a:ob_f19}
\end{figure}
\item 点击 “install”进行安装。
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f20}
\caption{Wireshark 开始安装}
\label{fig:a:ob_f20}
\end{figure}
\item 弹出Npacp组件安装窗口点击 “install”进行安装。
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f21}
\caption{Wireshark 安装Npacp组件}
\label{fig:a:ob_f21}
\end{figure}
\end{enumerate}
\item 使用教程
\begin{enumerate}
\item 捕获网络接口
\begin{enumerate}
\item 打开安装好的wireshark会进入如下所示界面。
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f22}
\caption{Wireshark启动界面说明}
\label{fig:a:ob_f22}
\end{figure}
\item 这里以有线网口为例,则点击选择 “以太网”,
就可以捕获有线网口的所有数据报文。如下所示。
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f23}
\caption{以太网接口捕获数据报文情况}
\label{fig:a:ob_f23}
\end{figure}
\end{enumerate}
\item wireshark 窗口介绍
wireshark主要分为这几个窗口如下所示。
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f24}
\caption{Wireshark窗口说明}
\label{fig:a:ob_f24}
\end{figure}
\begin{enumerate}
\item Display Filter(显示过滤器):用于设置过滤条件进行数据包列表过滤。
\item Packet List Pane(封包列表):简要地显示捕获到的数据包,
每个数据包包含编号,时间戳,源地址,目标地址,协议,长度,以及数据包信息。
不同协议的数据包使用了不同的颜色区分显示。。
\item Packet Details Pane(封包详细信息):在数据包列表中选择指定数据包,
在数据包详细信息中会显示数据包的所有详细信息内容。
数据包详细信息面板是最重要的,用来查看协议中的每一个字段。
\item Packet Bytes Pane(16进制数据)以十六进制和ASCII码的形式显示数据包的内容。
这里显 示了一个数据包未经处理的原始样子,也就是在链路上传播时的数据形式。
\item Miscellanous(状态栏)包含有专家信息、注释、包的数量和Profile。
\end{enumerate}
\item 过滤报文
\begin{enumerate}
\item 在显示过滤器栏中,输入指定地过滤条件即可过滤报文。
\item 如过滤ip地址为“192.168.1.1”的报文,
则输入过滤条件“ip.addr == 192.168.1.1”。如下所示。
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f25}
\caption{过滤指定ip地址报文}
\label{fig:a:ob_f24}
\end{figure}
\item 如过滤mac地址为“01:00:5e:7f:ff:fa”的报文
则输入过滤条件 “eth.addr == 01:00:5e:7f:ff:fa”如下所示。
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f26}
\caption{过滤指定mac地址报文}
\label{fig:a:ob_f24}
\end{figure}
\item 由于篇幅的原因wireshark的其他使用在本文档就不再说明了。
\end{enumerate}
\end{enumerate}
\end{enumerate}
\subsubsection{CP2102串口驱动的安装使用}
\subsubsection{测试三层路由功能}
\begin{enumerate}
\item 在“06\_软件包及工具/CP2102串口驱动”目录下
根据电脑的操作系统选择对应的软件包。
\item 如以windows~10操作系统的电脑为例
则选择 “06\_软件包及工具/CP2102串口驱动/win10版/CP210x\_Windows10\_Driver.zip”。
如下所示。
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f27}
\caption{CP2102串口驱动压缩包}
\label{fig:a:ob_f27}
\end{figure}
\item 解压软件包若根据系统为64位则双击“CP210xVCPInstaller\_x64.exe”运行安装。
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f28}
\caption{解压CP2102串口驱动压缩包}
\label{fig:a:ob_f28}
\end{figure}
\item 如下所示,完成安装。
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f29}
\caption{CP2102串口驱动完成安装}
\label{fig:a:ob_f29}
\end{figure}
\item 搭建三层路由拓扑
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f18}
\caption{三层路由拓扑}
\label{fig:a:ob_f18}
\end{figure}
其中主机A的IP地址设置为“192.168.0.111”主机B的IP地址设置为“192.168.2.119”。
\item OpenBox-S4上运行三层路由程序
 在串口登录界面或网络登录界面输入命令l3router如下图所示
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f19}
\caption{运行三层路由程序}
\label{fig:a:ob_f19}
\end{figure}
\item 在PC两端进行PING测试
在主机A的CMD (命令提示符) 程序中。输入并执行命令“ping 192.168.2.119 ”即可测试跨路由功能。测试结果如下所示:
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f20}
\caption{端主机PING通结果图三层路由}
\label{fig:a:ob_f20}
\end{figure}
\end{enumerate}
\subsection{系统更新}
\subsubsection{系统组成}
OpenBox-S4的系统架构为通用多核CPU加FPGA
使用的是Xilinx公司的ZYNQ系列芯片提供的整体封装解决方案。
在ZYNQ芯片中包含CPU系统与FPGA系统两部分其内部通过高速总线连接。
在OpenBox-S4的设备中其管理接口MGMT由CPU引出其他4个标准网口则由FPGA引出。
整个系统的逻辑运行是从SD卡中的几个文件开始
主要包括BOOT.bin、devicetree.dtb、uImage和uramdisk.image.gz四个部分。
其中BOOT.bin定义的整个芯片的物理系统构成、连接关系和FPGA的功能逻辑
devicetree.dtb文件则定义了系统的硬件资源定义在CPU运行系统内核镜像时
提供外设硬件及资源定义参数uImage是CPU运行的系统内核镜像文件
提供linux的内核运行环境及外设驱动uramdisk.image.gz是linux系统的根文件系统
包含内核引导起来后所使用的存储根文件系统、
系统配置信息、系统命令工具和用户命令等。
在所有的OpenBox-S4设备的系统中BOOT.bin与devicetree.dtb是匹配成套生成的
uImage和uramdisk.image.gz是所有系统通用匹配使用的。
用户如果要修改芯片系统架构、连接以及硬件逻辑,
则需要重新生成BOOT.bin和devicetree.dtb文件替换原来系统的这两件文件
即可重新定义设备的硬件逻辑功能。如果需要重新定义系统内核功能,
则需要重新编译生成uImage文件进行替换。如果是用户软件逻辑或工具命令
则可随时通过网络、U盘等上传至系统/mnt/openbox/目录即可使用。
\subsubsection{系统更新}
如上节所述更新系统最多是替换该设备环境中的4个核心文件
通常用户只修改硬件逻辑就不需要替换uImage和uramdisk.image.gz文件
如果不调修改原有接口的地址资源配置地址也无需devicetree.dtb文件
仅需要更新替换Boot.bin文件即可。此文档主要描述一下
如何更新整个系统运行环境即替换系统的4个核心文件。
\subsubsection{测试SDN交换功能}
\begin{enumerate}
\item 备份系统原有系统核心文件
通过设备的管理接口连接到用户操作主机,
通过SCP远程复制的方法将OpenBox-S4的系统备份到用户主机本地保存。
Windows主机请使用putty配套的pscp命令工具用法相同。
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f30}
\caption{下载备份原有系统}
\label{fig:a:ob_f30}
\end{figure}
\item 上传用户新的系统核心文件
将用户修改系统硬件逻辑后生成的BOOT.bin和devicetree.dtb
文件保存在本地update目录中
将备份目录中的uImage和uramdisk.image.gz文件复制到update目录
确保update更新目录中包含OpenBox-S4系统运行环境的4个核心文件
其中BOOT.bin和devicetree.dtb是用户最新生成的。执行如下命令
将更新目录的4个核心文件上传替换原来OpenBox-S4上面的核心文件。
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f31}
\caption{上传更新用户系统}
\label{fig:a:ob_f31}
\end{figure}
\item 断电后重启设备验证系统
确认更新文件已经上传后,即可关机、断电和重新加电进行测试。
重新加电进入系统后,使用系统自带工具读取硬件系统版本号。
如果其版本号读出与你的硬件逻辑定义一致,则说明系统更新成功。
如果不同说明系统更新没有替换原来的文件,请检查上传操作是否与上述截图一致,
是否有报错信息。系统自带标准五级流水线版本号为0x2020181108
如下图所示,即说明系统更新成功
当前运行系统的硬件版本号为用户更新版本号0x2020191231
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f32}
\caption{读硬件版本号验证}
\label{fig:a:ob_f32}
\end{figure}
\item 搭建SDN交换拓扑
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f21}
\caption{SDN交换拓扑}
\label{fig:a:ob_f21}
\end{figure}
其中主机A的IP地址设置为“192.168.2.111”主机B的IP地址设置为“192.168.2.119”。
\item 在192.168.1.3的主机中启动SDN控制器
 在终端命令行下输入 “java jar target/floodlight.jar”即启动floodlight控制器。如下所示
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f22}
\caption{启动floodlight控制器}
\label{fig:a:ob_f22}
\end{figure}
\item 在可编程网络平台上运行SDN交换程序
 在串口登录界面或网络登录界面输入命令:” xofp -4 192.168.1.3 i obx0,obx1,obx2,obx3 ”, 连接Floodlight控制器。如下所示
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f23}
\caption{运行SDN交换程序}
\label{fig:a:ob_f23}
\end{figure}
\item 访问floodlight控制器首页
 在控制器主机打开浏览器在浏览器地址栏输入“127.0.0.1:8080/ui/index.html “访问floodlight控制器首页。界面如下所示
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f24}
\caption{访问floodlight控制器首页}
\label{fig:a:ob_f24}
\end{figure}
\item 在PC两端进行PING测试
在主机A的CMD (命令提示符) 程序中。输入并执行命令“ping 192.168.2.119 ”即可测试两台主机之间的联通性。测试结果如下所示:
\begin{figure}[!htp]
\centering
\includegraphics[width=11cm]{f25}
\caption{端主机PING通结果图SDN交换}
\label{fig:a:ob_f25}
\end{figure}
\end{enumerate}

@ -3,16 +3,9 @@
\chapter{路由器实现}
\label{chap:router-ob}
本单元实验使学生能初步使用可编程网络设备开发平台进行路由器基本功能的设计与实现,
通过程序来实现路由器中最基本的三个功能:
包括二层交换功能、三层路由功能及组网功能。
深入理解路由器的基本工作原理与分组处理流程,
从而培养学生对网络设备使用和研发的能力。
本单元实验使学生能初步使用可编程网络设备开发平台进行路由器基本功能的设计与实现,通过程序来实现路由器中最基本的三个功能:包括二层交换功能、三层路由功能及组网功能。深入理解路由器的基本工作原理与分组处理流程,从而培养学生对网络设备使用和研发的能力。
可编程网络设备开发平台是一款基于FAST架构的软硬件
软件在CPU上使用C语言编程硬件在FPGA芯片上使用Verilog语言编程
全可编程的网络实验教学平台,平台的软硬件逻辑代码开源免费,支持用户二次开发。
其基本使用方法与编程开发方法见附录\ref{app:openbox}:《可编程网络平台-操作手册》
可编程网络设备开发平台是一款基于FAST架构的软硬件软件在CPU上使用C语言编程硬件在FPGA芯片上使用Verilog语言编程全可编程的网络实验教学平台平台的软硬件逻辑代码开源免费支持用户二次开发。其基本使用方法与编程开发方法见附录\ref{app:openbox}:《可编程网络平台-操作手册》
和附录\ref{app:fast}《FAST编程入门指南》。
可编程网络设备开发平台在后文简称为“可编程网络平台”,图标LOGO为FAST节点名称为OpenBox-S4。
可编程网络设备开发平台的具体设备型号为OpenBox-S4在案例文档中简称为“可编程网络平台”在实验图中的图标LOGO为FAST节点名称为OpenBox-S4。

@ -6,28 +6,19 @@
\subsection{实验目的}
\label{subsec:c:router-ob:s:networking_object}
本实验的主要目的是让学生将自己开发的路由器进行组网实验,
引入路由协议的配置与学习,实现多网段主机间的相互通信。
熟悉Quagga软件的安装与使用和两种基本路由协议RIP与OSPF的配置与使用。
本实验的主要目的是让学生将自己开发的路由器进行组网实验引入路由协议的配置与学习实现多网段主机间的相互通信。熟悉Quagga软件的安装与使用和两种基本路由协议RIP与OSPF的配置与使用。
\subsection{实验内容}
\label{subsec:c:router-ob:s:networking_content}
使用学生开发的路由器平台,搭建至少跨两跳路由器的复杂路由组网环境,
验证多网段主机的相互连通性。主要完成以下内容:
使用学生开发的路由器平台,搭建至少跨两跳路由器的复杂路由组网环境,验证多网段主机的相互连通性。主要完成以下内容:
\begin{enumerate}
\item \textbf{搭建自研路由器环境:}使用学生自己研发的路由器组建网络,
搭建不少于3台路由器和2台测试主机的网络环境进行验证
\item \textbf{安装并配置路由协议学习环境:}运行Quagga环境
分配配置RIP路由协议与OSPF路由协议并将两种协议启动运行
\item \textbf{验证组网功能:}验证不同路由协议下组网运行功能,
验证不同网段内主机的相互通信功能
\item \textbf{观察分析路由器工作流程:}观察各路由节点学习非互联网段的路由转发表,
打印输出各路由节点的FIB表
\item \textbf{观察分析内核FIB的变化}在网络正常运行状态下,
断开中间某个路由器间的链路观察断开链路两端路由器的内核FIB表变化情况
同时验证路由器内FIB表同步情况
\item \textbf{搭建自研路由器环境:}使用学生自己研发的路由器组建网络搭建不少于2台路由器和2台测试主机的网络环境进行验证
\item \textbf{安装并配置路由协议学习环境:}运行Quagga环境分别配置RIP路由协议与OSPF路由协议并将两种协议启动运行
\item \textbf{验证组网功能:}验证不同路由协议下组网运行功能,验证不同网段内主机的相互通信功能;
\item \textbf{观察分析路由器工作流程:}观察各路由节点学习非互联网段的路由转发表打印输出各路由节点的FIB表
\item \textbf{观察分析内核FIB的变化}在网络正常运行状态下断开中间某个路由器间的链路观察断开链路两端路由器的内核FIB表变化情况同时验证路由器内FIB表同步情况。
\end{enumerate}
\subsection{实验原理、方法和手段}
@ -35,30 +26,21 @@
\subsubsection{路由协议及基本工作原理}
路由协议工作在路由器的控制平面,创建了路由表,描述了网络拓扑结构。
通过在路由器之间共享路由信息来相互学习总个网络可达区域内可到达的路由网段信息。
路由信息在相邻路由器之间传递,确保所有路由器知道到其它路由器的路径。
路由协议工作在路由器的控制平面,创建了路由表,描述了网络拓扑结构。通过在路由器之间共享路由信息来相互学习整个网络可达区域内路由网段信息。路由信息在相邻路由器之间传递,确保所有路由器知道到其它路由器的路径。
路由协议主要包括RIP、OSPF、ISIS和BGP等。
RIP、OSPF、IS-IS是内部网关协议IGP
适用于单个ISP的统一路由协议的运行
一般由一个ISP运营的网络位于一个AS自治系统
有统一的AS number自治系统号
BGP是自治系统间的路由协议是一种外部网关协议
多用于不同ISP之间交换路由信息以及大型企业、政府等具有较大规模的私有网络。
路由协议主要包括RIP、OSPF、ISIS和BGP等。RIP、OSPF、IS-IS是内部网关协议IGP适用于单个ISP的统一路由协议的运行一般由一个ISP运营的网络位于一个AS自治系统有统一的AS number自治系统号。BGP是自治系统间的路由协议是一种外部网关协议多用于不同ISP之间交换路由信息以及大型企业、政府等具有较大规模的私有网络。
\subsubsection{路由组网环境}
本实验建议采用学生自研的路由器进行组网测试,
组网测试通过的组可以在中间穿插商用路由器一起验证。
本实验建议采用学生自研的路由器进行组网测试,组网测试通过的组可以在中间穿插商用路由器一起验证。
\subsection{实验条件}
\label{subsec:c:router-ob:s:networking_requirement}
\begin{itemize}
\item 可编程网络平台两个,交换测试主机两台,
网络配置与连接拓扑如\ref{fig:c:router-ob_networking-topo}所示;
\item 串口线根,网线三根;
\item 可编程网络平台两个,交换测试主机两台,网络配置与连接拓扑如
\ref{fig:c:router-ob_networking-topo}所示;
\item 串口线根,网线三根;
\item 学生自研路由器程序。
\end{itemize}
@ -79,31 +61,6 @@ BGP是自治系统间的路由协议是一种外部网关协议
\item Quagga安装
\begin{code}[console]
root@HNXS-FAST:/home/hnxs# apt-get install quagga
正在读取软件包列表... 完成
正在分析软件包的依赖关系树
正在读取状态信息... 完成
建议安装:
snmpd
下列【新】软件包将被安装:
quagga
升级了 0 个软件包,新安装了 1 个软件包,要卸载 0 个软件包,有 1 个软件包未被升级。
有 1 个软件包没有被完全安装或卸载。
需要下载 1,154 kB 的归档。
解压缩后会消耗 4,605 kB 的额外空间。
获取:1 https://mirrors.ustc.edu.cn/ubuntu-ports xenial-updates/main armhf quagga armhf 0.99.24.1-2ubuntu1.4 [1,154 kB]
已下载 1,154 kB耗时 1秒 (997 kB/s)
正在预设定软件包 ...
正在选中未选择的软件包 quagga。
(正在读取数据库 ... 系统当前共安装有 21814 个文件和目录。)
正准备解包 .../quagga_0.99.24.1-2ubuntu1.4_armhf.deb ...
正在解包 quagga (0.99.24.1-2ubuntu1.4) ...
正在处理用于 libc-bin (2.23-0ubuntu3) 的触发器 ...
正在处理用于 ureadahead (0.100.0-19) 的触发器 ...
正在处理用于 systemd (229-4ubuntu4) 的触发器 ...
正在设置 quagga (0.99.24.1-2ubuntu1.4) ...
正在处理用于 libc-bin (2.23-0ubuntu3) 的触发器 ...
正在处理用于 ureadahead (0.100.0-19) 的触发器 ...
正在处理用于 systemd (229-4ubuntu4) 的触发器 ...
\end{code}
\item Quagga启动配置
@ -159,10 +116,7 @@ BGP是自治系统间的路由协议是一种外部网关协议
!
log stdout
\end{code}
上述文件是S4-A路由器的rip配置文件另一台配置文件与上述基本相同
只是其neighbor的地址是192.168.3.2。
这两台路由器是通过S4-A的一个端口IP为192.168.3.1
故其neighbor为192.168.3.2和S4-B的一个端口IP为192.168.3.2)连接起来的。
上述文件是S4-A路由器的rip配置文件另一台配置文件与上述基本相同只是其neighbor的地址是192.168.3.2。这两台路由器是通过S4-A的一个端口IP为192.168.3.1故其neighbor为192.168.3.2和S4-B的一个端口IP为192.168.3.2)连接。
\item OSPF协议启动配置
\begin{code}[console]
@ -220,11 +174,10 @@ BGP是自治系统间的路由协议是一种外部网关协议
root@HNXS:/home/hnxs# systemctl start quagga
\end{code}
\item 将自研路由器和测试主机组网路由节点不少于2个,连线可以组成环状
\item 将自研路由器和测试主机组网路由节点不少于2个
\item 运行自研路由器并在两个测试主机上分别ping对方主机IP地址
请参考实验\ref{sec:c:router-ob:s:router}内容。
\item 观察某个节点路由器分组处理流程,
从打印消息上观察控制平面与数据平面的分组处理情况;
请参考实验\ref{sec:c:router-ob:s:router}内容。
\item 观察某个节点路由器分组处理流程,从打印消息上观察控制平面与数据平面的分组处理情况;
\item 观察每个节点上内核FIB表内容
\begin{code}[console]
@ -239,9 +192,8 @@ BGP是自治系统间的路由协议是一种外部网关协议
192.168.5.0 192.168.3.2 255.255.255.0 UG 2 0 0 obx3
192.168.6.0 192.168.3.2 255.255.255.0 UG 2 0 0 obx3
\end{code}
观察新增加的表项内容,最后三条是非本地路由可直达的网段,
其均需要通过192.168.3.2网送才可达。
\item 观察路由器FIB表的更新情况判断是否检测到内核FIB变化是否已经同步更新
观察新增加的表项内容最后三条是非本地路由可直达的网段均需要通过192.168.3.2网关才可达。
\item 观察路由器FIB表的更新情况判断是否检测到内核FIB变化是否已经同步更新。
\end{enumerate}
\subsection{思考题}
@ -264,11 +216,11 @@ BGP是自治系统间的路由协议是一种外部网关协议
\subsection{考核方法}
\label{subsec:c:router-ob:s:networking_criterion}
完成本次实验,需要提交一份实验报告和一程序输出日志。
完成本次实验,需要提交一份实验报告和一程序输出日志。
\begin{enumerate}
\item 20分在规定时间内完成实验并提交实验成果
\item 30分实验报告内容详细有关键步骤截图与分析说明
\item 20分所有节点正常运行不同网段的主机可以相互ping通
\item 20分Quagga安装配置正确RIP和OSPF配置正确工作正常
\item 10分实验报告与源代码内容完整、格式整洁
\item 10分实验报告与源代码内容完整、格式规范
\end{enumerate}

@ -6,27 +6,17 @@
\subsection{实验目的}
\label{subsec:c:router-ob:s:router_object}
本实验的主要目的是让学生掌握二层以太网帧、ARP协议和三层IP协议等的数据结构
熟悉各协议的解析与封装过程,
掌握三层路由器的工作原理、分组处理流程、FIB表和邻接表生成与使用。
熟悉路由器数据平面与控制平面的切分及不同的工作处理流程。
本实验的主要目的是让学生掌握二层以太网帧、ARP协议和三层IP协议等的数据结构熟悉各协议的解析与封装过程掌握三层路由器的工作原理、分组处理流程、FIB表和邻接表生成与使用。熟悉路由器数据平面与控制平面的切分及不同的工作处理流程。
\subsection{实验内容}
\label{subsec:c:router-ob:s:router_content}
使用可编程网络平台及三层路由器示例框架源码,
设计完成一个三层路由器原型系统。主要完成以下内容:
使用可编程网络平台及三层路由器示例框架源码,设计完成一个三层路由器原型系统。主要完成以下内容:
\begin{enumerate}
\item \textbf{系统路由验证:}搭建测试环境,
验证系统自带三层路由原型系统的功能,实现不同网段主机的相互通信功能;
\item \textbf{逻辑设计与实现:}基于路由器示例框架代码,
分别设计完成路由器的分组解析、FIB同步与查表、
二层与三层数据更新、ARP请求与响应等模块功能
\item \textbf{功能调试与验证:}根据路由器分组处理流程,
分别调试每一类分组的处理逻辑。如ARP请求类分组、
ARP响应类分组、控制平面分组和数据平面分组
组网测试路由器功能,实现不同网段内主机之间的相互通信功能。
\item \textbf{系统路由验证:}搭建测试环境,验证系统自带三层路由原型系统的功能,实现不同网段主机的相互通信功能;
\item \textbf{逻辑设计与实现:}基于路由器示例框架代码分别设计完成路由器的分组解析、FIB同步与查表、二层与三层数据更新、ARP请求与响应等模块功能
\item \textbf{功能调试与验证:}根据路由器分组处理流程分别调试每一类分组的处理逻辑。如ARP请求类分组、ARP响应类分组、控制平面分组和数据平面分组组网测试路由器功能实现不同网段内主机之间的相互通信功能。
\end{enumerate}
\subsection{实验原理、方法和手段}
@ -34,44 +24,30 @@
\subsubsection{系统路由验证}
请参考附《可编程网络平台-操作手册》完成。
请参考附\ref{app:openbox}《可编程网络平台-操作手册》完成。
\subsubsection{三层路由器工作原理}
三层路由器工作于OSI模型的第3层网络层根据网络层中的目的IP地址进行查表
获得分组转发的下一跳输出端口及下一跳的IP地址。更新网络层的TTL值与CSUM值
并在输出端口对二层数据进行重新封装二层数据后转发。
路由器还具备ARP响应与请求功能
支持响应请求自己IP的MAC信息与请求路由下一跳IP的MAC信息。
三层路由器工作于OSI模型的第3层网络层根据网络层中的目的IP地址进行查表获得分组转发的下一跳输出端口及下一跳的IP地址。更新IP层的ttl值与checksum值并在输出端口对二层数据进行重新封装二层数据后转发。路由器还具备ARP响应与请求功能支持响应请求自己IP的MAC信息与请求路由下一跳IP的MAC信息。
\subsubsection{路由器分组处理流程}
\begin{enumerate}
\item \textbf{线程同步系统FIB表}通过一个独立线程读取内核FIB表信息
保存到路由器的FIB表结构中循环不断的获取内核FIB表
一但有更新则刷新自己的FIB表内容
\item \textbf{输入分组解析:}接收各端口输入分组信息,并进行分组解析处理,
根据MAC地址信息和目的IP地址信息判断分组为控制平面分组还是数据平面分组
\item \textbf{控制平面与数据平面分流:}将控制平面数据转发到协议栈进行处理,
将数据平台数据转发到路由器数据转发逻辑中处理。
若是本机MAC的ARP请求则构造ARP响应进行回复
\item \textbf{提取目的IP并查表}路由器数据转发逻辑进一步解析数据,
解析提取目的IP地址送入FIB查表引擎进行匹配
获取分组的下一跳IP地址及输出端口信息
\item \textbf{更新三层数据:}更新分组TTL值与CSUM值根据FIB表结果
将分组转发至对应端口输出队列;
\item \textbf{更新二层数据:}更新FIB查表下一跳IP的MAC地址信息
查表无结果则启动ARP请求模块若查到对应MAC信息则更新二层数据后直接转发
\item \textbf{ARP请求}根据请求的IP地址与发送端口信息构造ARP协议的请求报文
发送到端口进行学习,并将学习结果保存到该端口的邻接表中;
\item \textbf{端口队列输出:}抽取端口输出队列内的发送分组,
更新二层数据后由端口直接发送。
保存到路由器的FIB表结构中循环不断的获取内核FIB表一旦有更新
则刷新自己的FIB表内容
\item \textbf{输入分组解析:}接收各端口输入分组信息并进行分组解析处理根据目的MAC和目的IP地址信息判断分组为控制平面分组还是数据平面分组
\item \textbf{控制平面与数据平面分流:}将控制平面数据转发到协议栈进行处理将数据平台数据转发到路由器数据转发逻辑中处理。若是本机MAC的ARP请求则构造ARP响应进行回复
\item \textbf{提取目的IP并查表}路由器数据转发逻辑进一步解析数据解析提取目的IP地址送入FIB查表引擎进行匹配获取分组的下一跳IP地址及输出端口信息
\item \textbf{更新三层数据:}更新分组ttl值与checksum值根据FIB表结果将分组转发至对应端口输出队列
\item \textbf{更新二层数据:}更新FIB查表下一跳IP的MAC地址信息查表无结果则启动ARP请求模块若查到对应MAC信息则更新二层数据后直接转发
\item \textbf{ARP请求}根据请求的IP地址与发送端口信息构造ARP协议的请求报文发送到端口进行学习并将学习结果保存到该端口的邻接表中
\item \textbf{端口队列输出:}抽取端口输出队列内的发送分组,更新二层数据后由端口直接发送。
\end{enumerate}
\subsection{实验条件}
\label{subsec:c:router-ob:s:router_requirement}
\begin{itemize}
\item 可编程网络平台一个,路由测试主机两台,
IP配置及连接拓扑如图\ref{fig:c:router-ob_router-topo}所示;
\item 可编程网络平台一个路由测试主机两台IP配置及连接拓扑如图\ref{fig:c:router-ob_router-topo}所示;
\item 串口线一根,网线两根;
\item 三层路由器框架源代码(开发环境与编译工具系统自带)。
\end{itemize}
@ -87,37 +63,12 @@
\label{subsec:c:router-ob:s:router_procedure}
\subsubsection{系统路由验证}
1. 登录可编程网络平台,启动系统自带三层路由器命令,
系统输出如下信息说明已正常启动且进入工作模式;
\begin{enumerate}
\item 登录可编程网络平台,启动系统自带三层路由器命令,系统输出如下信息说明已正常启动且进入工作模式;
\begin{code}[console]
root@HNXS-FAST:/mnt/openbox# l3router
Port[0]->obx0,MAC->00:0A:35:01:00:5B,IPv4->192.168.0.1,
IPv6->0000:0000:0000:0000:0000:0000:0000:0000
Port[1]->obx1,MAC->00:0A:35:00:00:02,IPv4->192.168.1.1,
IPv6->0000:0000:0000:0000:0000:0000:0000:0000
Port[2]->obx2,MAC->00:0A:35:00:00:03,IPv4->192.168.2.1,
IPv6->0000:0000:0000:0000:0000:0000:0000:0000
Port[3]->obx3,MAC->00:0A:35:00:00:04,IPv4->192.168.3.1,
IPv6->0000:0000:0000:0000:0000:0000:0000:0000
Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT Port
obx0 0000A8C0 00000000 0001 0 0 0 00FFFFFF 0 0 0 0
obx1 0001A8C0 00000000 0001 0 0 0 00FFFFFF 0 0 0 1
obx2 0002A8C0 00000000 0001 0 0 0 00FFFFFF 0 0 0 2
obx3 0003A8C0 00000000 0001 0 0 0 00FFFFFF 0 0 0 3
Create update_fib4_thread OK!
Create handle_queue_packet on Port[0] thread OK!
handle_queue_packet on port[0]
handle_queue_packet[0]->Wait pkt INQUEUE...
Create handle_queue_packet on Port[1] thread OK!
handle_queue_packet on port[1]
handle_queue_packet[1]->Wait pkt INQUEUE...
Create handle_queue_packet on Port[2] thread OK!
handle_queue_packet on port[2]
handle_queue_packet[2]->Wait pkt INQUEUE...
Create handle_queue_packet on Port[3] thread OK!
handle_queue_packet on port[3]
handle_queue_packet[3]->Wait pkt INQUEUE...
部分模块输出信息省略…
fastU->REG Version:20180827,OpenBox HW Version:2030200722
FAST UA REG->from pid:907,state:21,mid:132
fastU->Register UA to FAST Kernel! Wait Reply......
@ -125,18 +76,18 @@
fastU->libua version:20180827
fastU->fast_ua_recv......
\end{code}
\end{enumerate}
\subsubsection{设计开发三层路由器}
\begin{enumerate}
\item 阅读三层路由器框架源代码文件,
根据三层路由工作原理及分组处理流程设计完成框架源代码中的TODO部分内容
\item 编译自己的三层路由器源码生成相应的路由器系统命令user\_l3router
\item 阅读三层路由器框架源代码文件根据三层路由工作原理及分组处理流程设计完成框架源代码中的TODO部分内容
\item 编译自己的三层路由器源码生成相应的路由器系统命令user\_l3router。
\end{enumerate}
\subsubsection{调试与验证}
\begin{enumerate}
\item 运行自己的三层路由器代码,验证路由器的功能;
\item 路由器正常工作后,可以显示如下信息;
\item 运行自己的三层路由器程序,验证路由器的功能;
\item 路由器正常工作后,显示如下信息;
\begin{itemize}
\item 加载路由器接口地址信息
\begin{code}[text]
@ -261,8 +212,7 @@
\label{subsec:c:router-ob:s:router_notice}
\begin{enumerate}
\item 可编程网络平台的路由器只是一个基础的路由器原型,
分组处理方法与流程设计并不是规范,学生可根据自己理解创新实现;
\item 可编程网络平台的路由器只是一个基础的路由器原型,分组处理方法与流程设计并不是必须严格遵守的规范,学生可根据自己理解创新实现;
\item 控制平面的数据是通过平台开发环境重新导入到了系统内核处理,
目的是为了支持该系统上的其他正常SOCKET应用如Quagga路由软件。
\end{enumerate}
@ -270,8 +220,7 @@
\subsection{考核方法}
\label{subsec:c:router-ob:s:router_criterion}
完成本次实验,需要提交一份实验报告、一份程序源代码和一分程序输出日志。
程序源代码中用户添加的代码需要有详细的注释说明。
完成本次实验,需要提交一份实验报告、一份程序源代码和一份程序输出日志。程序源代码中用户添加的代码需要有详细的注释说明。
\begin{enumerate}
\item 20分在规定时间内完成实验并提交实验成果
@ -279,5 +228,5 @@
\item 10分程序正常运行测试主机可以ping通或抓包接收到对端报文
\item 10分ARP请求与响应功能正常工作
\item 10分测试主机可以ping通路由器端口的IP地址
\item 10分实验报告与源代码内容完整、格式整洁
\item 10分实验报告与源代码内容完整、格式规范
\end{enumerate}

@ -6,25 +6,17 @@
\subsection{实验目的}
\label{subsec:c:router-ob:s:switch_object}
本实验的主要目的是让学生掌握可编程网络平台的二层以太网数据收发方法,
熟悉二层以太网帧的数据结构掌握MAC地址的解析与使用。
熟悉二层交换机的分组交换原理、
设计完成二层交换的分组处理流程和转发表的老化功能与处理方法。
本实验的主要目的是让学生掌握可编程网络平台的二层以太网数据收发方法熟悉二层以太网帧的数据结构掌握MAC地址的解析与使用。熟悉二层交换机的分组交换原理、设计完成二层交换的分组处理流程和转发表的老化功能与处理方法。
\subsection{实验内容}
\label{subsec:c:router-ob:s:switch_content}
使用可编程网络平台及二层交换机示例框架源码,
设计完成一个二层以太网交换机原型系统。主要完成以下内容:
使用可编程网络平台及二层交换机示例框架源码,设计完成一个二层以太网交换机原型系统。主要完成以下内容:
\begin{enumerate}
\item \textbf{平台使用与验证:}掌握可编程网络平台及示例开发代码的修改、
编译和运行操作,验证系统自带二层交换机的功能;
\item \textbf{逻辑设计与实现:}设计满足二层交换功能的分组处理流程和逻辑,
如源MAC学习功能、目的MAC查表功能、
端口输出单播与泛洪功能和MAC转发表老化功能
\item \textbf{功能调试与验证:}验证自己开发的二层交换机功能,
是否满足各端口间相互通信功能;
\item \textbf{平台使用与验证:}掌握可编程网络平台及示例开发代码的修改、编译和运行操作,验证系统自带二层交换机的功能;
\item \textbf{逻辑设计与实现:}设计满足二层交换功能的分组处理流程和逻辑如源MAC学习功能、目的MAC查表功能、端口输出单播与泛洪功能和MAC转发表老化功能
\item \textbf{功能调试与验证:}调试自己开发的二层交换机逻辑,验证是否满足各端口间的交换通信功能。
\end{enumerate}
\subsection{实验原理、方法和手段}
@ -32,50 +24,33 @@
\subsubsection{平台基本使用}
请参考附录\ref{app:openbox}:《可编程网络平台操作手册》完成。
请参考附录\ref{app:openbox}:《可编程网络平台-操作手册》完成。
\subsubsection{二层交换工作原理}
二层交换机工作于OSI模型的第2层数据链路层
可以识别数据帧中的源MAC地址与输入端口信息
并将这些MAC地址与对应的端口记录在自己内部的一个地址表交换表中。
然后根据目的MAC地址进行交换表的查找获得目的MAC的输出端口然后进行转发。
根据目的MAC地址的不同转发方式还分为单端口转发、多端口转发和泛洪转发。
二层交换机工作于OSI模型的第2层数据链路层可以识别数据帧中的源MAC地址与输入端口信息并将这些MAC地址与对应的端口记录在自己内部的一个地址表交换表中。然后根据目的MAC地址进行交换表的查找获得目的MAC的输出端口然后进行转发。根据目的MAC地址的不同转发方式还分为单端口转发单播、多端口转发多播和泛洪转发广播
\subsubsection{二层交换分组处理流程}
\begin{enumerate}
\item \textbf{源MAC学习}当交换机从某个端口收到一个数据帧,
它先读取包头中的源MAC地址和输入端口号
这样就知道源MAC地址的机器是连在交换机的哪个端口上。
以此做为MAC转发表的核心数据结构学习或更新到转发表中
\item \textbf{目的MAC查表}读取数据帧头中的目的MAC地址
并在MAC转发表中查找找到相同MAC的匹配项后
获取该表项相应的端口信息(返回-1表示查表不命中
\item \textbf{转发输出:}根据目的MAC的查表结果判断输出端口号
若端口号为-1表示查不到目的MAC表项则进行泛洪转发
否则把数据帧直接复制到查表返回的端口上进行转发;
\item \textbf{MAC表老化}每次源MAC学习时都更新该MAC表项的使用时间
单独启动一个线程逐项比较MAC表项的最新使用时间与系统当前时间的差值
如果超过指定老化时长如3分钟则将该表项删除。
表项删除可将其有效位置无效,提高处理效率。
\item \textbf{源MAC学习}当交换机从某个端口收到一个数据帧它先读取包头中的源MAC地址和输入端口号这样就知道源MAC地址的机器是连在交换机的哪个端口上。以此做为MAC转发表的核心数据结构学习或更新到转发表中
\item \textbf{目的MAC查表}读取数据帧头中的目的MAC地址并在MAC转发表中查找找到相同MAC的匹配项后获取该表项相应的端口信息返回-1表示查表不命中
\item \textbf{转发输出:}根据目的MAC的查表结果判断输出端口号若端口号为-1表示查不到目的MAC表项则进行泛洪转发否则把数据帧直接复制到查表返回的端口上进行转发
\item \textbf{MAC表老化}每次源MAC学习时都更新该MAC表项的使用时间单独启动一个线程逐项比较MAC表项的最新使用时间与系统当前时间的差值如果超过指定老化时长如3分钟则将该表项删除。表项删除可将其有效位置无效提高处理效率。
\end{enumerate}
\subsubsection{实验方法及手段}
可编程网络平台提供了完整软硬件开发环境和网络功能
(交换或路由等)的示例应用程序及相应框架源代码。
学生使用挖空了部分逻辑功能的示例框架源码版本完成网络功能的设计与调试工作。
可编程网络平台提供了完整软硬件开发环境和网络功能(交换或路由等)的示例应用程序及相应框架源代码。学生使用挖空了部分逻辑功能的示例框架源码版本完成网络功能的设计与调试工作。
\subsection{实验条件}
\label{subsec:c:router-ob:s:switch_requirement}
\begin{itemize}
\item 可编程网络平台一台,交换测试主机两台,
连接拓扑及网络配置如上\ref{fig:c:router-ob_switch-topo}所示;
\item 可编程网络平台一个,交换测试主机两台,连接拓扑及网络配置
如下\ref{fig:c:router-ob_switch-topo}所示;
\item 串口线一根,网线两根;
\item 网络创新实验平台使用手册和二层交换机框架源代码
(开发环境与编译工具系统自带)。
\item 可编程网络平台使用手册和二层交换机框架源代码(开发环境与编译工具系统自带)。
\end{itemize}
\begin{figure}[!ht]
@ -91,9 +66,8 @@
\subsubsection{平台搭建与系统交换验证}
\begin{enumerate}
\item 参考附件《可编程网络平台-操作手册》搭建可编程网络平台的运行环境;
\item 在串口登录界面输入如下命令,启动系统自带二层交换机命令。
系统输出如下信息说明已正常启动且进入工作模式;
\item 请参考附录\ref{app:openbox}:《可编程网络平台-操作手册》完成;
\item 在串口登录界面输入如下命令,启动系统自带二层交换机命令。系统输出如下信息说明已正常启动且进入工作模式。
\begin{code}[console]
root@HNXS-FAST:/mnt/openbox# l2switch
fastU->REG Version:20180827,OpenBox HW Version:2030200722
@ -142,13 +116,9 @@
}
\end{code}
上述框架代码需要实现的主要功能是源MAC地址的学习
参数输入为分组数据的输入端口号和源MAC地址的指针。
通过对系统MAC转发表的查找判断原MAC转发表中是否存在该表项
若存在,则更新该表项的使用时间;
若不存在,则找一个空闲的表项位置存储该条表项,并更新表项使用时间。
上述框架代码需要实现的主要功能是源MAC地址的学习参数输入为分组数据的输入端口号和源MAC地址的指针。通过对系统MAC转发表的查找判断源MAC转发表中是否存在该表项若存在则更新该表项的使用时间若不存在则找一个空闲的表项位置存储该条表项并更新表项使用时间。
\item 编译自己的二层交换机源码生成相应的交换机系统命令user\_l2switch
\item 编译自己的二层交换机源码生成相应的交换机系统命令user\_l2switch。
\begin{code}[console]
root@HNXS-FAST:/home/hnxs/l2switch# make
gcc o user_l2switch main_l2switch lreg lrule lua -lthread
@ -161,7 +131,7 @@
\subsubsection{调试与验证}
\begin{enumerate}
\item 运行自己的二层交换机代码,验证交换机的功能;
\item 运行自己的二层交换机程序,验证交换机的功能;
\begin{code}[console]
root@HNXS-FAST:/home/hnxs/l2switch# ./user_l2switch
@ -177,7 +147,7 @@
\end{code}
运行当前目录下用户的可执行文件,必须在前面加上”./”
\item 二层交换机正常工作后,可以显示如下信息;
\item 二层交换机正常工作后,显示如下信息;
\begin{code}[console]
root@HNXS-FAST:/mnt/openbox# l2switch
fastU->REG Version:20180827,OpenBox HW Version:2030200722
@ -199,26 +169,26 @@
pkt_send_normal->0xb4c00468,outport:2,len:102
pkt_send_normal->0xb4c00468,outport:3,len:102
ID PORT0 PORT1 PORT2 PORT3
0 B8:27:EB:04:FC:F0 B8:27:EB:76:8F:DA . .
1 . . . .
0 B8:27:EB:04:FC:F0 B8:27:EB:76:8F:DA . .
1 . . . .
\end{code}
\begin{itemize}
\item 端口接收到报文显示输入端口及源目的MAC地址内容
\item 端口接收到报文,终端显示输入端口及源目的MAC地址内容
\begin{code}[text]
inport:0,dstmid:129,len:102,dmac:33:33:00:00:00:02,
smac:B8:27:EB:04:FC:F0
\end{code}
\item 进入源MAC学习阶段并更新MAC时间
\item 进入源MAC学习阶段并更新MAC时间
\begin{code}[text]
learn_smac->
update_mac_time->port:0,index:0
learn_smac->add new MAC,port:0,index:0
\end{code}
\item 进入目的MAC查表阶段输出查表结果
\item 进入目的MAC查表阶段输出查表结果
\begin{code}[text]
find_dmac->ret = -1
\end{code}
\item 进行报文转发
\item 进行报文转发
\begin{code}[text]
//泛洪发送
------pkt_send_flood------
@ -228,7 +198,7 @@
//单播发送
pkt_send_normal->0xb4c00468,outport:3,len:102
\end{code}
\item 实时输出端口MAC地址信息如下表示在端口0和端口1上分别学习到了两个MAC地址信息
\item 实时输出端口MAC地址信息终端输出如下信息表示在端口0和端口1上分别学习到了两个MAC地址信息
\begin{code}[text]
ID PORT0 PORT1 PORT2 PORT3
0 B8:27:EB:04:FC:F0 B8:27:EB:76:8F:DA . .
@ -236,11 +206,9 @@
\end{code}
\end{itemize}
\item 交换机工作不正确时开启xprintf函数打印调试
重返步骤3仔细阅读二层交换框架代码、交换机的工作原理及分组处理流程
\item 交换机工作不正确时开启xprintf函数打印调试。重返步骤3仔细阅读二层交换框架代码、交换机的工作原理及分组处理流程
\item 交换机正常工作后,尝试不断切换连两根网线连接交换机的端口,
观察测试主机的ping丢包观察交换机工作界面的输出显示。
\item 交换机正常工作后尝试切换测试主机连接在交换机的端口位置观察测试主机的ping丢包观察交换机工作界面的输出显示。
\end{enumerate}
\subsection{思考题}
@ -248,8 +216,7 @@
\begin{enumerate}
\item 交换机区分IPv4和IPv6协议吗区分TCP和UDP吗
\item 广播风暴broadcast storm是如何产生的如何避免
在不同的应用环境中分别采取的什么方法?
\item 广播风暴broadcast storm是如何产生的如何避免在不同的应用环境中分别采取的什么方法
\item 广播与组播报文如何判断?组播报文如何转发?
\item MAC转发表的老化时间与哪些因素相关网络规模、MAC表项大小
\end{enumerate}
@ -260,20 +227,19 @@
\begin{enumerate}
\item 可编程网络平台的使用手册需要仔细阅读,严格参照文档说明搭建和运行该平台系统;
\item 代码修改若不习惯vim命令可将其文件通过网络方式下载到自己电脑编辑修改完成后再上传到实验平台进行验证。Windows平台的上传下载工具为pscp.exe
\item 二层交换机框架代码只完成了基本的二层数据收发功能,交换机的其他功能逻辑需要自己完成,注意一定要紧扣二层交换机的实验原理完成;
\item 二层交换机框架代码只完成了基本的二层数据收发功能,交换机的其他功能逻辑需要自己完成,根据二层交换机的实验原理与分组处理流程完成;
\item 系统命令运行直接输入命令名称,当前目录的可执行文件运行需要在前面加上“./”。
\end{enumerate}
\subsection{考核方法}
\label{subsec:c:router-ob:s:switch_criterion}
完成本次实验,需要提交一份实验报告、一份程序源代码和一分程序输出日志。
程序源代码中用户添加的代码需要有详细的注释说明。
完成本次实验,需要提交一份实验报告、一份程序源代码和一份程序输出日志。程序源代码中用户添加的代码需要有详细的注释说明。
\begin{enumerate}
\item 20分在规定时间内完成实验并提交实验成果
\item 40分实验报告中有详细的交换逻辑设计分析与实现说明
\item 10分程序正常运行测试主机可以ping通或抓包接收到对端报文
\item 10分MAC转发表在设定时间后可以老化
\item 10分测试主机切换端口连接后仍能ping通
\item 10分实验报告与源代码内容完整、格式整洁
\item 10分实验报告与源代码内容完整、格式规范
\end{enumerate}

@ -3,9 +3,4 @@
\chapter{软件定义网络与网络测量}
\label{chap:sdn-ob}
本单元实验使学生能初步使用SDN平台进行网络功能的设计与实现
通过实验来掌握OpenFlow协议的基本功能与应用
以及网络拓扑构建的基本实现。初步掌握网络测试的常用原理及方法,
了解在测试过程中影响测量精度的原因及如何提高测量精度。
能通过实验理解软硬件协同测量的方法与特点。
本单元实验使学生能初步使用Software Defined Network简称SDN平台进行网络功能的设计与实现通过实验来掌握OpenFlow协议的基本功能与应用以及网络拓扑构建的基本实现。初步掌握网络测试的常用原理及方法了解在测试过程中影响测量精度的原因及如何提高测量精度。能通过实验理解软硬件协同测量的方法与特点。

@ -6,28 +6,18 @@
\subsection{实验目的}
\label{subsec:c:sdn-ob:s:ns_object}
本实验的主要目的是让学生掌握网络测试的常用原理及方法,
了解在测试过程中影响测量精度的原因及如何提高测量精度。
了解软硬件结果的测量方法与优势。
本本实验的主要目的是让学生掌握网络测试的常用原理及方法,了解在测试过程中影响测量精度的原因及如何提高测量精度。了解软硬件结合的测量方法与优势。
\subsection{实验内容}
\label{subsec:c:sdn-ob:s:ns_content}
使用可编程网络平台及用户应用AMS自动测量系统软件源代码
对网络远端的服务器进行RTT延时测量和带宽测量
测量不同长度网线的数据传输时长。主要完成以下内容:
使用可编程网络平台及用户应用AMS自动测量系统软件源代码对网络远端的服务器进行RTT延时测量和带宽测量测量不同长度网线的数据传输时长。主要完成以下内容
\begin{enumerate}
\item 测量RTT时长使用AMS软件测量一台校园网内服务器的RTT时间
测量报文使用ping协议文本
\item 测量带宽:在测量网络中添加一台可编程网络平台,
配置为带宽响应测量模式,测量这两个节点之间的实时网络流量,
并用不同测量报文大小来验证测量结果;
\item 测量网线时延:测量不同长度网线的数据传输时延,
根据测量结果分析本系统的测量优势与局限;
\item 添加软件计时测量:修改测量报文代码,
在开始发送时取系统时间做为软件发送时间,
在接收到报文后为每个报文设置系统接收时间计算软件的RTT时间。
\item \textbf{测量RTT时长}使用AMS软件测量一台校园网内服务器的RTT时间测量报文使用ping协议文本
\item \textbf{测量带宽:}在测量网络中添加一台可编程网络平台,配置为带宽响应测量模式,测量这两个节点之间的实时网络流量,并用不同测量报文大小来验证测量结果;
\item \textbf{测量网线时延:}测量不同长度网线的数据传输时延,根据测量结果分析本系统的测量优势与局限;
\item \textbf{添加软件计时测量:}修改测量报文代码在开始发送时取系统时间做为软件发送时间在接收到报文后为每个报文设置系统接收时间计算软件的RTT时间。
\end{enumerate}
\subsection{实验原理、方法和手段}
@ -51,7 +41,7 @@
计算测量结果。硬件的时间控制精度为8ns
故测量数据的收发时间均控制在8ns误差范围内。
根据时间的精准控制,扩展出硬件背靠背发包测试网络带宽,
精准周期发包测量精准抖动。
精准周期发包测量网络抖动。
\subsubsection{测量流程}
@ -83,10 +73,10 @@
\label{subsec:c:sdn-ob:s:ns_requirement}
\begin{itemize}
\item 可编程网络平台两个,被测试服务器一台;
\item 可编程网络平台两个,被测试主机一台;
连接拓扑如图\ref{fig:c:sdn-ob_ns-topo}所示;
\item 串口线一根,网线多根;
\item AMS软件源代码
\item AMS软件源代码
\end{itemize}
\begin{figure}[!ht]
@ -99,7 +89,7 @@
\subsection{实验步骤}
\label{subsec:c:sdn-ob:s:ns_procedure}
\begin{enumerate}
\item 测试平台与被测量主机间的连接性,在平台\texttt{ping 192.168.1.111}
\item 测试测量平台与被测量主机间的连接性,在测量平台\texttt{ping 192.168.1.111}
\begin{code}[console]
root@HNXS-FAST:/home/hnxs/ams# ping 192.168.1.111
PING 192.168.1.111 (192.168.1.111) 56(84) bytes of data.
@ -112,7 +102,7 @@
rtt min/avg/max/mdev = 1.576/1.640/1.746/0.088 ms
\end{code}
\item 运行AMS测量命令测量服务RTT的命令如下
\item 运行AMS测量命令测量服务RTT的命令如下
\begin{code}[console]
root@HNXS-FAST:/home/hnxs/ams# ams 192.168.1.111 5 70 1000000000
fastU->REG Version:20180827,OpenBox HW Version:2030200722
@ -125,7 +115,7 @@
fastU->fast_ua_recv......
\end{code}
系统输出如上信息说明AMS运行成功并发送5个70字节大小的ping报文出去默认间隔为1秒。等待ping响应回来。
\item 观察RTT测量结果
\item 观察RTT测量结果
\begin{code}[text]
AMS ID PKT_SIZE TS(ns)
0, 70, 1583184
@ -136,7 +126,7 @@
\end{code}
观察测量结果计算结果在1.5ms左右与之前的ping测试结果相差不大。
\item 测试两个测量平台之间的实时网络带宽
\item 测试两个测量平台之间的实时网络带宽
\begin{code}[console]
root@HNXS-FAST:/home/hnxs/ams# ams 192.168.1.111 5 100 0
fastU->REG Version:20180827,OpenBox HW Version:2030200722
@ -150,19 +140,19 @@
\end{code}
测试之前要在此链路中间增加一个背景流使用iperf的UDP流大小为600Mbps
系统给服务器发送5个100字节大小的ping报文出去默认间隔为1秒。
系统给测试主机发送5个100字节大小的ping报文出去默认间隔为1秒。
\item 观察带宽测试结果
\item 观察带宽测试结果
\begin{code}[text]
AMS ID PKT_SIZE BW(bps)
0, 70, 341467254
\end{code}
Iperf的背景流设置参数为600M时其实际带宽会跑到648Mbps左右。
iperf的背景流设置参数为600M时其实际带宽会跑到648Mbps左右。
链路上只有两种数据流,该测量值只是某个测量小时段的带宽反馈,
UDP流也存在不稳定性故其结果相加不可能完全是1000Mbps。
其相加结果与千兆带宽基本相等。
\item 测量网线传输延时
\item 测量网线传输延时
\begin{code}[console]
root@HNXS-FAST:/home/hnxs/ams# ams
fastU->REG Version:20180827,OpenBox HW Version:2030200722
@ -175,7 +165,7 @@
fastU->fast_ua_recv......
\end{code}
网络测量时需要连接在设备的0和1号端口上默认测量32组数据
网络测量时需要连接在设备的0和1号端口上。
\item 观察网线测量结果
\begin{code}[text]
@ -187,10 +177,9 @@
4, 100, 20202
\end{code}
从数据分析每组测量结果有些误差,但基本
\item 分析测量数据的差异
\item 分析测量数据的差异。
\begin{enumerate}
\item 对相同测试案例进行多组测量,观察数据变化
\item 对相同测试案例进行多组测量,观察数据变化
\item 分析RTT测量时软件计时测量与硬件计时测量的差异。
\end{enumerate}
\end{enumerate}
@ -208,9 +197,9 @@
\label{subsec:c:sdn-ob:s:ns_notice}
\begin{enumerate}
\item 测量服务器的PING延时需要修改发包内容为正确的PING报文内容。
\item 测量其他网络节点的ping延时需要修改发包内容为正确的ping报文内容;
\item 测量报文的间隔可以设置为零,但真正发包时的发包时刻计算却不是零,
是因为硬件报文是逐个逐个发送的,且每个报文发送时间长短与其报文长度相关
是因为硬件报文是逐个逐个发送的,且每个报文发送时间长短与其报文长度相关;
\item 时间计算与带宽计算中均用到了除法,引入了误差。
硬件时钟本身是存在误差(时钟飘移)的,也会引入计数的误差。
\end{enumerate}
@ -218,12 +207,12 @@
\subsection{考核方法}
\label{subsec:c:sdn-ob:s:ns_criterion}
完成本次实验,需要提交一份实验报告和一程序输出日志。
完成本次实验,需要提交一份实验报告和一程序输出日志。
\begin{enumerate}
\item 20分在规定时间内完成实验并提交实验成果
\item 25分实现软件计时测量与硬件测量对比
\item 25分将多线测量结果以图形曲线形式汇总并做分析总结
\item 20分完成网络抖动测量并做图形化汇总统计
\item 10分实验报告与源代码内容完整、格式整洁
\item 10分实验报告与源代码内容完整、格式规范
\end{enumerate}

@ -6,48 +6,39 @@
\subsection{实验目的}
\label{subsec:c:sdn-ob:s:sdn_object}
本实验的主要目的是让学生了解SDN的概念及三层结构原理
掌握OpenFlow协议格式、内容、工作流程及对应功能作用。
掌握SDN控制器北向API使用方法可通过API编程获取和设置交换机数据。
本实验的主要目的是让学生了解SDN的概念及架构原理掌握OpenFlow协议格式、内容、工作流程及对应功能作用。掌握SDN控制器北向API使用方法可通过API编程获取和设置交换机数据。
\subsection{实验内容}
\label{subsec:c:sdn-ob:s:sdn_content}
使用可编程网络平台及SDN交换机示例框架代码完成OpenFlow协议的部分功能逻辑。
验证并分析SDN交换机的工作原理与处理流程。主要完成以下内容
使用可编程网络平台及SDN交换机示例框架代码完成OpenFlow协议的部分功能逻辑。验证并分析SDN交换机的工作原理与处理流程。主要完成以下内容
\begin{enumerate}
\item \textbf{阅读协议:}阅读OpenFlow 1.3版本协议白皮书,
掌握其协议内容及对应功能;
\item \textbf{设计实现协议功能:}基于SDN交换机示例框架代码
选择开发OpenFlow协议的部分功能完成逻辑设计与实现
\item \textbf{验证交换机功能:}运行自己的SDN交换机控制器建立连接,
\item \textbf{验证交换机功能:}运行自己的SDN交换机控制器建立连接,
在控制器查询其工作状态与相关协议功能展示。
如交换机基本信息描述、交换机流表状态、
交换机端口状态及计数统计、网络拓扑展示效果;
\item \textbf{检验流表:}验证SDN交换机连接主机间的通信功能
并观察流表内容及变化情况;
\item \textbf{REST API应用}使用实验提供的北向REST~API接口查询控制器
\item \textbf{REST API应用}使用实验提供的北向REST API接口查询控制器
获取或设置交换机的不同功能数据;
\item \textbf{定义流表:}使用REST API接口修改流表内容
观察主机的通信情况是否受到影响
观察主机的通信情况是否受到影响
\end{enumerate}
\subsection{实验原理、方法和手段}
\label{subsec:c:sdn-ob:s:sdn_principle}
\subsection{SDN交换机工作原理}
SDN即Software Defined Network软件定义网络
是一种新型网络创新架构,用于解决传统网络架构中对于网络虚拟化、
各类自动化部署以及新型网络协议的问题。
\subsubsection{SDN交换机工作原理}
SDN是一种新型网络创新架构用于解决传统网络架构中对于网络虚拟化、各类自动化部署以及新型网络协议的问题。
SDN将传统的紧耦合网络设备被拆分成了应用、控制、转发三层
其中应用和控制层面能够控制网络中数据的流向以及协议控制,
而底层的网络设备被抽象为了可自定义的转发逻辑实体,
可被上层应用定义为不同类型的转发设备。
SDN将传统的紧耦合网络设备拆分成了应用、控制和转发三层其中应用和控制层面能够控制网络中数据的流向以及协议控制而底层的网络设备被抽象为了可自定义的转发逻辑实体可被上层应用定义为不同类型的转发设备。
在应用层用户可通过通用、简单的API获取网络信息
并可修改转发设备的工作逻辑,达到动态改变网络架构的目的。
在应用层用户可通过通用、简单的API获取网络信息并可修改转发设备的工作逻辑达到动态改变网络架构与功能的目的。
\subsection{SDN交换机分组处理流程}
\begin{enumerate}
@ -55,7 +46,7 @@ SDN将传统的紧耦合网络设备被拆分成了应用、控制、转发三
SDN交换机运行OpenFlow协议代理程序与上层控制器建立通信连接。
交换机解析处理OpenFlow协议
根据协议要求完成协议功能的相关数据收集和配置功能,
构造相应的OpenFlow协议应答控制器
构造相应的OpenFlow协议应答控制器
\item \textbf{建立连接:}OpenFlow协议代理运行时
交换机首先和控制器建立连接,
@ -67,26 +58,26 @@ SDN将传统的紧耦合网络设备被拆分成了应用、控制、转发三
\item \textbf{处理转发分组:}当交换机接收到一个数据转发分组时,
提取分组数据中的相关字段组成查表关键字,然后在本地进行流表匹配。
如果匹配成功,则根据流表的动作处理该分组,如从其他端口转发出去;
如果匹配不成功,则会命中默认动作,将分组打包送到控制器;
如果匹配不成功,则会执行默认动作,将分组打包送到控制器;
\item \textbf{PACKET\_IN分组上传}交换机查表不命中或是接收到链路探测报文,
则将该数据封装在OpenFlow的PACKET\_IN消息中上传给控制器
\item \textbf{PACKET\_OUT分组下发}通过PACKET\_IN上传的分组
经过控制器分析处理后会将其封装在OpenFlow协议的PACKET\_OUT消息中
并携带输出端口信息下发到交换机。交换机接收到该消息数据后,
根据输出信息指示,将该分组从指定端口输出。
通过PACKET\_OUT发送的分组数据还包括链路探测协议报文
通过PACKET\_OUT发送的分组数据还包括链路探测协议报文
\item \textbf{FLOW\_MOD消息处理}
控制器通过下发FLOW\_MOD消息给交换机的流表设置转发表项内容
FLOW\_MOD消息中包括分组特征元组信息和动作执行列表。
特征元组通常包括常用的MAC信息、帧类型和五元组信息等
动作通常包括输出端口或丢弃信息等
动作通常包括输出端口或丢弃信息等
\end{enumerate}
\subsection{实验条件}
\label{subsec:c:sdn-ob:s:sdn_requirement}
\begin{itemize}
\item 可编程网络平台一个,交换测试主机两台,
\item 可编程网络平台一个,测试主机两台,
SDN控制器安装SDN控制器软件Floodlight一台。
网络配置及连接拓扑如图\ref{fig:c:sdn-ob_sdn-topo}所示;
\item 串口线一根,网线三根;
@ -105,7 +96,7 @@ SDN将传统的紧耦合网络设备被拆分成了应用、控制、转发三
\subsubsection{编译运行SDN交换机验证交换机基本功能}
请参考附\ref{app:openbox}:《可编程网络平台-操作手册》完成。
请参考附\ref{app:openbox}:《可编程网络平台-操作手册》完成。
\subsubsection{基于SDN交换机源码选择实现自己的协议功能}
@ -134,8 +125,7 @@ SDN将传统的紧耦合网络设备被拆分成了应用、控制、转发三
return CONTINUE;
}
\end{code}
用户可以根据自己能力选择实现OpenFlow协议的部分消息功能
一旦处理了该消息一定要返回HANDLE否则直接break即可。
用户可以根据自己的需求选择实现OpenFlow协议的部分消息功能一旦处理了该消息一定要返回消息处理标识HANDLE否则直接break即可。
\item 编译源代码
\begin{code}[console]
root@HNXS-FAST:/home/hnxs/sdn# make
@ -148,7 +138,7 @@ SDN将传统的紧耦合网络设备被拆分成了应用、控制、转发三
\subsubsection{运行修改后的交换机再次验证SDN交换机的功能}
\begin{enumerate}
\item 运行SDN交换机交换机正常工作后输出如下
\item 运行SDN交换机交换机正常工作后输出如下
\begin{code}[console]
root@HNXS-FAST:/home/hnxs/sdn# ./ user_openflow -4 192.168.1.3 -i obx0,obx1,obx2,obx3
fastU->REG Version:20180827,OpenBox HW Version:2030200722
@ -172,9 +162,15 @@ SDN将传统的紧耦合网络设备被拆分成了应用、控制、转发三
obx3 ADD!
\end{code}
\item 查看控制器界面基本信息,
在浏览器打开控制器WEB网站\url{http://192.168.1.3/ui/index.html}
控制界面如图\ref{fig:c:sdn-ob_sdn-switch}所示:
\item 查看控制器界面基本信息在浏览器打开控制器WEB网站http://192.168.1.3/ui/index.html控制界面如图\ref{fig:c:sdn-ob_sdn-main}所示:
\begin{figure}[!htp]
\centering
\includegraphics[width=14cm]{sdn-main}
\caption{SDN主界面信息}
\label{fig:c:sdn-ob_sdn-main}
\end{figure}
\item 查看连接交换机信息,如图\ref{fig:c:sdn-ob_sdn-switch}所示:
\begin{figure}[!htp]
\centering
\includegraphics[width=14cm]{sdn-switch}
@ -182,8 +178,7 @@ SDN将传统的紧耦合网络设备被拆分成了应用、控制、转发三
\label{fig:c:sdn-ob_sdn-switch}
\end{figure}
\item 查看连接测试主机信息,
SDN主机及连接信息如图\ref{fig:c:sdn-ob_sdn-host}所示:
\item 查看连接测试主机信息SDN主机及连接信息如图\ref{fig:c:sdn-ob_sdn-host}所示:
\begin{figure}[!htp]
\centering
\includegraphics[width=14cm]{sdn-host}
@ -191,8 +186,7 @@ SDN将传统的紧耦合网络设备被拆分成了应用、控制、转发三
\label{fig:c:sdn-ob_sdn-host}
\end{figure}
\item 查看端口状态与计数信息与流表信息,
端口状态与流表计数信息如图\ref{fig:c:sdn-ob_port-flowtable}所示:
\item 查看端口状态与计数信息与流表信息,端口与流表信息如图\ref{fig:c:sdn-ob_port-flowtable}所示:
\begin{figure}[!htp]
\centering
\includegraphics[width=14cm]{port-flowtable}
@ -200,7 +194,7 @@ SDN将传统的紧耦合网络设备被拆分成了应用、控制、转发三
\label{fig:c:sdn-ob_port-flowtable}
\end{figure}
\item 查看网络拓扑信息,如图\ref{fig:c:sdn-ob_sdn-test-topo}所示:
\item 查看网络拓扑信息,网络拓扑信息如图\ref{fig:c:sdn-ob_sdn-test-topo}所示:
\begin{figure}[!htp]
\centering
\includegraphics[width=14cm]{sdn-test-topo}
@ -211,8 +205,7 @@ SDN将传统的紧耦合网络设备被拆分成了应用、控制、转发三
\subsubsection{在测试主机ping的前后分别观察流表变化}
\begin{enumerate}
\item ping之前的流表信息使用REST API方式获取其json数据
如图\ref{fig:c:sdn-ob_empty-flowtable}所示:
\item ping之前的流表信息为空如图\ref{fig:c:sdn-ob_empty-flowtable}所示:
\begin{figure}[!htp]
\centering
\includegraphics[width=14cm]{empty-flowtable}
@ -227,18 +220,15 @@ SDN将传统的紧耦合网络设备被拆分成了应用、控制、转发三
\caption{ping通后流表信息}
\label{fig:c:sdn-ob_flowtable-ping}
\end{figure}
Ping通之后在SDN交换机的流表里多了4条转发流表
分别是两个方向的ARP应答报文转发表和两个方向的IP报文转发表
具体内容在后面的REST~API数据中查验
由此可以说明控制器向SDN交换机注入了四条转发流表才让两边的主机ping通了。
ping通之后在SDN交换机的流表里多了4条转发流表分别是两个方向的ARP应答报文转发表和两个方向的IP报文转发表具体内容在后面的REST API数据中查验。由此可以说明控制器向SDN交换机注入了四条转发流表允许两边的主机相互ping通。
\end{enumerate}
\subsubsection{使用REST API接口查询交换机的相关功能数据}
\begin{enumerate}
\item 查询交换机基本信息
\begin{code}[console]
# curl http://192.168.1.3:8080/wm/core/switch/\
00:00:00:0a:00:00:08:01/desc/json
# curl http://192.168.1.3:8080/wm/core/switch/00:00:00:0a:00:00:08:01/desc/json
\end{code}
\begin{code}[json]
{
@ -254,8 +244,7 @@ SDN将传统的紧耦合网络设备被拆分成了应用、控制、转发三
\end{code}
\item 查询端口计数信息
\begin{code}[console]
# curl http://192.168.1.3:8080/wm/core/switch/\
00:00:00:0a:00:00:08:01/port/json
# curl http://192.168.1.3:8080/wm/core/switch/00:00:00:0a:00:00:08:01/port/json
\end{code}
\begin{code}[json]
{
@ -277,78 +266,15 @@ SDN将传统的紧耦合网络设备被拆分成了应用、控制、转发三
"collisions": "0",
"duration_sec": "4294966827",
"duration_nsec": "573987"
}, {
"port_number": "1",
"receive_packets": "86",
"transmit_packets": "205",
"receive_bytes": "11427",
"transmit_bytes": "22632",
"receive_dropped": "0",
"transmit_dropped": "0",
"receive_errors": "0",
"transmit_errors": "0",
"receive_frame_errors": "0",
"receive_overrun_errors": "0",
"receive_CRC_errors": "0",
"collisions": "0",
"duration_sec": "4294966827",
"duration_nsec": "573991"
}, {
"port_number": "2",
"receive_packets": "0",
"transmit_packets": "0",
"receive_bytes": "0",
"transmit_bytes": "0",
"receive_dropped": "0",
"transmit_dropped": "0",
"receive_errors": "0",
"transmit_errors": "0",
"receive_frame_errors": "0",
"receive_overrun_errors": "0",
"receive_CRC_errors": "0",
"collisions": "0",
"duration_sec": "4294966827",
"duration_nsec": "573992"
}, {
"port_number": "3",
"receive_packets": "616",
"transmit_packets": "220",
"receive_bytes": "56948",
"transmit_bytes": "24659",
"receive_dropped": "0",
"transmit_dropped": "0",
"receive_errors": "0",
"transmit_errors": "0",
"receive_frame_errors": "0",
"receive_overrun_errors": "0",
"receive_CRC_errors": "0",
"collisions": "0",
"duration_sec": "4294966827",
"duration_nsec": "573994"
}, {
"port_number": "4",
"receive_packets": "0",
"transmit_packets": "0",
"receive_bytes": "0",
"transmit_bytes": "0",
"receive_dropped": "0",
"transmit_dropped": "0",
"receive_errors": "0",
"transmit_errors": "0",
"receive_frame_errors": "0",
"receive_overrun_errors": "0",
"receive_CRC_errors": "0",
"collisions": "0",
"duration_sec": "4294966827",
"duration_nsec": "573995"
}]
},
此处省略其他多个类似端口的统计信息
]
}]
}
\end{code}
\item 查询交换机流表信息
\begin{code}[console]
# curl http://192.168.1.3:8080/wm/core/switch/\
00:00:00:0a:00:00:08:01/flow/json
# curl http://192.168.1.3:8080/wm/core/switch/00:00:00:0a:00:00:08:01/flow/json
\end{code}
\begin{code}[json]
{
@ -400,63 +326,17 @@ SDN将传统的紧耦合网络设备被拆分成了应用、控制、转发三
"actions": "output=1"
}
}
}, {
"version": "OF_13",
"cookie": "9007199288295424",
"table_id": "0x0",
"packet_count": "161",
"byte_count": "571408",
"duration_sec": "0",
"duration_nsec": "0",
"priority": "1",
"idle_timeout_s": "5",
"hard_timeout_s": "0",
"flags": [],
"match": {
"in_port": "1",
"eth_dst": "b8:27:eb:c1:d1:39",
"eth_src": "b8:27:eb:d8:83:20",
"eth_type": "0x800",
"ipv4_src": "192.168.2.111",
"ipv4_dst": "192.168.2.119"
},
"instructions": {
"instruction_apply_actions": {
"actions": "output=3"
}
}
}, {
"version": "OF_13",
"cookie": "9007199305072640",
"table_id": "0x0",
"packet_count": "2",
"byte_count": "571416",
"duration_sec": "0",
"duration_nsec": "0",
"priority": "1",
"idle_timeout_s": "5",
"hard_timeout_s": "0",
"flags": [],
"match": {
"in_port": "3",
"eth_dst": "b8:27:eb:d8:83:20",
"eth_src": "b8:27:eb:c1:d1:39",
"eth_type": "0x806"
},
"instructions": {
"instruction_apply_actions": {
"actions": "output=1"
}
}
}]
},
此处省略其他几条流表的信息
]
}
\end{code}
\end{enumerate}
\subsubsection*{修改Python脚本手动配置流表观察测试主机的通信变化}
\subsubsection{修改Python脚本手动配置流表观察测试主机的通信变化}
\begin{enumerate}
\item 修改流表脚本,使其转发端口错误
\item 修改流表脚本,使其转发端口错误;
\begin{code}[console]
#vim openflow_flow-test.py
\end{code}
@ -507,17 +387,14 @@ SDN将传统的紧耦合网络设备被拆分成了应用、控制、转发三
"eth_dst":" b8:27:eb:c1:d1:39", #dmac
"eth_src":" b8:27:eb:d8:83:20", #smac
"eth_type":"0x800", #type
#"ip_proto":"0x11", #proto
"in_port":"1", #inport
"ipv4_src":"192.168.2.111", #sip
"ipv4_dst":"192.168.2.119", #dip
#"tp_src":"50001", #sport
#"tp_dst":"50001", #dport
"actions":"output=2" #正确值应该为3
"actions":"output=2" #执行动作输出端口为2
}
flowbe1 = {
'switch':"00:00:00:0a:00:00:08:01",
"table":"1",
"table":"0",
"name":"flow-1",
"cookie":"61",
"priority":"1",
@ -525,32 +402,27 @@ SDN将传统的紧耦合网络设备被拆分成了应用、控制、转发三
"eth_dst":"b8:27:eb:d8:83:20", #dmac
"eth_src":"b8:27:eb:c1:d1:39", #smac
"eth_type":"0x800", #type
#"ip_proto":"0x11", #proto
"in_port":"3", #inport
"ipv4_src":"192.168.2.119", #sip
"ipv4_dst":"192.168.2.111", #dip
#"tp_src":"50001", #sport
#"tp_dst":"50001", #dport
"actions":"output=2" #正确值应该为1
"actions":"output=2" #执行动作输出端口为2
}
pusher.set(flowbe0)
pusher.set(flowbe1)
\end{code}
脚本执行命令如下:
\item 重启SDN控制器并停止测试主机的ping操作
\item 配置用户流表,脚本执行命令如下:
\begin{code}[console]
# python openflow_flow-test.py
(200, 'OK', '{"status" : "Entry pushed"}')
(200, 'OK', '{"status" : "Entry pushed"}')
\end{code}
脚本执行成功两条流表添加成功在测试主机两边进行ping测试
是否发现已经ping不通了
\item 修改流表脚本,使其转发端口正确,再次验证;
脚本执行成功两条流表添加成功在测试主机两边进行ping测试观察是否能够ping通
\item 修改流表脚本,使其转发端口正确,再次验证。
\begin{enumerate}
\item 两种动作分别修改为1进3出和3进1出。
添加流表后再重新ping测试是否发现又可以ping通了
\item 两种动作分别修改为1进3出和3进1出。添加流表后再重新ping测试观察是否能够ping通
\item 由此说明对于SDN交换机
可以通过用户修改流表的方式来定义某一条具体流的转发行为。
\end{enumerate}
@ -569,24 +441,20 @@ SDN将传统的紧耦合网络设备被拆分成了应用、控制、转发三
\label{subsec:c:sdn-ob:s:sdn_notice}
\begin{enumerate}
\item SDN控制器为JAVA实现有时候WEB存在缓存
导致数据显示不及时,在流表更新显示(两次实验对比)时,
先清空历史缓存数据后再显示。
\item Python脚本为一个http协议的客户端脚本程序
通过http协议及REST API的路径请求或设置SDN控制器WEB的对应功能模块
获取或设置该模块的返回数据或输入参数传输数据类型为json格式。
\item SDN控制器为JAVA实现有时候WEB存在缓存导致数据显示不及时在流表更新显示两次实验对比先清空历史缓存数据后再显示
\item Python脚本实现了一个http协议的客户端脚本程序通过http协议及REST API的路径请求或设置SDN控制器WEB的对应功能模块获取或设置该模块的返回数据或输入参数传输数据类型为json格式。
\end{enumerate}
\subsection{考核方法}
\label{subsec:c:sdn-ob:s:sdn_criterion}
完成本次实验,需要提交一份实验报告和一分程序输出日志。
完成本次实验,需要提交一份实验报告、一份程序源代码和一份程序输出日志。
\begin{enumerate}
\item 20分在规定时间内完成实验并提交实验成果
\item 40分根据实现OpenFlow消息类型的多少计分简单类型5分复杂类型10分
\item 20分通过脚本设置可以实现两个测试主机ping能和不能ping通
\item 40分根据实现OpenFlow消息类型的多少计分简单类型5分复杂类型10分
\item 10分通过脚本设置可以实现两个测试主机ping通和不能ping通
\item 20分通过网上搜索学习
使用其他多个REST~API查询到了交换机更多的数据内容
\item 10分实验报告与源代码内容完整、格式整洁
使用其他多个REST API查询到了交换机更多的数据内容
\item 10分实验报告与源代码内容完整、格式规范
\end{enumerate}

@ -17,16 +17,9 @@
掌握网络拓扑的构建方法。主要完成以下内容:
\begin{enumerate}
\item \textbf{打印连接主机信息:}基于SDN交换机源码
在端口分组接收回调函数中添加相关逻辑,
解析输入分组数据提取设备MAC与IP信息打印显示其内容
\item \textbf{打印接收LLDP消息}基于SDN交换机源码
在端口分组接收回调函数中添加相关逻辑,
解析输入分组数据打印LLDP分组的相关协议字段
\item \textbf{打印发送LLDP消息}基于SDN交换机源码
在OpenFlow协议回调函数中添加相关逻辑
提取SDN控制器下发的PACKET\_OUT消息且消息封装的分组协议为LLDP格式
打印输出LLDP分组中的相关协议字段
\item \textbf{打印连接主机信息:}基于SDN交换机源码在端口分组接收回调函数中添加相关逻辑解析输入分组数据提取设备MAC与IP信息打印显示其内容
\item \textbf{打印接收LLDP消息}基于SDN交换机源码在端口分组接收回调函数中添加相关逻辑解析输入分组数据打印LLDP分组的相关协议字段
\item \textbf{打印发送LLDP消息}基于SDN交换机源码在OpenFlow协议回调函数中添加相关逻辑提取SDN控制器下发的PACKET\_OUT消息且消息封装的分组协议为LLDP格式打印输出LLDP分组中的相关协议字段
\item \textbf{提取控制器链路与设备信息:}
使用REST~API接口获取SDN控制器的网络链路信息和设备连接信息
\item \textbf{构建拓扑图:}以WEB形式展示网络拓扑结构图
@ -39,16 +32,9 @@
\subsubsection{LLDP工作原理}
LLDP是一个用于信息通告和获取的协议但是需要注意的一点是
LLDP发送的信息通告不需要确认不能发送一个请求来请求获取某些信息
也就是说LLDP是一个单向的协议只有主动通告一种工作方式
无需确认,不能查询、请求。
LLDP是一个用于信息通告和获取的协议发送的信息通告不需要确认不能发送一个请求来请求获取某些信息也就是说LLDP是一个单向的协议只有主动通告一种工作方式无需确认不能查询、请求。LLDP帧的发送有两种触发方式一是定时器到期触发二是设备状态发生了变化触发。
LLDP协议主要完成的功能有初始化并维护本地MIB 库中的信息;
从本地MIB 库中提取信息并将信息封装到LLDP帧中。
LLDP帧的发送有两种触发方式一是定时器到期触发一是设备状态发生了变化触发
识别并处理接收到的LLDPDU帧维护远端设备LLDP MIB 信息库;
当本地或远端设备MIB信息库中有信息发生变化时发出通告事件。
LLDP协议主要完成的功能包括初始化并维护本地MIB 库中的信息从本地MIB库中提取信息并将信息封装到LLDP帧中识别并处理接收到的LLDPDU帧维护远端设备LLDP MIB 信息库当本地或远端设备MIB信息库中有信息发生变化时发出通告事件。
网络拓扑的测量是通过一些链路探测协议在各交换节点中相互收发来完成的链路的拓扑测量功能。
SDN交换机使用LLDP链路探测协议主要是通过PACKET\_OUT消息发送LLDP分组
@ -79,11 +65,10 @@ SDN交换机使用LLDP链路探测协议主要是通过PACKET\_OUT消息发送LL
\label{subsec:c:sdn-ob:s:topo_requirement}
\begin{itemize}
\item 网络创新实验平台两个,交换测试主机两台SDN控制器一台。
\item 可编程网络平台两个测试主机两台SDN控制器一台。
连接拓扑如图\ref{fig:c:sdn-ob_openflow-topo}所示;
\item 串口线一根,网线五根;
\item 网络创新实验平台使用手册、开发环境;
\item OpenFlow拓扑实验环境配置手册
\item 串口线两根,网线五根;
\item SDN交换机框架源码。
\end{itemize}
\begin{figure}[!ht]
@ -97,9 +82,9 @@ SDN交换机使用LLDP链路探测协议主要是通过PACKET\_OUT消息发送LL
\label{subsec:c:sdn-ob:s:topo_procedure}
\begin{enumerate}
\item 运行SDN交换机
\item 运行SDN交换机
请参考附《可编程网络平台-操作手册》完成。
请参考附\ref{app:openbox}《可编程网络平台-操作手册》完成。
\item 基于SDN交换机开源代码在端口分组接收回调函数中添加相应逻辑
\begin{code}[c]
int port_recv_callback(int inport,struct fast_packet *pkt,int pkt_len)
@ -113,16 +98,16 @@ SDN交换机使用LLDP链路探测协议主要是通过PACKET\_OUT消息发送LL
\item 解析接收数据,判断以太网帧类型,
如果帧类型为0x88CC则说明是LLDP协议分组根据LLDP协议打印相关协议字段内容
\item 解析分组提取输入帧类型为0x0800的分组
打印输出其源MAC地址与源IP地址仅输出IP地址为单播类型的条目
打印输出其源MAC地址与源IP地址仅输出IP地址为单播类型的条目
\end{enumerate}
\item 编译SDN交换机验证添加逻辑功能观察是否正确打印需要的消息内容
\item 分析端口接收回调函数中打印的消息内容;
\begin{enumerate}
\item 从LLDP分组中可解析得知对端交换机的某个端口发送到本交换机的某个端口
\item 从LLDP分组中可解析得知对端交换机的某个端口发送到本交换机的某个端口
\item 从普通IPv4报文中可以获得连接到该交换机上的主机节点信息
MAC地址和IPv4地址
MAC地址和IPv4地址
\end{enumerate}
\item 验证并观察SDN控制器自带的拓扑展示界面
\item 验证并观察SDN控制器自带的拓扑展示界面
\begin{enumerate}
\item 在控制器主机打开WEB界面输入地址
\texttt{127.0.0.1/ui/index.html}。查看浏览器界面数据;
@ -133,8 +118,8 @@ SDN交换机使用LLDP链路探测协议主要是通过PACKET\_OUT消息发送LL
\item 再连接上另一台主机,刷新拓扑界面,
查看到界面又新增了一台主机并显示其IP地址信息
\item 断开两台交换机之间的网线,新拓扑界面,
查看两个交换机之间的连线消失
\item 断开一台测试主机,新拓扑界面,查看其对应的主机从界面消失
查看两个交换机之间的连线消失;
\item 断开一台测试主机,新拓扑界面,查看其对应的主机从界面消失
\end{enumerate}
\item 使用控制器的北向REST API接口查询网络的所有链路连接关系数据
API接口为\texttt{/wm/topology/links/json}
@ -148,7 +133,7 @@ SDN交换机使用LLDP链路探测协议主要是通过PACKET\_OUT消息发送LL
\label{subsec:c:sdn-ob:s:topo_rethink}
\begin{enumerate}
\item 网络拓扑中的设备节点信息学习,使用广播报文中的信息会带来哪些影响
\item 在网络拓扑的探测学习中,主机节点信息通过哪种协议分组学习效果最好
\item OpenFlow交换机之间用一台普通交换机连接能学习到全网的拓扑结构信息吗
分析原因。
\end{enumerate}
@ -156,18 +141,18 @@ SDN交换机使用LLDP链路探测协议主要是通过PACKET\_OUT消息发送LL
\subsection{注意事项及有关说明}
\label{subsec:c:sdn-ob:s:topo_notice}
\begin{enumerate}
\item JAVA的WEB程序显示的缓存每新刷新操作前请清理浏览器历史缓存数据
\item SDN控制器的WEB界面有缓存每次物理拓扑更新后要先清理浏览器历史缓存数据再刷新WEB界面
\end{enumerate}
\subsection{考核方法}
\label{subsec:c:sdn-ob:s:topo_criterion}
完成本次实验,需要提交一份实验报告和一分程序输出日志。
完成本次实验,需要提交一份实验报告、一份程序源代码和一份程序输出日志。
\begin{enumerate}
\item 20分在规定时间内完成实验并提交实验成果
\item 20分正确打印输入与输出LLDP消息内容和连接主机信息
\item 20分正确打印输入与输出LLDP消息内容和连接主机信息
\item 20分通过REST API编程获取链路状态信息与设备信息并能生成拓扑关系图
\item 20分以图形界面形式展示拓扑图
\item 10分动态修改物理拓扑后程序可以及时刷新出正确拓扑图状态
\item 10分实验报告与源代码内容完整、格式整洁
\item 10分实验报告与源代码内容完整、格式规范
\end{enumerate}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 241 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 241 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 735 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 127 KiB

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 220 KiB

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 184 KiB

After

Width:  |  Height:  |  Size: 290 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 167 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 347 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 KiB

After

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 220 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 200 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 223 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Loading…
Cancel
Save