一、网络层服务
- 从发送主机向接收主机传送数据段
- 发送主机:将数据段封装到数据报(datagram)中
- 接收主机:向传输层交付数据段(segment)
- 每个主机和路由器都运行着网络层协议
- 路由器检验所有穿越他的IP数据报的头部域,以决策如何处理IP数据报
核心功能-转发和路由
- 转发(forwarding): 将分组从路由器的输入端口转移到合适的输出端口
- 路由算法:确定分组从源到目的经过的路径
核心功能-网络建立
- 数据分组传输之前两端主机需要首先建立虚拟/逻辑连接;网络设备(如路由器)参与连接的建立
- 网络层连接与传输层连接的对比:
- 网络层:两个主机之间 (路径上的路由器等网络设备参与其中)
- 传输层:两个应用进程之间(对中间设备透明)
网络服务模型
- 类似于传输层的无连接服务(UDP)和面向连接
服务(TCP),但是网络层服务:- 网络核心实现
- 主机到主机服务
无连接服务
- 不事先为系列分组的传输确定传输路径
- 每个分组独立确定传输路径
- 不同分组可能传输路径不同
- 典型实例:数据报网络(datagram network )
连接服务
- 首先为系列分组的传输确定从源到目的经过的路径(建立连接);发送顺序可以保证
- 沿着该路径传送系列分组,系列分组传输路径相同
- 传输结束后需要拆除连接
- 典型实例:虚电路网络
二、虚电路网络(简称VC,提供连接服务)
-
一条从源主机到目的主机,类似于电路的路径(逻辑连接)
-
分组交换(确定路径,意味着利用链路的全部带宽;)
-
源到目的的经过的网络层设备共同完成虚电路网络
-
通信过程:呼叫建立-》数据传输-》拆除呼叫
-
每个分组携带虚电路标志而不是目的主机地址,如图所示:
-
经过的每个网络设备维护每条经过他的虚电路的连接状态
-
链路,网络设备资源(如带宽,缓存等)可以面向VC进行预分配
- ATM的电路仿真(CBR)。虽然使用分组交换的技术,但是也可以实现电路交换的性能保障
- 集成电路交换和分组交换的优点于一身
VC的实现
每条虚电路包括:
-
从源主机到目的主机的一条路径
-
虚电路号(VCID):沿着每段链路有一个编号
- 反映了一条链路的通信能力
- 如电话线和光纤线
- 不可能每条链路是统一的虚电路号。同一条虚电路在不同链路上的虚电路号可能不同
-
沿路的每个网络层设备,利用转发表记录经过他的每条虚电路
-
沿着虚电路传输的分组,携带对应虚电路的VCID而不是目的地址
-
同一条虚电路在每段链路上的VCID通常是不同的
- 路由器在转发分组时依据转发表改写和替换虚电路号
VC的实例
NAT网络地址转换
距离向量路由算法
- 每个结点从一个或多个直接相连的邻居中收集信息
- 将计算结果分发给邻居
- 自我终止
- 不要求所有结点步伐一致的操作
引言
设 d x ( y ) d_x(y) dx(y)是结点 x x x到结点 y y y之间的最低开销最短路径的开销。列出DP方程可知: d x ( y ) = m i n v ∈ N ( x ) { c ( x , v ) + d v ( y ) } d_x(y) = min_{v\in N(x) }\{c(x,v)+d_v(y)\} dx(y)=minv∈N(x){c(x,v)+dv(y)}
- 方程直接给出了转发表的表项
- 例如对于结点x,想发给结点y,令 v ∗ v^* v∗为使得上述式子的最优解成立的v值,所以首先应当向 v ∗ v^* v∗转发分组
基本思路
- 每个节点x从 D x ( y ) D_x(y) Dx(y)开始,对于在N中的所有节点y估计从x到y的最短路径的开销。
- 定义距离向量:
D
x
=
[
D
x
(
y
)
:
y
∈
N
]
\mathbf{D}_x = [D_x(y):y\in N]
Dx=[Dx(y):y∈N]
- 这是一种估计向量,是从x到N中其他所有结点y的开销估计向量
- 每个结点x需要维护:
- 到x的每个邻居的开销 c ( x , v ) c(x,v) c(x,v)
- 自身的距离向量 D x \mathbf{D}_x Dx
- 每个邻居的距离向量,即 D z , ∀ z ∈ N ( x ) \mathbf{D}_z,\forall z\in N(x) Dz,∀z∈N(x)
- 每个结点时不时的向他的邻居发送他的距离向量副本
- 例如当结点x收到它邻居w的一个距离向量副本时,
- 首先保存w的距离向量
- 然后重新计算x自己的距离向量,针对于距离向量中的每个分量重新计算:
D
x
(
y
)
=
m
i
n
v
{
c
(
x
,
v
)
+
D
v
(
y
)
}
D_x(y) = min_v\{c(x,v)+D_v(y)\}
Dx(y)=minv{c(x,v)+Dv(y)}
其中v是x的邻居。一定要注意这里计算的是距离向量中的每个分量,即对不同的y值分别以上述式子进行计算更新。如果x的距离向量 D x \mathbf{D}_x Dx因为上述式子的更新而改变,接下来x向其邻居发送其更新以后的 D x \mathbf{D}_x Dx。循环执行上述过程可以保证 D x ( y ) D_x(y) Dx(y)可以收敛到 d x ( y ) d_x(y) dx(y)
- 例如当结点x收到它邻居w的一个距离向量副本时,
主循环
解释:
- 当结点发现它直接相连的链路开销发生变化或从某个邻居接收到一个距离向量的更新时,
- 更新其估计值。
- 如果至少有一个分量发生了改变,那么还需要通知他的邻居
- 需要保存邻居的距离向量?
完整的算法框架
- 尤其需要注意初始化操作干了什么事
应用实例
实例在如下的网络结构上进行:
设初始路由选择表如图所示:
先解释一下这三个表格的含义:
- 每一个表格对应一个结点的路由选择表
- 例如第一个表格对应结点x的路由选择表。其中每一行代表该对应结点的距离向量。例如对于上图中第一个表格的第一行,代表结点x自身的距离向量 D x \mathbf{D}_x Dx,该行的每一列是距离向量中的每个分量。
- 而由于结点x还需要维护其余节点的距离向量,所以在第二行和第三行存有 D y \mathbf{D}_y Dy和 D z \mathbf{D}_z Dz的距离向量。
- 初始状态下,x,y,z都没有收到它们的邻居的任何消息。因此在上图所示的表格中除了自身距离向量所对应的行外其余的行(也就是对应的各自邻居结点的距离向量的每个分量)中的元素都被设置为
∞
\infty
∞。
- 对于每个结点的表格,其自身的距离向量的设置方式是将和自己有边相连得点对应得分量设置为和其相连得边的权重,其余的分量设置为 ∞ \infty ∞
上述的初始化完成后,由上述完整框架的初始化代码,每个结点向他的两个邻居发送其自身的距离向量
- 对每个结点,当收到邻居发送的距离向量后
- 存储邻居的距离向量
- 更新自身的距离向量值
- 例如对于结点x有如下的操作
类似的对于结点y和z进行操作,得到完整的第二列图像。在得到距离向量(各表中的每一行)的同时,还可以得到转发表。
- 例如对于结点x,由于使得
D
x
(
y
)
和
D
x
(
z
)
D_x(y)和D_x(z)
Dx(y)和Dx(z)取值最小的后继结点都是结点
y
y
y,因此对于结点x我们有
v
∗
(
y
)
=
y
,
v
∗
(
z
)
=
y
v^*(y) = y,v^*(z) = y
v∗(y)=y,v∗(z)=y
在结点重新计算他们的距离向量以后,再次向邻居发送他们的更新距离向量(如果他们已经被改变的话,也就是说只要有一个分量改变那么就需要进行发送了)。如图所示:
上图中的第二列到第三列的箭头说明了这种情况。 - 可以看到,比较第二列和第一列的表格,结点x和结点y的距离向量的至少一个分量发生了改变(也就是表格的一行中至少一个元素发生了改变)。而结点 y y y自身的距离向量并没有改变。
- 因此只是结点
x
x
x向结点
y
,
z
y,z
y,z,结点
z
z
z向结点
x
,
y
x,y
x,y发送他们的距离向量。而结点
y
y
y并不向结点
x
,
z
x,z
x,z发送它的距离向量。
- 进而使得每个结点保存它们收到的最新的邻居距离向量信息
- 然后使得每个结点重新计算他们自身的距离向量信息
链路开销改变和链路故障
好消息传播快
首先考察链路开销从4减少到1后的情况:
在此只关注
y
y
y与
z
z
z到目的地
x
x
x的距离表中的有关表项。导致下列的事件序列的发生:
- t 0 t_0 t0时刻,y检测到链路开销的变化并更新其距离向量 D y \mathbf{D}_y Dy,并通知邻居这个变化(需要通知,这是因为显然该距离向量中某个分量发生了变化)
- t 1 t_1 t1时刻, z z z收到 y y y的更新的距离向量。并更新其距离表。计算出到 x x x的最低开销。显然 D z \mathbf{D}_z Dz也发生了变化,因此通知其邻居发送它的新距离向量
- y y y收到 z z z的距离向量,存z的最新距离向量。再更新自身的距离向量,没有任何一个分量发生变化,因此y不再发送任何报文给z。
因此两次迭代就达到了静止状态。好消息传播快!
坏消息传播慢
再次考察下图中将边权重从4增加到60的情况:
- 设再
t
0
t_0
t0时刻,y检测到了链路开销增加。于是更新其距离向量中到达结点x的分量
D
y
(
x
)
D_y(x)
Dy(x)。注意此时此刻
D
z
(
x
)
D_z(x)
Dz(x)并没有更新。因此更新方式如下:
D y ( x ) = m i n { c ( y , x ) + D x ( x ) , c ( y , z ) + D z ( x ) } = 6 D_y(x) = min\{c(y,x) + D_x(x),c(y,z) + D_z(x)\} = 6 Dy(x)=min{c(y,x)+Dx(x),c(y,z)+Dz(x)}=6
,更新后y为了抵达x选择通过z进行路由。显然从网络的全局来看这个更新是十分错误的。这是由于就此时此刻也就是 t 0 t_0 t0而言y仅有 D z ( x ) D_z(x) Dz(x)的原始信息,以及到x的直接开销从4增加到了60;y还期望通过z来抵达最终目的x; - 此时时刻到达了
t
1
t_1
t1,遇到了路由选择黑洞:
- 为了到达x,y选择从z进行路由
- 为了到达x,z又选择从y进行路由
- 分组在这两个结点间不停的来回往复
- 到达时刻 t 1 t_1 t1,由于 y y y的距离向量 D y \mathbf{D}_y Dy发生了变化,将该新的距离向量通知结点 z z z
- 在 t 1 t_1 t1后的某个事件,z又收到y的新的距离向量,距离向量中的一个分量有 D y ( x ) = 6 D_y(x) = 6 Dy(x)=6发生了变化,因此z需要重新计算自身的距离向量,计算出到结点 x x x的全新的开销即z的距离向量的一个分量 D z ( x ) = m i n { D y ( x ) + c ( z , y ) , D x ( x ) + c ( z , x ) } = 7 D_z(x) = min\{D_y(x) + c(z,y),D_x(x) + c(z,x)\} = 7 Dz(x)=min{Dy(x)+c(z,y),Dx(x)+c(z,x)}=7算完以后,由于z自身的距离向量发生变化,有需要通知结点y自身的距离向量发生了变化,即发送自身的距离向量给结点y
- 当结点y收到结点z的距离向量之后
- y重新计算自身的距离向量,到x的分量改变为 D y ( x ) = 8 D_y(x) = 8 Dy(x)=8
- y决定以 D y ( x ) = 8 D_y(x) = 8 Dy(x)=8发送自身的距离向量 D y \mathbf{D}_y Dy
- 当结点z收到结点y的距离向量之后
- z重新计算自身的距离向量,到x的分量改变为 D z ( x ) = 9 D_z(x) = 9 Dz(x)=9
- z决定以 D z ( x ) = 9 D_z(x) = 9 Dz(x)=9发送自身的距离向量 D z \mathbf{D}_z Dz
- 以上两步不断循环,那么应该是循环多少次后收敛?
- 考虑当以上过程执行到 D y ( x ) = 49 D_y(x) = 49 Dy(x)=49时,结点y向结点z发送它自身的距离向量
- D z ( x ) D_z(x) Dz(x)以上述计算方式,计算结果为50。则z可以直接从(z,x)进行路由,而不是经过y进行路由。z再向y进行发送
- y更新到x的距离向量后,向z发送,z不再进行更新。
- 因此迭代一共44次。(在z和y之间交换报文)
- 无穷计数问题:考虑上图中 c ( y , x ) c(y,x) c(y,x)变为10000且 c ( z , x ) c(z,x) c(z,x)变为9999;
poisoned reverse(善意的谎言)
在上图中:
- 如果z通过y路由选择目的地x,则z将通告y它到x的距离时无穷大。也就是z发送给y的距离向量中有 D z ( x ) = ∞ D_z(x) = \infty Dz(x)=∞
- 但是z实际保存自身的距离向量中有自己的 D z ( x ) = 5 D_z(x) = 5 Dz(x)=5,z传播了一个善意的谎言
如何解决上述问题:
链路开销还没有变化之前,由于z通过路由器y路由给x,因此y的距离表指示
D
z
(
x
)
=
∞
D_z(x) = \infty
Dz(x)=∞。
- t 0 t_0 t0时刻当链路开销变化时,y更新其表中的 D y ( x ) D_y(x) Dy(x)分量,更新方式如下: D y ( x ) = m i n { D z ( x ) + c ( z , y ) , D x ( x ) + c ( x , y ) } = 60 D_y(x) = min\{D_z(x) + c(z,y),D_x(x) + c(x,y)\} = 60 Dy(x)=min{Dz(x)+c(z,y),Dx(x)+c(x,y)}=60即y仍然选择直接将数据路由给x,而不是经过y再路由。
- t 1 t_1 t1时刻z收到 D y \mathbf{D}_y Dy的更新。需要更新自己的距离向量 D z ( x ) = m i n { D x ( x ) + c ( z , x ) , D y ( x ) + c ( z , y ) } = 50 D_z(x) = min\{D_x(x)+c(z,x),D_y(x)+c(z,y)\} = 50 Dz(x)=min{Dx(x)+c(z,x),Dy(x)+c(z,y)}=50即此时z并未选择经过y然后再到达x而是直接选择走直接抵达x的路径。
- t 2 t_2 t2时刻z通知 y y y自身的距离向量发生了改变,由于此时z到达结点x并不经过结点y的路由,因此通知结点y自身的 D z ( x ) = 50 D_z(x) = 50 Dz(x)=50.
- 结点y在收到结点z的更新后,y以如下方式更新自身距离向量中的 D y ( x ) D_y(x) Dy(x)分量: D y ( x ) = m i n { D z ( x ) + c ( y , z ) , D x ( x ) + c ( x , y ) } = 51 D_y(x) = min\{D_z(x) + c(y,z),D_x(x) + c(x,y)\} = 51 Dy(x)=min{Dz(x)+c(y,z),Dx(x)+c(x,y)}=51显然此时y选择通过z进行路由。在y更新了自己的距离向量后,又再次需要通知结点z自身的距离向量发生了变化,但此时由于结点 y y y到达x的路由又需要经过结点z,因此又编造了一个善意的谎言 D y ( x ) = ∞ D_y(x) = \infty Dy(x)=∞发送给z。
- 然后
D
z
(
x
)
D_z(x)
Dz(x)不会发生变化了。
note:未必能消除所有无穷计数问题。考虑3个或更多结点的环路。
maximum metric(定义最大路径度量值)
定义一个最大的有效费用值,如15跳步,16跳步表示∞(不可到达)
R1检测到左边的子网192.168.1.0/24断开不能到达了。
-
如图所示,在 t 0 t_0 t0时刻,R2到达左侧子网的距离为2跳,且事先已经被算出
-
由于R1已经和左边的网络断开了,由距离向量路由算法R1更新其距离向量中到达左边子网的分量为:2 + 1=3;其中2为路由器R2的距离向量值(之前交换过来的)。1为R1到R2的一跳。如图所示:
-
然后R1将自身更新后的距离向量交换给R2;R2重新计算自身的距离向量为3 + 1 =4;如图所示:
-
R2的距离向量交换给R1,R1再交还给R2。以此类推
-
如此往复,当R2的值被更新到16时,即认为这个子网已经不可达了
-
如图所示,最终R1也收到了网络不可达的信息