diff --git a/.gitignore b/.gitignore
index 7d445d1..040b98c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,3 +24,4 @@ _minted-*
*.exe
*.obj
*.listing
+settings.json
diff --git a/Readme.md b/Readme.md
index 97cb99f..0a65d4e 100644
--- a/Readme.md
+++ b/Readme.md
@@ -1,11 +1,11 @@
-# 计算机网络 共同实验指导书
+# 计算机网络 实验指导书
## 1. 概述
-计算机网络共同实验指导书是由计算机网络教案社区发起,
+计算机网络实验指导书是由计算机网络教案社区发起,
配合社区网络教案,由各高校专家教授共同联合编纂的一份实验指导材料。
-本项目工程包含了“计算机网络共同实验指导书”使用的各类相关文件。
+本项目工程包含了“计算机网络实验指导书”使用的各类相关文件。
## 2. 目录结构
diff --git a/book/instructions.cls b/book/instructions.cls
index aa142bc..b186e68 100644
--- a/book/instructions.cls
+++ b/book/instructions.cls
@@ -66,6 +66,7 @@
\newcommand{\sectionbreak}{\clearpage}
\usepackage{setspace}
+\usepackage{lscape}
% \usepackage{makecell}
%======================================================================
@@ -402,7 +403,7 @@
%定制代码框
\newtcblisting{code}[1][]{
center,
- width=0.9\linewidth,
+ width=0.95\linewidth,
listing only,
breakable=true,
minted language=#1,
diff --git a/book/instructions.tex b/book/instructions.tex
index c39aa3e..bcd3883 100644
--- a/book/instructions.tex
+++ b/book/instructions.tex
@@ -14,8 +14,9 @@
% 版本声明
\clearpage
\begin{center}
- \Large{\sffamily\bfseries\heiti Version 0.4} \\ \vspace{2em}
- \Large{\sffamily\bfseries\heiti 发布日期: \today} \\ \vspace{1em}
+ \Large{Version 1.0$\alpha$} \\ \vspace{2em}
+ \Large{发布日期: {\number\year 年 \number\month 月 \number\day 日}}
+ % \\ \vspace{1em}
\end{center}
% \vfill
@@ -48,24 +49,43 @@
\pagestyle{fancy}
\setcounter{page}{1}
+% “网络抓包与协议分析”
\graphicspath{{../figure/chapters/wireshark/}}
\input{../data/ch_wireshark/preface}
\input{../data/ch_wireshark/sec_arp}
\input{../data/ch_wireshark/sec_ip}
\input{../data/ch_wireshark/sec_tcp}
+% “基于套接字的网络程序设计”
\graphicspath{{../figure/chapters/socket/}}
\input{../data/ch_socket/preface}
\input{../data/ch_socket/sec_udp}
\input{../data/ch_socket/sec_web}
\input{../data/ch_socket/sec_smtp}
+
+% “组网基础”
\graphicspath{{../figure/chapters/ensp/}}
\input{../data/ch_ensp/preface}
\input{../data/ch_ensp/sec_static}
\input{../data/ch_ensp/sec_rip}
\input{../data/ch_ensp/sec_ospf}
+% “路由器实现”
+\graphicspath{{../figure/chapters/router-openbox/}}
+\input{../data/ch_router-openbox/preface}
+\input{../data/ch_router-openbox/sec_switch}
+\input{../data/ch_router-openbox/sec_router}
+\input{../data/ch_router-openbox/sec_networking}
+
+% “软件定义网络与网络测量”
+\graphicspath{{../figure/chapters/sdn-openbox/}}
+\input{../data/ch_sdn-openbox/preface}
+\input{../data/ch_sdn-openbox/sec_sdn}
+\input{../data/ch_sdn-openbox/sec_topo}
+\input{../data/ch_sdn-openbox/sec_ns}
+
+
%=========================================================================
% 附录
\appendix
@@ -82,9 +102,22 @@
\renewcommand{\thetable}{\Alph{chapter}--\arabic{table}}
\renewcommand{\chaptername}{附录\Alph{chapter}}
+% 速查手册
+\graphicspath{{../figure/appendixes/cheat_sheet/}}
+\input{../data/appendix/cheat_sheet}
+
+% 华为网络仿真平台eNSP简介
\graphicspath{{../figure/appendixes/ensp/}}
\input{../data/appendix/ensp}
+% 可编程网络平台-操作手册
+\graphicspath{{../figure/appendixes/openbox/}}
+\input{../data/appendix/openbox}
+
+% FAST软件编程入门指南
+\graphicspath{{../figure/appendixes/fast/}}
+\input{../data/appendix/fast}
+
\backmatter
%======================================================================
% 参考文献
diff --git a/code/reference/ch_socket/SMTPClient.py b/code/reference/ch_socket/SMTPClient.py
new file mode 100644
index 0000000..bfec76a
--- /dev/null
+++ b/code/reference/ch_socket/SMTPClient.py
@@ -0,0 +1,66 @@
+from socket import *
+from base64 import *
+
+mailfrom = "mail from:2@test.com\r\n"
+rcptto = "rcpt to:1@test.com\r\n"
+data = "data\r\n"
+quitmsg = "quit\r\n"
+
+msg = "\r\n I love computer networks!"
+endmsg = "\r\n.\r\n"
+#此处使用易邮邮件服务器软件搭建了一个内网邮件服务器
+mailserver = '10.130.82.62'
+mailport = 25
+connectaddress = (mailserver, mailport)
+# Create socket called clientSocket and establish a TCP connection with mailserver
+clientSocket = socket(AF_INET, SOCK_STREAM)
+clientSocket.connect(connectaddress)
+
+recv = clientSocket.recv(1024)
+print (recv)
+if recv[:3] != '220':
+ print ('220 reply not received from server.')
+# Send HELO command and print server response.
+heloCommand = 'HELO Alice\r\n'
+clientSocket.send(bytes(heloCommand.encode()))
+recv1 = clientSocket.recv(1024)
+print (recv1.decode())
+if recv1[:3] != '250':
+ print ('250 reply not received from server.')
+
+#print('000000000000000')
+#从命令和打印服务器响应发送邮件。
+login = b'auth login\r\n'
+clientSocket.send(login)
+recv2 = clientSocket.recv(1024).decode('utf-8')
+print ('222+',recv2)
+
+userCommand = b64encode('2@test.com'.encode('utf-8'))
+clientSocket.send((str(userCommand,encoding='utf-8')+'\r\n').encode())
+recv3 = clientSocket.recv(1024).decode('utf-8')
+print ('333+',recv3)
+
+password = b64encode('2'.encode('utf-8'))
+clientSocket.send((str(password,encoding='utf-8')+'\r\n').encode())
+recv4 = clientSocket.recv(1024).decode('utf-8')
+print ('444+',recv4)
+
+#print('0000000000000000')
+
+clientSocket.send(bytes(mailfrom.encode()))
+check = clientSocket.recv(1024)
+print(check)
+clientSocket.send(bytes(rcptto.encode()))#将RCPT发送到命令和打印服务器响应。
+check1 = clientSocket.recv(1024)
+print(check1)
+clientSocket.send(bytes(data.encode()))#发送数据命令和打印服务器响应。
+check2 = clientSocket.recv(1024)
+print(check2)
+clientSocket.send(bytes((mailfrom+msg+endmsg).encode()))#发送消息数据。
+check3 = clientSocket.recv(1024)
+print(check3)
+#发送退出命令并获得服务器响应。
+clientSocket.send(bytes(quitmsg.encode()))
+check4 = clientSocket.recv(1024)
+print(check4)
+clientSocket.close()
diff --git a/code/reference/ch_socket/UDP_Pinger_Client.py b/code/reference/ch_socket/UDP_Pinger_Client.py
new file mode 100644
index 0000000..db005cf
--- /dev/null
+++ b/code/reference/ch_socket/UDP_Pinger_Client.py
@@ -0,0 +1,19 @@
+from socket import *
+import time
+serverName = 'localhost'
+serverPort = 12000
+clientSocket = socket(AF_INET, SOCK_DGRAM)
+clientSocket.settimeout(1)
+
+for i in range(0, 10):
+ sendTime = time.time()
+ message = ('Ping %d %s' % (i + 1, sendTime)).encode()
+ try:
+ clientSocket.sendto(message, (serverName, serverPort))
+ modifiedMessage, serverAddress = clientSocket.recvfrom(2048)
+ rtt = time.time() - sendTime
+ print('Sequence %d: Reply from %s RTT = %.3fs' % (i + 1, serverName, rtt))
+ except Exception as e:
+ print('Sequence %d: Request timed out' % (i + 1))
+
+clientSocket.close()
diff --git a/code/reference/ch_socket/UDP_Pinger_Server.py b/code/reference/ch_socket/UDP_Pinger_Server.py
new file mode 100644
index 0000000..25bda49
--- /dev/null
+++ b/code/reference/ch_socket/UDP_Pinger_Server.py
@@ -0,0 +1,11 @@
+import random
+from socket import *
+serverSocket = socket(AF_INET, SOCK_DGRAM)
+serverSocket.bind(('', 12000))
+while True:
+ rand = random.randint(0, 10)
+ message, address = serverSocket.recvfrom(1024)
+ message = message.upper()
+ if (rand < 4):
+ continue
+ serverSocket.sendto(message, address)
diff --git a/code/reference/ch_socket/Websever.py b/code/reference/ch_socket/Websever.py
new file mode 100644
index 0000000..d901408
--- /dev/null
+++ b/code/reference/ch_socket/Websever.py
@@ -0,0 +1,62 @@
+# Import socket module
+from socket import *
+import sys # In order to terminate the program
+
+# Create a TCP server socket
+#(AF_INET is used for IPv4 protocols)
+#(SOCK_STREAM is used for TCP)
+
+serverSocket = socket(AF_INET, SOCK_STREAM)
+
+# Assign a port number
+serverPort = 80
+
+# Bind the socket to server address and server port
+serverSocket.bind(("", serverPort))
+
+# Listen to at most 1 connection at a time
+serverSocket.listen(1)
+
+# Server should be up and running and listening to the incoming connections
+
+while True:
+ print('The server is ready to receive')
+
+ # Set up a new connection from the client
+ connectionSocket, addr = serverSocket.accept()
+
+ # If an exception occurs during the execution of try clause
+ # the rest of the clause is skipped
+ # If the exception type matches the word after except
+ # the except clause is executed
+ try:
+ # Receives the request message from the client
+ message = connectionSocket.recv(1024).decode()
+ # Extract the path of the requested object from the message
+ # The path is the second part of HTTP header, identified by [1]
+ filename = message.split()[1]
+ # Because the extracted path of the HTTP request includes
+ # a character '\', we read the path from the second character
+ f = open(filename[1:])
+ # Store the entire contenet of the requested file in a temporary buffer
+ outputdata = f.read()
+ # Send the HTTP response header line to the connection socket
+ connectionSocket.send("HTTP/1.1 200 OK\r\n\r\n".encode())
+
+ # Send the content of the requested file to the connection socket
+ for i in range(0, len(outputdata)):
+ connectionSocket.send(outputdata[i].encode())
+ connectionSocket.send("\r\n".encode())
+
+ # Close the client connection socket
+ connectionSocket.close()
+
+ except IOError:
+ # Send HTTP response message for file not found
+ connectionSocket.send("HTTP/1.1 404 Not Found\r\n\r\n".encode())
+ connectionSocket.send("
404 Not Found
\r\n".encode())
+ # Close the client connection socket
+ connectionSocket.close()
+
+serverSocket.close()
+sys.exit()#Terminate the program after sending the corresponding data
diff --git a/code/reference/ch_socket/readme.md b/code/reference/ch_socket/readme.md
new file mode 100644
index 0000000..addcd4e
--- /dev/null
+++ b/code/reference/ch_socket/readme.md
@@ -0,0 +1,12 @@
+# 套接字编程参考实现
+
+# 说明
+
+这个目录中的四个Python文件是实验单元“基于套接字的网络编程”
+中三个实验的参考实现代码。
+
+其中:
+
+* UDP_Pinger_*.py 是实验“套接字基础与UDP通信”的参考实现
+* Websever.py 是实验“TCP通信与Web服务器”的参考实现
+* SMTPClient.py 是实验“SMTP客户端实现”的参考实现
\ No newline at end of file
diff --git a/data/appendix/cheat_sheet.tex b/data/appendix/cheat_sheet.tex
new file mode 100644
index 0000000..0462b18
--- /dev/null
+++ b/data/appendix/cheat_sheet.tex
@@ -0,0 +1,252 @@
+%# -*- coding: utf-8-unix -*-
+
+\chapter{速查手册}
+\label{app:cheatsheet}
+
+为了方便老师根据本学校的实际教学情况选择实验内容,
+特将本指导书所收录全部实验的基本信息汇总于此,
+供老师快速查阅。
+
+\begin{itemize}
+ \item \textbf{基本信息:}
+ 表\ref{tab:a:csheet:basic}汇总了本指导书所收录实验的实验目的、
+ 难度与建议的课时安排等基本信息;
+
+ \item \textbf{实验任务与要求:}
+ 表\ref{tab:a:csheet:task-summary}汇总了本指导书所收录的实验的实验任务与要求;
+
+ \item \textbf{考核方式:}
+ 建议根据每次实验上交实验报告,上课实际操作、作品评价等内容综合进行形成性考核,
+ 通用的实验成绩形成性考核标准见表\ref{tab:a:csheet:criterion},
+ 各实验如有特殊要求,还在正文中指出了各自的细节评分标准。
+\end{itemize}
+
+\renewcommand{\arraystretch}{1.5}
+
+\begin{table}[!ht]
+ \small
+ \centering
+ \caption{实验成绩形成性考核标准}
+ \label{tab:a:csheet:criterion}
+ \begin{tabular}{|m{2.5cm}<{\centering}|m{11cm}|} \hline
+ \heiti 考核项目 & \multicolumn{1}{c|}{\heiti 评分标准} \\ \hline
+ \multirow{5}{2.5cm}{\centering 实验速度\\ (20分)}
+ & 完成时间排名<= 20\%获得20分;\\ \cline{2-2}
+ & 20\%<完成时间排名<= 40\%获得18分;\\ \cline{2-2}
+ & 40\%<完成时间排名<= 60\%获得16分;\\ \cline{2-2}
+ & 60\%<完成时间排名<= 80\%获得14分;\\ \cline{2-2}
+ & 完成时间排名>80\%获得12分。 \\ \hline
+ \multirow{4}{2.5cm}{\centering 实验完成情况\\(30分)}
+ & 熟练掌握实验所需的设备、器件和软件(5分)\\ \cline{2-2}
+ & 掌握正确的实验方法(5分)\\ \cline{2-2}
+ & 独立完成实验(10分)\\ \cline{2-2}
+ & 根据实验结果提出实验改进措施并持续改进实验。(10分)\\ \hline
+ \multirow{4}{2.5cm}{\centering 实验报告\\(50分)}
+ & 格式正确、规范。(10分)\\ \cline{2-2}
+ & 完整记录实验过程。(10分)\\ \cline{2-2}
+ & 在实验过程中运用所学的的理论知识发现问题并解决问题。(20分)\\ \cline{2-2}
+ & 能够正确记录和分析实验结果。(10分)\\ \hline
+ \end{tabular}
+\end{table}
+
+\newcommand*{\tabitem}[1]{\hangindent=1em\makebox[1em]{$\bullet$}#1}
+\small
+\begin{longtable}{|m{1.5cm}<{\centering}
+ |m{1.7cm}<{\centering}
+ |m{8.5cm}
+ |m{0.7cm}<{\centering}
+ |m{1.2cm}|}
+ \caption{\label{tab:a:csheet:basic}实验基本信息}\\
+
+ \hline
+ \heiti 单元 & \multicolumn{1}{c|}{\heiti 实验} &
+ \multicolumn{1}{c|}{\heiti 目的} &
+ \multicolumn{1}{c|}{\heiti 课时} &
+ \multicolumn{1}{c|}{\heiti 难度} \\ \hline
+ \endfirsthead
+ \hline
+ \heiti 单元 & \multicolumn{1}{c|}{\heiti 实验} &
+ \multicolumn{1}{c|}{\heiti 目的} &
+ \multicolumn{1}{c|}{\heiti 课时} &
+ \multicolumn{1}{c|}{\heiti 难度} \\ \hline
+ \endhead
+
+ \multirow{3}{1.5cm}{\centering 网络抓包与协议分析}
+ & Wireshark软件使用和ARP分析 &
+ \tabitem{掌握Wireshark的基本操作,使用捕获过滤器和显示过滤器,抓取和分析有线局域网的数据包。} \par
+ \tabitem{掌握以太网MAC帧的基本结构。} \par
+ \tabitem{掌握ARP协议的特点及工作过程。}
+ & 2 & $\star$ \\ \cline{2-5}
+
+ & IP和ICMP分析 &
+ \tabitem{熟练使用Wireshark软件,观察IP数据报的基本结构,分析数据报的分片过程;} \par
+ \tabitem{掌握基于ICMP协议的ping和traceroute命令及其工作过程。}
+ & 2 & $\star\star$ \\ \cline{2-5}
+
+ & TCP与拥塞控制 &
+ \tabitem{运用Wireshark观察分析TCP协议报文,分析通信时序,理解TCP的工作过程;} \par
+ \tabitem{分析TCP连接管理、流量控制和拥塞控制的过程,能够分析TCP的性能问题。}
+ & 4 & $\star\star\star$ \\ \hline
+
+ & 套接字基础与UDP通信 &
+ \tabitem{掌握Python中UDP套接字编程基础;} \par
+ \tabitem{掌握使用UDP套接字发送和接收数据包,以及设置正确的套接字超时;} \par
+ \tabitem{了解Ping应用程序及其在计算数据包丢失率等统计数据方面的有用性。}
+ & 2 & $\star$ \\ \cline{2-5}
+
+ 基于套接字的网络程序设计
+ & TCP通信与Web服务器 &
+ \tabitem{掌握Python中TCP套接字编程基础;} \par
+ \tabitem{理解HTTP报文格式;} \par
+ \tabitem{了解开发简单Web服务器的流程。}
+ & 2 & $\star\star$ \\ \cline{2-5}
+
+ & SMTP客户端实现 &
+ \tabitem{理解和掌握Python中TCP套接字编程基础;} \par
+ \tabitem{理解SMTP报文格式;} \par
+ \tabitem{了解开发简单应用程序的流程。}
+ & 4 & $\star\star\star$ \\ \hline
+
+ 组网基础
+ & 静态路由 &
+ \tabitem{掌握静态路由协议;} \par
+ \tabitem{理解路由器工作原理;} \par
+ \tabitem{掌握路由器相关的配置、检测操作。}
+ & 2 & $\star$ \\ \hline
+
+ \multirow{2}{1.5cm}{\centering 组网基础}
+ & 动态路由(RIP) &
+ \tabitem{理解动态路由协议RIP的工作原理;} \par
+ \tabitem{掌握采用动态路由协议RIP进行网络设计的基本原则和方法。}
+ & 2 & $\star\star$ \\ \cline{2-5}
+
+ & 动态路由(OSPF) &
+ \tabitem{理解动态路由协议OSPF的工作原理;} \par
+ \tabitem{掌握采用动态路由协议OSPF进行网络设计的基本原则和方法。}
+ & 2 & $\star\star\star$ \\ \hline
+
+ \multirow{3}{1.5cm}{\centering 路由器实现}
+ & 二层交换机实现&
+ \tabitem{掌握二层以太网数据收发方法;} \par
+ \tabitem{熟悉二层交换机的交换原理、分组处理流程和转发表的老化功能与处理方法。}
+ & 3 & $\star\star$ \\ \cline{2-5}
+
+ & 三层路由器实现 &
+ \tabitem{掌握二层以太网帧的数据结构、ARP协议和IP协议等,熟悉各协议的解析与封装过程;} \par
+ \tabitem{掌握路由器数据平面与控制平面的切分及工作处理流程的不同。}
+ & 2 & $\star\star\star$ \\ \cline{2-5}
+
+ & 三层路由器组网 &
+ \tabitem{掌握路由器控制平台的工作任务及工作原理,熟悉多种路由协议的工作原理及适应范围。}
+ & 2 & $\star\star$ \\ \hline
+
+ \multirow{3}{1.5cm}{\centering 软件定义网络与网络测量}
+ & 基于OpenFlow的SDN交换机 &
+ \tabitem{了解SDN的概念及三层结构原理,掌握Open Flow协议格式、内容、工作流程及对应功能作用;} \par
+ \tabitem{掌握SDN控制器北向API使用方法,可通过API编程获取和设置交换机数据。}
+ & 3 & $\star\star\star\star$ \\ \cline{2-5}
+
+ & 基于OpenFlow的拓扑测量 &
+ \tabitem{了解OpenFlow协议中PACKET\_IN和链路探测协议(LLDP)的工作原理和拓扑构建方法。}
+ & 3 & $\star\star\star\star$ \\ \cline{2-5}
+
+ & 纳秒级高精度硬件测量 &
+ \tabitem{掌握网络测试的常用方法,了解在测试过程中影响测量精度的原因及如何提高测量精度。}
+ & 3 & $\star\star\star\star$ \\ \hline
+\end{longtable}
+
+\begin{landscape}
+
+\renewcommand{\arraystretch}{1.5}
+\small
+\begin{longtable}{|m{1.5cm}<{\centering}
+ |m{2cm}<{\centering}
+ |m{8cm}|m{9cm}|}
+ \caption{\label{tab:a:csheet:task-summary}实验任务与要求汇总}\\
+
+ \hline
+ \heiti 单元 & \heiti 实验 &
+ \multicolumn{1}{c|}{\heiti 任务} &
+ \multicolumn{1}{c|}{\heiti 要求} \\ \hline
+ \endfirsthead
+ \hline
+ \heiti 单元 & \heiti 实验 &
+ \multicolumn{1}{c|}{\heiti 任务} &
+ \multicolumn{1}{c|}{\heiti 要求} \\ \hline
+ \endhead
+ \hline
+ \endfoot
+ \endlastfoot
+
+ \multirow{3}{1.5cm}{\centering 网络抓包与协议分析} &
+ Wireshark软件使用和ARP分析 &
+ 熟悉使用Wireshark主菜单、工具栏和主窗口;掌握捕获过滤器和显示过滤器;捕获有线局域网的数据包并保存;了解MAC地址组成;观察以太网帧的首部和尾部,计算帧长度和FCS;抓取ARP请求和应答报文,分析其工作过程。 &
+ 详见实验指导书。安装并学习使用Wireshark软件,现场检查操作正确性;按步骤进行以太网帧和ARP命令的实验;收集分析数据,回答思考题,并编写实验报告。\\ \cline{2-4}
+
+ & IP和ICMP分析 &
+ 执行ping命令,观察IP数据报和ICMP询问报文的结构;改变ping命令的参数,观察IP数据报分片;执行Traceroute命令,观察ICMP差错报文的结构,并分析其工作原理。 &
+ 详见实验指导书,根据老师的安排确定实验内容;部署实验环境;按步骤进行实验;收集分析数据,回答思考题,并编写实验报告。\\ \cline{2-4}
+
+ & TCP与拥塞控制 &
+ 观察正常TCP连接中三次握手与四次挥手报文,绘制出时序图,并标出双方TCP状态的变化;观察分析TCP通信过程中各类异常(连接建立过程的异常、SNY洪泛攻击、数据超时和乱序等);运行基于TCP传输的Python程序,观察收发报文中通告窗口的变化,了解滑动窗口工作的原理;观察大文件传输过程,分析识别TCP的慢启动、拥塞避免、快速恢复等拥塞控制过程;运行iperf3进行网络性能测试,比较不同拥塞控制性能表现。 &
+ 详见实验指导书,根据老师的安排确定实验内容;部署实验环境;按步骤进行实验;收集分析数据,回答思考题,并编写实验报告。\\ \hline
+
+ \multirow{3}{1.5cm}{基于套接字的网络程序设计} &
+
+ 套接字基础与UDP通信&
+ 使用Python编写一个简单的,非标准的基于UDP的ping程序,该程序能够发送简单的ping报文,接收从服务器往返的对应pong报文,并确定从该客户发送ping报文到接收pong报文为止的时延(往返时延RTT)。&
+ 根据实验指导书,参考服务器端代码,完成客户端代码,测试和分析实验结果。\\ \cline{2-4}
+
+ & TCP通信与Web服务器 &
+ 使用Python开发一个一次能处理一个HTTP请求的Web服务器。&
+ 根据实验指导书,在提供的框架基础上完成客户端代码,测试和分析实验结果。\\ \cline{2-4}
+
+ & SMTP客户端实现 &
+ 使用Python开发一个能够发送文本信息的简单的SMTP客户端。&
+ 根据实验指导书,在提供的框架基础上完成客户端代码,测试和分析实验结果。\\ \hline
+
+ \multirow{3}{1.5cm}{组网基础} &
+
+ 静态路由&
+ 完成路由规划并在华为网络模拟器eNSP中完成IP地址和静态路由的配置,掌握采用静态路由进行网络设计的基本原则和方法,理解静态路由的工作原理。&
+ 根据实验指导书,完成实验环境的安装和配置,按步骤进行实验,观察和记录实验结果并编写实验报告。\\ \cline{2-4}
+
+ & 动态路由(RIP) &
+ 完成路由规划并在华为网络模拟器eNSP中完成IP地址和RIP协议的配置,掌握采用动态路由协议RIP进行网络设计的基本原则和方法,理解动态路由协议RIP的工作原理。&
+ 根据实验指导书,完成实验环境的安装和配置,按步骤进行实验,观察和记录实验结果并编写实验报告。\\ \cline{2-4}
+
+ & 动态路由(OSPF) &
+ 完成路由规划并在华为网络模拟器eNSP中完成IP地址和OSPF协议的配置,掌握采用动态路由协议OSPF进行网络设计的基本原则和方法,理解动态路由协议OSPF的工作原理。&
+ 根据实验指导书,完成实验环境的安装和配置,按步骤进行实验,观察和记录实验结果并编写实验报告。\\ \hline
+
+ \multirow{3}{1.5cm}{路由器实现} &
+
+ 二层交换机实现&
+ 基于网络创新实验开发平台,使用C语言编程开发实现一个软件二层交换机系统原型;实现二层以太网分组交换功能;完成二层分组数据解析、MAC表学习与查找以及MAC表老化功能。&
+ 基于网络创新实验开发平台的参考示例程序完成;实现测试主机在多个设备端口间均能ping通;拔掉交换机端口网线1分钟后触发该端口MAC表项老化和删除功能;主机网线连接端口变化时,打印输出原来连接端口与新连接端口号信息。\\ \cline{2-4}
+
+ & 三层路由器实现 &
+ 基于网络创新实验开发平台,使用C语言编程开发实现一个软件三层交换机系统原型,实现不同网段的分组通信功能;完成端口ARP协议交互功能;完成FIB表获取与查询功能;完成分组数据二层与三层的协议解析与封装功能。&
+ 基于网络创新实验开发平台的参考示例程序完成;分组数据仅需支持ARP与IPv4协议格式;不同端口内不同网段的主机均能相互ping通;FIB表内容从系统内核获取并能周期刷新;根据协议解析内容区分打印数据平面分组与控制平面分组数据流摘要信息,两种类型数据分开处理;区分打印ARP主动请求学习与被动响应的处理过程;在测试主机ping 8.8.8.8,观察路由器FIB查表的执行步骤,分析原因。\\ \cline{2-4}
+
+ & 三层路由组网实现&
+ 在自研三层路由器原型系统上运行Quagga协议,并正确配置路由协议,使用两个以上路由器原型系统实现多网段互联互通。&
+ 正确安装Quagga运行环境,正确配置RIP与OSPF两种路由协议;单独运行一种路由协议能正确学习到远端网络路由转发表内容;各网段在不同路由协议使用情况下均能相互ping通;与不同的实验组同学组网验证;断开某个网段的连线,验证路由器FIB表的更新(原来存在的表项消失)。\\ \hline
+
+ \multirow{3}{1.5cm}{软件定义网络与网络测量} &
+
+ 基于OpenFlow的SDN交换机&
+ 基于网络创新实验开发平台,使用C语言编程开发实现一个SDN交换机系统原型,实现SDN交换机的基本通信及配置管理功能;&
+ 参考OpenFlow~1.3协议格式,实现指定的消息;能利用PACKET\_IN报文上报端口输入的完整二层以太网数据;ACTION动作可只支持端口转发与丢弃;基于实验平台的硬件流表管理API接口将流表配置的OFPT\_FLOW\_MOD消息内容同步到硬件表项中。\\ \cline{2-4}
+
+ & 基于OpenFlow的拓扑测量 &
+ 使用多个自研的SDN交换机组网互连,通过LLDP的链路探测协议完成全网拓扑的构建;编程展示网络拓扑信息图。&
+ 基于自研的SDN交换机原型实现;最少使用3台设备;SDN控制器建议使用Floodlight;区分打印交换机自身发出的LLDP协议分组和接收到其他交换机的LLDP分组,显示分组摘要信息;通过REST API接口获取SDN控制器的链路连接信息与设备信息;基于WEB网页编程展示网络拓扑图。变换不同网络连接结构,刷新验证WEB页面的拓扑图,要求与真实网络连接关系一致。3台设备中间使用一台普通交换机连接,再次验证拓扑图显示,分析原因。\\ \cline{2-4}
+
+ & 纳秒级高精度硬件测量&
+ 基于网络创新实验开发平台,完成测量节点到服务器的RTT延时测量、网络带宽测量以及不同长度网线传输延时测量。&
+ 基于网络创新实验开发平台的测量工具与源码;测量服务器RTT延时的报文使用ping协议格式;测量网络带宽时,在网络内使用固定背景流量大于500M,测量分组的大小设置64与1500,计算测量带宽差异;测量1米与10米网线的传输延时,判断并分析二者的延时差别。\\ \hline
+
+\end{longtable}
+
+\end{landscape}
\ No newline at end of file
diff --git a/data/appendix/ensp.tex b/data/appendix/ensp.tex
index e8d5378..1e67cba 100644
--- a/data/appendix/ensp.tex
+++ b/data/appendix/ensp.tex
@@ -1,53 +1,64 @@
%# -*- coding: utf-8-unix -*-
-\chapter{华为网络仿真平台ENSP简介}
-\label{app:ENSP}
+\chapter{华为网络仿真平台eNSP简介}
+\label{app:eNSP}
-掌握华为ENSP软件的安装、操作和使用;熟悉华为模拟设备的基本配置及其配置命令;
+掌握华为eNSP软件的安装、操作和使用;熟悉华为模拟设备的基本配置及其配置命令;
掌握常见问题的解决方法。
-\subsection{本地安装华为ENSP软件}
-可在本机安装华为ENSP软件。
-安装版本如选择的是华为ENSP17年版本的,则安装包里自带所需软件,
-则无需另行下载,默认4款软件全部安装;
-如选择的是华为ENSP最新版即19年的版本,
-在安装之前须自行下载安装以下3款软件且最好版本号一致:
+\subsection{本地安装华为eNSP软件}
+可在本机安装华为eNSP软件。
-\begin{figure}[!ht]
+安装版本如选择的是华为eNSP17年版本的,
+则安装包里自带所需软件,则无需另行下载,
+默认4款软件全部安装;如选择的是华为eNSP最新版即19年的版本,
+在安装之前须自行下载安装以下3款软件且最好版本号一致。
+
+eNSP的正常实验依赖与WinPcap、Wireshark和VirtualBox三款软件,
+支持的版本如下表。
+
+\renewcommand{\arraystretch}{1.5}
+\begin{table}[!ht]
+ \small
\centering
- \includegraphics[width=11cm]{a1_ENSP-version}
- \caption{ENSP版本}
- \label{fig:a1_ENSP-version}
-\end{figure}
+ \caption{华为eNSP需安装软件及对应版本号}
+ \label{tab:a:wireshark_eth-format}
+ \begin{tabular}{|c|c|} \hline
+ \heiti 软件类别 & \heiti 版本号\\ \hline
+ WinPcap & 4.1.3\\ \hline
+ Wireshark & 2.6.6\\ \hline
+ VirtualBox & 4.2.X-5.2.X\\ \hline
+ \end{tabular}
+\end{table}
-\textbf{安装注意事项:}先装3款基础软件后再安装华为ENSP,
+\textbf{安装注意事项:}先装3款基础软件后再安装华为eNSP,
所有安装都建议默认安装,最好不要更改安装盘,更不要设置中文安装目录,
否则可能使用时会出现问题,则只能重装。
-\subsection{华为ENSP操作和使用}
-华为ENSP的操作和使用,强烈建议查看其帮助,并不断实践,如图:
+\subsection{华为eNSP操作和使用}
+华为eNSP的操作和使用,强烈建议查看其帮助,并不断实践,如图:
\begin{figure}[!ht]
\centering
- \includegraphics[width=13cm]{a1_ENSP-UI}
- \caption{华为ENSP界面}
- \label{fig:a1_ENSP-ui}
+ \includegraphics[width=13cm]{eNSP-UI}
+ \caption{华为eNSP界面}
+ \label{fig:a1_eNSP-ui}
\end{figure}
\begin{figure}[!ht]
\centering
- \includegraphics[width=13cm]{a1_ENSP-help}
- \caption{华为ENSP帮助界面}
- \label{fig:a1_ENSP-help}
+ \includegraphics[width=13cm]{eNSP-help}
+ \caption{华为eNSP帮助界面}
+ \label{fig:a1_eNSP-help}
\end{figure}
\subsection{华为模拟设备的基本配置及其配置命令}
-命令行接口是用户对命令行使用的常用工具。
-通过命令行接口输入命令,您可以对交换机进行配置和管理。
-用户登录到交换机出现命令行提示符后,
-即进入命令行接口CLI(Command Line Interface)。
-命令行接口是用户与交换机进行交互的常用工具。
-系统向用户提供一系列命令,
-用户可以通过命令行接口输入命令,对交换机进行配置和管理。
+ 命令行接口是用户对命令行使用的常用工具。
+ 通过命令行接口输入命令,您可以对交换机进行配置和管理。
+ 用户登录到交换机出现命令行提示符后,
+ 即进入命令行接口CLI(Command Line Interface)。
+ 命令行接口是用户与交换机进行交互的常用工具。
+ 系统向用户提供一系列命令,
+ 用户可以通过命令行接口输入命令,对交换机进行配置和管理。
\subsubsection{命令视图}
@@ -55,16 +66,18 @@
系统的所有命令都注册在某个(或某些)命令视图下,
只有在相应的视图下才能执行该视图下的命令。
+\renewcommand{\arraystretch}{1.5}
\begin{table}[!ht]
+ \small
\centering
\caption{命令视图分类表}
\label{tab:a:ensp_command_ui}
- \begin{tabular}{m{5cm}<{\centering}m{6cm}<{\centering}} \toprule
- 视图 & 表现形式\\ \midrule
- 用户视图(缺省配置) & \texttt{}\\
- 系统视图 & \texttt{[Quidway]}\\
- 接口视图 & \texttt{[Quidway-ethernetX]}\\
- VLAN视图 & \texttt{[Quidway-VLANX]}\\ \bottomrule
+ \begin{tabular}{|c|c|} \hline
+ \heiti 视图 & \heiti 表现形式\\ \hline
+ 用户视图(缺省配置) & \texttt{}\\ \hline
+ 系统视图 & \texttt{[Quidway]}\\ \hline
+ 接口视图 & \texttt{[Quidway-ethernetX]}\\ \hline
+ VLAN视图 & \texttt{[Quidway-VLANX]}\\ \hline
\end{tabular}
\end{table}
@@ -98,7 +111,7 @@
[Quidway]
\end{code}
\end{itemize}
-
+
说明:命令行提示符“Quidway”是缺省的主机名(sysname)。
通过提示符可以判断当前所处的视图,例如:“<>”表示用户视图,
“[]”表示除用户视图以外的其它视图。
@@ -112,7 +125,7 @@ Ctrl+Z:(在其他模式下)保存设置并退出到特权模式
Tab键的功用:完成一个命令的输入。在超级终端中,可能不支持某些组合键。
\textbf{注:}在不引起歧义的情况下,命令和参数均可以缩写
-
+
\textbf{在线帮助}
输入命令行或进行配置业务时,在线帮助可以提供在配置手册之外的实时帮助。
@@ -124,25 +137,30 @@ Tab键的功用:完成一个命令的输入。在超级终端中,可能不
\item 命令行错误信息
\end{itemize}
+\renewcommand{\arraystretch}{1.5}
\begin{table}[!ht]
+ \small
\centering
\caption{帮助类型与对应命令表}
- \label{tab:tab:a:ensp_help}
- \begin{tabular}{m{2cm}<{\centering}m{5cm}<{\centering}m{6cm}<{\centering}} \toprule
- 帮助类型 & 表现形式 & 备注\\ \midrule
- \multirow{2}{*}{完全帮助} & \texttt{?} & 相应命令模式下\\
- & \texttt{[Quidway] sysname ?} & 键入命令,后接以空格分隔的“?”\\\midrule
- 部分帮助 & \texttt{d?} & 键入一字符串,其后紧接“?”,列出以该字符串开头的所有关键字\\\midrule
- 命令行错误信息 & & 如未通过语法检查则系统会向用户报告错误信息\\ \bottomrule
+ \label{tab:a:ensp_help}
+ \begin{tabular}{|m{2cm}<{\centering}|m{5cm}<{\centering}|m{6cm}<{\centering}|} \hline
+ \heiti 帮助类型 & \heiti 表现形式 & \heiti 备注\\ \hline
+ \multirow{2}{*}{完全帮助} & \texttt{?} & 相应命令模式下\\ \cline{2-3}
+ & \texttt{[Quidway] sysname ?} & 键入命令,后接以空格分隔的“?”\\ \hline
+ 部分帮助 & \texttt{d?} & 键入一字符串,其后紧接“?”,列出以该字符串开头的所有关键字\\ \hline
+ 命令行错误信息 & & 如未通过语法检查则系统会向用户报告错误信息\\ \hline
\end{tabular}
\end{table}
\begin{enumerate}
\item \textbf{完全帮助}
-
+
应用完全帮助,系统可以协助您在输入命令行时,给予全部关键字或参数的提示。
+
命令行的完全帮助可以通过以下3种方式获取:
+
在所有命令视图下,键入“?”获取该命令视图下所有的命令及其简单描述。
+
\begin{code}[text]
?
\end{code}
@@ -205,44 +223,49 @@ Tab键的功用:完成一个命令的输入。在超级终端中,可能不
Bootrombpdu
bpdu-tunnel buffer
\end{code}
-
+
输入命令的某个关键字的前几个字母,按下键,
可以显示出完整的关键字,前提是这几个字母可以唯一标示出该关键字,
否则,连续按下键,可出现不同的关键字,用户可以从中选择所需要的关键字。
-
+
\item 命令行错误信息
所有用户键入的命令,如果通过语法检查,则正确执行,
- 否则系统将会向用户报告错误信息。常见错误信息参见下表:
+ 否则系统将会向用户报告错误信息。常见错误信息参见表\ref{tab:a:ensp_error}:
\begin{table}[!ht]
+ \small
\centering
\caption{命令行常见错误信息表}
- \label{tab:tab:a:ensp_error}
- \begin{tabular}{m{4cm}<{\centering}m{5cm}<{\centering}} \toprule
- 英文错误信息 & 错误原因\\ \midrule
- \multirow{2}{*}{Unrecognized command} & 没有查找到命令\\
- & 没有查找到关键字\\\midrule
- \multirow{2}{*}{Wrong parameter} & 参数类型错\\
- & 参数值越界\\\midrule
- Incomplete command & 输入命令不完整\\\midrule
- Too many parameters & 输入参数太多\\\midrule
- Ambiguous command & 输入命令不明确\\ \bottomrule
- \end{tabular}
+ \label{tab:a:ensp_error}
+ \begin{tabular}{|m{4cm}<{\centering}|m{5cm}<{\centering}|} \hline
+ \heiti 英文错误信息 & \heiti 错误原因\\ \hline
+ \multirow{2}{*}{Unrecognized command} & 没有查找到命令\\ \cline{2-2}
+ & 没有查找到关键字\\ \hline
+ \multirow{2}{*}{Wrong parameter} & 参数类型错\\ \cline{2-2}
+ & 参数值越界\\\hline
+ Incomplete command & 输入命令不完整\\\hline
+ Too many parameters & 输入参数太多\\\hline
+ Ambiguous command & 输入命令不明确\\ \hline
+ \end{tabular}
\end{table}
- \textbf{注意:}可以用display cur检查当前系统中已经配置的命令。
+ \textbf{注意:}可以用display~cur检查当前系统中已经配置的命令。
如果命令输出过多,显示一屏幕后会暂停,
这时可以用空格键翻页,用q或者ctrl+c退出。
\end{enumerate}
\subsection{常见问题的解决方法}
- 模拟器毕竟是模拟的,有问题是难免的,如下图令人崩溃的设备启动后进入命令配置界面的等待。如长时间都不能正常工作,建议新建一台设备,如正常后替代失常设备,重新连线。就本人多年指导经验,各种问题会小概率出现,默认重装,更换版本则解决地较为彻底。
+ 模拟器毕竟是模拟的,有问题是难免的,
+ 如下图令人崩溃的设备启动后进入命令配置界面的等待。
+ 如长时间都不能正常工作,建议新建一台设备,如正常后替代失常设备,
+ 重新连线。就本人多年指导经验,各种问题会小概率出现,
+ 默认重装,更换版本则解决地较为彻底。
\begin{figure}[!ht]
\centering
- \includegraphics[width=10cm]{a1_error}
+ \includegraphics[width=10cm]{error}
\caption{令人崩溃的等待}
\label{fig:a1_error}
\end{figure}
diff --git a/data/appendix/fast.tex b/data/appendix/fast.tex
new file mode 100644
index 0000000..f116ec9
--- /dev/null
+++ b/data/appendix/fast.tex
@@ -0,0 +1,836 @@
+%# -*- coding: utf-8-unix -*-
+
+\chapter{FAST软件编程入门指南}
+\label{app:fast}
+
+\subsection{前言}
+
+本文档的主要阅读对象是首次使用FAST平台进行软件开发的工作人员。
+文档主要描述了FAST架构软件的主要功能、如何获取软件代码、
+介绍软件架构与对应代码结构、编译运行FAST代码。
+详细介绍了FAST开发的主要使用函数,
+描述了用户如何使用开发函数进行自己代码的开发流程,
+最后提供一个完整的开发示例说明,供初学者学习使用。
+
+\subsection{FAST能做什么}
+
+FAST平台的主要功能是软硬件配合的网络分组处理功能,
+硬件的主要作用是解析报文,对报文进行查表匹配,
+进行指定的动作处理,然后分发报文。
+报文分发可以直接转发到硬件端口,也可以送到CPU端的UA进程再处理,
+UA处理完成后可以再通过硬件转发从端口输出。
+软件的主要功能有两点:
+一是对硬件的流表与对应动作进行配置,指定报文从硬件端口转发或送到CPU端的UA;
+二是处理硬件无法处理的报文,处理完成后再转发到硬件输出。
+
+FAST软件的编程主要包括UA编程、规则管理编程和寄存器访问控制编程。
+UA编程主要处理硬件送到指定软件的分组数据;
+规则管理编程主要是对硬件流表的读写管理;
+寄存器访问控制编程主要是对硬件各寄存器资源的访问控制。
+对硬件规则的读写与对硬件其他寄存器的读写需要了解FAST架构的虚拟地址空间定义。
+
+\subsection{FAST软件获取}
+\label{subsec:app:fast_get-soft}
+
+FAST的软硬件代码和相关工具下载请查看文章结尾的百度网盘链接。
+
+\subsection{FAST代码结构}
+
+\subsubsection{目录结构}
+
+\renewcommand{\arraystretch}{1.5}
+\begin{table}[!ht]
+ \small
+ \centering
+ \caption{FAST代码目录结构}
+ \label{tab:a:fast_dir-structure}
+ \begin{tabular}{|c|c|c|} \hline
+ \heiti 序号 & \heiti 目录名称 & \heiti 说明\\ \hline
+ 1 & include & 开发所用头文件目录\\ \hline
+ 2 & lib & ua、寄存器读写库目录\\ \hline
+ 4 & app & fast应用工具\\ \hline
+ 6 & tools & 调试测试示例工具\\ \hline
+ 7 & src & 综合示例代码测试\\ \hline
+ \end{tabular}
+\end{table}
+
+\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 其他:不同平台的适配头文件
+\end{enumerate}
+
+\subsubsection{开发示例}
+
+开发示例提供了一个基于FAST架构的2层交换机实例,
+综合使用了libreg和libua两个库实现了一个全软件的2层交换机功能。
+
+\begin{enumerate}
+ \item L2switch
+
+ L2switch是基于FAST架构开发一个2层以太网交换机原型,
+ 通过对流表默认规则的设置,将硬件所有的分组重定向到UA程序,
+ 然后在UA的分组处理回调函数中实现对分组的2层交换,
+ 然后将分组从指定端口发送或泛洪发送。
+ 该示例主要演示了UA编程开发的主要方法与流程、使用的相关函数,
+ 硬件寄存器地址的操作,以及2层交换机的实现原理。
+
+\item xofp
+
+ xofp是基于FAST架构开发一个SDN交换机原型,
+ 通过OpenFlow协议连接SDN控制器,SDN交换机默认规则是送往SDN控制器,
+ SDN控制器根据报文数据,配置流表转发下发给硬件,下次进来的报文直接转发输出。
+ 该示例主要演示了SDN交换机OpenFLow协议、处理OpenFLow消息、
+ 使用的相关函数,硬件寄存器地址的操作,以及SDN交换机的实现原理。
+\end{enumerate}
+
+\subsubsection{工具}
+
+示例程序的另一种表现就是FAST提供的一些小工具,包括单独的寄存器读写命令、规则输出命令、端口状态显示命令和端口分组计数命令。
+
+\begin{enumerate}
+ \item Reg\_rw
+
+ 该工具主要是使用libreg库实现一个对用户指定的寄存器进行读写访问操作,展示了用户如何调用libreg的相关库函数进行寄存器访问操作的方法。
+ \item Rule\_hw
+
+ 该工具主要是使用libreg库和librule库实现对硬件流表的获取并分组输出操作,展示了用户如何调用librule库的相关库函数进行规则操作。该工具目前只使用了硬件规则的读取操作,更多规则的功能操作可参考综合测试程序
+ \item Port\_status
+
+ 该工具主要使用libreg库实现了对各端口的协商状态、链路状态等寄存器的访问并进行各状态值的解释。主要展示了不同端口状态的寄存器地址如何计算,各状态寄存器值返回如何解释,示例代码中包含了目前支持的所有状态寄存器及对应功能说明
+ \item Port\_counts
+
+ 该工具主要使用libreg库实现了对各端口分组计数的统计显示,主要展示了不同功能计数统计的寄存器虚拟地址空间定义,各端口对应功能寄存器的计算方法。示例代码中包含了目前支持的所有功能计数统计寄存器定义与说明
+\end{enumerate}
+
+\subsubsection{综合测试}
+
+综合测试程序包含了libreg、librule和libua库的综合开发示例功能。
+首先,用户可以通过此程序了解各功能库的主要使用函数及调用顺序;
+其次,用户可以通过此程序的编译参数了解不同功能库如何添加对应库功能支持
+
+subsection{FAST代码运行}
+
+\subsubsection{软硬件环境}
+FAST平台由湖南新实网络科技有限公司提供销售、售后与技术支持。
+该平台可通过采购或免费申请试用获取,用户拿到FAST平台后,
+默认系统环境均已支持FAST硬件基础版本与FAST软件基础版本。
+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
+ \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}
+
+\subsubsection{代码执行}
+\begin{enumerate}
+ \item 读硬件版本号
+ \begin{code}[console]
+ openbox@OpenBox~/hnxs/fast-0.4.5$ reg_rw rd 0
+ \end{code}
+\end{enumerate}
+
+\subsection{FAST数据结构}
+\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 "
+ #else
+ #error "Please fix "
+ #endif
+ };
+\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*/
+ {
+ 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,此为确保数据结构大小做的填充*/
+ };
+\end{code}
+
+\subsection{FAST开发函数}
+
+\subsubsection{硬件资源与寄存器}
+\begin{enumerate}
+ \item int fast\_init\_hw(u64 addr,u64 len);
+ 硬件资源初始化。所有涉及到需要操作硬件寄存器、流表和动作等均需要先调用此函数,
+ 实例化硬件资源,使软件具体访问硬件的能力。
+
+ 参数:addr,在PCIe标准设备中表示硬件资源的内存映射地址,
+ 通常情况下,用户可以直接填写0。
+
+ 参数:len,在PCIe标准调和中表示硬件资源的内存地址空间大小,
+ 通常情况下,用户可以直接填写0。
+
+ 返回值:0表示硬件资源实例化正常,非零表示失败,
+ 如果失败将无法对硬件进行任何操作,程序将自动退出。
+ \item void fast\_distroy\_hw(void);
+ 硬件资源销毁。PCIe设备主要是撤销对硬件资源的映射,
+ OpenBox-S4主要是对设备发送关闭报文。
+ 一般情况下,用户程序退出时应该调用此函数,释放资源。
+ 但是我们内部并没有做特殊的资源处理,均为系统可自动回收功能,
+ 即使用户不调用此函数,当程序正常退出时,系统也能正常回收资源,
+ 不影响程序再次运行使用。
+ \item u64 fast\_reg\_rd(u64 regaddr);
+ 寄存器读函数。读取用户指定寄存器位置的值返回。
+ 该函数内部会根据平台的不同使用不同的方法去访问硬件寄存器。
+ PCIe的平台以正常寄存器方式访问,而NetMagic~08需要使用NMAC报文进行交互获取。
+ 这些不同的操作方式均已对用户屏蔽,用户无需关心该函数底层如何交互与实现,
+ 仅需调用此函数接口来操作寄存器读操作即可。
+
+ 参数:regaddr,表示用户将要读取的寄存器地址,
+ 该地址即FAST平台所定义的虚拟地址空间,该值均使用相对偏移值的方式使用,
+ 即FAST平台定义的值,对PCIe平台设备访问需要使用绝对地址访问才可以正常访问寄存器,
+ 相对地址转绝对地址已经封装在函数内部,
+ 用户对所有寄存器的操作均可只用相对值访问即可。
+
+ 返回值:返回该寄存器对应的值。该值的位宽是64位,
+ 在所有FAST平台寄存器的位宽均为64位。
+ \item void fast\_reg\_wr(u64 regaddr,u64 regvalue);
+ 寄存器写函数。将指定值写对硬件对应的寄存器位置。
+ 该函数内部会根据平台的不同使用不同的方法去操作硬件寄存器。
+ PCIe的平台以正常寄存器方式访问,而NetMagic~08需要使用NMAC报文进行交互获取。
+ 这些不同的操作方式均已对用户屏蔽,用户无需关心该函数底层如何交互与实现,
+ 仅需调用此函数接口来操作寄存器写操作即可。
+
+ 参数:regaddr,表示用户将要写入的寄存器地址,
+ 该地址即FAST平台所定义的虚拟地址空间,该值均使用相对偏移值的方式使用,
+ 即FAST平台定义的值,
+ 对PCIe平台设备访问需要使用绝对地址访问才可以正常访问寄存器,
+ 相对地址转绝对地址已经封装在函数内部,
+ 用户对所有寄存器的操作均可只用相对值访问即可。
+
+ 参数:regvalue,表示要写入上述参数寄存器位置的值。该值的位宽为64位。
+\end{enumerate}
+\subsubsection{流表操作}
+\begin{enumerate}
+ \item void init\_rule(u32 default\_action);
+ 初始化规则。初始化规则函数的主要功能是在软件分配软件规则空间,
+ 将硬件规则空间清零,设置硬件规则的默认动作。
+ 该函数只在进行流表操作的应用中进行调用,而且只能被调用一次。
+ 如果有多个应用需要操作规则,
+ 整个系统在关机或重启前所有的应用中也只能由一个应用来调用一次。
+ 主要是该函数会将硬件所有存在流表清空。用户需要自己非常清楚对流表的操作,
+ 在一次流表清空后才可以对流表进行其他操作。
+
+ 参数:default\_action,默认动作。当所有的流表均不能匹配时,
+ 硬件需要执行一个默认的动作来完成这个分组的处理,
+ 流表可以为空,但默认动作必须要有。详细的动作含义可以参考动作说明。
+
+ \item int fast\_add\_rule(struct fast\_rule *rule);
+ 添加一条规则。添加规则函数,先将用户的规则添加在软件流表中,
+ 经过各种比较判断后,看是否能正常添加,有无冲突或是否存在,
+ 如果可以正常添加,则先将规则存储在软件,
+ 然后将此条软件规则数据通过寄存器方式下发到硬件对应规则的存储位置。
+
+ 参数:rule,规则对象,内部具体字段参考流规则数据结构定义
+
+ 返回值:返回当前添加规则成功后此条规则所在的索引号
+ \item int fast\_modify\_rule(struct fast\_rule *rule,int idx);
+ 修改一条已经存在的规则。此函数主要是用来修改已经存在的规则,
+ 对其关键字、掩码、动作和优先级等进行修改。
+ 该函数的索引值参数如果指向一条空规则,其操作流程将类似于添加规则函数。
+
+ 参数:rule,新规则对象,内部具体字段参考流规则数据结构定义
+
+ 参数:idx,旧规则所在索引号
+
+ 返回值:返回输入参数的idx值说明操作成功,其他值说明操作失败
+ \item int fast\_del\_rule(int idx);
+ 删除一条已经存储的规则,或将一条规则置为无效。
+ 只需要提供规则所在的索引号,软件可通过索引号定位到对应硬件存储规则位置,
+ 将规则的有效位置为无效,实现一条规则的删除。
+ 删除硬件成功后,将其对应的软件规则进行清除。
+
+ 参数:idx,删除规则所在索引号
+
+ 返回值:返回输入参数的idx值说明操作成功,其他值说明操作失败
+ \item int read\_hw\_rule(struct fast\_rule *rule,int index);
+ 读取一条硬件规则。将存储在硬件规则内对应索引的数据读取出来,
+ 还原为一条软件规则数据,存储在用户提供的指针位置。
+
+ 参数:rule,将要存储规则的内存指针
+
+ 参数:idx,将要读取规则所在硬件的索引号
+
+ 返回值:返回输入参数的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();
+ 启动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的源代码进行修改,整个代码结构不变,
+可以直接使用原工程中的所有Makefile文件,
+修改完成后,直接make即可得到用户所需要的可执行文件;
+第二种是用户根据自己需要,选择需要的开发库与头文件,
+自己重新组织新的代码目录与结构进行开发,
+原工程中的Makefile文件均不可再用,需要自己重写Makefile文件。
+
+\subsubsection{修改源码开发}
+
+\begin{enumerate}
+ \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[])
+ {
+ int i = 0,p1 = 1,p2 = 2,idx1 = 0,idx2 = 1;
+ struct fast_rule rule[2] = {{0},{0}};//初始化两条全空的规则
+
+ if(argc == 3)
+ {
+ 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;
+ rule[i].priority =0xA;
+ rule[i].action = ACTION_PORT<<28|p2;//动作字段的涵义请参考fast_type.h
+ rule[i].md5[0] = i+1;
+
+ //给规则对应字段设置掩码,掩码为1表示使用,为0表示忽略
+ 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;
+ rule[i].action = ACTION_PORT<<28|p1;//动作字段的涵义请参考fast_type.h
+ rule[i].md5[0] = i+1;
+
+ //给规则对应字段设置掩码,掩码为1表示使用,为0表示忽略
+ 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)
+ {
+ 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目录下,执行交叉编译
+
+ \begin{code}[console]
+ # cd fast-0.4.5
+ # make
+ \end{code}
+
+ 编译完成后将把tools/rule\_hw目录下rule\_hw工具放到OpenBox-S4设备,
+ 执行修改过的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节测试交叉编译。
\ No newline at end of file
diff --git a/data/appendix/openbox.tex b/data/appendix/openbox.tex
new file mode 100644
index 0000000..e5ce51d
--- /dev/null
+++ b/data/appendix/openbox.tex
@@ -0,0 +1,458 @@
+%# -*- coding: utf-8-unix -*-
+
+\chapter{可编程网络平台-操作手册}
+\label{app:openbox}
+
+\subsection{FAST简介}
+
+针对近年来关于工业控制网络创新技术、创新网络结构、
+时间敏感网络、SDN网络、FPGA硬件加速技术及下一代网络技术的研究需求,
+由国防科大与湖南新实共同发起的开源项目
+——FAST(FPGA Accelerated Switcing plaTform)于2016年创建。
+
+FAST平台的架构是一种通用多核CPU加FPGA形态的网络处理架构,
+该平台架构主要由硬件逻辑和软件逻辑两部分组成,
+实现软硬件耦合通信与支持软硬件可编程的网络创新实验系统。
+其中硬件包括平台相关的数据IO和FAST硬件逻辑。
+软件部分包括通用操作系统与FAST软件逻辑。
+FAST软件逻辑包括FAST软件开发环境和FAST UA程序。
+在FAST平台,不仅支持FAST的UA编程开发,同时也支持通用APP的运行。
+
+\subsection{设备简介}
+
+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}
+
+\end{enumerate}
+
+\subsubsection{检测准备}
+\begin{enumerate}
+ \item 物品准备
+ \begin{table}[!htp]
+ \small
+ \centering
+ \caption{所需实验物品}
+ \label{tab:a:openbox_items}
+ \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}
+\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 点击 “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协议版本4(TCP/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}
+
+\end{enumerate}
+\subsection{搭建环境}
+OpenBox-S4是一款软硬件全可编程网络实验平台,
+根据FAST架构搭建其软硬件基础运行环境,
+内部软硬件用户逻辑支持所有FAST架构开发的应用,
+是一款专业的网络实验与研究验证平台。
+\subsubsection{连接二层交换拓扑}
+
+\begin{figure}[!htp]
+ \centering
+ \includegraphics[width=11cm]{f13}
+ \caption{二层交换连接拓扑示意图}
+ \label{fig:a:ob_f13}
+\end{figure}
+
+其中PC1的IP地址设置为“192.168.1.20”,PC2的IP地址设置为“192.168.1.21”
+\subsubsection{在OpenBox-S4上运行二层交换程序}
+
+\begin{figure}[!htp]
+ \centering
+ \includegraphics[width=11cm]{f14}
+ \caption{二层交换命令启动输出图}
+ \label{fig:a:ob_f14}
+\end{figure}
+
+在串口登录界面或网络登录界面输入命令:l2switch
+
+\begin{figure}[!htp]
+ \centering
+ \includegraphics[width=11cm]{f15}
+ \caption{二层交换命令运行输出图}
+ \label{fig:a:ob_f15}
+\end{figure}
+
+\subsubsection{在PC两端进行PING测试}
+
+\begin{figure}[!htp]
+ \centering
+ \includegraphics[width=11cm]{f16}
+ \caption{端主机PING通结果图}
+ \label{fig:a:ob_f16}
+\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_f25}
+ \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_f26}
+ \end{figure}
+ \item 由于篇幅的原因,wireshark的其他使用,在本文档就不再说明了。
+ \end{enumerate}
+ \end{enumerate}
+\end{enumerate}
+\subsubsection{CP2102串口驱动的安装使用}
+\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}
+\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个核心文件。
+
+\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}
+\end{enumerate}
diff --git a/data/ch_ensp/preface.tex b/data/ch_ensp/preface.tex
index dd6ae7d..3678d82 100644
--- a/data/ch_ensp/preface.tex
+++ b/data/ch_ensp/preface.tex
@@ -6,6 +6,6 @@
掌握静态路由、动态路由RIP和OSPF协议的配置,并理解分析静态与动态路由的区别,
两种动态路由协议各自的适用环境,理解网络收敛的概念。
推荐使用华为ENSP模拟器,
-在附录\ref{app:ENSP}中有该软件的安装、操作和使用,
+在附录\ref{app:eNSP}:《华为网络仿真平台 ENSP 简介》中有该软件的安装、操作和使用,
以熟悉华为模拟设备的基本配置及其配置命令,
掌握软件安装常见问题的解决方法。
diff --git a/data/ch_ensp/sec_ospf.tex b/data/ch_ensp/sec_ospf.tex
index d36cf6b..ba15c27 100644
--- a/data/ch_ensp/sec_ospf.tex
+++ b/data/ch_ensp/sec_ospf.tex
@@ -14,10 +14,10 @@
\begin{itemize}
\item 华为路由器IP地址的配置;
- \item 动态路由协议OSPF的配置;
+ \item 动态路由协议ospf的配置;
\item 路由规划;
\item 网络测试与排错操作;
- \item RIP与OSPF路由协议的区别。
+ \item rip与ospf路由协议的区别。
\end{itemize}
\subsection{实验原理、方法和手段}
@@ -42,31 +42,35 @@
\label{subsec:c:ensp:s:ospf_requirement}
\begin{itemize}
- \item 华为ENSP仿真平台中:2台PC,两台路由器;
+ \item 华为ENSP仿真平台中:2台PC,3台路由器;
\item 双绞线若干。
\end{itemize}
\subsection{实验步骤}
\label{subsec:c:ensp:s:ospf_procedure}
-实验说明:路由器端口以具体选用的设备为准,
-如果是实际设备,请观察路由器前面板和后面板的端口名称,
-并使用disp int或者disp cur命令查看端口的实际名称。
-在对路由器进行配置时,
-可使用disp cur命令来检查当前路由器上生效的配置命令。
+实验说明:路由器端口以具体选用的设备为准,如果是实际设备,
+请观察路由器前面板和后面板的端口名称
+,并使用disp int或者disp cur命令查看端口的实际名称。
+在对路由器进行配置时,可使用disp cur命令来检查当前路由器上生效的配置命令。
+
+(如保存了实验3.2-rip,则在原rip实验基础上选下文第7步,
+即跳过前6步已配置完成的命令,直接配置第7步;
+如是全新实验,则从第一步开始,顺序配置,第7步跳过。)
\begin{enumerate}
- \item 硬件连接,完成PC1、PC2到路由器RT1和RT2的网络连接,
- 路由器RT1到路由器RT2的连接;
+ \item 硬件连接,完成PC1、PC2到路由器的网络连接;
PC1到路由器RT1控制线的连接,PC2到路由器RT2控制线的连接。
拓扑图检查无误后方可进行后面的实验步骤,
实验报告中的拓扑图必须标清路由器实际连接的端口。
\item 为PC1、PC2分别设置IP地址、掩码和网关。
- \item 使用sysname命令为路由器R1和R2命名。
+ \item 使用sysname命令为三个路由器命名。
路由器R1的名称为学生自己的姓名拼音+R1,
- 路由器R2的名称为学生自己的姓名拼音+R2,要求记录输入的命令和输出(截屏)。
+ 路由器R2的名称为学生自己的姓名拼音+R2,
+ 路由器R3的名称为学生自己的姓名拼音+R3,
+ 要求记录输入的命令和输出(截屏)。
- R1上的重命名命令如下例:
+ R1上的命令:
\begin{code}[text]
system-view
[Huawei]sysname zhangsanR1
@@ -76,11 +80,11 @@
\begin{figure}[!htp]
\centering
\includegraphics[width=10cm]{sysname-R1_3}
- \caption{R1的sys配置图}
+ \caption{R1配置图}
\label{fig:c:ensp_sysname-R1_3}
\end{figure}
- R2上的重命名命令如下例:
+ R2上的命令:
\begin{code}[text]
system-view
[Huawei]sysname zhangsanR2
@@ -90,96 +94,111 @@
\begin{figure}[!htp]
\centering
\includegraphics[width=10cm]{sysname-R2_3}
- \caption{R2的sys配置图}
+ \caption{R2配置图}
\label{fig:c:ensp_sysname-R2_3}
\end{figure}
-
- \item 为路由器R1的 GE0接口配置IP地址。
- 配置完成后PC1应该可以Ping通RT1的 GE0口的地址。
- 为路由器R2的 GE1接口配置IP地址。
- 配置完成后PC2应该可以Ping通RT2的GE1口的地址。
- 要求记录输入的命令和输出(截屏)。
- (本模拟器R1实际使用的接口名由实际使用的路由器型号确定,
- 可能有Ethernet0/0/0;或GigabitEthernet0/0/x;或FastEthernet0/0/x)
- R1上的重命名命令如下例:
+ R3上的命令:
+ \begin{code}[text]
+ system-view
+ [Huawei]sysname zhangsanR3
+ \end{code}
+
+ \item (从左至右配置)为路由器R1的两个接口配置IP地址。
+ 配置完成后PC1应该可以Ping通RT1的E0口的地址。
+ 要求记录输入的命令和输出(截屏)。
+ (本模拟器R1实际使用的接口名由实际使用的路由器型号确定,可能有Ethernet0/0/0;
+ 或GigabitEthernet0/0/x;或FastEthernet0/0/x)
+ R1上的命令:
\begin{code}[text]
[zhangsanR1]interface GigabitEthernet 0/0/0
[zhangsanR1- GigabitEthernet0/0/0]ip address 192.168.1.1 255.255.255.0
[zhangsanR1- GigabitEthernet0/0/0]
\end{code}
-
+
PC1可以Ping通R1的192.168.1.1地址
\begin{code}[text]
- PC1> ping 192.168.1.1
- \end{code}
-
- R2上的命令:
- \begin{code}[text]
- [zhangsanR2]interface GigabitEthernet 0/0/1
- [zhangsanR1-GigabitEthernet0/0/1]ip address 192.168.3.1 255.255.255.0
+ PC1>ping 192.168.1.1
\end{code}
- PC2可以Ping通R2的192.168.3.1地址
+ 图3.3-4 Ping通效果图
+ 为路由器R1的 GE1接口配置IP地址。
\begin{code}[text]
- PC1>ping 192.168.3.1
- \end{code}
-
- \item 为路由器R1的 Ethernet0/0/1接口配置IP地址,
- 为路由器R2的Ethernet0/0/0接口配置IP地址。
- 配置完成后路由器R1和R2应该可以互相Ping通。
- 要求记录输入的命令和输出(截屏)。
- \begin{code}[text]
+ [zhangsanR1]interface GigabitEthernet 0/0/1
[zhangsanR1-GigabitEthernet0/0/1]ip address 192.168.2.1 255.255.255.0
[zhangsanR1-GigabitEthernet0/0/1]quit
\end{code}
-
+ \item 为路由器R2的GE0、GE1接口配置IP地址。
+ 配置完成后路由器R1和R2应该可以互相Ping通。要求记录输入的命令和输出(截屏)
\begin{code}[text]
+ [zhangsanR2]interface GigabitEthernet 0/0/0
[zhangsanR2-GigabitEthernet0/0/0]ip address 192.168.2.2 255.255.255.0
[zhangsanR2-GigabitEthernet0/0/0]quit
\end{code}
- \item (如在实验3.2的基础上进行实验则执行此步骤,否则直接配置第七步)
- 为RT1和RT2配置动态路由协议ospf,首先删除原来的rip配置。
+ \begin{code}[text]
+ [zhangsanR2]interface GigabitEthernet 0/0/1
+ [zhangsanR2-GigabitEthernet0/0/1]ip address 192.168.3.1 255.255.255.0
+ [zhangsanR2-GigabitEthernet0/0/1]quit
+ \end{code}
+ \item 为路由器R3的GE0、GE1接口配置IP地址。
+ 配置完成后,直连路由应可相互Ping通,如PC2应可Ping通R3的GE1口的地址。
+ \begin{code}[text]
+ [zhangsanR3]interface GigabitEthernet 0/0/0
+ [zhangsanR3-GigabitEthernet0/0/0]ip address 192.168.3.2 255.255.255.0
+ [zhangsanR3-GigabitEthernet0/0/0]quit
+ \end{code}
+
+ \begin{code}[text]
+ [zhangsanR3]interface GigabitEthernet 0/0/1
+ [zhangsanR3-GigabitEthernet0/0/1]ip address 192.168.4.1 255.255.255.0
+ [zhangsanR3-GigabitEthernet0/0/1]quit
+ \end{code}
+ PC2可以Ping通R2的192.168.4.1地址
+ \begin{code}[text]
+ PC1>ping 192.168.4.1
+ \end{code}
+
+ (此前同实验3.2-rip的1-6步骤,如在原rip基础上配置则配置下文第7步;
+ 如是全新实验,则跳过第7步,直接配置第8步)
+
+ \item (视情况选择)为3个路由器配置动态路由协议ospf,首先删除原来的rip配置。
要求记录输入的命令和输出(截屏或文本复制)。
配置后可以用display current configuration检查配置,
- 或者display ip routing-table检查路由表。
- 要求记录输入的命令和输出(截屏)。
+ 或者display ip routing-table检查路由表。要求记录输入的命令和输出(截屏)。
\begin{code}[text]
[zhangsanR1]undo rip
\end{code}
-
- \begin{figure}[!htp]
- \centering
- \includegraphics[width=12cm]{confirm}
- \label{fig:c:ensp_confirm}
- \end{figure}
-
确认删除?Y
此时用disp cur检查配置,rip相关配置全部删除;
disp ip routing-table检查路由表,rip那条路由也将被删除
+
\begin{code}[text]
[zhangsanR2]undo rip
\end{code}
确认删除?Y
-
- \item 为RT1和RT2配置动态路由协议ospf。
+
+ \begin{code}[text]
+ [zhangsanR3]undo rip
+ \end{code}
+ 确认删除?Y
+
+ \item 为3个路由器分别配置动态路由协议ospf。
配置后可以用disp cur检查配置,或者disp ip routing-table检查路由表。
- 配置完成后路由器R1和R2应该可以互相Ping通。
+ 配置完成后,网络收敛,则网络任意两点间,应该可以互相Ping通。
要求记录输入的命令和输出(截屏)。
-
\begin{code}[text]
[zhangsanR1]ospf
[zhangsanR1-ospf-1]area 0
[zhangsanR1-ospf-1-area-0.0.0.0]network 192.168.1.0 0.0.0.255
[zhangsanR1-ospf-1-area-0.0.0.0]network 192.168.2.0 0.0.0.255
[ctrl+z]
- [zhangsanR1]ping 192.168.3.2
+ [zhangsanR1]ping 192.168.4.2
\end{code}
-
+
\begin{code}[text]
[zhangsanR2]ospf
[zhangsanR2-ospf-1]area 0
@@ -189,7 +208,31 @@
[ctrl+z]
[zhangsanR2]ping 192.168.1.2
\end{code}
-
+
+ \begin{code}[text]
+ [zhangsanR3]ospf
+ [zhangsanR3-ospf-1]area 0
+ [zhangsanR3-ospf-1-area-0.0.0.0]network 192.168.3.0 0.0.0.255
+ [zhangsanR3-ospf-1-area-0.0.0.0]network 192.168.4.0 0.0.0.255
+ [zhangsanR3-ospf-1-area-0.0.0.0]display ip routing-table
+ [ctrl+z]
+ [zhangsanR3]ping 192.168.1.2
+ \end{code}
+ 如未ping通,则可能网络未收敛,当网络收敛时,网络任意两点间,
+ 应该可以互相ping通。请复核。
+
+ \begin{code}[text]
+ [zhangsanR1]display ip routing-table
+ \end{code}
+ (R1路由表截屏)
+ \begin{code}[text]
+ [zhangsanR2]display ip routing-table
+ \end{code}
+ (R2路由表截屏)
+ \begin{code}[text]
+ [zhangsanR3]display ip routing-table
+ \end{code}
+ (R3路由表截屏)
\end{enumerate}
\subsection{思考题}
@@ -203,12 +246,13 @@ Rip和OSPF协议的区别是什么?请对比路由表,收敛速度等。
\begin{enumerate}
\item 路由器端口以具体选用的设备为准,
请将E0口和E1口对应到实际设备上的端口名称,
- 接口名由实际使用的路由器型号确定,
- 可能有Ethernet0/0/0;或GigabitEthernet0/0/x;或FastEthernet0/0/x。
+ 接口名由实际使用的路由器型号确定,可能有Ethernet0/0/0;
+ 或GigabitEthernet0/0/x;或FastEthernet0/0/x。
如果是实际设备,请观察路由器前面板和后面板的端口名称,
并使用disp int或者disp cur命令查看端口的实际名称。
在对路由器进行配置时,可使用disp cur命令来检查当前路由器上生效的配置命令。
- \item 此实验的第1-5步骤同前一实验3.2-rip,
- 如在原rip基础上配置选第六步;
- 如是全新实验,则跳过第六步,直接配置第七步。
+ \item 此实验的第1-6步骤同前一实验3.2-rip,
+ 如保存了实验3.2-rip,则在原rip实验基础上选下文第7步,
+ 即跳过前6步已配置完成的命令,直接配置第7步;
+ 如是全新实验,则从第一步开始,顺序配置,第7步跳过。
\end{enumerate}
\ No newline at end of file
diff --git a/data/ch_ensp/sec_rip.tex b/data/ch_ensp/sec_rip.tex
index 47916a0..22b699c 100644
--- a/data/ch_ensp/sec_rip.tex
+++ b/data/ch_ensp/sec_rip.tex
@@ -27,7 +27,7 @@
观察并记录各设备状态变化情况,特别留意路由信息的交换和路由表。
解释说明与路由协议、路由表的相关性。
-可参考下图连线,具体联线情况请自行标注。
+可参考图\ref{fig:c:ensp_RIP-topo}连线,具体联线情况请自行标注。
\begin{figure}[!htp]
\centering
@@ -40,7 +40,7 @@
\label{subsec:c:ensp:s:rip_requirement}
\begin{itemize}
- \item 华为ENSP仿真平台中:2台PC,两台路由器;
+ \item 华为ENSP仿真平台中:2台PC,3台路由器;
\item 双绞线若干。
\end{itemize}
@@ -49,19 +49,20 @@
实验说明:路由器端口以具体选用的设备为准。
如果是实际设备,请观察路由器前面板和后面板的端口名称,
-并使用disp int或者disp cur命令查看端口的实际名称。在对路由器进行配置时,
-可使用disp cur命令来检查当前路由器上生效的配置命令。
+并使用disp~int或者disp~cur命令查看端口的实际名称。
+在对路由器进行配置时,可使用disp cur命令来检查当前路由器上生效的配置命令。
\begin{enumerate}
- \item 硬件连接,完成PC1、PC2到路由器RT1和RT2的网络连接,
- 路由器RT1到路由器RT2的连接;
+ \item 硬件连接,完成PC1、PC2到路由器的网络连接;
PC1到路由器RT1控制线的连接,PC2到路由器RT2控制线的连接。
拓扑图检查无误后方可进行后面的实验步骤,
实验报告中的拓扑图必须标清路由器实际连接的端口。
\item 为PC1、PC2分别设置IP地址、掩码和网关。
- \item 使用sysname命令为路由器R1和R2命名。
+ \item 使用sysname命令为三个路由器命名。
路由器R1的名称为学生自己的姓名拼音+R1,
- 路由器R2的名称为学生自己的姓名拼音+R2,要求记录输入的命令和输出(截屏)。
+ 路由器R2的名称为学生自己的姓名拼音+R2,
+ 路由器R3的名称为学生自己的姓名拼音+R3,
+ 要求记录输入的命令和输出(截屏)。
R1上的命令:
\begin{code}[text]
system-view
@@ -88,10 +89,14 @@
\label{fig:c:ensp_sysname-R2_2}
\end{figure}
- \item 为路由器R1的 GE0接口配置IP地址。
- 配置完成后PC1应该可以Ping通RT1的 GE0口的地址。
- 为路由器R2的 GE1接口配置IP地址。
- 配置完成后PC2应该可以Ping通RT2的GE1口的地址。
+ R3上的命令:
+ \begin{code}[text]
+ system-view
+ [Huawei]sysname zhangsanR3
+ \end{code}
+
+ \item (从左至右配置)为路由器R1的两个接口配置IP地址。
+ 配置完成后PC1应该可以Ping通RT1的E0口的地址。
要求记录输入的命令和输出(截屏)。
(本模拟器R1实际使用的接口名由实际使用的路由器型号确定,
可能有Ethernet0/0/0;或GigabitEthernet0/0/x;或FastEthernet0/0/x)
@@ -116,70 +121,89 @@
\label{fig:c:ensp_ping_2}
\end{figure}
- R2上的命令:
+ \item 为路由器R1的 GE1接口配置IP地址。
\begin{code}[text]
- [zhangsanR2]interface GigabitEthernet 0/0/1
- [zhangsanR1-GigabitEthernet0/0/1]ip address 192.168.3.1 255.255.255.0
- \end{code}
-
- PC2可以Ping通R2的192.168.3.1地址
-
+ [zhangsanR1]interface GigabitEthernet 0/0/1
+ [zhangsanR1-GigabitEthernet0/0/1]ip address 192.168.2.1 255.255.255.0
+ [zhangsanR1-GigabitEthernet0/0/1]quit
+\end{code}
+\item 为路由器R2的GE0、GE1接口配置IP地址。
+配置完成后路由器R1和R2应该可以互相Ping通。
+要求记录输入的命令和输出(截屏)
\begin{code}[text]
- PC1>ping 192.168.3.1
- \end{code}
-
- \item 为路由器R1的 Ethernet0/0/1接口配置IP地址,
- 为路由器R2的Ethernet0/0/0接口配置IP地址。
- 配置完成后路由器R1和R2应该可以互相Ping通。
- 要求记录输入的命令和输出(截屏)。
-
+ [zhangsanR2]interface GigabitEthernet 0/0/0
+ [zhangsanR2-GigabitEthernet0/0/0]ip address 192.168.2.2 255.255.255.0
+ [zhangsanR2-GigabitEthernet0/0/0]quit
+\end{code}
+
\begin{code}[text]
- [zhangsanR1-GigabitEthernet0/0/1]ip address 192.168.2.1 255.255.255.0
- [zhangsanR1-GigabitEthernet0/0/1]quit
+ [zhangsanR2]interface GigabitEthernet 0/0/1
+ [zhangsanR2-GigabitEthernet0/0/1]ip address 192.168.3.1 255.255.255.0
+ [zhangsanR2-GigabitEthernet0/0/1]quit
+\end{code}
+\item 为路由器R3的GE0、GE1接口配置IP地址。配置完成后,
+直连路由应可相互Ping通,如PC2应可Ping通R3的GE1口的地址。
+ \begin{code}[text]
+ [zhangsanR3]interface GigabitEthernet 0/0/0
+ [zhangsanR3-GigabitEthernet0/0/0]ip address 192.168.3.2 255.255.255.0
+ [zhangsanR3-GigabitEthernet0/0/0]quit
+\end{code}
+
+ \begin{code}[text]
+ [zhangsanR3]interface GigabitEthernet 0/0/1
+ [zhangsanR3-GigabitEthernet0/0/1]ip address 192.168.4.1 255.255.255.0
+ [zhangsanR3-GigabitEthernet0/0/1]quit
\end{code}
+ PC2可以Ping通R2的192.168.4.1地址
\begin{code}[text]
- [zhangsanR2-GigabitEthernet0/0/0]ip address 192.168.2.2 255.255.255.0
- [zhangsanR2-GigabitEthernet0/0/0]quit
+ PC1>ping 192.168.4.1
\end{code}
-
- \item 为RT1和RT2配置动态路由协议rip。
- 要求记录输入的命令和输出(截屏或文本复制)。
- 配置后可以用disp cur检查配置,或者disp ip routing-table检查路由表。
- 要求记录输入的命令和输出(截屏)。
-
+
+ \item 为三个路由器分别配置动态路由协议rip(从左至右)。要求记录输入的命令和输出(截屏或文本复制)。配置后可以用disp cur检查配置,或者disp ip routing-table检查路由表。要求记录输入的命令和输出(截屏)。
\begin{code}[text]
[zhangsanR1]rip
[zhangsanR1-rip]network 192.168.1.0
[zhangsanR1-rip]network 192.168.2.0
\end{code}
-
+
\begin{code}[text]
[zhangsanR2]rip
- [zhangsanR2-rip]network 192.168.3.0
[zhangsanR2-rip]network 192.168.2.0
+ [zhangsanR2-rip]network 192.168.3.0
\end{code}
-
+
+ \begin{code}[text]
+ [zhangsanR3]rip
+ [zhangsanR3-rip]network 192.168.3.0
+ [zhangsanR3-rip]network 192.168.4.0
+ \end{code}
+
\begin{code}[text]
[zhangsanR1]display ip routing-table
\end{code}
-
+ (R1路由表截屏)
\begin{code}[text]
[zhangsanR2]display ip routing-table
\end{code}
-
- 等待1分钟后,在两台路由器上重复disp ip rout(缩写)命令,
- 比较路由表,rip协议是否出现?
+ (R2路由表截屏)
+ \begin{code}[text]
+ [zhangsanR3]display ip routing-table
+ \end{code}
+ (R3路由表截屏)
+ 等待1分钟后,在两台路由器上重复disp ip rout(缩写)命令,
+ 比较路由表,rip协议是否全部出现?
+
注意:如果要删除某路由器上的所有rip配置,或路由输入错误,
则输入下列命令则可删除刚才的路由
\begin{code}[text]
[zhangsanR2]undo rip
\end{code}
-
+
\item 验证PC1和PC2可以ping通。要求记录输入的命令和输出(截屏)。
+
\item (为后续实验,建议保存拓扑和具体设备的配置命令,
即在和模式中输入save命令,并保存已配置命令
-
\end{enumerate}
\subsection{思考题}
@@ -194,5 +218,9 @@
\subsection{注意事项及有关说明}
\label{subsec:c:ensp:s:rip_notice}
-路由器端口以具体选用的设备为准,请将E0口和E1口对应到实际设备上的端口名称,接口名由实际使用的路由器型号确定,可能有Ethernet0/0/0;或GigabitEthernet0/0/x;或FastEthernet0/0/x。如果是实际设备,请观察路由器前面板和后面板的端口名称,并使用disp int或者disp cur命令查看端口的实际名称。在对路由器进行配置时,可使用disp cur命令来检查当前路由器上生效的配置命令。
-
+路由器端口以具体选用的设备为准,请将E0口和E1口对应到实际设备上的端口名称,
+接口名由实际使用的路由器型号确定,可能有Ethernet0/0/0;
+或GigabitEthernet0/0/x;或FastEthernet0/0/x。如果是实际设备,
+请观察路由器前面板和后面板的端口名称,
+并使用disp int或者disp cur命令查看端口的实际名称。
+在对路由器进行配置时,可使用disp cur命令来检查当前路由器上生效的配置命令。
diff --git a/data/ch_ensp/sec_static.tex b/data/ch_ensp/sec_static.tex
index f931ba9..985d1e3 100644
--- a/data/ch_ensp/sec_static.tex
+++ b/data/ch_ensp/sec_static.tex
@@ -32,20 +32,18 @@
\end{figure}
\begin{enumerate}
- \item 用路由器连接若干局域网,
- 局域网之间建议采用Ethernet协议连接,
- 局域网之间采用静态路由,
- 从而使在不同局域网上的计算机能够交换信息。
+ \item 用路由器连接若干局域网,局域网之间建议采用Ethernet协议连接,
+ 局域网之间采用静态路由,从而使在不同局域网上的计算机能够交换信息。
观察联通前后计算机和路由器路由表的变化情况,并给出解释。
\item 通过ping其他主机,用Wireshark捕捉网络流量,
- 找出与ping相关的ARP协议、ICMP协议报文逐字节地进行剖析(选做)。
+ 找出与ping相关的ARP协议、ICMP协议报文逐字节地进行剖析(选做)
\end{enumerate}
\subsection{实验条件}
\label{subsec:c:ensp:s:static_requirement}
\begin{itemize}
- \item 华为ENSP仿真平台中:2台PC,两台路由器;
+ \item 华为ENSP仿真平台中:2台PC,三台路由器;
\item 双绞线若干。
\end{itemize}
@@ -60,16 +58,17 @@
如果是实际设备,请观察路由器前面板和后面板的端口名称,
并使用disp int或者disp cur命令查看端口的实际名称。
在对路由器进行配置时,可使用disp cur命令来检查当前路由器上生效的配置命令。
+
\begin{enumerate}
- \item 硬件连接,完成PC1、PC2到路由器RT1和RT2的网络连接,
- 路由器RT1到路由器RT2的连接;PC1到路由器RT1控制线的连接,
- PC2到路由器RT2控制线的连接。
- 拓扑图检查无误后方可进行后面的实验步骤,
+ \item 硬件连接,完成PC1、PC2到路由器的网络连接;
+ PC1到路由器RT1控制线的连接,PC2到路由器RT2控制线的连接。
+ 拓扑图检查无误后方可进行后面的实验步骤,
实验报告中的拓扑图必须标清路由器实际连接的端口。
\item 为PC1、PC2分别设置IP地址、掩码和网关。
- \item 使用sysname命令为路由器R1和R2命名。
+ \item 使用sysname命令为三个路由器命名。
路由器R1的名称为学生自己的姓名拼音+R1,
路由器R2的名称为学生自己的姓名拼音+R2,
+ 路由器R3的名称为学生自己的姓名拼音+R3,
要求记录输入的命令和输出(截屏)。
R1上的命令:
@@ -97,13 +96,18 @@
\caption{R1配置图}
\label{fig:c:ensp_sysname-R2_1}
\end{figure}
-
- \item 为路由器R1的 GE0接口配置IP地址。
+
+ R3上的命令:
+ \begin{code}[text]
+ system-view
+ [Huawei]sysname zhangsanR3
+ \end{code}
+
+ \item (从左至右配置)为路由器R1的两个接口配置IP地址。
配置完成后PC1应该可以Ping通RT1的E0口的地址。
- 为路由器R2的 E1接口配置IP地址。
- 配置完成后PC2应该可以Ping通RT2的E1口的地址。
要求记录输入的命令和输出(截屏)。
- (本模拟器R1实际使用的接口名由实际使用的路由器型号确定,可能有Ethernet0/0/0;或GigabitEthernet0/0/x;或FastEthernet0/0/x)
+ (本模拟器R1实际使用的接口名由实际使用的路由器型号确定,
+ 可能有Ethernet0/0/0;或GigabitEthernet0/0/x;或FastEthernet0/0/x)
R1上的命令:
\begin{code}[text]
@@ -111,6 +115,7 @@
[zhangsanR1- GigabitEthernet0/0/0]ip address 192.168.1.1 255.255.255.0
[zhangsanR1- GigabitEthernet0/0/0]
\end{code}
+
PC1可以Ping通R1的192.168.1.1地址
\begin{code}[text]
PC1>ping 192.168.1.1
@@ -123,57 +128,102 @@
\label{fig:c:ensp_ping_1}
\end{figure}
- R2上的命令:
+ 为路由器R1的 GE1接口配置IP地址。
\begin{code}[text]
- [zhangsanR2]interface GigabitEthernet 0/0/1
- [zhangsanR1-GigabitEthernet0/0/1]ip address 192.168.3.1 255.255.255.0
- \end{code}
- PC2可以Ping通R2的192.168.3.1地址
- \begin{code}[text]
- PC1>ping 192.168.3.1
+ [zhangsanR1]interface GigabitEthernet 0/0/1
+ [zhangsanR1-GigabitEthernet0/0/1]ip address 192.168.2.1 255.255.255.0
+ [zhangsanR1-GigabitEthernet0/0/1]quit
\end{code}
- \item 为路由器R1的 Ethernet0/0/1接口配置IP地址,
- 为路由器R2的Ethernet0/0/0接口配置IP地址。
- 配置完成后路由器R1和R2应该可以互相Ping通。要求记录输入的命令和输出(截屏)。
+ \item 为路由器R2的GE0、GE1接口配置IP地址。
+ 配置完成后路由器R1和R2应该可以互相Ping通。
+ 要求记录输入的命令和输出(截屏)
+
\begin{code}[text]
- [zhangsanR1-GigabitEthernet0/0/1]ip address 192.168.2.1 255.255.255.0
- [zhangsanR1-GigabitEthernet0/0/1]quit
+ [zhangsanR2]interface GigabitEthernet 0/0/0
[zhangsanR2-GigabitEthernet0/0/0]ip address 192.168.2.2 255.255.255.0
[zhangsanR2-GigabitEthernet0/0/0]quit
\end{code}
- \item 为RT1和RT2配置路由。要求记录输入的命令和输出(截屏或文本复制)。
+
+ \begin{code}[text]
+ [zhangsanR2]interface GigabitEthernet 0/0/1
+ [zhangsanR2-GigabitEthernet0/0/1]ip address 192.168.3.1 255.255.255.0
+ [zhangsanR2-GigabitEthernet0/0/1]quit
+ \end{code}
+
+ \item 为路由器R3的GE0、GE1接口配置IP地址。配置完成后,
+ 直连路由应可相互Ping通,如PC2应可Ping通R3的GE1口的地址。
+
+ \begin{code}[text]
+ [zhangsanR3]interface GigabitEthernet 0/0/0
+ [zhangsanR3-GigabitEthernet0/0/0]ip address 192.168.3.2 255.255.255.0
+ [zhangsanR3-GigabitEthernet0/0/0]quit
+ \end{code}
+
+ \begin{code}[text]
+ [zhangsanR3]interface GigabitEthernet 0/0/1
+ [zhangsanR3-GigabitEthernet0/0/1]ip address 192.168.4.1 255.255.255.0
+ [zhangsanR3-GigabitEthernet0/0/1]quit
+ \end{code}
+
+ PC2可以Ping通R2的192.168.4.1地址
+ \begin{code}[text]
+ PC1>ping 192.168.4.1
+ \end{code}
+
+ \item 为三个路由器分别从左至右配置静态路由。
+ 要求记录输入的命令和输出(截屏或文本复制)。
配置后可以用disp cur检查配置,或者disp ip route检查路由表。
要求记录输入的命令和输出(截屏)。
+
+ 静态路由配置命令:ip route-static 目的网络号 掩码 下一跳的ip地址
+ 具体环境配置:
+
\begin{code}[text]
[zhangsanR1]ip route-static 192.168.3.0 255.255.255.0 192.168.2.2
+ [zhangsanR1]ip route-static 192.168.4.0 255.255.255.0 192.168.2.2
+ \end{code}
+
+ \begin{code}[text]
[zhangsanR2]ip route-static 192.168.1.0 255.255.255.0 192.168.2.1
+ [zhangsanR2]ip route-static 192.168.4.0 255.255.255.0 192.168.3.2
\end{code}
- 注意:如果路由输入错误,如输入
+
\begin{code}[text]
- [rt1]ip route-static 192.168.3.0 255.255.255.0 192.168.2.2
+ [zhangsanR3]ip route-static 192.168.1.0 255.255.255.0 192.168.3.1
+ [zhangsanR3]ip route-static 192.168.2.0 255.255.255.0 192.168.3.1
+ \end{code}
+
+ 注意:如果路由命令输入错误,如输入
+ \begin{code}[text]
+ [rt1]ip route-static 192.168.3.0 255.255.255.0 192.168.2.1
\end{code}
则输入下列命令则可删除刚才的路由
\begin{code}[text]
- [rt1]undo ip route-static 192.168.3.0 255.255.255.0 192.168.2.2
+ [rt1]undo ip route-static 192.168.3.0 255.255.255.0 192.168.2.1
\end{code}
- \item 验证PC1和PC2可以ping通。
+
+ \item 如配置正确,此时网络收敛,则任何两点之间(含非直连)均可ping通,
+ 验证,如PC1和PC2可以ping通。
分别使用ping命令和traceRT命令来验证,解释结果显示。
要求记录输入的命令和输出(截屏)。
+
\begin{code}[text]
- Ping 192.168.3.2
- traceRT 192.168.3.2
+ Ping 192.168.4.2
+ traceRT 192.168.4.2
\end{code}
- \item (可选作)在PC1上使用抓包工具进行抓包。
- 首先使用arp –d命令清空arp表。
- 再使用Ping命令测试到PC2的连通性(192.168.3.2)。
+
+ \item (以下内容为选做)
+ 在PC1上使用抓包工具进行抓包。首先使用arp –d命令清空arp表。
+ 再使用Ping命令测试到PC2的连通性(192.168.4.2)。
分析抓到的ping命令的icmp报文。
+
\end{enumerate}
\subsection{思考题}
\label{subsec:c:ensp:s:static_rethink}
-如未达到网络收敛状态时,最远两端能够ping通,
+如未达到网络收敛状态时,即使最远两端能够ping通,
请问网络中间的任意两点间也能ping通吗?为什么?
\subsection{注意事项及有关说明}
@@ -181,8 +231,8 @@
路由器端口以具体选用的设备为准,
请将E0口和E1口对应到实际设备上的端口名称,
-接口名由实际使用的路由器型号确定,
-可能有Ethernet0/0/0;或GigabitEthernet0/0/x;或FastEthernet0/0/x。
+接口名由实际使用的路由器型号确定,可能有Ethernet0/0/0;
+或GigabitEthernet0/0/x;或FastEthernet0/0/x。
如果是实际设备,请观察路由器前面板和后面板的端口名称,
并使用disp int或者disp cur命令查看端口的实际名称。
在对路由器进行配置时,可使用disp cur命令来检查当前路由器上生效的配置命令。
diff --git a/data/ch_router-openbox/preface.tex b/data/ch_router-openbox/preface.tex
new file mode 100644
index 0000000..853cb0f
--- /dev/null
+++ b/data/ch_router-openbox/preface.tex
@@ -0,0 +1,18 @@
+%# -*- coding: utf-8-unix -*-
+
+\chapter{路由器实现}
+\label{chap:router-ob}
+
+本单元实验使学生能初步使用可编程网络设备开发平台进行路由器基本功能的设计与实现,
+通过程序来实现路由器中最基本的三个功能:
+包括二层交换功能、三层路由功能及组网功能。
+深入理解路由器的基本工作原理与分组处理流程,
+从而培养学生对网络设备使用和研发的能力。
+
+可编程网络设备开发平台是一款基于FAST架构的软硬件
+(软件在CPU上使用C语言编程,硬件在FPGA芯片上使用Verilog语言编程)
+全可编程的网络实验教学平台,平台的软硬件逻辑代码开源免费,支持用户二次开发。
+其基本使用方法与编程开发方法见附录\ref{app:openbox}:《可编程网络平台-操作手册》
+和附录\ref{app:fast}:《FAST编程-入门指南》。
+可编程网络设备开发平台在后文简称为“可编程网络平台”,图标LOGO为FAST,节点名称为OpenBox-S4。
+
diff --git a/data/ch_router-openbox/sec_networking.tex b/data/ch_router-openbox/sec_networking.tex
new file mode 100644
index 0000000..04d5746
--- /dev/null
+++ b/data/ch_router-openbox/sec_networking.tex
@@ -0,0 +1,274 @@
+%# -*- coding: utf-8-unix -*-
+
+\section{三层路由器组网}
+\label{sec:c:router-ob:s:networking}
+
+\subsection{实验目的}
+\label{subsec:c:router-ob:s:networking_object}
+
+本实验的主要目的是让学生将自己开发的路由器进行组网实验,
+引入路由协议的配置与学习,实现多网段主机间的相互通信。
+熟悉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表同步情况
+\end{enumerate}
+
+\subsection{实验原理、方法和手段}
+\label{subsec:c:router-ob:s:networking_principle}
+
+\subsubsection{路由协议及基本工作原理}
+
+路由协议工作在路由器的控制平面,创建了路由表,描述了网络拓扑结构。
+通过在路由器之间共享路由信息来相互学习总个网络可达区域内可到达的路由网段信息。
+路由信息在相邻路由器之间传递,确保所有路由器知道到其它路由器的路径。
+
+路由协议主要包括:RIP、OSPF、IS-IS和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 学生自研路由器程序。
+\end{itemize}
+
+\begin{figure}[!ht]
+ \centering
+ \includegraphics[width=12cm]{networking-topo}
+ \caption{三层路由组网实验拓扑图}
+ \label{fig:c:router-ob_networking-topo}
+\end{figure}
+
+\subsection{实验步骤}
+\label{subsec:c:router-ob:s:networking_procedure}
+
+\begin{enumerate}
+ \item 在每个路由器节点安装quagga软件,配置其正常工作。
+ 路由协议选择RIP和OSPF两种,每次测试只启动一种协议即可;
+ \begin{itemize}
+ \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启动配置
+ \begin{code}[console]
+ root@HNXS-FAST:/home/hnxs# vim /etc/quagga/daemons
+ zebra=yes
+ bgpd=no
+ ospfd= yes
+ ospf6d=no
+ ripd= yes
+ ripngd=no
+ isisd=no
+ babeld=no
+ \end{code}
+
+ 将上述文件内容中的3个no修改为yes,表示启动该功能模块。
+
+ \item RIP协议启动配置
+ \begin{code}[console]
+ root@HNXS:/home/hnxs# vim /etc/quagga/ripd.conf
+ \end{code}
+
+ ripd.conf配置文件示例如下:
+
+ \begin{code}[text]
+ ! -*- rip -*-
+ !
+ ! RIPd sample configuration file
+ !
+ ! $Id: ripd.conf.sample,v 1.1 2002/12/13 20:15:30 paul Exp $
+ !
+ hostname ripd
+ password zebra
+ !
+ ! debug rip events
+ ! debug rip packet
+ !
+ router rip
+ ! network 11.0.0.0/8
+ ! network eth0
+ ! route 10.0.0.0/8
+ ! distribute-list private-only in eth0
+ network obx0
+ network obx1
+ network obx2
+ network obx3
+ neighbor 192.168.3.1
+ !
+ !access-list private-only permit 10.0.0.0/8
+ !access-list private-only deny any
+ !
+ !log file /var/log/quagga/ripd.log
+ !
+ 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)连接起来的。
+
+ \item OSPF协议启动配置
+ \begin{code}[console]
+ root@HNXS:/home/hnxs# vim /etc/quagga/ospfd.conf
+ \end{code}
+
+ ospfd.conf配置文件示例如下:
+
+ \begin{code}[text]
+ ! -*- ospf -*-
+ !
+ ! OSPFd sample configuration file
+ !
+ !
+ hostname ospfd
+ password zebra
+ !enable password please-set-at-here
+ !
+ !router ospf
+ ! network 192.168.1.0/24 area 0
+ !
+ ospf router-id 192.168.3.1
+ network 192.168.0.0/24 area 0
+ network 192.168.1.0/24 area 0
+ network 192.168.2.0/24 area 0
+ network 192.168.3.0/24 area 0
+ log stdout
+ \end{code}
+
+ 上述为S4-A路由器的配置文件,另一台路由器配置文件为:
+ \begin{code}[text]
+ ! -*- ospf -*-
+ !
+ ! OSPFd sample configuration file
+ !
+ !
+ hostname ospfd
+ password zebra
+ !enable password please-set-at-here
+ !
+ !router ospf
+ ! network 192.168.1.0/24 area 0
+ !
+ ospf router-id 192.168.3.2
+ network 192.168.4.0/24 area 0
+ network 192.168.5.0/24 area 0
+ network 192.168.6.0/24 area 0
+ network 192.168.3.0/24 area 0
+ log stdout
+ \end{code}
+ \end{itemize}
+
+ \item 启动路由协议
+ \begin{code}[console]
+ root@HNXS:/home/hnxs# systemctl start quagga
+ \end{code}
+
+ \item 将自研路由器和测试主机组网,路由节点不少于2个,连线可以组成环状;
+ \item 运行自研路由器,并在两个测试主机上分别ping对方主机IP地址;
+ 请参考实验\ref{sec:c:router-ob:s:router}内容。
+ \item 观察某个节点路由器分组处理流程,
+ 从打印消息上观察控制平面与数据平面的分组处理情况;
+ \item 观察每个节点上内核FIB表内容;
+
+ \begin{code}[console]
+ root@HNXS-FAST:/mnt/openbox# route -n
+ Kernel IP routing table
+ Destination Gateway Genmask Flags Metric Ref Use Iface
+ 192.168.0.0 0.0.0.0 255.255.255.0 U 0 0 0 obx0
+ 192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 obx1
+ 192.168.2.0 0.0.0.0 255.255.255.0 U 0 0 0 obx2
+ 192.168.3.0 0.0.0.0 255.255.255.0 U 0 0 0 obx3
+ 192.168.4.0 192.168.3.2 255.255.255.0 UG 2 0 0 obx3
+ 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变化,是否已经同步更新;
+\end{enumerate}
+
+\subsection{思考题}
+\label{subsec:c:router-ob:s:networking_rethink}
+
+\begin{enumerate}
+ \item 路由协议的邻接信息学习后如何去重?如何收敛?
+ \item 默认网关的作用是什么?
+\end{enumerate}
+
+\subsection{注意事项及有关说明}
+\label{subsec:c:router-ob:s:networking_notice}
+
+\begin{enumerate}
+ \item RIP协议与OSPF协议一定要根据网络连接接口及相应IP地址配置网段信息,
+ 修改文件时注意不要使用中文符号;
+ \item 每次只启动一个协议,以更好验证其效果。
+\end{enumerate}
+
+\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分)实验报告与源代码内容完整、格式整洁。
+\end{enumerate}
diff --git a/data/ch_router-openbox/sec_router.tex b/data/ch_router-openbox/sec_router.tex
new file mode 100644
index 0000000..fae5866
--- /dev/null
+++ b/data/ch_router-openbox/sec_router.tex
@@ -0,0 +1,283 @@
+%# -*- coding: utf-8-unix -*-
+
+\section{三层路由器实现}
+\label{sec:c:router-ob:s:router}
+
+\subsection{实验目的}
+\label{subsec:c:router-ob:s:router_object}
+
+本实验的主要目的是让学生掌握二层以太网帧、ARP协议和三层IP协议等的数据结构,
+熟悉各协议的解析与封装过程,
+掌握三层路由器的工作原理、分组处理流程、FIB表和邻接表生成与使用。
+熟悉路由器数据平面与控制平面的切分及不同的工作处理流程。
+
+\subsection{实验内容}
+\label{subsec:c:router-ob:s:router_content}
+
+使用可编程网络平台及三层路由器示例框架源码,
+设计完成一个三层路由器原型系统。主要完成以下内容:
+
+\begin{enumerate}
+ \item \textbf{系统路由验证:}搭建测试环境,
+ 验证系统自带三层路由原型系统的功能,实现不同网段主机的相互通信功能;
+ \item \textbf{逻辑设计与实现:}基于路由器示例框架代码,
+ 分别设计完成路由器的分组解析、FIB同步与查表、
+ 二层与三层数据更新、ARP请求与响应等模块功能;
+ \item \textbf{功能调试与验证:}根据路由器分组处理流程,
+ 分别调试每一类分组的处理逻辑。如ARP请求类分组、
+ ARP响应类分组、控制平面分组和数据平面分组;
+ 组网测试路由器功能,实现不同网段内主机之间的相互通信功能。
+\end{enumerate}
+
+\subsection{实验原理、方法和手段}
+\label{subsec:c:router-ob:s:router_principle}
+
+\subsubsection{系统路由验证}
+
+请参考附件《可编程网络平台-操作手册》完成。
+\subsubsection{三层路由器工作原理}
+三层路由器工作于OSI模型的第3层(网络层),根据网络层中的目的IP地址进行查表,
+获得分组转发的下一跳输出端口及下一跳的IP地址。更新网络层的TTL值与CSUM值,
+并在输出端口对二层数据进行重新封装二层数据后转发。
+路由器还具备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{端口队列输出:}抽取端口输出队列内的发送分组,
+ 更新二层数据后由端口直接发送。
+\end{enumerate}
+
+\subsection{实验条件}
+\label{subsec:c:router-ob:s:router_requirement}
+
+\begin{itemize}
+ \item 可编程网络平台一个,路由测试主机两台,
+ IP配置及连接拓扑如图\ref{fig:c:router-ob_router-topo}所示;
+ \item 串口线一根,网线两根;
+ \item 三层路由器框架源代码(开发环境与编译工具系统自带)。
+\end{itemize}
+
+\begin{figure}[!ht]
+ \centering
+ \includegraphics[width=8cm]{router-topo}
+ \caption{三层路由器实验拓扑图}
+ \label{fig:c:router-ob_router-topo}
+\end{figure}
+
+\subsection{实验步骤}
+\label{subsec:c:router-ob:s:router_procedure}
+
+\subsubsection{系统路由验证}
+1. 登录可编程网络平台,启动系统自带三层路由器命令,
+系统输出如下信息说明已正常启动且进入工作模式;
+
+\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......
+ fastU->UA->pid:907,mid:132,Register OK!
+ fastU->libua version:20180827
+ fastU->fast_ua_recv......
+\end{code}
+
+\subsubsection{设计开发三层路由器}
+\begin{enumerate}
+ \item 阅读三层路由器框架源代码文件,
+ 根据三层路由工作原理及分组处理流程设计完成框架源代码中的TODO部分内容;
+ \item 编译自己的三层路由器源码,生成相应的路由器系统命令user\_l3router;
+\end{enumerate}
+
+\subsubsection{调试与验证}
+\begin{enumerate}
+ \item 运行自己的三层路由器代码,验证路由器的功能;
+ \item 路由器正常工作后,可以显示如下信息;
+ \begin{itemize}
+ \item 加载路由器接口地址信息
+ \begin{code}[text]
+ 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
+ \end{code}
+
+ \item 同步内核FIB表
+ \begin{code}[text]
+ 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
+ \end{code}
+
+ \item 启动端口输出队列线程
+ \begin{code}[text]
+ 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...
+ \end{code}
+
+ \item 开始接收分组处理
+ \begin{code}[text]
+ fastU->REG Version:20180827,OpenBox HW Version:2030200722
+ FAST UA REG->from pid:923,state:21,mid:132
+ fastU->Register UA to FAST Kernel! Wait Reply......
+ fastU->UA->pid:923,mid:132,Register OK!
+ fastU->libua version:20180827
+ fastU->fast_ua_recv......
+ \end{code}
+
+ \item 控制平面分组处理
+ \begin{code}[text]
+ UA Recv ptk 0xb2c00468,len:130,inport:0
+ Recv IPv4 Packet!
+ Recv Unicast Host Packet,Dispatch Packet!
+ Control Plane->Send to Protocol Stack[128]!
+ \end{code}
+
+ \item 数据平面分组处理
+ \begin{code}[text]
+ UA Recv ptk 0xb2c00468,len:130,inport:2
+ Recv IPv4 Packet!
+ Recv Unicast Host Packet,Dispatch Packet!
+ Data Plane->FIB(dst:192.168.0.111) tblidx:0
+ Data Plane->Next Hop:192.168.0.111,outport:0
+ //查不到MAC,入队后学习MAC
+ Data Plane->port[0],NEIGH[1],IN QUEUE[1]
+ Data Plane->Active Thread on Port[0],QUEUE[1] len:2
+ //查询到MAC,直接封闭二层数据后发送
+ Data Plane->port[2],NEIGH[0],DMAC->B8:27:EB:C1:D1:39
+ Pack L2 on Port[2]
+ pkt_send_normal->0xb2c00468,outport:2,len:130
+ \end{code}
+
+ \item ARP请求处理
+ \begin{code}[text]
+ send_arp_request 192.168.2.119 on Port[2]
+ pkt_send_normal->0xb2b00468,outport:2,len:74
+ pkt_send_normal->0xb2b00468,outport:2,len:74
+ pkt_send_normal->0xb2b00468,outport:2,len:74
+ \end{code}
+
+ \item ARP响应处理
+ \begin{code}[text]
+ UA Recv ptk 0xb2c00468,len:92,inport:0
+ Recv ARP Packet!
+ ARP->Host IPv4
+ ARP->Response,192.168.0.111[B8:27:EB:D8:83:20]--> 192.168.0.1[00:0A:35:01:00:5B]
+ Learn SMAC Port[0],B8:27:EB:D8:83:20
+ Learn SMAC Port[0],NEIGH[0],Update[B8:27:EB:D8:83:20]!
+ \end{code}
+
+ \item 路由不可达
+ \begin{code}[text]
+ ICMP Report and Drop!
+ \end{code}
+
+ \item FIB表刷新
+ \begin{code}[text]
+ FIB4 fresh...
+ \end{code}
+
+ \end{itemize}
+
+ \item 路由器工作不正确时,使用\texttt{xprintf}函数打印调试,
+ 建议根据不同类别数据流进行打印分析,调试某一些报文时,其他无关内容均不打印;
+ \item 在任意一台测试主机\texttt{ping 8.8.8.8},
+ 观察路由器分组处理流程及FIB表查找结果变化;
+ \item 路由器正常工作后,复制保留程序输出日志信息。
+\end{enumerate}
+
+\subsection{思考题}
+\label{subsec:c:router-ob:s:router_rethink}
+
+\begin{enumerate}
+ \item 系统内核的FIB表是如何生成的?生成FIB表的路由协议有哪些,各适应哪些环境?
+ \item 什么是静态路由表?什么是动态路由表?
+ \item FIB表查表不命中如何处理?
+ FIB表指示的下一跳IP的MAC地址不存在如何处理当前分组数据?
+ \item 本程序采用单核单线程处理多个端口的数据转发,如何改成多核多线程方式?
+\end{enumerate}
+
+\subsection{注意事项及有关说明}
+\label{subsec:c:router-ob:s:router_notice}
+
+\begin{enumerate}
+ \item 可编程网络平台的路由器只是一个基础的路由器原型,
+ 分组处理方法与流程设计并不是规范,学生可根据自己理解创新实现;
+ \item 控制平面的数据是通过平台开发环境重新导入到了系统内核处理,
+ 目的是为了支持该系统上的其他正常SOCKET应用,如Quagga路由软件。
+\end{enumerate}
+
+\subsection{考核方法}
+\label{subsec:c:router-ob:s:router_criterion}
+
+完成本次实验,需要提交一份实验报告、一份程序源代码和一分程序输出日志。
+程序源代码中用户添加的代码需要有详细的注释说明。
+
+\begin{enumerate}
+ \item (20分)在规定时间内完成实验,并提交实验成果;
+ \item (40分)实验报告中有详细的路由逻辑设计分析与实现说明;
+ \item (10分)程序正常运行,测试主机可以ping通或抓包接收到对端报文;
+ \item (10分)ARP请求与响应功能正常工作;
+ \item (10分)测试主机可以ping通路由器端口的IP地址;
+ \item (10分)实验报告与源代码内容完整、格式整洁。
+\end{enumerate}
diff --git a/data/ch_router-openbox/sec_switch.tex b/data/ch_router-openbox/sec_switch.tex
new file mode 100644
index 0000000..4e9a3cf
--- /dev/null
+++ b/data/ch_router-openbox/sec_switch.tex
@@ -0,0 +1,279 @@
+%# -*- coding: utf-8-unix -*-
+
+\section{二层交换机实现}
+\label{sec:c:router-ob:s:switch}
+
+\subsection{实验目的}
+\label{subsec:c:router-ob:s:switch_object}
+
+本实验的主要目的是让学生掌握可编程网络平台的二层以太网数据收发方法,
+熟悉二层以太网帧的数据结构,掌握MAC地址的解析与使用。
+熟悉二层交换机的分组交换原理、
+设计完成二层交换的分组处理流程和转发表的老化功能与处理方法。
+
+\subsection{实验内容}
+\label{subsec:c:router-ob:s:switch_content}
+
+使用可编程网络平台及二层交换机示例框架源码,
+设计完成一个二层以太网交换机原型系统。主要完成以下内容:
+
+\begin{enumerate}
+ \item \textbf{平台使用与验证:}掌握可编程网络平台及示例开发代码的修改、
+ 编译和运行操作,验证系统自带二层交换机的功能;
+ \item \textbf{逻辑设计与实现:}设计满足二层交换功能的分组处理流程和逻辑,
+ 如源MAC学习功能、目的MAC查表功能、
+ 端口输出(单播与泛洪)功能和MAC转发表老化功能;
+ \item \textbf{功能调试与验证:}验证自己开发的二层交换机功能,
+ 是否满足各端口间相互通信功能;
+\end{enumerate}
+
+\subsection{实验原理、方法和手段}
+\label{subsec:c:router-ob:s:switch_principle}
+
+\subsubsection{平台基本使用}
+
+请参考附录\ref{app:openbox}:《可编程网络平台-操作手册》完成。
+
+\subsubsection{二层交换工作原理}
+
+二层交换机工作于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分钟)则将该表项删除。
+ 表项删除可将其有效位置无效,提高处理效率。
+\end{enumerate}
+
+\subsubsection{实验方法及手段}
+
+可编程网络平台提供了完整软硬件开发环境和网络功能
+(交换或路由等)的示例应用程序及相应框架源代码。
+学生使用挖空了部分逻辑功能的示例框架源码版本完成网络功能的设计与调试工作。
+
+\subsection{实验条件}
+\label{subsec:c:router-ob:s:switch_requirement}
+
+\begin{itemize}
+ \item 可编程网络平台一台,交换测试主机两台,
+ 连接拓扑及网络配置如上图\ref{fig:c:router-ob_switch-topo}所示;
+ \item 串口线一根,网线两根;
+ \item 网络创新实验平台使用手册和二层交换机框架源代码
+ (开发环境与编译工具系统自带)。
+\end{itemize}
+
+\begin{figure}[!ht]
+ \centering
+ \includegraphics[width=8cm]{switch-topo}
+ \caption{二层交换机实验拓扑图}
+ \label{fig:c:router-ob_switch-topo}
+ \end{figure}
+
+\subsection{实验步骤}
+\label{subsec:c:router-ob:s:switch_procedure}
+
+\subsubsection{平台搭建与系统交换验证}
+
+\begin{enumerate}
+ \item 参考附件《可编程网络平台-操作手册》搭建可编程网络平台的运行环境;
+ \item 在串口登录界面输入如下命令,启动系统自带二层交换机命令。
+ 系统输出如下信息说明已正常启动且进入工作模式;
+ \begin{code}[console]
+ root@HNXS-FAST:/mnt/openbox# l2switch
+ fastU->REG Version:20180827,OpenBox HW Version:2030200722
+ FAST UA REG->from pid:902,state:21,mid:129
+ fastU->Register UA to FAST Kernel! Wait Reply......
+ fastU->UA->pid:902,mid:129,Register OK!
+ fastU->libua version:20180827
+ Create nm08_mac_aging thread OK!
+ aging[0]->invalid mac:0
+ fastU->fast_ua_recv......
+ ID PORT0 PORT1 PORT2 PORT3
+ 0 . . . .
+ aging[1]->invalid mac:0
+ ID PORT0 PORT1 PORT2 PORT3
+ 0 . . . .
+ aging[2]->invalid mac:0
+ \end{code}
+\end{enumerate}
+
+\subsubsection{设计开发二层交换机}
+
+\begin{enumerate}
+ \item 阅读二层交换机框架源代码文件,
+ 根据二层交换工作原理及分组处理流程设计完成框架源代码中的TODO部分内容;
+ \begin{code}[console]
+ root@HNXS-FAST:/# cd /home/hnxs/l2switch/
+ root@HNXS-FAST:/home/hnxs/l2switch# vim main_l2switch.c
+ \end{code}
+
+ 以下为main\_l2switch.c文件的具体内容
+ \begin{code}[c]
+ /**
+ * @brief
+ *
+ * @param inport
+ * @param src_mac
+ */
+ /*地址学习过程,将报文的源MAC学习到对应端口MAC表中*/
+ void learn_smac(u8 inport,u8 *src_mac)
+ {
+ /*更新之前查找空白存储MAC位置*/
+ int i = 0,j = -1;
+ xprintf("learn_smac->\n");
+ //TODO User add code
+ xprintf("learn_smac->add new MAC,port:%d,index:%d\n",inport,j);
+ }
+ \end{code}
+
+ 上述框架代码需要实现的主要功能是源MAC地址的学习,
+ 参数输入为分组数据的输入端口号和源MAC地址的指针。
+ 通过对系统MAC转发表的查找,判断原MAC转发表中是否存在该表项,
+ 若存在,则更新该表项的使用时间;
+ 若不存在,则找一个空闲的表项位置存储该条表项,并更新表项使用时间。
+
+ \item 编译自己的二层交换机源码,生成相应的交换机系统命令user\_l2switch;
+ \begin{code}[console]
+ root@HNXS-FAST:/home/hnxs/l2switch# make
+ gcc –o user_l2switch main_l2switch –lreg –lrule –lua -lthread
+ root@HNXS-FAST:/home/hnxs/l2switch# ls
+ main_l2switch.c Makefile user_l2switch
+ \end{code}
+ user\_l2switch为用户代码编译输出的可执行文件。
+\end{enumerate}
+
+\subsubsection{调试与验证}
+
+\begin{enumerate}
+ \item 运行自己的二层交换机代码,验证交换机的功能;
+
+ \begin{code}[console]
+ root@HNXS-FAST:/home/hnxs/l2switch# ./user_l2switch
+ fastU->REG Version:20180827,OpenBox HW Version:2030200722
+ FAST UA REG->from pid:902,state:21,mid:129
+ fastU->Register UA to FAST Kernel! Wait Reply......
+ fastU->UA->pid:902,mid:129,Register OK!
+ fastU->libua version:20180827
+ Create nm08_mac_aging thread OK!
+ aging[0]->invalid mac:0
+ fastU->fast_ua_recv......
+ 后面打印以学生代码为准……
+ \end{code}
+ 运行当前目录下用户的可执行文件,必须在前面加上”./”
+
+ \item 二层交换机正常工作后,可以显示如下信息;
+ \begin{code}[console]
+ root@HNXS-FAST:/mnt/openbox# l2switch
+ fastU->REG Version:20180827,OpenBox HW Version:2030200722
+ FAST UA REG->from pid:902,state:21,mid:129
+ fastU->Register UA to FAST Kernel! Wait Reply......
+ fastU->UA->pid:902,mid:129,Register OK!
+ fastU->libua version:20180827
+ Create nm08_mac_aging thread OK!
+ aging[0]->invalid mac:0
+ fastU->fast_ua_recv......
+ inport:0,dstmid:129,len:102,dmac:33:33:00:00:00:02,
+ smac:B8:27:EB:04:FC:F0
+ learn_smac->
+ update_mac_time->port:0,index:0
+ learn_smac->add new MAC,port:0,index:0
+ find_dmac->ret = -1
+ ------pkt_send_flood------
+ pkt_send_normal->0xb4c00468,outport:1,len:102
+ 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 . . . .
+ \end{code}
+ \begin{itemize}
+ \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时间
+ \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查表阶段,输出查表结果
+ \begin{code}[text]
+ find_dmac->ret = -1
+ \end{code}
+ \item 进行报文转发
+ \begin{code}[text]
+ //泛洪发送
+ ------pkt_send_flood------
+ pkt_send_normal->0xb4c00468,outport:1,len:102
+ pkt_send_normal->0xb4c00468,outport:2,len:102
+ pkt_send_normal->0xb4c00468,outport:3,len:102
+ //单播发送
+ pkt_send_normal->0xb4c00468,outport:3,len:102
+ \end{code}
+ \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 . .
+ 1 . . . .
+ \end{code}
+ \end{itemize}
+
+ \item 交换机工作不正确时,开启xprintf函数打印调试;
+ 重返步骤3,仔细阅读二层交换框架代码、交换机的工作原理及分组处理流程;
+
+ \item 交换机正常工作后,尝试不断切换连两根网线连接交换机的端口,
+ 观察测试主机的ping丢包,观察交换机工作界面的输出显示。
+\end{enumerate}
+
+\subsection{思考题}
+\label{subsec:c:router-ob:s:switch_rethink}
+
+\begin{enumerate}
+ \item 交换机区分IPv4和IPv6协议吗?区分TCP和UDP吗?
+ \item 广播风暴(broadcast storm)是如何产生的?如何避免?
+ 在不同的应用环境中分别采取的什么方法?
+ \item 广播与组播报文如何判断?组播报文如何转发?
+ \item MAC转发表的老化时间与哪些因素相关?网络规模、MAC表项大小?
+\end{enumerate}
+
+\subsection{注意事项及有关说明}
+\label{subsec:c:router-ob:s:switch_notice}
+
+\begin{enumerate}
+ \item 可编程网络平台的使用手册需要仔细阅读,严格参照文档说明搭建和运行该平台系统;
+ \item 代码修改若不习惯vim命令,可将其文件通过网络方式下载到自己电脑,编辑修改完成后,再上传到实验平台进行验证。Windows平台的上传下载工具为pscp.exe;
+ \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分)实验报告与源代码内容完整、格式整洁。
+\end{enumerate}
diff --git a/data/ch_sdn-openbox/preface.tex b/data/ch_sdn-openbox/preface.tex
new file mode 100644
index 0000000..a923b63
--- /dev/null
+++ b/data/ch_sdn-openbox/preface.tex
@@ -0,0 +1,11 @@
+%# -*- coding: utf-8-unix -*-
+
+\chapter{软件定义网络与网络测量}
+\label{chap:sdn-ob}
+
+本单元实验使学生能初步使用SDN平台进行网络功能的设计与实现,
+通过实验来掌握OpenFlow协议的基本功能与应用,
+以及网络拓扑构建的基本实现。初步掌握网络测试的常用原理及方法,
+了解在测试过程中影响测量精度的原因及如何提高测量精度。
+能通过实验理解软硬件协同测量的方法与特点。
+
diff --git a/data/ch_sdn-openbox/sec_ns.tex b/data/ch_sdn-openbox/sec_ns.tex
new file mode 100644
index 0000000..2ef32f8
--- /dev/null
+++ b/data/ch_sdn-openbox/sec_ns.tex
@@ -0,0 +1,229 @@
+%# -*- coding: utf-8-unix -*-
+
+\section{纳秒级高精度硬件测量}
+\label{sec:c:sdn-ob:s:ns}
+
+\subsection{实验目的}
+\label{subsec:c:sdn-ob:s:ns_object}
+
+本实验的主要目的是让学生掌握网络测试的常用原理及方法,
+了解在测试过程中影响测量精度的原因及如何提高测量精度。
+了解软硬件结果的测量方法与优势。
+
+\subsection{实验内容}
+\label{subsec:c:sdn-ob:s:ns_content}
+
+使用可编程网络平台及用户应用AMS(自动测量系统)软件源代码,
+对网络远端的服务器进行RTT延时测量和带宽测量,
+测量不同长度网线的数据传输时长。主要完成以下内容:
+
+\begin{enumerate}
+ \item 测量RTT时长:使用AMS软件测量一台校园网内服务器的RTT时间,
+ 测量报文使用ping协议文本;
+ \item 测量带宽:在测量网络中添加一台可编程网络平台,
+ 配置为带宽响应测量模式,测量这两个节点之间的实时网络流量,
+ 并用不同测量报文大小来验证测量结果;
+ \item 测量网线时延:测量不同长度网线的数据传输时延,
+ 根据测量结果分析本系统的测量优势与局限;
+ \item 添加软件计时测量:修改测量报文代码,
+ 在开始发送时取系统时间做为软件发送时间,
+ 在接收到报文后为每个报文设置系统接收时间,计算软件的RTT时间。
+\end{enumerate}
+
+\subsection{实验原理、方法和手段}
+\label{subsec:c:sdn-ob:s:ns_principle}
+
+\subsubsection{测量原理}
+网络测量主要是通过时间和数据量相关和相对的关系来反映网络中的各种特性,
+如带宽、延时、抖动和丢包等。
+
+网络测量的分类标准有多种。根据测量的方式分为:
+主动测量和被动测量;根据测量点的多少分为:单点测量与多点测量;
+根据被测量者知情与否分为:协作式测量与非协作式测量;
+根据测量所采用的协议分为:基于BGP协议的测量、
+基于TCP/IP协议的测量以及基于SNMP协议的测量;
+根据测量的内容分为:拓扑测量与性能测量。
+\subsubsection{可编程网络平台的测量特征}
+
+本实验的测量最主要方法是由软件构造测量报文和设定发送报文的时刻表,
+由硬件在指定时间进行报文发送,并在接收获得回应报文后标记硬件的接收时刻。
+接收数据由软件汇总统计计数,与原发送数据进行时间关联,
+计算测量结果。硬件的时间控制精度为8ns,
+故测量数据的收发时间均控制在8ns误差范围内。
+根据时间的精准控制,扩展出硬件背靠背发包测试网络带宽,
+精准周期发包测量精准抖动。
+
+\subsubsection{测量流程}
+
+\begin{enumerate}
+ \item \textbf{软件构造测量报文:}根据测量要求,软件构造测量报文,
+ 报文内容由用户决定。如果测量通用服务器,可以使用ping报文;
+ \item \textbf{软件设置测量报文的发送间隔:}软件设备每个测量报文的发送间隔,
+ 间隔时间可以是零,表示硬件背靠背发送报文;
+ \item \textbf{软件发送测量报文到硬件缓存:}软件将所有测量报文构造好后,
+ 通过分组发送函数发送到硬件缓存。硬件最大缓存32个MTU为1500的分组数据;
+ \item \textbf{软件启动发送:}所有测量分组发送到硬件完成后,
+ 软件可以随时启动发送,通过写硬件状态寄存器的方式通知硬件开始发送测量报文;
+ \item \textbf{硬件根据时间参数严格输出测量报文:}
+ 硬件从开始接收到发送标记时刻开始发送第一个报文,
+ 然后根据报文携带的间隔时间,循环等待,直到下一个报文发送时刻,
+ 将该报文依次发送出去;
+ \item \textbf{硬件接收测量响应报文,标记硬件时间戳:}
+ 等待测量响应服文返回,当接收到任何响应报文后,
+ 硬件均会在报文的头部添加本址硬件时间戳信息,然后将该报文发送给软件;
+ \item \textbf{软件接收报文:}软件根据测量要求,循环接收测量响应报文,
+ 如ping 32个报文后需要接收到32个响应报文;
+ \item \textbf{软件计算测量结果:}测量响应报文接收完成后,
+ 将之前设置的测量配置参数(各报文发送间隔)、
+ 硬件开始发送报文时间戳和接收报文内的时间戳等信息汇总起来进行计算,
+ 得到测量结果后打印输出。
+\end{enumerate}
+
+\subsection{实验条件}
+\label{subsec:c:sdn-ob:s:ns_requirement}
+
+\begin{itemize}
+ \item 可编程网络平台两个,被测试服务器一台;
+ 连接拓扑如图\ref{fig:c:sdn-ob_ns-topo}所示;
+ \item 串口线一根,网线多根;
+ \item AMS软件源代码;
+\end{itemize}
+
+\begin{figure}[!ht]
+ \centering
+ \includegraphics[width=9cm]{ns-topo}
+ \caption{高精度网络测量实验拓扑图}
+ \label{fig:c:sdn-ob_ns-topo}
+\end{figure}
+
+\subsection{实验步骤}
+\label{subsec:c:sdn-ob:s:ns_procedure}
+\begin{enumerate}
+ \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.
+ 64 bytes from 192.168.1.111: icmp_seq=1 ttl=64 time=1.57 ms
+ 64 bytes from 192.168.1.111: icmp_seq=2 ttl=64 time=1.60 ms
+ 64 bytes from 192.168.1.111: icmp_seq=3 ttl=64 time=1.74 ms
+ ^C
+ --- 192.168.1.111 ping statistics ---
+ 3 packets transmitted, 3 received, 0% packet loss, time 2003ms
+ rtt min/avg/max/mdev = 1.576/1.640/1.746/0.088 ms
+ \end{code}
+
+ \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
+ FAST UA REG->from pid:1068,state:21,mid:131
+ fastU->Register UA to FAST Kernel! Wait Reply......
+ fastU->UA->pid:1068,mid:131,Register OK!
+ fastU->libua version:20180827
+ fastU->librule version:20181015,Default Action:0x40000080
+ wait for ams pkts...
+ fastU->fast_ua_recv......
+ \end{code}
+ 系统输出如上信息说明AMS运行成功,并发送5个70字节大小的ping报文出去,默认间隔为1秒。等待ping响应回来。
+ \item 观察RTT测量结果
+ \begin{code}[text]
+ AMS ID PKT_SIZE TS(ns)
+ 0, 70, 1583184
+ 1, 70, 1625224
+ 2, 70, 1707240
+ 3, 70, 1492256
+ 4, 70, 1650272
+ \end{code}
+ 观察测量结果,计算结果在1.5ms左右,与之前的ping测试结果相差不大。
+
+ \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
+ FAST UA REG->from pid:1068,state:21,mid:131
+ fastU->Register UA to FAST Kernel! Wait Reply......
+ fastU->UA->pid:1068,mid:131,Register OK!
+ fastU->libua version:20180827
+ fastU->librule version:20181015,Default Action:0x40000080
+ wait for ams pkts...
+ fastU->fast_ua_recv......
+ \end{code}
+
+ 测试之前,要在此链路中间增加一个背景流,使用iperf的UDP流大小为600Mbps,
+ 系统给服务器发送5个100字节大小的ping报文出去,默认间隔为1秒。
+
+\item 观察带宽测试结果
+ \begin{code}[text]
+ AMS ID PKT_SIZE BW(bps)
+ 0, 70, 341467254
+ \end{code}
+ Iperf的背景流设置参数为600M时,其实际带宽会跑到648Mbps左右。
+ 链路上只有两种数据流,该测量值只是某个测量小时段的带宽反馈,
+ UDP流也存在不稳定性,故其结果相加不可能完全是1000Mbps。
+ 其相加结果与千兆带宽基本相等。
+
+\item 测量网线传输延时
+ \begin{code}[console]
+ root@HNXS-FAST:/home/hnxs/ams# ams
+ fastU->REG Version:20180827,OpenBox HW Version:2030200722
+ FAST UA REG->from pid:1068,state:21,mid:131
+ fastU->Register UA to FAST Kernel! Wait Reply......
+ fastU->UA->pid:1068,mid:131,Register OK!
+ fastU->libua version:20180827
+ fastU->librule version:20181015,Default Action:0x40000080
+ wait for ams pkts...
+ fastU->fast_ua_recv......
+ \end{code}
+
+ 网络测量时需要连接在设备的0和1号端口上,默认测量32组数据。
+
+ \item 观察网线测量结果
+ \begin{code}[text]
+ AMS ID PKT_SIZE TS(ns)
+ 0, 100, 20194
+ 1, 100, 20214
+ 2, 100, 20210
+ 3, 100, 20216
+ 4, 100, 20202
+ \end{code}
+
+ 从数据分析每组测量结果有些误差,但基本
+ \item 分析测量数据的差异
+ \begin{enumerate}
+ \item 对相同测试案例进行多组测量,观察数据变化。
+ \item 分析RTT测量时,软件计时测量与硬件计时测量的差异。
+ \end{enumerate}
+\end{enumerate}
+
+\subsection{思考题}
+\label{subsec:c:sdn-ob:s:ns_rethink}
+
+\begin{enumerate}
+ \item 硬件背靠背报文发送是什么意思?其测量的原理是什么?
+ \item 通过硬件方式测量多组延时数据,为什么仍有较大波动?
+ \item 如何测量网络的抖动?
+\end{enumerate}
+
+\subsection{注意事项及有关说明}
+\label{subsec:c:sdn-ob:s:ns_notice}
+
+\begin{enumerate}
+ \item 测量服务器的PING延时,需要修改发包内容为正确的PING报文内容。
+ \item 测量报文的间隔可以设置为零,但真正发包时的发包时刻计算却不是零,
+ 是因为硬件报文是逐个逐个发送的,且每个报文发送时间长短与其报文长度相关。
+ \item 时间计算与带宽计算中均用到了除法,引入了误差。
+ 硬件时钟本身是存在误差(时钟飘移)的,也会引入计数的误差。
+\end{enumerate}
+
+\subsection{考核方法}
+\label{subsec:c:sdn-ob:s:ns_criterion}
+
+完成本次实验,需要提交一份实验报告和一分程序输出日志。
+\begin{enumerate}
+ \item (20分)在规定时间内完成实验,并提交实验成果;
+ \item (25分)实现软件计时测量与硬件测量对比;
+ \item (25分)将多线测量结果以图形曲线形式汇总并做分析总结;
+ \item (20分)完成网络抖动测量,并做图形化汇总统计;
+ \item (10分)实验报告与源代码内容完整、格式整洁。
+\end{enumerate}
+
diff --git a/data/ch_sdn-openbox/sec_sdn.tex b/data/ch_sdn-openbox/sec_sdn.tex
new file mode 100644
index 0000000..98dca17
--- /dev/null
+++ b/data/ch_sdn-openbox/sec_sdn.tex
@@ -0,0 +1,592 @@
+%# -*- coding: utf-8-unix -*-
+
+\section{基于OpenFlow的SDN交换机}
+\label{sec:c:sdn-ob:s:sdn}
+
+\subsection{实验目的}
+\label{subsec:c:sdn-ob:s:sdn_object}
+
+本实验的主要目的是让学生了解SDN的概念及三层结构原理,
+掌握OpenFlow协议格式、内容、工作流程及对应功能作用。
+掌握SDN控制器北向API使用方法,可通过API编程获取和设置交换机数据。
+
+\subsection{实验内容}
+\label{subsec:c:sdn-ob:s:sdn_content}
+
+使用可编程网络平台及SDN交换机示例框架代码,完成OpenFlow协议的部分功能逻辑。
+验证并分析SDN交换机的工作原理与处理流程。主要完成以下内容:
+
+\begin{enumerate}
+ \item \textbf{阅读协议:}阅读OpenFlow 1.3版本协议白皮书,
+ 掌握其协议内容及对应功能;
+ \item \textbf{设计实现协议功能:}基于SDN交换机示例框架代码,
+ 选择开发OpenFlow协议的部分功能,完成逻辑设计与实现;
+ \item \textbf{验证交换机功能:}运行自己的SDN交换机,跟控制器建立连接,
+ 在控制器查询其工作状态与相关协议功能展示。
+ 如交换机基本信息描述、交换机流表状态、
+ 交换机端口状态及计数统计、网络拓扑展示效果;
+ \item \textbf{检验流表:}验证SDN交换机连接主机间的通信功能,
+ 并观察流表内容及变化情况;
+ \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(软件定义网络),
+是一种新型网络创新架构,用于解决传统网络架构中对于网络虚拟化、
+各类自动化部署以及新型网络协议的问题。
+
+SDN将传统的紧耦合网络设备被拆分成了应用、控制、转发三层,
+其中应用和控制层面能够控制网络中数据的流向以及协议控制,
+而底层的网络设备被抽象为了可自定义的转发逻辑实体,
+可被上层应用定义为不同类型的转发设备。
+
+在应用层,用户可通过通用、简单的API获取网络信息,
+并可修改转发设备的工作逻辑,达到动态改变网络架构的目的。
+
+\subsection{SDN交换机分组处理流程}
+\begin{enumerate}
+ \item \textbf{启动协议通道:}
+ SDN交换机运行OpenFlow协议代理程序与上层控制器建立通信连接。
+ 交换机解析处理OpenFlow协议,
+ 根据协议要求完成协议功能的相关数据收集和配置功能,
+ 构造相应的OpenFlow协议应答控制器。
+
+ \item \textbf{建立连接:}OpenFlow协议代理运行时,
+ 交换机首先和控制器建立连接,
+ 并发送OFP\_HELLO消息用以确认双方都支持的OFP协议版本信息;
+ \item \textbf{查询或设置数据:}
+ 控制器通过OpenFlow的具体消息协议查询或设置交换机其他相关功能的数据,
+ 如OFPT\_HELLO、OFPT\_ECHO\_REQUEST、OFPT\_PACKET\_IN、OFPT\_PACKET\_OUT、
+ OFPT\_FLOW\_MOD、OFPT\_PORT\_MOD、OFPMP\_DESC、OFPMP\_FLOW、OFPMP\_PORT\_STATS等;
+ \item \textbf{处理转发分组:}当交换机接收到一个数据转发分组时,
+ 提取分组数据中的相关字段组成查表关键字,然后在本地进行流表匹配。
+ 如果匹配成功,则根据流表的动作处理该分组,如从其他端口转发出去;
+ 如果匹配不成功,则会命中默认动作,将分组打包送到控制器;
+ \item \textbf{PACKET\_IN分组上传:}交换机查表不命中或是接收到链路探测报文,
+ 则将该数据封装在OpenFlow的PACKET\_IN消息中,上传给控制器;
+ \item \textbf{PACKET\_OUT分组下发:}通过PACKET\_IN上传的分组,
+ 经过控制器分析处理后,会将其封装在OpenFlow协议的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 可编程网络平台一个,交换测试主机两台,
+ SDN控制器(安装SDN控制器软件Floodlight)一台。
+ 网络配置及连接拓扑如图\ref{fig:c:sdn-ob_sdn-topo}所示;
+ \item 串口线一根,网线三根;
+ \item SDN交换机框架开发源代码、流表配置Python脚本。
+\end{itemize}
+
+\begin{figure}[!ht]
+ \centering
+ \includegraphics[width=9cm]{sdn-topo}
+ \caption{OpenFlow交换机实验拓扑图}
+ \label{fig:c:sdn-ob_sdn-topo}
+\end{figure}
+
+\subsection{实验步骤}
+\label{subsec:c:sdn-ob:s:sdn_procedure}
+
+\subsubsection{编译运行SDN交换机,验证交换机基本功能;}
+
+请参考附件\ref{app:openbox}:《可编程网络平台-操作手册》完成。
+
+\subsubsection{基于SDN交换机源码,选择实现自己的协议功能;}
+
+\begin{enumerate}
+ \item 修改源代码
+ \begin{code}[c]
+ enum ofperr handle_openflow_callback(struct ofp_buffer *ofpbuf,int len)
+ {
+ int oftype = ofpbuf->header.type;
+
+ SHOW_FUN(0);
+ LOG_DBG("ofpbuf->header.type=%d\n",ofpbuf->header.type);
+ switch(oftype)
+ {
+ case OFPT_HELLO:
+ /*用户不实现该类消息处理,则直接break,函数返回CONTINUE,
+ *由系统库完成后续处理;*/
+ break;
+ case OFPT_PACKET_OUT:
+ /*若用户想实现该消息的处理,则在此处完成对消息的功能逻辑,
+ *然后直接返回HANDLE,表示已经处理,库函数直接返回*/
+ //TO DO 用户在些添加处理逻辑,完成该消息功能
+ return HANDLE;
+ //可再增加其他OpenFlow协议的消息类型
+ }
+ return CONTINUE;
+ }
+ \end{code}
+ 用户可以根据自己能力选择实现OpenFlow协议的部分消息功能,
+ 一旦处理了该消息,一定要返回HANDLE,否则直接break即可。
+ \item 编译源代码
+ \begin{code}[console]
+ root@HNXS-FAST:/home/hnxs/sdn# make
+ gcc –o user_openflow –l reg –l ua –l rule –l ofp -lpthread
+ root@HNXS-FAST:/home/hnxs/sdn# ls
+ main_openflow.c Makefile user_openflow
+ root@HNXS-FAST:/home/hnxs/sdn#
+ \end{code}
+\end{enumerate}
+
+\subsubsection{运行修改后的交换机,再次验证SDN交换机的功能;}
+\begin{enumerate}
+ \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
+ port_name:eth0,port:0
+ port_name:obx0,port:0
+ xofp uses obsolete (PF_INET,SOCK_PACKET)
+ port_name:obx1,port:1
+ port_name:obx2,port:2
+ port_name:obx3,port:3
+ fastU->librule version:20181015,Default Action:0x40000080
+ xofp)Connect to SDN Controller [ 192.168.1.3:6653 ] OK!
+ 0_nms_of13)DELETE ALL RULE!
+ eth0 ADD!
+ obx0 ADD!
+ obx1 ADD!
+ obx2 ADD!
+ obx0(0x29008) Start...
+ obx2(0x2e100) Start...
+ obx3(0x30958) Start...
+ obx1(0x2b890) Start...
+ obx3 ADD!
+ \end{code}
+
+ \item 查看控制器界面基本信息,
+ 在浏览器打开控制器WEB网站\url{http://192.168.1.3/ui/index.html},
+ 控制界面如图\ref{fig:c:sdn-ob_sdn-switch}所示:
+ \begin{figure}[!htp]
+ \centering
+ \includegraphics[width=14cm]{sdn-switch}
+ \caption{SDN交换机信息}
+ \label{fig:c:sdn-ob_sdn-switch}
+ \end{figure}
+
+ \item 查看连接测试主机信息,
+ SDN主机及连接信息如图\ref{fig:c:sdn-ob_sdn-host}所示:
+ \begin{figure}[!htp]
+ \centering
+ \includegraphics[width=14cm]{sdn-host}
+ \caption{SDN主机信息}
+ \label{fig:c:sdn-ob_sdn-host}
+ \end{figure}
+
+ \item 查看端口状态与计数信息与流表信息,
+ 端口状态与流表计数信息如图\ref{fig:c:sdn-ob_port-flowtable}所示:
+ \begin{figure}[!htp]
+ \centering
+ \includegraphics[width=14cm]{port-flowtable}
+ \caption{端口状态与流表计数信息}
+ \label{fig:c:sdn-ob_port-flowtable}
+ \end{figure}
+
+ \item 查看网络拓扑信息,如图\ref{fig:c:sdn-ob_sdn-test-topo}所示:
+ \begin{figure}[!htp]
+ \centering
+ \includegraphics[width=14cm]{sdn-test-topo}
+ \caption{SDN网络拓扑信息}
+ \label{fig:c:sdn-ob_sdn-test-topo}
+ \end{figure}
+\end{enumerate}
+
+\subsubsection{在测试主机ping的前后,分别观察流表变化;}
+\begin{enumerate}
+ \item ping之前的流表信息(使用REST API方式获取其json数据),
+ 如图\ref{fig:c:sdn-ob_empty-flowtable}所示:
+ \begin{figure}[!htp]
+ \centering
+ \includegraphics[width=14cm]{empty-flowtable}
+ \caption{空流表信息}
+ \label{fig:c:sdn-ob_empty-flowtable}
+ \end{figure}
+
+ \item ping之后的流表信息,如图\ref{fig:c:sdn-ob_flowtable-ping}所示:
+ \begin{figure}[!htp]
+ \centering
+ \includegraphics[width=14cm]{flowtable-ping}
+ \caption{ping通后流表信息}
+ \label{fig:c:sdn-ob_flowtable-ping}
+ \end{figure}
+ 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
+ \end{code}
+ \begin{code}[json]
+ {
+ "desc": {
+ "version": "OF_13",
+ "manufacturer_description": "HuNan XinShi NetWork",
+ "hardware_description": "OpenBox HW 2017",
+ "software_description": "OpenBox Driver 1.0.0",
+ "serial_number": "None",
+ "datapath_description": "None"
+ }
+ }
+ \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
+ \end{code}
+ \begin{code}[json]
+ {
+ "port_reply": [{
+ "version": "OF_13",
+ "port": [{
+ "port_number": "local",
+ "receive_packets": "10957",
+ "transmit_packets": "1180",
+ "receive_bytes": "592738",
+ "transmit_bytes": "143898",
+ "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": "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
+ \end{code}
+ \begin{code}[json]
+ {
+ "flows": [{
+ "version": "OF_13",
+ "cookie": "9007199254740992",
+ "table_id": "0x0",
+ "packet_count": "5",
+ "byte_count": "571392",
+ "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": "0x806"
+ },
+ "instructions": {
+ "instruction_apply_actions": {
+ "actions": "output=3"
+ }
+ }
+ }, {
+ "version": "OF_13",
+ "cookie": "9007199271518208",
+ "table_id": "0x0",
+ "packet_count": "162",
+ "byte_count": "571400",
+ "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": "0x800",
+ "ipv4_src": "192.168.2.119",
+ "ipv4_dst": "192.168.2.111"
+ },
+ "instructions": {
+ "instruction_apply_actions": {
+ "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脚本,手动配置流表,观察测试主机的通信变化;}
+
+\begin{enumerate}
+ \item 修改流表脚本,使其转发端口错误
+ \begin{code}[console]
+ #vim openflow_flow-test.py
+ \end{code}
+ \begin{code}[python]
+ import httplib
+ import json
+
+ class StaticFlowPusher(object):
+ def __init__(self, server):
+ self.server = server
+
+ def get(self, data):
+ ret = self.rest_call({}, 'GET')
+ return json.loads(ret[2])
+
+ def set(self, data):
+ ret = self.rest_call(data, 'POST')
+ return ret[0] == 200
+
+ def remove(self, objtype, data):
+ ret = self.rest_call(data, 'DELETE')
+ return ret[0] == 200
+
+ def rest_call(self, data, action):
+ path = '/wm/staticflowpusher/json'
+ headers = {
+ 'Content-type': 'application/json',
+ 'Accept': 'application/json',
+ }
+ body = json.dumps(data)
+ conn = httplib.HTTPConnection(self.server, 8080)
+ conn.request(action, path, body, headers)
+ response = conn.getresponse()
+ ret = (response.status, response.reason, response.read())
+ print ret
+ conn.close()
+ return ret
+
+ pusher = StaticFlowPusher('192.168.1.3')
+
+ flowbe0 = {
+ 'switch':"00:00:00:0a:00:00:08:01",
+ "table":"0",
+ "name":"flow-0",
+ "cookie":"60",
+ "priority":"1",
+ "active":"true",
+ "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
+ }
+ flowbe1 = {
+ 'switch':"00:00:00:0a:00:00:08:01",
+ "table":"1",
+ "name":"flow-1",
+ "cookie":"61",
+ "priority":"1",
+ "active":"true",
+ "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
+ }
+
+ pusher.set(flowbe0)
+ pusher.set(flowbe1)
+ \end{code}
+
+ 脚本执行命令如下:
+ \begin{code}[console]
+ # python openflow_flow-test.py
+ (200, 'OK', '{"status" : "Entry pushed"}')
+ (200, 'OK', '{"status" : "Entry pushed"}')
+ \end{code}
+
+ 脚本执行成功,两条流表添加成功,在测试主机两边进行ping测试,
+ 是否发现已经ping不通了?
+ \item 修改流表脚本,使其转发端口正确,再次验证;
+ \begin{enumerate}
+ \item 两种动作分别修改为:1进3出和3进1出。
+ 添加流表后,再重新ping测试,是否发现又可以ping通了?
+ \item 由此说明:对于SDN交换机,
+ 可以通过用户修改流表的方式来定义某一条具体流的转发行为。
+ \end{enumerate}
+\end{enumerate}
+
+\subsection{思考题}
+\label{subsec:c:sdn-ob:s:sdn_rethink}
+
+\begin{enumerate}
+ \item WEB界面上显示的转发流表是如何生成的?分析其生成流程;
+ \item 测试主机第一次ping通的数据处理流程与第二次ping通的数据处理流程有何不同?
+ \item 控制器界面的拓扑图是如何生成的?需要哪些数据?
+\end{enumerate}
+
+\subsection{注意事项及有关说明}
+\label{subsec:c:sdn-ob:s:sdn_notice}
+
+\begin{enumerate}
+ \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 (20分)通过网上搜索学习,
+ 使用其他多个REST~API查询到了交换机更多的数据内容;
+ \item (10分)实验报告与源代码内容完整、格式整洁。
+\end{enumerate}
+
diff --git a/data/ch_sdn-openbox/sec_topo.tex b/data/ch_sdn-openbox/sec_topo.tex
new file mode 100644
index 0000000..184f9b5
--- /dev/null
+++ b/data/ch_sdn-openbox/sec_topo.tex
@@ -0,0 +1,173 @@
+%# -*- coding: utf-8-unix -*-
+
+\section{基于OpenFlow的拓扑测量}
+\label{sec:c:sdn-ob:s:topo}
+
+\subsection{实验目的}
+\label{subsec:c:sdn-ob:s:topo_object}
+
+本实验的主要目的是让学生了解OpenFlow协议中PACKET\_IN和链路探测协议
+(LLDP)的工作原理和网络拓扑构建方法。
+
+\subsection{实验内容}
+\label{subsec:c:sdn-ob:s:topo_content}
+
+使用可编程网络平台及SDN交换机源码,分析LLDP的工作原理。
+通过PACKET\_IN消息收集网络设备节点信息。
+掌握网络拓扑的构建方法。主要完成以下内容:
+
+\begin{enumerate}
+ \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形式展示网络拓扑结构图;
+ \item \textbf{修改网络验证:}改变物理网络拓扑结构后,
+ 重新展示学习到的网络拓扑结构图。
+\end{enumerate}
+
+\subsection{实验原理、方法和手段}
+\label{subsec:c:sdn-ob:s:topo_principle}
+
+\subsubsection{LLDP工作原理}
+
+LLDP是一个用于信息通告和获取的协议,但是需要注意的一点是,
+LLDP发送的信息通告不需要确认,不能发送一个请求来请求获取某些信息,
+也就是说LLDP是一个单向的协议,只有主动通告一种工作方式,
+无需确认,不能查询、请求。
+
+LLDP协议主要完成的功能有:初始化并维护本地MIB 库中的信息;
+从本地MIB 库中提取信息,并将信息封装到LLDP帧中。
+LLDP帧的发送有两种触发方式,一是定时器到期触发,一是设备状态发生了变化触发;
+识别并处理接收到的LLDPDU帧;维护远端设备LLDP MIB 信息库;
+当本地或远端设备MIB信息库中有信息发生变化时,发出通告事件。
+
+网络拓扑的测量是通过一些链路探测协议在各交换节点中相互收发来完成的链路的拓扑测量功能。
+SDN交换机使用LLDP链路探测协议主要是通过PACKET\_OUT消息发送LLDP分组,
+通过PACKET\_IN接收LLDP分组,通过计算获取交换机之间的连通关系和端口连接关系。
+
+\subsubsection{SDN交换机中LLDP的分组处理流程}
+\begin{enumerate}
+ \item 主动发送LLDP:
+ SDN控制器主动构造特定的LLDP报文(含交换机标记与输出端口信息),
+ 封装在OpenFlow的PACKET\_OUT方法中,从指定的交换机各端口发送出去;
+ \item 接收处理LLDP:如果端口连接的是主机,则主机会丢弃该报文,
+ 若同样是OpenFlow交换机,则会通过PACKET\_IN的方式将该LLDP报文转发给控制器;
+ \item LLDP学习:控制器收到LLDP报文后,
+ 则会学习到这两个交换机之间存在一条连接链路;
+ \item 网络设备信息学习:主机连接到交换机后,
+ 主机端会主动构造一些广播报文发送到网络上,
+ 这些报文会携带上本机的MAC地址和IP地址等信息
+ 交换机接收到主机发送报文后,在其交换流表中找不到转发表项,
+ 则会将该报文完整内容和其所输入的端口信息封装在OpenFlow协议的PACKET\_IN方法中,
+ 将报文送到SDN控制器;控制器接收到该消息后,
+ 通过学习对比发现是一台新主机入网,则会将该报文中的源MAC地址、
+ IP地址和接收交换机信息及输入端口信息等均记录在一张网络设备信息数据表中;
+ \item 构建设备连接关系:
+ 交换机之间的链路信息加上交换机与主机之间的链路信息就完整的构成了全网的拓扑连接关系。
+\end{enumerate}
+
+\subsection{实验条件}
+\label{subsec:c:sdn-ob:s:topo_requirement}
+
+\begin{itemize}
+ \item 网络创新实验平台两个,交换测试主机两台,SDN控制器一台。
+ 连接拓扑如图\ref{fig:c:sdn-ob_openflow-topo}所示;
+ \item 串口线一根,网线五根;
+ \item 网络创新实验平台使用手册、开发环境;
+ \item OpenFlow拓扑实验环境配置手册
+\end{itemize}
+
+\begin{figure}[!ht]
+ \centering
+ \includegraphics[width=10cm]{openflow-topo}
+ \caption{OpenFlow拓扑测量实验拓扑图}
+ \label{fig:c:sdn-ob_openflow-topo}
+\end{figure}
+
+\subsection{实验步骤}
+\label{subsec:c:sdn-ob:s:topo_procedure}
+
+\begin{enumerate}
+ \item 运行SDN交换机
+
+ 请参考附件《可编程网络平台-操作手册》完成。
+ \item 基于SDN交换机开源代码,在端口分组接收回调函数中添加相应逻辑;
+ \begin{code}[c]
+ int port_recv_callback(int inport,struct fast_packet *pkt,int pkt_len)
+ {
+ //解析分组字段,提取LLDP分组,并打印输出其相关协议字段
+
+ //解析分组字段,判断帧类型为0x0800,源IP为单播地址的分组,打印其源MAC地址与IP地址
+ }
+ \end{code}
+ \begin{enumerate}
+ \item 解析接收数据,判断以太网帧类型,
+ 如果帧类型为0x88CC,则说明是LLDP协议分组,根据LLDP协议打印相关协议字段内容;
+ \item 解析分组,提取输入帧类型为0x0800的分组,
+ 打印输出其源MAC地址与源IP地址(仅输出IP地址为单播类型的条目);
+ \end{enumerate}
+ \item 编译SDN交换机,验证添加逻辑功能,观察是否正确打印需要的消息内容;
+ \item 分析端口接收回调函数中打印的消息内容;
+ \begin{enumerate}
+ \item 从LLDP分组中可解析得知对端交换机的某个端口发送到本交换机的某个端口
+ \item 从普通IPv4报文中可以获得连接到该交换机上的主机节点信息
+ (MAC地址和IPv4地址)
+ \end{enumerate}
+ \item 验证并观察SDN控制器自带的拓扑展示界面
+ \begin{enumerate}
+ \item 在控制器主机打开WEB界面,输入地址:
+ \texttt{127.0.0.1/ui/index.html}。查看浏览器界面数据;
+ \item 切换浏览器的拓扑显示版块,
+ 查看网络拓扑展示效果可以看到两台交换机中间用线连接;
+ \item 连接上一台测试主机,刷新拓扑界面,
+ 查看到界面新增了一台主机,并显示其IP地址信息;
+ \item 再连接上另一台主机,刷新拓扑界面,
+ 查看到界面又新增了一台主机,并显示其IP地址信息;
+ \item 断开两台交换机之间的网线,新拓扑界面,
+ 查看两个交换机之间的连线消失了;
+ \item 断开一台测试主机,新拓扑界面,查看其对应的主机从界面消失;
+ \end{enumerate}
+ \item 使用控制器的北向REST API接口查询网络的所有链路连接关系数据,
+ API接口为:\texttt{/wm/topology/links/json};
+ \item 使用控制器的北向REST API接口查询全网所有设备节点信息,
+ API接口为:\texttt{/wm/device/};
+ \item 自己开发网络拓扑展示效果图;
+ \item 修改网络拓扑后验证自己开发程序的效果。
+\end{enumerate}
+
+\subsection{思考题}
+\label{subsec:c:sdn-ob:s:topo_rethink}
+
+\begin{enumerate}
+ \item 网络拓扑中的设备节点信息学习,使用广播报文中的信息会带来哪些影响?
+ \item OpenFlow交换机之间用一台普通交换机连接,能学习到全网的拓扑结构信息吗?
+ 分析原因。
+\end{enumerate}
+
+\subsection{注意事项及有关说明}
+\label{subsec:c:sdn-ob:s:topo_notice}
+\begin{enumerate}
+ \item JAVA的WEB程序显示的缓存,每新刷新操作前,请清理浏览器历史缓存数据。
+\end{enumerate}
+
+\subsection{考核方法}
+\label{subsec:c:sdn-ob:s:topo_criterion}
+
+完成本次实验,需要提交一份实验报告和一分程序输出日志。
+\begin{enumerate}
+ \item (20分)在规定时间内完成实验,并提交实验成果;
+ \item (20分)正确打印输入与输出LLDP消息内容和连接主机信息
+ \item (20分)通过REST API编程获取链路状态信息与设备信息,并能生成拓扑关系图;
+ \item (20分)以图形界面形式展示拓扑图;
+ \item (10分)动态修改物理拓扑后,程序可以及时刷新出正确拓扑图状态;
+ \item (10分)实验报告与源代码内容完整、格式整洁。
+\end{enumerate}
diff --git a/data/ch_socket/sec_smtp.tex b/data/ch_socket/sec_smtp.tex
index c2d3bfc..4d43058 100644
--- a/data/ch_socket/sec_smtp.tex
+++ b/data/ch_socket/sec_smtp.tex
@@ -1,23 +1,23 @@
%# -*- coding: utf-8-unix -*-
\section{SMTP客户端实现}
-\label{sec:c:socket_s2}
+\label{sec:c:socket:s:smtp}
\subsection{实验目的}
-\label{subsec:c:socket_s3_object}
+\label{subsec:c:socket:s:smtp_object}
进一步理解和掌握Python中TCP套接字编程的基础知识,
理解SMTP报文格式,了解开发一个简单应用程序的流程。
\subsection{实验内容}
-\label{subsec:c:socket_s3_content}
+\label{subsec:c:socket:s:smtp_content}
创建一个可以向任何接收方发送电子邮件的简单邮件客户端。
通过Python编写代码与邮件服务器创建一个TCP连接,
使用SMTP协议与邮件服务器交谈并发送邮件报文,最后关闭连接。
\subsection{实验原理、方法和手段}
-\label{subsec:c:socket_s3_principle}
+\label{subsec:c:socket:s:smtp_principle}
SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,
是因特网电子邮件中主要的应用层协议,它使用TCP可靠数据传输服务,
@@ -68,7 +68,7 @@ RFC5321给出了SMTP的定义。SMTP有众多出色的性质,
用一个独立的句点指示该邮件的结束,并且仅当所有邮件发送完后才发送QUIT。
\subsection{实验条件}
-\label{subsec:c:socket_s3_requirement}
+\label{subsec:c:socket:s:smtp_requirement}
\begin{itemize}
\item 下列装有python环境的电脑一台;
@@ -76,8 +76,14 @@ RFC5321给出了SMTP的定义。SMTP有众多出色的性质,
\item 部分代码(实验步骤中已给出)。
\end{itemize}
+参考资料:
+
+\begin{itemize}
+ \item {J.F Kurose and K.W. Ross, 计算机网络自顶向下方法(第7版)}
+\end{itemize}
+
\subsection{实验步骤}
-\label{subsec:c:socket_s3_procedure}
+\label{subsec:c:socket:s:smtp_procedure}
通过Python开发一个简单的SMTP客户端发送邮件。
补充完善下面的代码并通过向不同的账号发送电子邮件测试程序。
@@ -111,16 +117,16 @@ RFC5321给出了SMTP的定义。SMTP有众多出色的性质,
\end{code}
\subsection{思考题}
-\label{subsec:c:socket_s3_rethink}
+\label{subsec:c:socket:s:smtp_rethink}
修改代码使程序发送的邮件中不仅包含文本还能够包含图片。
\subsection{注意事项及有关说明}
-\label{subsec:c:socket_s3_notice}
+\label{subsec:c:socket:s:smtp_notice}
注意部分邮件服务器默认关闭SMTP,需进入设置手动开启SMTP协议。
\subsection{考核方法}
-\label{subsec:c:socket_s3_criterion}
+\label{subsec:c:socket:s:smtp_criterion}
同实验\ref{sec:c:socket:s:udp}。
diff --git a/data/ch_socket/sec_udp.tex b/data/ch_socket/sec_udp.tex
index aac2375..43918b0 100644
--- a/data/ch_socket/sec_udp.tex
+++ b/data/ch_socket/sec_udp.tex
@@ -44,7 +44,7 @@ UDP报文没有可靠性保证、顺序保证和流量控制字段等,可靠
一旦数据传输结束,服务器和客户通过调用close( )来关闭套接字。
具体流程如图\ref{fig:c:socket_udp-flow}所示。
-\begin{figure}[!htp]
+\begin{figure}[!ht]
\centering
\includegraphics[width=8cm]{udp-flow}
\caption{无连接客户/服务器流程图}
@@ -60,6 +60,13 @@ UDP报文没有可靠性保证、顺序保证和流量控制字段等,可靠
\item 服务器程序(实验步骤中已给出)。
\end{itemize}
+
+参考资料:
+
+\begin{itemize}
+ \item {J.F Kurose and K.W. Ross, 计算机网络自顶向下方法(第7版)}
+\end{itemize}
+
\subsection{实验步骤}
\label{subsec:c:socket:s:udp_procedure}
diff --git a/data/ch_socket/sec_web.tex b/data/ch_socket/sec_web.tex
index b71533e..0626ed8 100644
--- a/data/ch_socket/sec_web.tex
+++ b/data/ch_socket/sec_web.tex
@@ -48,6 +48,12 @@ Web服务器接受并解析HTTP请求,从服务器的文件系统中获取请
\item 部分代码(实验步骤中已给出)。
\end{itemize}
+参考资料:
+
+\begin{itemize}
+ \item {J.F Kurose and K.W. Ross, 计算机网络自顶向下方法(第7版)}
+\end{itemize}
+
\subsection{实验步骤}
\label{subsec:c:socket:s:web_procedure}
diff --git a/data/ch_wireshark/sec_arp.tex b/data/ch_wireshark/sec_arp.tex
index 1d43652..433905e 100644
--- a/data/ch_wireshark/sec_arp.tex
+++ b/data/ch_wireshark/sec_arp.tex
@@ -61,7 +61,7 @@ Wireshark可以在Windows、Linux和MacOS操作系统中运行,
\caption{以太网帧格式}
\label{tab:c:wireshark_eth-format}
\begin{tabular}{|c|c|c|c|c|c|} \hline
- \heiti 前导字符 & \heiti 目的MAC地址 & \heiti 源MAC地址 &
+ \heiti 前导字符 & \heiti 目的MAC地址 & \heiti 源MAC地址 &
\heiti 类型 & \heiti IP数据报 & \heiti 帧校验\\ \hline
8字节 & 6字节 & 6字节 & 2字节 & 46-1500字节 & 4字节 \\ \hline
\end{tabular}
@@ -244,29 +244,30 @@ IP地址长度为4字节。每个字段的含义如下:
计算以太网帧的尾部校验和,并与Wireshark显示数值进行比较验证。
\subsubsection{ARP协议分析}
\begin{enumerate}
- \item 使用\texttt{arp –d}命令(其语法见图\ref{fig:arp-cmd}),清空本机已有的ARP缓存,
+ \item 使用\texttt{arp –d}命令(其语法见图\ref{fig:arp-cmd}),
+ 清空本机已有的ARP缓存,
开启Wireshark,ping本机的同网段地址,在显示过滤器条框中输入“\texttt{arp}”,
观察捕获的ARP报文的各个字段,分析请求/响应的过程。
- \begin{figure}[!ht]
- \centering
- \begin{code}[text]
- arp [-a [InetAddr] [-N IfaceAddr]] [-g [InetAddr] [-N IfaceAddr]]
- [-d InetAddr [IfaceAddr]] [-s InetAddr EtherAddr [IfaceAddr]]
-
- -a 显示所有接口/特定接口的当前 ARP 缓存表
- -g 同-a
- -d 删除所有/指定的IP地址项
- -s 在ARP缓存中添加对应InetAddr地址的EtherAddr地址静态项
- \end{code}
- \caption{arp命令语法及参数}
- \label{fig:arp-cmd}
- \end{figure}
-
\item 使用\texttt{arp –d}命令,清空本机已有的ARP缓存。开启Wireshark,
ping本机的不同网段地址或域名,观察捕获的ARP报文的各个字段,
分析请求/响应的过程。
\end{enumerate}
+\begin{figure}[!ht]
+ \centering
+ \begin{code}[text]
+ arp [-a [InetAddr] [-N IfaceAddr]] [-g [InetAddr] [-N IfaceAddr]]
+ [-d InetAddr [IfaceAddr]] [-s InetAddr EtherAddr [IfaceAddr]]
+
+ -a 显示所有接口/特定接口的当前 ARP 缓存表
+ -g 同 -a
+ -d 删除所有/指定的IP地址项
+ -s 在ARP缓存中添加对应InetAddr地址的EtherAddr地址静态项
+ \end{code}
+ \caption{arp命令语法及参数}
+ \label{fig:arp-cmd}
+\end{figure}
+
\subsection{思考题}
\label{subsec:c:wireshark:s:arp_rethink}
diff --git a/data/cover.tex b/data/cover.tex
index d0a8b8d..5999843 100644
--- a/data/cover.tex
+++ b/data/cover.tex
@@ -48,9 +48,9 @@
\fill[c1] ([xshift=2cm,yshift=2cm]current page.center) rectangle ++ (-13.7,7.7);
\node[text=white,anchor=west,scale=4,inner sep=0pt] at
-([xshift=-8.55cm,yshift=7cm]current page.center) {计算机网络};
+([xshift=-8.3cm,yshift=7cm]current page.center) {计算机网络};
\node[text=white,anchor=west,scale=2,inner sep=0pt] at
-([xshift=-6.2cm,yshift=4.2cm]current page.center) {共同实验指导书};
+([xshift=-4.2cm,yshift=4.2cm]current page.center) {实验指导书};
\node[text=gray,anchor=west,scale=1.5,inner sep=0pt] at
([xshift=-3cm,yshift=-10.5cm]current page.center) {计算机网络教案社区};
diff --git a/data/preface.tex b/data/preface.tex
index 988fbe7..d849068 100644
--- a/data/preface.tex
+++ b/data/preface.tex
@@ -1,29 +1,39 @@
\begin{pre}
- \thispagestyle{empty}
-本实验指导书是为计算机网络教案社区发布的课件配套撰写的实验指导书。
-总体上分为基础实验与高级实验两大部分。
-基础实验主要包括网络协议分析与网络程序设计两个单元(共计6个实验),
-高级实验主要包括组网基础、路由器设计实现、
-软件定义网络与网络测量等三个单元(共计8个实验),
-供有需要的高校选用。
-
-考虑到每个学校都有各自的教学大纲和实验环境,
-不同学校前序课程不同,开设网络课程的学期也不一致,
-社区难以顾及方方面面的需求。
-因此本实验指导书主要是提出了一个实验框架,其中同时包括了基础、进阶和创新内容,
-故而命名为“共同”实验。
-在实际使用中,
-各位任课老师可以根据具体需求在本指导书的基础上通过
-增删、组合、修改等方法设计合宜的实验方案。
-
-本实验指导书由计算机网络教案社区发起,
-各高校专家教授共同联合编纂,各章节主要编纂人员如下:
+\thispagestyle{empty}
+本实验指导书由“计算机网络教案”社区发起,
+各高校专家教授共同联合编纂,
+汇集了可以配合高校“计算机网络”课程开设的各类实验。
+考虑到高校教学大纲与实验环境各异,
+不同学校前序课程不同,开设网络课程的学期也不一致。
+社区尽力采集了不同难度的多种实验,
+以配合各高校的实际情况。
+
+本指导书中的实验可以分为基础实验与高级实验两大部分。
+其中基础实验主要包括“网络协议分析”与“网络程序设计”两个单元(共计6个实验),
+高级实验主要包括“组网基础”、“路由器实现”、
+“软件定义网络与网络测量”三个单元(共计9个实验)。
+
+所有实验的目的、任务、要求、难度与建议实验课时数
+在附录\ref{app:cheatsheet}中做了汇总,方便老师快速查询。
+在实际使用中,任课老师可以根据具体授课需要在本指导书的基础上通过
+增删、组合、修改等方法设计适合自身课程的实验方案。
+
+由于时间仓促,加之编者水平有限,
+本指导书中缺点和疏漏在所难免。
+作为社区项目,恳请广大读者和同行专家批评指正,
+同时欢迎更多读者和专家参与本项目的编纂和开发。
+
+\vspace{1em}
+
+本实验指导书各章节主要编纂人员如下:
\begin{itemize}
\item 第一单元:谢怡、陈建发、洪劼超、雷蕴奇,厦门大学
- \item 第二单元:吴荻,国防科技大学
+ \item 第二单元:吴荻、周丽涛,国防科技大学
\item 第三单元:张晓丽,昆明理工大学
+ \item 第四单元:胡罡、孙志刚,国防科技大学
+ \item 第五单元:夏竟、蔡志平、徐明,国防科技大学
\item 统筹规划:徐明、夏竟,国防科技大学
\end{itemize}
diff --git a/figure/appendixes/ensp/a1_ENSP-UI.png b/figure/appendixes/ensp/ENSP-UI.png
similarity index 100%
rename from figure/appendixes/ensp/a1_ENSP-UI.png
rename to figure/appendixes/ensp/ENSP-UI.png
diff --git a/figure/appendixes/ensp/a1_ENSP-help.png b/figure/appendixes/ensp/ENSP-help.png
similarity index 100%
rename from figure/appendixes/ensp/a1_ENSP-help.png
rename to figure/appendixes/ensp/ENSP-help.png
diff --git a/figure/appendixes/ensp/a1_ENSP-version.png b/figure/appendixes/ensp/a1_ENSP-version.png
deleted file mode 100644
index e7f4138..0000000
Binary files a/figure/appendixes/ensp/a1_ENSP-version.png and /dev/null differ
diff --git a/figure/appendixes/ensp/a1_error.png b/figure/appendixes/ensp/error.png
similarity index 100%
rename from figure/appendixes/ensp/a1_error.png
rename to figure/appendixes/ensp/error.png
diff --git a/figure/appendixes/openbox/f01.png b/figure/appendixes/openbox/f01.png
new file mode 100644
index 0000000..c92df2c
Binary files /dev/null and b/figure/appendixes/openbox/f01.png differ
diff --git a/figure/appendixes/openbox/f02.png b/figure/appendixes/openbox/f02.png
new file mode 100644
index 0000000..3f6f1a8
Binary files /dev/null and b/figure/appendixes/openbox/f02.png differ
diff --git a/figure/appendixes/openbox/f03.png b/figure/appendixes/openbox/f03.png
new file mode 100644
index 0000000..2360ba9
Binary files /dev/null and b/figure/appendixes/openbox/f03.png differ
diff --git a/figure/appendixes/openbox/f04.png b/figure/appendixes/openbox/f04.png
new file mode 100644
index 0000000..149bb7d
Binary files /dev/null and b/figure/appendixes/openbox/f04.png differ
diff --git a/figure/appendixes/openbox/f05.png b/figure/appendixes/openbox/f05.png
new file mode 100644
index 0000000..6c9bab7
Binary files /dev/null and b/figure/appendixes/openbox/f05.png differ
diff --git a/figure/appendixes/openbox/f06.png b/figure/appendixes/openbox/f06.png
new file mode 100644
index 0000000..cea7720
Binary files /dev/null and b/figure/appendixes/openbox/f06.png differ
diff --git a/figure/appendixes/openbox/f07.png b/figure/appendixes/openbox/f07.png
new file mode 100644
index 0000000..b9d20a5
Binary files /dev/null and b/figure/appendixes/openbox/f07.png differ
diff --git a/figure/appendixes/openbox/f08.png b/figure/appendixes/openbox/f08.png
new file mode 100644
index 0000000..c67efbe
Binary files /dev/null and b/figure/appendixes/openbox/f08.png differ
diff --git a/figure/appendixes/openbox/f09.png b/figure/appendixes/openbox/f09.png
new file mode 100644
index 0000000..2e64974
Binary files /dev/null and b/figure/appendixes/openbox/f09.png differ
diff --git a/figure/appendixes/openbox/f10.png b/figure/appendixes/openbox/f10.png
new file mode 100644
index 0000000..31ddcb9
Binary files /dev/null and b/figure/appendixes/openbox/f10.png differ
diff --git a/figure/appendixes/openbox/f11.png b/figure/appendixes/openbox/f11.png
new file mode 100644
index 0000000..ee5a310
Binary files /dev/null and b/figure/appendixes/openbox/f11.png differ
diff --git a/figure/appendixes/openbox/f12.png b/figure/appendixes/openbox/f12.png
new file mode 100644
index 0000000..ddd98f8
Binary files /dev/null and b/figure/appendixes/openbox/f12.png differ
diff --git a/figure/appendixes/openbox/f13.png b/figure/appendixes/openbox/f13.png
new file mode 100644
index 0000000..315c25b
Binary files /dev/null and b/figure/appendixes/openbox/f13.png differ
diff --git a/figure/appendixes/openbox/f14.png b/figure/appendixes/openbox/f14.png
new file mode 100644
index 0000000..fb2fdd2
Binary files /dev/null and b/figure/appendixes/openbox/f14.png differ
diff --git a/figure/appendixes/openbox/f15.png b/figure/appendixes/openbox/f15.png
new file mode 100644
index 0000000..1d46ca8
Binary files /dev/null and b/figure/appendixes/openbox/f15.png differ
diff --git a/figure/appendixes/openbox/f16.png b/figure/appendixes/openbox/f16.png
new file mode 100644
index 0000000..408ed26
Binary files /dev/null and b/figure/appendixes/openbox/f16.png differ
diff --git a/figure/appendixes/openbox/f17.png b/figure/appendixes/openbox/f17.png
new file mode 100644
index 0000000..f8604e9
Binary files /dev/null and b/figure/appendixes/openbox/f17.png differ
diff --git a/figure/appendixes/openbox/f18.png b/figure/appendixes/openbox/f18.png
new file mode 100644
index 0000000..ed563b7
Binary files /dev/null and b/figure/appendixes/openbox/f18.png differ
diff --git a/figure/appendixes/openbox/f19.png b/figure/appendixes/openbox/f19.png
new file mode 100644
index 0000000..0468a3a
Binary files /dev/null and b/figure/appendixes/openbox/f19.png differ
diff --git a/figure/appendixes/openbox/f20.png b/figure/appendixes/openbox/f20.png
new file mode 100644
index 0000000..b3ee7a7
Binary files /dev/null and b/figure/appendixes/openbox/f20.png differ
diff --git a/figure/appendixes/openbox/f21.png b/figure/appendixes/openbox/f21.png
new file mode 100644
index 0000000..3866bbf
Binary files /dev/null and b/figure/appendixes/openbox/f21.png differ
diff --git a/figure/appendixes/openbox/f22.png b/figure/appendixes/openbox/f22.png
new file mode 100644
index 0000000..7ae9490
Binary files /dev/null and b/figure/appendixes/openbox/f22.png differ
diff --git a/figure/appendixes/openbox/f23.png b/figure/appendixes/openbox/f23.png
new file mode 100644
index 0000000..241deaf
Binary files /dev/null and b/figure/appendixes/openbox/f23.png differ
diff --git a/figure/appendixes/openbox/f24.png b/figure/appendixes/openbox/f24.png
new file mode 100644
index 0000000..b30dccc
Binary files /dev/null and b/figure/appendixes/openbox/f24.png differ
diff --git a/figure/appendixes/openbox/f25.png b/figure/appendixes/openbox/f25.png
new file mode 100644
index 0000000..40e1eb6
Binary files /dev/null and b/figure/appendixes/openbox/f25.png differ
diff --git a/figure/appendixes/openbox/f26.png b/figure/appendixes/openbox/f26.png
new file mode 100644
index 0000000..a21459b
Binary files /dev/null and b/figure/appendixes/openbox/f26.png differ
diff --git a/figure/appendixes/openbox/f27.png b/figure/appendixes/openbox/f27.png
new file mode 100644
index 0000000..83ba863
Binary files /dev/null and b/figure/appendixes/openbox/f27.png differ
diff --git a/figure/appendixes/openbox/f28.png b/figure/appendixes/openbox/f28.png
new file mode 100644
index 0000000..4aa8f2a
Binary files /dev/null and b/figure/appendixes/openbox/f28.png differ
diff --git a/figure/appendixes/openbox/f29.png b/figure/appendixes/openbox/f29.png
new file mode 100644
index 0000000..f6a713b
Binary files /dev/null and b/figure/appendixes/openbox/f29.png differ
diff --git a/figure/appendixes/openbox/f30.png b/figure/appendixes/openbox/f30.png
new file mode 100644
index 0000000..0c26214
Binary files /dev/null and b/figure/appendixes/openbox/f30.png differ
diff --git a/figure/appendixes/openbox/f31.png b/figure/appendixes/openbox/f31.png
new file mode 100644
index 0000000..1cce3d1
Binary files /dev/null and b/figure/appendixes/openbox/f31.png differ
diff --git a/figure/appendixes/openbox/f32.png b/figure/appendixes/openbox/f32.png
new file mode 100644
index 0000000..ec5dcdd
Binary files /dev/null and b/figure/appendixes/openbox/f32.png differ
diff --git a/figure/chapters/ensp/OSPF-topo.png b/figure/chapters/ensp/OSPF-topo.png
index 8983c02..ce8eea1 100644
Binary files a/figure/chapters/ensp/OSPF-topo.png and b/figure/chapters/ensp/OSPF-topo.png differ
diff --git a/figure/chapters/ensp/RIP-topo.png b/figure/chapters/ensp/RIP-topo.png
index 8983c02..ce8eea1 100644
Binary files a/figure/chapters/ensp/RIP-topo.png and b/figure/chapters/ensp/RIP-topo.png differ
diff --git a/figure/chapters/ensp/confirm.jpg b/figure/chapters/ensp/confirm.jpg
deleted file mode 100644
index 4f4cad0..0000000
Binary files a/figure/chapters/ensp/confirm.jpg and /dev/null differ
diff --git a/figure/chapters/ensp/ping_1.png b/figure/chapters/ensp/ping_1.png
index 02241de..9e67fc7 100644
Binary files a/figure/chapters/ensp/ping_1.png and b/figure/chapters/ensp/ping_1.png differ
diff --git a/figure/chapters/ensp/ping_2.jpg b/figure/chapters/ensp/ping_2.jpg
deleted file mode 100644
index fd6779e..0000000
Binary files a/figure/chapters/ensp/ping_2.jpg and /dev/null differ
diff --git a/figure/chapters/ensp/ping_2.png b/figure/chapters/ensp/ping_2.png
new file mode 100644
index 0000000..9e67fc7
Binary files /dev/null and b/figure/chapters/ensp/ping_2.png differ
diff --git a/figure/chapters/ensp/static-topo.png b/figure/chapters/ensp/static-topo.png
index 8983c02..ce8eea1 100644
Binary files a/figure/chapters/ensp/static-topo.png and b/figure/chapters/ensp/static-topo.png differ
diff --git a/figure/chapters/ensp/sysname-R1_1.png b/figure/chapters/ensp/sysname-R1_1.png
index 734ad5c..a3b9fa1 100644
Binary files a/figure/chapters/ensp/sysname-R1_1.png and b/figure/chapters/ensp/sysname-R1_1.png differ
diff --git a/figure/chapters/ensp/sysname-R1_2.jpg b/figure/chapters/ensp/sysname-R1_2.jpg
deleted file mode 100644
index 64e0264..0000000
Binary files a/figure/chapters/ensp/sysname-R1_2.jpg and /dev/null differ
diff --git a/figure/chapters/ensp/sysname-R1_2.png b/figure/chapters/ensp/sysname-R1_2.png
new file mode 100644
index 0000000..a3b9fa1
Binary files /dev/null and b/figure/chapters/ensp/sysname-R1_2.png differ
diff --git a/figure/chapters/ensp/sysname-R1_3.jpg b/figure/chapters/ensp/sysname-R1_3.jpg
deleted file mode 100644
index 64e0264..0000000
Binary files a/figure/chapters/ensp/sysname-R1_3.jpg and /dev/null differ
diff --git a/figure/chapters/ensp/sysname-R1_3.png b/figure/chapters/ensp/sysname-R1_3.png
new file mode 100644
index 0000000..a3b9fa1
Binary files /dev/null and b/figure/chapters/ensp/sysname-R1_3.png differ
diff --git a/figure/chapters/ensp/sysname-R2_1.png b/figure/chapters/ensp/sysname-R2_1.png
index d9d538f..4541556 100644
Binary files a/figure/chapters/ensp/sysname-R2_1.png and b/figure/chapters/ensp/sysname-R2_1.png differ
diff --git a/figure/chapters/ensp/sysname-R2_2.jpg b/figure/chapters/ensp/sysname-R2_2.jpg
deleted file mode 100644
index 85f674b..0000000
Binary files a/figure/chapters/ensp/sysname-R2_2.jpg and /dev/null differ
diff --git a/figure/chapters/ensp/sysname-R2_2.png b/figure/chapters/ensp/sysname-R2_2.png
new file mode 100644
index 0000000..4541556
Binary files /dev/null and b/figure/chapters/ensp/sysname-R2_2.png differ
diff --git a/figure/chapters/ensp/sysname-R2_3.jpg b/figure/chapters/ensp/sysname-R2_3.jpg
deleted file mode 100644
index 85f674b..0000000
Binary files a/figure/chapters/ensp/sysname-R2_3.jpg and /dev/null differ
diff --git a/figure/chapters/ensp/sysname-R2_3.png b/figure/chapters/ensp/sysname-R2_3.png
new file mode 100644
index 0000000..4541556
Binary files /dev/null and b/figure/chapters/ensp/sysname-R2_3.png differ
diff --git a/figure/chapters/router-openbox/networking-topo.pdf b/figure/chapters/router-openbox/networking-topo.pdf
new file mode 100644
index 0000000..b4a67e6
Binary files /dev/null and b/figure/chapters/router-openbox/networking-topo.pdf differ
diff --git a/figure/chapters/router-openbox/router-topo.pdf b/figure/chapters/router-openbox/router-topo.pdf
new file mode 100644
index 0000000..ebed0a1
Binary files /dev/null and b/figure/chapters/router-openbox/router-topo.pdf differ
diff --git a/figure/chapters/router-openbox/switch-topo.pdf b/figure/chapters/router-openbox/switch-topo.pdf
new file mode 100644
index 0000000..7bbf12c
Binary files /dev/null and b/figure/chapters/router-openbox/switch-topo.pdf differ
diff --git a/figure/chapters/sdn-openbox/empty-flowtable.jpg b/figure/chapters/sdn-openbox/empty-flowtable.jpg
new file mode 100644
index 0000000..49c76a9
Binary files /dev/null and b/figure/chapters/sdn-openbox/empty-flowtable.jpg differ
diff --git a/figure/chapters/sdn-openbox/flowtable-ping.jpg b/figure/chapters/sdn-openbox/flowtable-ping.jpg
new file mode 100644
index 0000000..4978088
Binary files /dev/null and b/figure/chapters/sdn-openbox/flowtable-ping.jpg differ
diff --git a/figure/chapters/sdn-openbox/ns-topo.pdf b/figure/chapters/sdn-openbox/ns-topo.pdf
new file mode 100644
index 0000000..2899166
Binary files /dev/null and b/figure/chapters/sdn-openbox/ns-topo.pdf differ
diff --git a/figure/chapters/sdn-openbox/openflow-topo.pdf b/figure/chapters/sdn-openbox/openflow-topo.pdf
new file mode 100644
index 0000000..1a88bdb
Binary files /dev/null and b/figure/chapters/sdn-openbox/openflow-topo.pdf differ
diff --git a/figure/chapters/sdn-openbox/port-flowtable.jpg b/figure/chapters/sdn-openbox/port-flowtable.jpg
new file mode 100644
index 0000000..360c1bd
Binary files /dev/null and b/figure/chapters/sdn-openbox/port-flowtable.jpg differ
diff --git a/figure/chapters/sdn-openbox/sdn-host.jpg b/figure/chapters/sdn-openbox/sdn-host.jpg
new file mode 100644
index 0000000..332c95d
Binary files /dev/null and b/figure/chapters/sdn-openbox/sdn-host.jpg differ
diff --git a/figure/chapters/sdn-openbox/sdn-switch.jpg b/figure/chapters/sdn-openbox/sdn-switch.jpg
new file mode 100644
index 0000000..88decd6
Binary files /dev/null and b/figure/chapters/sdn-openbox/sdn-switch.jpg differ
diff --git a/figure/chapters/sdn-openbox/sdn-test-topo.jpg b/figure/chapters/sdn-openbox/sdn-test-topo.jpg
new file mode 100644
index 0000000..444d449
Binary files /dev/null and b/figure/chapters/sdn-openbox/sdn-test-topo.jpg differ
diff --git a/figure/chapters/sdn-openbox/sdn-topo.pdf b/figure/chapters/sdn-openbox/sdn-topo.pdf
new file mode 100644
index 0000000..7694945
Binary files /dev/null and b/figure/chapters/sdn-openbox/sdn-topo.pdf differ
diff --git a/figure/src/openbox_topo.vsd b/figure/src/openbox_topo.vsd
new file mode 100755
index 0000000..c877e22
Binary files /dev/null and b/figure/src/openbox_topo.vsd differ