|
|
%# -*- 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}
|