交换结构
交换结构是路由器的核心功能,通过交换功能把分组从输入端口转发至输出端口,这就是交换结构的主要功能。交换结构有多种形式,主要分为 通过内存交换、通过总线交换、通过互联网络进行交换,下面我们分开来探讨一下。
- 经过内存交换:最开始的传统计算机就是使用
内存交换
的,在输入端口和输出端口之间是通过 CPU 进行的。输入端口和输出端口的功能就好像传统操作系统中的 I/O 设备一样。当一个分组到达输入端口时,这个端口会首先以中断
的方式向路由选择器发出信号,将分组从输入端口拷贝到内存中。然后,路由选择处理器从分组首部中提取目标地址,在转发表中找出适当的输出端口进行转发,同时将分组复制到输出端口的缓存中。
这里需要注意一点,如果内存带宽以每秒读取或者写入 B 个数据包,那么总的交换机吞吐量(数据包从输入端口到输出端口的总速率) 必须小于 B/2。
- 经过总线交换:在这种处理方式中,总线经由输入端口直接将分组传送到输出端口,中间不需要路由选择器的干预。总线的工作流程如下:输入端口给分组分配一个
标签
,然后分组经由总线发送给所有的输出端口,每个输出端口都会判断标签中的端口和自己的是否匹配,如果匹配的话,那么这个输出端口就会把标签拆掉,这个标签只用于交换机内部跨越总线。如果同时有多个
分组到达路由器的话,那么只有一个分组能够被处理,其他分组需要再进入交换结构前等待。
- 经过互联网络交换:克服单一、共享式总线带宽限制的一种方法是使用一个更复杂的互联网络。如下图所示
每条垂直的的总线在交叉点与每条水平的总线交叉,交叉点通过交换结构控制器能够在任何时候开启和闭合。当分组到达输入端口 A 时,如果需要转发到端口 X,交换机控制器会闭合 A 到 X 交叉部分的交叉点,然后端口 A 在总线上进行分组转发。这种网络互联式的交换结构是 非阻塞的(non-blocking)
的,也就是说 A -> X 的交叉点闭合不会影响 B -> Y 的链路。如果来自两个不同输入端口的两个分组其目的地为相同的输出端口的话,这种情况下只能有一个分组被交换,另外一个分组必须进行等待。
输出端口处理
如下图所示,输出端口处理取出已经存放在输出端口内存中的分组并将其发送到输出链路上。包括选择和去除排队的分组进行传输,执行所需的链路层和物理层的功能。
在输入端口中有等待进入交换的排队队列,而在输出端口中有等待转发的排队队列,排队的位置和程度取决于流量负载、交换结构的相对频率和线路速率。
随着队列的不断增加,会导致路由器的缓存空间被耗尽,进而使没有内存可以存储溢出的队列,致使分组出现丢包(packet loss)
,这就是我们说的在网络中丢包或者被路由器丢弃。
何时出现排队
下面我们通过输入端口的排队队列和输出端口的排队队列来介绍一下可能出现的排队情况。
输入队列
如果交换结构的处理速度没有输入队列到达的速度快,在这种情况下,输入端口将会出现排队情况,到达交换结构前的分组会加入输入端口队列中,以等待通过交换结构传送到输出端口。
为了描述清楚输入队列,我们假设以下情况:
- 使用网络互联的交换方式;
- 假定所有链路的速度相同;
- 在链路中一个分组由输入端口交换到输出端口所花的时间相同,从任意一个输入端口传送到给定的输出端口;
- 分组按照 FCFS 的方式,只要输出端口不同,就可以进行并行传送。但是如果位于任意两个输入端口中的分组是发往同一个目的地的,那么其中的一个分组将被阻塞,而且必须在输入队列中等待,因为交换结构一次只能传输一个到指定端口。
如下图所示
在 A 队列中,输入队列中的两个分组会发送至同一个目的地 X,假设在交换结构正要发送 A 中的分组,在这个时候,C 队列中也有一个分组发送至 X,在这种情况下,C 中发送至 X 的分组将会等待,不仅如此,C 队列中发送至 Y 输出端口的分组也会等待,即时 Y 中没有出现竞争的情况。这种现象叫做 线路前部阻塞(Head-Of-The-Line, HOL)
。
输出队列
我们下面讨论输出队列中出现等待的情况。假设交换速率要比输入/输出的传输速率快很多,而且有 N 个输入分组的目的地是转发至相同的输出端口。在这种情况下,在向输出链路发送分组的过程中,将会有 N 个新分组到达传输端口。因为输出端口在一个单位时间内只能传输一个分组,那么这 N 个分组将会等待。然而在等待 N 个分组被处理的过程中,同时又有 N 个分组到达,所以 ,分组队列能够在输出端口形成。这种情况下最终会因为分组数量变的足够大,从而耗尽
输出端口的可用内存。
如果没有足够的内存来缓存分组的话,就必须考虑其他的方式,主要有两种:一种是丢失分组,采用 弃尾(drop-tail)
的方法;一种是删除一个或多个已经排队的分组,从而来为新的分组腾出空间。
网络层的策略对 TCP 拥塞控制影响很大的就是路由器的分组丢弃策略。在最简单的情况下,路由器的队列通常都是按照 FCFS 的规则处理到来的分组。由于队列长度总是有限的,因此当队列已经满了的时候,以后再到达的所有分组(如果能够继续排队,这些分组都将排在队列的尾部)将都被丢弃。这就叫做尾部丢弃策略。
通常情况下,在缓冲填满之前将其丢弃是更好的策略。
如上图所示,A B C 每个输入端口都到达了一个分组,而且这个分组都是发往 X 的,同一时间只能处理一个分组,然后这时,又有两个分组分别由 A B 发往 X,所以此时有 4 个分组在 X 中进行等待。
等上一个分组被转发完成后,输出端口就会选择在剩下的分组中根据 分组调度(packet scheduleer)
选择一个分组来进行传输,我们下面就会聊到分组传输。
分组调度
现在我们来讨论一下分组调度次序的问题,即排队的分组如何经输出链路传输的问题。我们生活中有无数排队的例子,但是我们生活中一般的排队算法都是 先来先服务(FCFS)
,也是先进先出(FIFO)
。
先进先出
先进先出就映射为数据结构中的队列
,只不过它现在是链路调度规则的排队模型。
FIFO 调度规则按照分组到达输出链路队列的相同次序来选择分组,先到达队列的分组将先会被转发。在这种抽象模型中,如果队列已满,那么弃尾的分组将是队列末尾的后面一个。
优先级排队
优先级排队是先进先出排队的改良版本,到达输出链路的分组被分类放入输出队列中的优先权类,如下图所示
通常情况下,每个优先级不同的分组有自己的优先级类,每个优先级类有自己的队列,分组传输会首先从优先级高的队列中进行,在同一类优先级的分组之间的选择通常是以 FIFO 的方式完成。
循环加权公平排队
在循环加权公平规则(round robin queuing discipline)
下,分组像使用优先级那样被分类。然而,在类之间却不存在严格的服务优先权。循环调度器在这些类之间循环轮流提供服务。如下图所示
在循环加权公平排队中,类 1 的分组被传输,接着是类 2 的分组,最后是类 3 的分组,这算是一个循环,然后接下来又重新开始,又从 1 -> 2 -> 3 这个顺序进行轮询。每个队列也是一个先入先出的队列。
这是一种所谓的保持工作排队(work-conserving queuing)
的规则,就是说如果轮询的过程中发现有空队列,输出端口不会等待分组,而是继续轮询下面的队列。
IP 协议
路由器对分组进行转发后,就会把数据包传到网络上,数据包最终是要传递到客户端或者服务器上的,那么数据包怎么知道要发往哪里呢?起到关键作用的就是 IP 协议。
IP 主要分为三个部分,分别是 IP 寻址、路由和分包组包。下面我们主要围绕这三点进行阐述。
IP 地址
既然一个数据包要在网络上传输,那么肯定需要知道这个数据包到底发往哪里,也就是说需要一个目标地址信息,IP 地址就是连接网络中的所有主机进行通信的目标地址,因此,在网络上的每个主机都需要有自己的 IP 地址。
在 IP 数据报发送的链路中,有可能链路非常长,比如说由中国发往美国的一个数据报,由于网络抖动等一些意外因素可能会导致数据报丢失,这时我们在这条链路中会放入一些 中转站
,一方面能够确保数据报是否丢失,另一方面能够控制数据报的转发,这个中转站就是我们前面聊过的路由器,这个转发过程就是 路由控制
。
路由控制(Routing)
是指将分组数据发送到最终目标地址的功能,即使网络复杂多变,也能够通过路由控制到达目标地址。因此,一个数据报能否到达目标主机,关键就在于路由器的控制。
这里有一个名词,就是 跳
,因为在一条链路中可能会布满很多路由器,路由器和路由器之间的数据报传送就是跳,比如你和隔壁老王通信,中间就可能会经过路由器 A-> 路由器 B -> 路由器 C 。
那么一跳的范围有多大呢?
一跳是指从源 MAC 地址到目标 MAC 地址之间传输帧的区间,这里引出一个新的名词,MAC 地址是啥?
MAC 地址指的就是计算机的物理地址(Physical Address)
,它是用来确认网络设备位置的地址。在 OSI 网络模型中,网络层负责 IP 地址的定位,而数据链路层负责 MAC 地址的定位。MAC 地址用于在网络中唯一标示一个网卡,一台设备若有一或多个网卡,则每个网卡都需要并会有一个唯一的 MAC 地址,也就是说 MAC 地址和网卡是紧密联系在一起的。
路由器的每一跳都需要询问当前中转的路由器,下一跳应该跳到哪里,从而跳转到目标地址。而不是数据报刚开始发送后,网络中所有的通路都会显示出来,这种多次跳转也叫做多跳路由
。
IP 地址定义
现如今有两个版本的 IP 地址,IPv4 和 IPv6,我们首先探讨一下现如今还在广泛使用的 IPv4 地址,后面再考虑 IPv6 。
IPv4 由 32 位正整数来表示,在计算机内部会转化为二进制来处理,但是二进制不符合人类阅读的习惯,所以我们根据易读性
的原则把 32 位的 IP 地址以 8 位为一组,分成四组,每组之间以 .
进行分割,再将每组转换为十进制数。如下图所示
那么上面这个 32 位的 IP 地址就会被转换为十进制的 156.197.1.1。
除此之外,从图中我们还可以得到如下信息
每个这样 8 位位一组的数字,自然是非负数,其取值范围是 [0,255]。
IP 地址的总个数有 2^32 次幂个,这个数值算下来是 4294967296
,大概能允许 43 亿台设备连接到网络。实际上真的如此吗?
实际上 IP 不会以主机的个数来配置的,而是根据设备上的 网卡(NIC)
进行配置,每一块网卡都会设置一个或者多个 IP 地址,而且通常一台路由器会有至少两块网卡,所以可以设置两个以上的 IP 地址,所以主机的数量远远达不到 43 亿。