传输层和网络层
传输层
传输层协议
传输层协议为运行在不同Host上的进程提供了一种逻辑通信机制
端系统运行传输层协议
- 发送方:将应用递交的消息分成一个或多个的Segment,并向下传给网络层。
- 接收方:将接收到的segment组装成消息,并向上交给应用层。
传输层可以为应用提供多种协议
- Internet上的TCP
- Internet上的UDP
传输层VS网络层:
- 网络层:提供主机之间的逻辑通信机制
- 传输层:提供应用进程(一个主机上可能运行多个进程)之间的逻辑通信机制
- 位于网络层之上
- 依赖于网络层服务
- 对网络层服务进行(可能的)增强
Internet传输层协议:
- 可靠、按序的交付服务(TCP)
- 拥塞控制
- 流量控制
- 连接建立
- 不可靠的交付服务(UDP):基于“尽力而为(Best-effort)”的网络层,没有做(可靠性方面的)扩展
注意:两种服务均不保证延迟和带宽
多路复用/分用
如果某层的一个协议对应直接上层的多个协议/实体,则需要复用/分用。
接收端进行多路分用:传输层依据头部信息将收到的Segment交给正确的Socket,即不同的进程
发送端进行多路复用:从多个Socket接收数据,为每块数据封装上头部信息,生成Segment、交给网络层
分用:
主机接收到IP数据报(datagram)
- 每个数据报携带源IP地址、目的IP地址。
- 每个数据报携带一个传输层的段(Segment)。
- 每个段携带源端口号和目的端口号
主机收到Segment之后,传输层协议提取IP地址和端口号信息,将Segment导向相应的Socket
- TCP做更多处理
无连接分用:
利用端口号创建Socket:
DatagramSocket mySocket1 = new DatagramSocket(9911);
DatagramSocket mySocket2 = new DatagramSocket(9922);
UDP的Socket用二元组标识:(目的IP地址,目的端口号)
主机收到UDP段后
- 检查段中的目的端口号
- 将UDP段导向绑定在该端口号的Socket
来自不同源IP地址和/或源端口号的IP数据包被导向同一个Socket
面向连接的分用:
TCP的Socket用四元组标识:(源IP地址,源端口号,目的IP地址,目的端口号)
接收端利用所有的四个值将Segment导向合适的Socket
服务器可能同时支持多个TCP Socket,每个Socket用自己的四元组标识
Web服务器为每个客户端开不同的Socket
UDP
UDP:User Datagram Protocol [RFC 768]
基于Internet IP协议,在其之上增加了功能:
- 复用/分用
- 简单的错误校验
但“Best effort”服务,UDP段可能的问题:
- 丢失
- 非按序到达
无连接:
- UDP发送方和接收方之间不需要握手
- 每个UDP段的处理独立于其他段
优点:
- 无需建立连接 (减少延迟)
- 实现简单:无需维护连接状态
- 头部开销少
- 没有拥塞控制: 应用可更好地控制发送时间和速率
应用:
- 流媒体应用:容忍丢失,速率敏感
- DNS
- SNMP
如何在UDP上实现可靠数据传输?
- 在应用层增加可靠性机制
- 应用特定的错误恢复机制
UDP校验:checksum
目的:检测UDP段在传输中是否发生错误(如位翻转)
发送方:
- 将段的内容视为16-bit整数
- 校验和计算:计算所有整数的和,进位加在和的后面,将得到的值按位求反,得到校验和
- 发送方将校验和放入校验和字段
接收方:
- 计算所收到段的校验和
- 将其与校验和字段进行对比
- 不相等:检测出错误
- 相等:没有检测出错误(但可能有错误)
可靠数据传输协议
可靠数据传输协议
可靠?不错、不丢、不乱
可靠数据传输协议对应用层、传输层、链路层都很重要
信道的不可靠特性决定了可靠数据传输协议(rdt)的复杂性
渐进地设计可靠数据传输协议的发送方和接收方
只考虑单向数据传输,但控制信息双向流动
利用状态机(Finite State Machine, FSM)刻画传输协议
Rdt 1.0:可靠信道上的可靠数据传输
底层信道完全可靠
- 不会发生错误(bit error)
- 不会丢弃分组
发送方和接收方的FSM独立
Rdt 2.0:产生位错误(bit error)的信道
底层信道可能翻转分组中的位(bit),利用校验和检测位错误
恢复错误?
- 确认机制(Acknowledgements, ACK):接收方显式地告知发送方分组已正确接收
- NAK:接收方显式地告知发送方分组有错误
- 发送方收到NAK后,重传分组
基于这种重传机制的rdt协议称为ARQ(Automatic Repeat reQuest)协议
Rdt 2.0中引入的新机制
- 差错检测
- 接收方反馈控制消息:ACK / NAK
- 重传
无错误场景
有错误场景
Rdt 2.1:应对ACK/NCK破坏
如果ACK/NAK消息发生错误/被破坏(corrupted)会怎么办?
- 为ACK/NAK增加校验和,检错并纠错
- 发送方收到被破坏ACK/NAK时不知道接收方发生了什么,添加额外的控制消息
- 如果ACK/NAK坏掉,发送方重传,但不能简单的重传:产生重复分组
如何解决重复分组问题?
- 序列号(Sequence number):发送方给每个分组增加序列号0,1
- 接收方丢弃重复分组
Rdt 2.2:无NAK消息协议
与rdt 2.1功能相同,但是只使用ACK
接收方通过ACK告知最后一个被正确接收的分组
在ACK消息中显式地加入被确认分组的序列号
发送方收到重复ACK之后,采取与收到NAK消息相同的动作,重传当前分组
Rdt 3.0:信道错误+分组丢失
校验和 + 序列号 + ACK + 重传 + 定时器
Rdt 3.0能够正确工作,但性能很差
流水线协议
流水线机制:提高资源利用率
流水线协议
允许发送方在收到ACK之前连续发送多个分组
- 更大的序列号范围
- 发送方和/或接收方需要更大的存储空间以缓存分组
滑动窗口协议
滑动窗口协议:Sliding-window protocol
窗口
- 允许使用的序列号范围
- 窗口尺寸为N:最多有N个等待确认的消息
滑动窗口:随着协议的运行,窗口在序列号空间内向前滑动
滑动窗口协议:GBN,SR
GBN(Go-Back-N)协议
分组头部包含k-bit序列号
窗口尺寸为N,最多允许N个分组未确认
ACK(n):确认到序列号n(包含n)的分组均已被正确接收
- 可能收到重复ACK
为空中的分组设置计时器(timer)
超时Timeout(n)事件: 重传序列号大于等于n,还未收到ACK的所有分组
ACK机制: 发送拥有最高序列号的、已被正确接收的分组的ACK
- 可能产生重复ACK
- 只需要记住唯一的expectedseqnum
乱序到达的分组:
- 直接丢弃,接收方没有缓存
- 重新确认序列号最大的、按序到达的分组
问:数据链路层采用后退N帧(GBN)协议,发送方已经发送了编号为0~7的帧。当计时器超时时,若发送方只收到0、2、3号帧的确认,则发送方需要重发的帧数是多少?分别是那几个帧?
解:根据GBN协议工作原理,GBN协议的确认是累积确认,所以此时发送端需要重发的帧数是4个,依次分别是4、5、6、7号帧
SR(Selective Repeat)协议
接收方对每个分组单独进行确认
- 设置缓存机制,缓存乱序到达的分组
发送方只重传那些没收到ACK的分组
- 为每个分组设置定时器
发送方窗口
- N个连续的序列号
- 限制已发送且未确认的分组
问题:
序列号: 0, 1, 2, 3 窗口尺寸:3 序列号空间大小与窗口尺寸需满足$N_S+N_R<=2$
TCP
TCP概述:RFCs-793, 1122, 1323, 2018, 2581
点对点:一个发送方,一个接收方
可靠的、按序的字节流
流水线机制:TCP拥塞控制和流量控制机制,设置窗口尺寸
发送方/接收方缓存
全双工(full-duplex):同一连接中能够传输双向数据流
面向连接:
- 通信双方在发送数据之前必须建立连接。
- 连接状态只在连接的两端中维护,在沿途节点中并不维护状态。
- TCP连接包括:两台主机上的缓存、连接状态变量、socket等
TCP段结构
序列号:
- 序列号指的是segment中第一个字节的编号,而不是segment的编号
- 建立TCP连接时,双方随机选择序列号
ACKs:
- 希望接收到的下一个字节的序列号
- 累计确认:该序列号之前的所有字节均已被正确接收到
Q:接收方如何处理乱序到达的Segment?
A:TCP规范中没有规定,由TCP的实现者做出决策
TCP可靠数据传输
TCP在IP层提供的不可靠服务基础上实现可靠数据传输服务
- 流水线机制
- 累积确认
- TCP使用单一重传定时器
- 触发重传的事件
- 超时
- 收到重复ACK
- 渐进式
- 暂不考虑重复ACK
- 暂不考虑流量控制
- 暂不考虑拥塞控制
- 大于RTT,但是RTT是变化的
- 过短:不必要的重传
- 过长:对段丢失时间反应慢
SampleRTT:测量从段发出去到收到ACK的时间(忽略重传)
SampleRTT变化:测量多个SampleRTT,求平均值,形成RTT的估计值EstimatedRTT
- 指数加权移动平均,典型值:0.125
- EstimatedRTT = (1-$\alpha $) * EstimatedRTT + $\alpha $ * SampleRTT
EstimatedRTT + “安全边界”
EstimatedRTT变化大 -> 较大边界
测量RTT的变化值:SampleRTT与EstimatedRTT的差值
- DevRTT = (1- $\beta $) DevRTT + $\beta $ | SampleRTT - EstimatedRTT |
- 典型值 $\beta $ = 0.25
定时器超时时间的设置:TimeoutInterval = EstimatedRTT + 4*DevRTT
TCP发送方:
- 创建Segment
- 序列号是Segment第一个字节的编号
- 开启计时器
- 设置超时时间:TimeOutInterval
超时
- 重传引起超时的Segment
- 重启定时器
收到ACK
- 如果确认此前未确认的Segment
- 更新SendBase
- 如果窗口中还有未被确认的分组,重新启动定时器
1 | NextSeqNum = InitialSeqNum |
TCP重传:
TCP ACK生成:RFC 1122, RFC 2581
快速重传机制:
TCP的实现中,如果发生超时,超时时间间隔将重新设置,即将超时时间间隔加倍,导致其很大,重发丢失的分组之前要等待很长时间
通过重复ACK检测分组丢失
- Sender会背靠背地发送多个分组
- 如果某个分组丢失,可能会引发多个重复的ACK
如果sender收到对同一数据的3个ACK,则假定该数据之后的段已经丢失
快速重传:在定时器超时之前即进行重传
TCP流量控制
接收方为TCP连接分配buffer,上层应用可能处理buffer中数据的速度较慢
速度匹配机制
(假定TCP receiver丢弃乱序的segments)
Buffer中的可用空间(spare room) = RcvWindow = RcvBuffer - [ LastByteRcvd - LastByteRead ]
Receiver通过在Segment 的头部字段将RcvWindow 告诉Sender
Sender限制自己已经发送的但还未收到ACK的数据不超过接收方的空闲RcvWindow尺寸
Q:Receiver告知Sender RcvWindow=0,会出现什么情况?
A:Sender不发送新的segment,就无法再收到RcvWindow,所以即使RcvWindow=0,Sender也要发送微小的Segment来获取RcvWindow。
TCP连接管理
建立连接
TCP sender和receiver在传输数据前需要建立连接。
初始化TCP变量
- Seq. #
- Buffer和流量控制信息
Client:连接发起者 Socket clientSocket = new Socket("hostname","port number");
Server: 等待客户连接请求 Socket connectionSocket = wwelcomeSocket.accept();
三次握手:Three way handshake
Step 1: client host sends TCP SYN segment to server
- specifies initial seq #
- no data
Step 2: server host receives SYN, replies with SYN+ACK segment
- server allocates buffers
- specifies server initial seq. #
Step 3: client receives SYN+ACK, replies with ACK segment, which may contain data
<四次挥手:服务器和客户端都可以关闭连接
这里以客户端申请关闭连接为例:client closes socket: clientSocket.close();
Step 1: client向server发送TCP FIN 控制segment
Step 2: server 收到FIN, 回复ACK. 关闭连接, 发送FIN.
Step 3: client 收到FIN, 回复ACK.
- 进入“等待” –如果收到FIN,会重新发送ACK
Step 4: server收到ACK. 连接关闭
TCP 为什么三次握手而不是两次握手(正解版)_萧萧九宸的博客-CSDN博客_tcp为什么是三次握手不是两次握手
拥塞控制原理
拥塞(Congestion)
非正式定义:“太多发送主机发送了太多数据或者发送速度太快,以至于网络无法处理”
表现:
- 分组丢失(路由器缓存溢出)
- 分组延迟过大(在路由器缓存中排队)
和流量控制的区别:流量控制只是单个端到端连接因缓存等原因要控制发送速率,拥塞控制是对多个TCP连接进行控制,尽力避免过长的延迟和堵塞。
拥塞的成因和代价:场景1:不会丢失分组,但排队延迟会无限大
拥塞的成因和代价:场景2:分组丢失重发
- 情况a:Sender能够通过某种机制获知路由器buffer信息,有空闲才发$\lambda_{in} = \lambda_{out}$ (goodput)
- 情况b:丢失后才重发 $\lambda^\prime_{in} > \lambda_{out}$
- 情况c:分组丢失和定时器超时后都重发, $\lambda^\prime_{in} $变得更大
拥塞的代价:
- 对给定的”goodput”,要做更多的工作(重传)
- 造成资源的浪费
拥塞的成因和代价:场景3
拥塞的另一个代价:当分组被drop时,任何用于该分组的“上游”传输能力全都被浪费掉
拥塞控制方法
端到端拥塞控制:
- 网络层不需要显式的提供支持
- 端系统通过观察loss,delay等网络行为判断是否发生拥塞
- TCP采取这种方法
网络辅助的拥塞控制:
- 路由器向发送方显式地反馈网络拥塞信息
- 简单的拥塞指示(1bit):SNA, DECbit, TCP/IP ECN, ATM
- 指示发送方应该采取何种速率
ATM ABR拥塞控制
ABR:available bit rate
弹性服务:调整发送速率
- 如果发送方路径“underloaded”,使用可用带宽
- 如果发送方路径拥塞,将发送速率降到最低保障速率
RM(resource management) cells:由发送方发送
- 交换机设置RM cell位(网络辅助)
- NI bit: rate不许增长
- CI bit: 拥塞指示
- RM cell由接收方返回给发送方
在RM cell中有显式的速率(ER)字段:两个字节
- 拥塞的交换机可以将ER置为更低的值
- 发送方获知路径所能支持的最小速率
数据cell中的EFCI位: 拥塞的交换机将其设为1
- 如果RM cell前面的data cell的EFCI位被设为1,那么发送方在返回的RM cell中置CI位
TCP拥塞控制
Sender限制发送速率:LastByteSent - LastByteAcked <= CongWin
rate ≈ CongWin / RTT (Bytes/sec)
CongWin:
- 动态调整以改变发送速率
- 反映所感知到的网络拥塞
Q:如何感知网络拥塞?
A:Loss事件 = timeout或3个重复ACK,发生loss事件后,发送方降低速率
Q:合理地调整发送速率?
- 加性增—乘性减: AIMD
- 慢启动: SS
加性增—乘性减: AIMD:
原理:逐渐增加发送速率,谨慎探测可用带宽,直到发生loss
方法: AIMD
Additive Increase:每个RTT将CongWin增大一个MSS(最大报文段长度)——拥塞避免
Multiplicative Decrease:发生loss后将CongWin减半
TCP慢启动: SS:
TCP连接建立时,CongWin=1
可用带宽可能远远高于初始速率:希望快速增长
- 例:MSS=500 byte,RTT=200msec,初始速率=20k bps
原理:当连接开始时,指数性增长
Slowstart algorithm:
initialize:Congwin = 1
for(each segment ACKed)
Congwin++
until(loss event OR CongWin > threshold)
Q:何时应该指数性增长切换为线性增长(拥塞避免)?
A:当CongWin达到Loss事件前值的1/2时。
实现方法:Loss事件发生时, Threshold被设为Loss事件前CongWin值的1/2。
Loss事件的处理:
3个重复ACKs:CongWin切到一半,然后线性增长
Timeout事件:CongWin直接设为1个MSS,然后指数增长,达到threshold后, 再线性增长
why:3个重复ACKs表示网络还能够传输一些 segments,timeout事件表明拥塞更为严重
总结:
When CongWin is below Threshold, sender in slow-start phase, window grows exponentially.
When CongWin is above Threshold, sender is in congestion-avoidance phase, window grows linearly.
When a triple duplicate ACK occurs, Threshold set to CongWin/2 and CongWin set to Threshold.
When timeout occurs, Threshold set to CongWin/2 and CongWin is set to 1 MSS
TCP拥塞控制算法:
TCP性能分析
TCP throughput:吞吐率
给定拥塞窗口大小和RTT,TCP的平均吞吐率是多少?(忽略掉Slow start)
- 假定发生超时时CongWin的大小为W,吞吐率是W/RTT
- 超时后,CongWin=W/2,吞吐率是W/2RTT
- 平均吞吐率为:0.75W/RTT
例:每个Segment有1500个byte, RTT是100ms,希望获得10Gbps的吞吐率
throughput = W*MSS*8/RTT,则W=throughput*RTT/(MSS*8)
throughput=10Gbps,则W=83,333,窗口大小为83,333
吞吐率与丢包率(loss rate, L)的关系
CongWin从W/2增加至W时出现第一个丢包,那么一共发送的分组数为
W/2+(W/2+1)+(W/2+2)+….+W = 3W$^2$/8+3W/4
W很大时,3W$^2$/8>>3W/4,因此L ≈ 8/(3W$^2$)
L = 2$\times$10$^{-10}$
高速网络下需要设计新的TCP
TCP的公平性:
如果K个TCP Session共享相同的瓶颈带宽R,那么每个Session的平均速率为R/K
公平性与UDP:
- 多媒体应用通常不使用TCP,以免被拥塞控制机制限制速率
- 使用UDP:以恒定速率发送,能够容忍丢失
- 产生了不公平
公平性与并发TCP连接:
- 某些应用会打开多个并发连接,如Web浏览器
- 产生公平性问题
例子:链路速率为R,已有9个连接
- 新来的应用请求1个TCP,获得R/10的速率
- 新来的应用请求11个TCP,获得 >R/2 的速率
网络层
网络层服务
从发送主机向接收主机传送数据段(segment)
发送主机:将数据段封装到数据报(datagram)中
接收主机:向传输层交付数据段(segment)
每个主机和路由器都运行网络层协议
路由器检验所有穿越它的IP数据报的头部域,决策如何处理IP数据报
网络层核心功能 - 转发与路由:
- 转发(forwarding): 将分组从路由器的输入端口转移到合适的输出端口
- 路由(routing): 确定分组从源到目的经过的路径
- 路由算法(routing algorithms)
网络层核心功能-连接建立:
数据分组传输之前两端主机需要首先建立虚拟/逻辑连接
- 网络设备(如路由器)参与连接的建立
网络层连接与传输层连接的对比:
- 网络层连接: 两个主机之间 (路径上的路由器等网络设备参与其中)
- 传输层连接: 两个应用进程之间(对中间网络设备透明)
网络层服务模型:
CBR VBR ABR UBR
无连接服务(connection-less service): 如 数据报网络(datagram network )
- 不事先为系列分组的传输确定传输路径
- 每个分组独立确定传输路径
- 不同分组可能传输路径不同
连接服务(connection service): 如 虚电路网络(virtual-circuit network,VC)
- 首先为系列分组的传输确定从源到目的经过的路径(建立连接)
- 然后沿该路径(连接)传输系列分组
- 系列分组传输路径相同
- 传输结束后拆除连接
数据报(datagram)网络与虚电路(virtual-circuit)网络是典型两类分组交换网络
数据报网络提供网络层无连接服务
虚电路网络提供网络层连接服务
类似于传输层的无连接服务(UDP)和面向连接服务(TCP),但是网络层服务:
- 主机到主机服务
- 网络核心实现
虚电路网络
虚电路Virtual circuits:一条从源主机到目的主机,类似于电路的路径(逻辑连接)
- 每个分组的传输利用链路的全部带宽
- 源到目的路径经过的网络层设备共同完成虚电路功能
通信过程:呼叫建立(call setup)→数据传输→拆除呼叫
每个分组携带虚电路标识(VCID),而不是目的主机地址
虚电路经过的每个网络设备(如路由器),维护每条经过它的虚电路连接状态
链路、网络设备资源(如带宽、缓存等)可以面向VC进行预分配
- 预分配资源=可预期服务性能,如ATM的电路仿真(CBR)
每条虚电路包括:
- 从源主机到目的主机的一条路径
- 虚电路号(VCID), 沿路每段链路一个编号
- 沿路每个网络层设备(如路由器),利用转发表记录经过的每条虚电路
沿某条虚电路传输的分组,携带对应虚电路的VCID,而不是目的地址
同一条VC ,在每段链路上的VCID通常不同
- 路由器转发分组时依据转发表改写/替换虚电路号
VC转发表
虚电路信令协议(signaling protocols)
- 用于VC的建立、维护与拆除,路径选择
- 应用于虚电路网络,如ATM、帧中继(frame-relay)网络等
- 目前的Internet不采用
数据报网络
- 网络层无连接
- 每个分组携带目的地址
- 路由器根据分组的目的地址转发分组
- 基于路由协议/算法构建转发表
- 检索转发表
- 每个分组独立选路
数据报转发表
- 路由算法(协议)确定通过网络的端到端路径
- 转发表确定在本路由器如何转发分组
最长前缀匹配优先
- 在检索转发表时,优先选择与分组目的地址匹配前缀最长的入口(entry)
数据报网络和VC网络
- Internet (数据报网络)
- 计算机之间的数据交换:“弹性”服务,没有严格时间需求
- 链路类型众多
- 特点、性能各异
- 统一服务困难
- “智能”端系统 (计算机)
- 可以自适应、性能控制、
- 差错恢复
- 简化网络,复杂“边缘”
- ATM (VC网络)
- 电话网络演化而来
- 核心业务是实时对话
- 严格的时间、可靠性需求
- 需要有保障的服务
- “哑(dumb)” 端系统(非智能)
- 电话机
- 传真机
- 简化“边缘”,复杂网络
IPv4协议
IP数据报
IP协议 和 ICMP协议
- 版本号字段占4位:IP协议的版本号
- E.g. 4→IPv4,6 → IPv6
- 首部长度字段占4位:IP分组首部长度
- 以4字节为单位
- E.g. 5→IP首部长度为20(5×4)字节
- 服务类型(TOS)字段占8位:指示期望获得哪种类型的服务
- 1998 年这个字段改名为区分服务
- 只有在网络提供区分服务(DiffServ)时使用
- 一般情况下不使用,通常IP分组的该字段(第2字节)的值为00H
- 总长度字段占16位:IP分组的总字节数(首部+数据)
- 最大IP分组的总长度:65535B,$2^{16} - 1$
- 最小的IP分组首部:20B
- IP分组可以封装的最大数据:65535-20=65515B
- 生存时间(TTL)字段占8位:IP分组在网络中可以通过的路由器数(或跳步数)
- 路由器转发一次分组,TTL减1
- 如果TTL=0,路由器则丢弃该IP分组
- 协议字段占8位:指示IP分组封装的是哪个协议的数据包
- 实现复用/分解
- E.g. 6为TCP,表示封装的为TCP段;17为UDP,表示封装的是UDP数据报
- 首部校验和字段占16位:实现对IP分组首部的差错检测
- 计算校验和时,该字段置全0
- 采用反码算数运算求和,和的反码作为首部校验和字段
- 逐跳计算、逐跳校验
- 源IP地址、目的IP地址字段各占32位:分别标识发送分组的源主机/路由器(网络接口)和接收分组的目的主机/路由器(网络接口)的IP地址
- 选项字段占长度可变,范围在1~40B之间:携带安全、源选路径、时间戳和路由记录等内容
- 实际上很少被使用
- 填充字段占长度可变,范围在0~3B之间:目的是补齐整个首部,符合32位对齐,即保证首部长度是4字节的倍数
IP分片和重组
最大传输单元(MTU):链路层数据帧可封装数据的上限,不同链路的MTU不同
大IP分组向较小MTU链路转发时,可以被分片(fragmented)
- 1个IP分组分为多片IP分组
- IP分片到达目的主机后进行重组(reassembled)
IP首部的相关字段用于标识分片以及确定分片的相对顺序
- 总长度、标识、标志位和片偏移
标识字段占16位:标识一个IP分组
- IP协议利用一个计数器,每产生IP分组计数器加1,作为该IP分组的标识
标志位字段占3位:
- DF(Don’t Fragment)
- DF = 1:禁止分片
- DF = 0:允许分片
- MF(More Fragment)
- MF = 1:非最后一片
- MF = 0:最后一片(或未分片)
- 保留
片偏移字段占13位:一个IP分组分片封装原IP分组数据的相对偏移量
- 片偏移字段以8字节为单位
IP分片过程:
假设原IP分组总长度为$L$,待转发链路的MTU为$M$,若$L>M$,且DF=0,则可以/需要分片
分片时每个分片的标识复制原IP分组的标识
通常分片时,除最后一个分片,其他分片均分为MTU允许的最大分片
IP编址
IP编址(addressing)
IP分组:源地址(SA)-从哪儿来,目的地址(DA)-到哪儿去
接口(interface):主机/路由器与物理链路的连接
- 实现网络层功能
- 路由器通常有多个接口
- 主机通常只有一个或两个接口 (e.g.,有线的以太网接口,无线的802.11接口)
IP地址:32比特(IPv4)编号标识主机、路由器的接口
IP地址与每个接口关联,怎样分配IP地址呢?
IP子网(Subnets)
IP地址:
- 网络号(NetID) – 高位比特
- 主机号(HostID) – 低位比特
IP子网:
- IP地址具有相同网络号的设备接口
- 不跨越路由器(第三及以上层网络设备)可以彼此物理联通的接口
有类IP地址
特殊IP地址:
私有(Private)IP地址:
子网划分
子网划分:IP子网更小范围网络
IP地址:
- 网络号(NetID) – 高位比特
- 子网号(SubID) – 原网络主机号部分比特
- 主机号(HostID) – 低位比特
子网掩码
子网掩码:确定是否划分了子网,利用多少位划分子网
- 形如IP地址:32位,点分十进制形式
- 取值:NetID、SubID位全取1,HostID位全取0
例如:
- A网的默认子网掩码为:255.0.0.0
- B网的默认子网掩码为:255.255.0.0
- C网的默认子网掩码为:255.255.255.0
- 借用3比特划分子网的B网的子网掩码为:255.255.224.0
子网地址+子网掩码→准确确定子网大小
子网掩码的应用:
将IP分组的目的IP地址与子网掩码按位与运算,提取子网地址
一个C类网络划分子网举例:
子网划分会造成边界部分的IP的浪费,但提高了网络性能
CIDR
无类域间路由(CIDR: Classless InterDomain Routing)
- 消除传统的 A 类、B 类和 C 类地址界限
- NetID+SubID→Network Prefix (Prefix)可以任意长度
- 融合子网地址与子网掩码,方便子网划分
- 无类地址格式:a.b.c.d/x,其中x为前缀长度
- 提高IPv4 地址空间分配效率
- 提高路由效率
- 将多个子网聚合为一个较大的子网
- 构造超网(supernetting)
路由聚合
路由聚合(route aggregation)
层级编址使得路由信息通告更高效:
选用更具体的路由:最长前缀匹配优先
DHCP协议
动态主机配置协议-DHCP: Dynamic Host Configuration Protocol(应用层协议)
一个主机如何获得IP地址?
- 硬编码
- 静态配置
- 动态主机配置协议-DHCP: Dynamic Host Configuration Protocol(应用层协议)
- 从服务器动态获取:
- IP地址
- 子网掩码
- 默认网关地址
- DNS服务器名称与IP地址
- “即插即用”
- 允许地址重用
- 支持在用地址续租
- 支持移动用户加入网络
- 从服务器动态获取:
获取IP过程:
- 主机广播 “DHCP discover”(发现报文)
- DHCP服务器利用 “DHCP offer” (提供报文) 进行响应
- 主机请求IP地址: “DHCP request” (请求报文)
- DHCP服务器分配IP地址: “DHCP ack” (确认报文)
DHCP工作过程示例
DHCP协议在应用层实现
- 请求报文封装到UDP数据报中
- IP广播
- 链路层广播(e.g. 以太网广播)
DHCP服务器构造ACK报文:包括分配给客户的IP地址、子网掩码、默认网关、DNS服务器地址
NAT
网络地址转换NAT
动机:
- 只需/能从ISP申请一个IP地址,IPv4地址耗尽
- 本地网络设备IP地址的变更,无需通告外界网络
- 变更ISP时,无需修改内部网络设备IP地址
- 内部网络设备对外界网络不可见,即不可直接寻址(安全)
实现:
- 替换:利用(NAT IP地址,新端口号)替换每个外出IP数据报的(源IP地址,源端口号)
- 记录:将每对(NAT IP地址, 新端口号) 与(源IP地址, 源端口号)的替换信息存储到NAT转换表中
- 替换:根据NAT转换表,利用(源IP地址, 源端口号)替换每个进入内网IP数据报的(目的IP地址,目的端口号),即(NAT IP地址, 新端口号)
16-bit端口号字段:可以同时支持60,000多并行连接
NAT主要争议:
- 路由器应该只处理第3层功能
- 违背端到端通信原则
- 应用开发者必须考虑到NAT的存在,e.g., P2P应用
- 地址短缺问题应该由IPv6来解决
NAT穿透问题
客户期望连接内网地址为10.0.0.1的服务器
- 客户不能直接利用地址10.0.0.1直接访问服务器
- 对外唯一可见的地址是NAT地址: 138.76.29.7
解决方案1: 静态配置NAT,将特定端口的连接请求转发给服务器
- e.g., (138.76.29.7, 2500) 总是转发给(10.0.0.1, 25000)
解决方案2:利用UPnP(Universal Plug and Play) 互联网网关设备协议IGD (Internet Gateway Device) 自动配置:
- 学习到NAT公共IP地址(138.76.29.7)
- 在NAT转换表中,增删端口映射
解决方案3:中继(如Skype)
- NAT内部的客户与中继服务器建立连接
- 外部客户也与中继服务器建立连接
- 中继服务器桥接两个连接的分组
ICMP
互联网控制报文协议ICMP
互联网控制报文协议 ICMP (Internet Control Message Protocol)支持主机或路由器:
- 差错(或异常)报告
- 网络探询
两类ICMP报文:
- 差错报告报文(5种)
- 目的不可达
- 源抑制(Source Quench)
- 超时/超期
- 参数问题
- 重定向 (Redirect)
- 网络探询报文(2组)
- 回声(Echo)请求与应答报文(Reply)
- 时间戳请求与应答报文
类型(Type) | 编码(Code) | description |
---|---|---|
0 | 0 | 回声应答 (ping) |
3 | 0 | 目的网络不可达 |
3 | 1 | 目的主机不可达 |
3 | 2 | 目的协议不可达 |
3 | 3 | 目的端口不可达 |
3 | 6 | 目的网络未知 |
3 | 7 | 目的主机未知 |
4 | 0 | 源抑制(拥塞控制-未用) |
8 | 0 | 回声请求(ping) |
9 | 0 | 路由通告 |
10 | 0 | 路由发现 |
11 | 0 | TTL超期 |
12 | 0 | IP首部错误 |
例外情况:
几种不发送 ICMP差错报告报文的特殊情况:
- 对ICMP差错报告报文不再发送 ICMP差错报告报文
- 除第1个IP数据报分片外,对所有后续分片均不发送ICMP差错报告报文
- 对所有多播IP数据报均不发送 ICMP差错报告报文
- 对具有特殊地址(如127.0.0.0 或 0.0.0.0)的IP数据报不发送ICMP 差错报告报文
几种 ICMP 报文已不再使用
- 信息请求与应答报文
- 子网掩码请求和应答报文
- 路由器询问和通告报文
ICMP报文的格式:
ICMP报文封装到IP数据报中传输
ICMP差错报告报文数据封装
ICMP的应用举例:Traceroute
获取到目的IP的路由路线
- 源主机向目的主机发送一系列UDP数据报
- 第1组IP数据报TTL =1
- 第2组IP数据报TTL=2, etc.
- 目的端口号为不可能使用的端口号
- 当第n组数据报(TTL=n)到达第n个路由器时:
- 路由器丢弃数据报
- 向源主机发送ICMP报文(type=11, code=0)
- ICMP报文携带路由器名称和IP地址信息
当ICMP报文返回到源主机时,记录RTT
停止准则:
- UDP数据报最终到达目的主机,目的主机返回“目的端口不可达”ICMP报文 (type=3, code=3),源主机停止
IPv6
最初动机:32位IPv4地址空间已分配殆尽
其他动机:改进首部格式
- 快速处理/转发数据报
- 支持QoS
IPv6数据报格式:
- 固定长度的40字节基本首部
- 不允许分片
- 优先级(priority):标识数据报的优先级
- 流标签(flow Label):标识同一“流”中的数据报
- 下一个首部(next header):标识下一个选项首部或上层协议首部(如TCP首部)
和IPv4相比其他改变:
校验和(checksum):彻底移除,以减少每跳处理时间
选项(options):允许,但是从基本首部移出,定义多个选项首部,通过“下一个首部”字段指示
ICMPv6:新版ICMP
- 附加报文类型,e.g. “Packet Too Big”
- 多播组管理功能
IPv6地址表示形式:
- 一般形式:1080:0:FF:0:8:800:200C:417A
- 共128位,8x16的形式,: 隔开,用16进制数表示
- 压缩形式:FF01:0:0:0:0:0:0:43
- 压缩→FF01::43 ( :: 表示多个0,但只能使用一次)
- IPv4-嵌入形式:0:0:0:0:0:FFFF:13.1.68.3或 ::FFFF:13.1.68.3
- 地址前缀:2002:43c:476b::/48(注: IPv6不再使用掩码)
- URLs:http://[3FFE::1:800:200C:417A]:8000
IPv6基本地址类型:
单播(unicast):一对一通信
多播(multicast):一对多通信
任意播(anycast):一对一组之一(最近一个)通信
IPv4向IPv6过渡
不可能在某个时刻所有路由器同时被更新为IPv6
不会有 “标志性的日期”
Q:IPv4和IPv6路由器共存的网络如何运行?
A:隧道(tunneling)
隧道(tunneling):IPv6数据报作为IPv4数据报的载荷进行封装,穿越IPv4网络
路由算法
路由算法(协议)确定去往目的网络的最佳路径
转发表确定在本路由器如何转发分组
网络抽象:图
图: $G = (N, E)$
- $N =$ 路由器集合$= { u, v, w, x, y, z }$
- $E =$ 链路集合 $={ (u,v), (u,x), (v,x), (v,w), (x,w), (x,y), (w,y), (w,z), (y,z) }$
- 附注: 图的抽象在网络领域应用很广泛
- E.g.:P2P,其中,N是 peers集合,而E是TCP连接集合
- 费用(Costs):带宽的倒数、拥塞程度等,eg:$c(w, z) = 5$
Q:关键问题: 源到目的(如u到z)的最小费用路径是什么?
A:路由算法: 寻找最小费用路径的算法
路由算法分类
静态路由 和 动态路由
静态路由:手工配置、路由更新慢、优先级高
动态路由:路由更新快、定期更新、及时响应链路费用或网络拓扑变化
全局信息 和 分散信息
全局信息:所有路由器掌握完整的网络拓扑和链路费用信息。如:链路状态(LS)路由算法
分散(decentralized)信息:路由器只掌握物理相连的邻居以及链路费用邻居间信息交换、运算的迭代过程。如:距离向量(DV)路由算法
链路状态路由算法
Dijkstra 算法:
- 所有结点(路由器)掌握网络拓扑和链路费用
- 通过“链路状态广播”
- 所有结点拥有相同信息
- 计算从一个结点(“源”)到达所有其他结点的最短路径
- 获得该结点的转发表
- 迭代: k次迭代后,得到到达k个目的结点的最短路径
$c(x,y)$: 结点x到结点y链路费用;如果x和y不直接相连,则$=∞$
$D(v)$: 从源到目的v的当前路径费用值
$p(v)$: 沿从源到v的当前路径,v的前序结点
$N’$: 已经找到最小费用路径的结点集合
示例:
算法复杂性: n个结点
- 每次迭代: 需要检测所有不在集合N’中的结点w
- n(n+1)/2次比较: $O(n^2)$
- 更高效的实现: $O(nlogn)$
问题:存在震荡(oscillations)可能
e.g. 假设链路费用是该链路承载的通信量:
距离向量路由算法
Bellman-Ford方程(动态规划)
令:$d_x(y)$:=从x到y最短路径的费用(距离)则:
示例:
显然: dv(z) = 5, dx(z) = 3, dw(z) = 3
du(z) = min { c(u,v) + dv(z), c(u,x) + dx(z), c(u,w) + dw(z) } = 4
重点:结点获得最短路径的下一跳, 该信息用于转发表中!
Dx(y) = 从结点x到结点y的最小费用估计
- x维护距离向量(DV): $Dx = [Dx(y): y \in N ]$
结点x:
- 已知到达每个邻居的费用: c(x,v)
- 维护其所有邻居的距离向量: $Dv = [Dv(y): y \in N ]$
核心思想:
- 每个结点不定时地将其自身的DV估计发送给其邻居
- 当x接收到邻居的新的DV估计时,即依据B-F更新其自身的距离向量估计:
- Dx(y) ← minv{c(x,v) + Dv(y)} for each node y $\in$ N
- Dx(y)将最终收敛于实际的最小费用 dx(y)
特点:
异步迭代:引发每次局部迭代的因素
- 局部链路费用改变
- 来自邻居的DV更新
分布式:每个结点只当DV变化时才通告给邻居,邻居在必要时(其DV更新
后发生改变)再通告它们的邻居
示例:
链路费用变化:
- 结点检测本地链路费用变化
- 更新路由信息,重新计算距离向量
- 如果DV改变,通告所有邻居
- t0 : y检测到链路费用改变 ,更新DV,通告其邻居.
- t1 : z收到y的DV更新,更新其距离向量表,计算到达x的最新最小费用,更新其DV,并发送给其所有邻居.
- t2 : y收到z的DV更新,更新其距离向量表,重新计算y的DV,未发生改变,不再向z发送DV
无穷计数问题:
解决方法一:毒性逆转(poisoned reverse)
如果一个结点(e.g. Z)到达某目的(e.g.X)的最小费用路径是通过某个邻居(e.g.Y),则通告给该邻居结点到达该目的的距离为无穷大
解决方法二:定义最大度量(maximum metric)
定义一个最大的有效费用值,如15跳步,16跳步表示$∞$
层次路由
层次路由准确的说是一种路由策略
将任意规模网络抽象为一个图计算路由-过于理想化
网络规模:考虑6亿目的结点的网络,路由表几乎无法存储!路由计算过程的信息(e.g. 链路状态分组、DV)交换量巨大,会淹没链路!
管理自治:每个网络的管理可能都期望自主控制其网内的路由。互联网(internet) = 网络之网络(network of networks)
聚合路由器为一个区域:自治系统AS(autonomous systems)
同一AS内的路由器运行相同的路由协议(算法)
- 自治系统内部路由协议(“intra-AS” routing protocol)
- 不同自治系统内的路由器可以运行不同的AS内部路由协议
互连的AS:
转发表由AS内部路由算法与AS间路由算法共同配置
- AS内部路由算法设置AS内部目的网络路由入口(entries)
- AS内部路由算法与AS间路由算法共同设置AS外部目的网络路由入口
自治系统间(Inter-AS)路由
假设AS1内某路由器收到一个目的地址在AS1之外的数据报:路由器应该将该数据
报转发给哪个网关路由器呢?
AS1必须:
- 学习到哪些目的网络可以通过AS2到达,哪些可以通过AS3到达
- 将这些网络可达性信息传播给AS1内部路由器
假设AS1学习到(通过AS间路由协议):子网x可以通过AS3 (网关 1c)到达,但不能通过AS2到达,AS间路由协议向所有内部路由器传播该可达性信息
路由器1d:利用AS内部路由信息,确定其到达1c的最小费用路径接口I,在转发表中增加入口:(x, I)
假设AS1通过AS间路由协议学习到:子网x通过AS3和AS2均可到达
为了配置转发表,路由器1d必须确定应该将去往子网x的数据报转发给哪个网关?这个任务也是由AS间路由协议完成!
热土豆路由: 将分组发送给最近的网关路由器.
路由协议
Internet采用层次路由
AS内部路由协议也称为内部网络协议IGP(interior gateway protocols)
最常见的AS内部路由协议:
- 路由信息协议:RIP(Routing Information Protocol)
- 开放最短路径优先:OSPF(Open Shortest Path First)
- 内部网关路由协议:IGRP(Interior Gateway Routing Protocol),是Cisco私有协议
Internet AS间路由协议:BGP
RIP协议
采用距离向量路由算法
- 距离度量:跳步数 (max = 15 hops), 每条链路1个跳步
- 每隔30秒,邻居之间交换一次DV,成为通告(advertisement)
- 每次通告:最多25个目的子网(IP地址形式)
示例:
链路失效、恢复:
如果180秒没有收到通告→邻居/链路失效
- 经过该邻居的路由不可用,重新计算路由
- 向邻居发送新的通告
- 邻居再依次向外发送通告(如果转发表改变)
- 链路失效信息能否快速传播到全网?可能发生无穷计数问题
- 毒性逆转技术用于预防乒乓(ping-pong)环路(另外:无穷大距离 = 16 hops)
RIP路由表的处理:
RIP路由表是利用一个称作route-d (daemon)的应用层进程进行管理(应用进程实现)
通告报文周期性地通过UDP数据报发送
OSPF协议
OSPF:Open Shortest Path First
“开放”: 公众可用
采用链路状态路由算法
- LS分组扩散(通告)
- 每个路由器构造完整的网络(AS)拓扑图
- 利用Dijkstra算法计算路由
OSPF通告中每个入口对应一个邻居
OSPF通告在整个AS范围泛洪,OSPF报文直接封装到IP数据报中
与OSPF极其相似的一个路由协议:IS-IS路由协议
OSPF优点(RIP不具备):
- 安全(security): 所有OSPF报文可以被认证(预防恶意入侵)
- 允许使用多条相同费用的路径 (RIP只能选一条)
- 对于每条链路,可以针对不同的TOS设置多个不同的费用度量 (e.g., 卫星链路可以针对“尽力”(best effort) ToS设置“低”费用;针对实时ToS设置“高”费用)
- 集成单播路由与多播路由: 多播OSPF协议(MOSPF) 与OSPF利用相同的网络拓扑数据
- OSPF支持对大规模AS分层(hierarchical)
分层的OSPF:
两级分层:局部区(Area),主干区(Backbone)
- 链路状态通告只限于区内
- 每个路由器掌握所在区的详细拓扑
- 只知道去往其他区网络的“方向” (最短路径)
内部路由器IR(Internal Routers)
区边界路由器(Area Border Routers): “汇总”到达所在区网络的距离,通告给其他区边界路由器
主干路由器(Backbone Routers): 在主干区内运行OSPF路由算法
AS边界路由器(AS boundary routers):连接其他AS
参考:RFC 2328
BGP协议
边界网关协议BGP (Border Gateway Protocol): 事实上的标准域间路由协议,是将Internet “粘合”为一个整体的关键
BGP为每个AS提供了一种手段:
- eBGP: 从邻居AS获取子网可达性信息.
- iBGP: 向所有AS内部路由器传播子网可达性信息.
- 基于可达性信息与策略,确定到达其他网络的 “好”路径
容许子网向Internet其余部分通告它的存在
BGP会话(session):两个BGP路由器 (“Peers”)交换BGP报文
- 通告去往不同目的前缀(prefix)的路径 (“路径向量(path vector)”协议)
- 报文交换基于半永久的TCP连接
BGP报文类型:
- OPEN: 与peer建立TCP连接,并认证发送方
- UPDATE: 通告新路径 (或撤销原路径)
- KEEPALIVE: 在无UPDATE时,保活连接;也用于对OPEN请求的确认
- NOTIFICATION: 报告先前报文的差错;也被用于关闭连接报文交换基于半永久的TCP连接
当AS3通告一个前缀给AS1时:
- AS3承诺可以将数据报转发给该子网
- AS3在通告中会聚合网络前缀
分发路径信息:
在3a与1c之间,AS3利用eBGP会话向AS1发送前缀可达性信息.
1c则可以利用iBGP向AS1内的所有路由器分发新的前缀可达性信息
1b可以(也可能不)进一步通过1b-到-2a的eBGP会话,向AS2通告新的可达性信息
当路由器获得新的前缀可达性时,即在其转发表中增加关于该前缀的入口(路由项)
路径属性与BGP路由(route):
通告的前缀信息包括BGP属性:前缀+属性= “路由”
两个重要属性:
- AS-PATH(AS路径): 包含前缀通告所经过的AS序列:如AS 67, AS 17
- NEXT-HOP(下一跳): 开始一个AS-PATH的路由器接口,指向下一跳AS.
- 可能从当前AS到下一跳AS存在多条链路
BGP路由选择:
网关路由器收到路由通告后,利用其输入策略(import policy)决策接受/拒绝该路由,基于策略(policy-based) 路由
路由器可能获知到达某目的AS的多条路由,基于以下准则选择:
- 本地偏好(preference)值属性: 策略决策(policy decision)
- 最短AS-PATH
- 最近NEXT-HOP路由器: 热土豆路由(hot potato routing)
- 附加准则
示例:
A,B,C是提供商网络/AS(provider network/AS)
X,W,Y是客户网络(customer network/AS)
W,Y是桩网络(stub network/AS): 只与一个其他AS相连
X是双宿网络(dual-homed network/AS): 连接两个其他AS(大于2个则为多宿网络)
X不期望经过他路由B到C的流量,因此,X不会向B通告任何一条到达C的路由
A向B通告一条路径:AW
B向X通告路径:BAW
B是否应该向C通告路径BAW呢?绝不! B路由CBAW的流量没有任何“收益”,因为W和C均不是B的客户。
B期望强制C通过A向W路由流量,B期望只路由去往/来自其客户的流量!
为什么采用不同的AS内与AS间路由协议?三方面 (inter-AS 域间,intra-AS 域内)
策略(policy):
- inter-AS: 期望能够管理控制流量如何被路由,谁路由经过其网络等.
- intra-AS: 单一管理,无需策略
决策规模(scale):
- 层次路由节省路由表大小,减少路由更新流量
- 适应大规模互联网
性能(performance):
- intra-AS: 侧重性能
- inter-AS: 策略主导