一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第21天,点击查看活动详情。
路由表结构
本文中我们主要学习的是如果通过路由器转发消息,首先我们先看下路由表的结构。路由表中包含的信息如下表所示。
| 目标地址(Destination) | 子网掩码(Netmask) | 网关(Gateway) | 接口(Interface) | 跃点数(Metric) |
|---|---|---|---|---|
| 10.10.1.0 | 255.255.255.0 | —— | e2 | 1 |
| 10.10.1.101 | 255.255.255.255 | —— | e2 | 1 |
| 192.168.1.0 | 255.255.255.0 | —— | e3 | 1 |
| 0.0.0.0 | 0.0.0.0 | 192.0.2.1 | e1 | 1 |
目标地址
最左侧的目标地址列记录的是接收方的信息。实际上这里的 IP 地址只包含了表示子网的网络包部分的比特值,而表示主机号部分的比特值全部为 0 (注:图中也有一些 IP 地址的主机号不是全部为 0,关于这些地址我们稍后解释)。
路由器会将接收到的网络包的接收方 IP 地址与路由表中的目标地址进行比较,并找到相应的记录。交换机在地址表中只匹配完全一直的记录,而路由器则会忽略主机号部分,只匹配网络号部分。
在匹配地址的过程中,路由器需要知道网络号的比特数,因此路由表中还有一列子网掩码。通过子网掩码可以判断出网络号的比特数。
路由器会忽略主机号,只匹配网络号。
路由聚合/拆分
刚才我们说过,目标地址列中的 IP 地址表示的是子网。但是也有一些例外,有时地址本身的子网掩码和路由表中的子网掩码是不一致的,这是 路由聚合 的结果。路由聚合会将几个子网合并成一个子网,并在路由表中只产生一条记录。
下面我们通过一个例子来详细介绍下。
假设现在有三个子网,分别是 10.10.1.0/24,10.10.2.0/24、10.10.3.0/24,路由器 A 需要将包发往这 3 个子网。在这种情况下,路由器 A 中原本有对应这 3 个子网的 3 条记录,但是我们把这三个子网聚合成一个子网为 10.10.0.0/16,这样也能够正确地进行转发,但我们减少了路由表中的记录数量,这就是路由聚合。经过路由聚合,多个子网会被合并成一个子网,子网掩码会发生变化,同时,目标地址列也会改成聚合后的地址。
相对地,还有另外一些情况,如将一个子网进行细分并注册在路由表中,然后拆分成多条记录。
此外,通过上述方法,我们也可以将某台计算机的地址写入路由表中,这时的子网掩码为 255.255.255.255,也就是说地址中的全部 32 个比特都为 1。这样一来,主机号部分比特全部为 0 可以表示一个子网,主机号部分比特不全部为 0 可以表示某一台计算机,两种情况可以用相同的规则来处理。
网关和接口
接下来在子网掩码的右边还有网关和接口两列,它们表示 网络包的转发目标。根据目标地址和子网掩码匹配到某条记录后,路由器就会将网络包交给接口列中指定的网络接口(即端口),并转发到网关列中指定的 IP 地址。
跃点数
最后一列是跃点计数,它表示距离目标 IP 地址的距离是远还是近。这个数字越小,表示距离目的地越近,数字越大,表示距离目的地越远。
路由表维护
路由表记录维护的方式和交换机也有所不同。交换机中对 MAC 地址表的维护是包转发操作中的一个步骤,而路由器中对路由表的维护是与包转发操作相互独立的,也就是说,在转发包的过程中不需要对路由表的内容进行维护。
对路由表进行维护的方法有几种,大体上可分为以下两类:
- 由人手动维护路由记录
- 根据路由协议机制,通过路由器之间的信息交换由路由器自行维护路由表的记录
路由器工作过程
包接收
下面我们再来简单描述下路由器的整个工作过程。首先路由器会接收网络包,以以太网端口接收包为例,以太网端口的结构和计算机的网卡基本相同。
首先,信号到达网线接口部分,其中的 PHY(MAU)模块和 MAC 模块将信号转换为数字信息,然后通过包末尾的 FCS 进行错误校验,如果没问题则检查 MAC 头部中的接收方 MAC 地址,看看是不是发给自己的包,如果是就放到接收缓冲区中,否则就丢弃这个包。如果包的接收方 MAC 地址不是自己,说明这个包是发给其他设备的,如果接收这个包就违反了以太网的规则。
总结一下就是:路由器的端口都具有 MAC 地址,只接收与自身地址匹配的包,遇到不匹配的包则直接丢弃。
查询路由表确定输出端口
完成包接收操作之后,路由器就会丢弃包开头的 MAC 头部。MAC 头部的作用就是将包送达路由器,其中的接收方 MAC 地址就是路由器的 MAC 地址。因此,当包到达路由器之后,MAC 头部的任务就完成了,于是 MAC 地址就会被丢弃。
通过路由器转发的网络包,其接收方 MAC 地址为路由器端口的 MAC 地址。
接下来,路由器会根据 MAC 头部后方的 IP 头部中的内容进行包的转发操作。
转发操作分为几个阶段,首先是查询路由表判断转发目标,即匹配相应的 IP 地址。这个匹配并不是匹配全部 32 个比特,而是根据子网掩码列中的值判断网络号的比特数,并匹配相应数量的比特。
按照这样的规则,我们可能会匹配到多条候选记录。其中,路由器首选寻找网络号比特数最长的一条记录(最长匹配原则)网络号比特数越长,说明主机号比特数越短,也就意外着该子网内可分配的主机数量越少,即子网中可能存在的主机数量越少。这一规则的目的是尽量缩小范围,所以根据这条记录判断的转发目标就会更加准确。
相比服务器所属的子网来说,直接指定服务器本身的地址时范围更小。按照最长匹配原则筛选后,如果只剩一条候选记录,则按照这条记录的内容进行转发。
然后,有时候路由表中会存在网络号长度相同的多条记录,例如考虑到路由器或网线的故障而设置的备用路由就属于这种情况。这时,需要根据跃点计数的值来进行判断。跃点计数越少说明该路由越近,因此应选择跃点计数较小的记录。
如果在路由器中无法找到匹配的记录,路由器会丢弃这个包,并他通过 ICMP 消息告知发送方。但是这里的处理方式和交换机不同,原因在于网络规模的大小。
交换机链接的网络最多也就是几千台设备的规模,这个规模并不大。如果是有几千台设备,遇到不知道应该转发到哪里的包,交换机可以将包发送到所有的端口上,虽然这个方法很简单粗暴,但不会引发什么问题。然而,路由器工作的网络环境就是互联网,它的规模是远远大于以太网的,全世界所有的设备都连接在互联网上,而且规模还在持续扩大。在如此庞大的网络中,如果将不知道应该转发到哪里的包发送到整个网络上,那就回产生大量的网络包,造成网络拥塞。因此,路由器遇到不知道该转发到哪里的包,就会直接丢弃。
找不到匹配路由时选择默认路由
那么当我们在路由表中找不到匹配路由怎么办呢?不必担心,路由表中有一行子网掩码为 0.0.0.0 的默认目标地址。
当匹配不到其他路由时,网络包就会被转发到互联网接入路由器。因此这条记录被称为 默认路由,这一行配置的网关地址被称为 默认网关。在计算机的 TCP/IP 设置窗口中也有一个填写默认网关的框,意思是一样的。计算机上也有一张和路由器一样的路由表,其中默认网关的地址就是我们在设置窗口中填写的地址。
这样一来,无论目标地址是表示一个子网还是表示某台设备,都可以用相同的方法查找出转发目标,而且也避免了不知道转发到哪里的问题。
设置包过期时间
从路由表中查找到转发目标之后,网络包就会被转交给输出端口,并最终发送出去。但在此之前,还有一些工作需要完成。第一个工作就是更新 IP 头部的 TTL(Time to Live,生存时间)字段。
TTL 字段表示包的有效期,包每经过一个路由器的转发,这个值就会减 1,当这个值变成 0 时,就表示超过了有效期,这个包就会被丢弃。
这个机制是为了防止包在一个地方陷入死循环。
发送方在发送包时会将 TTL 设为 64 或 128。
通过分片功能拆分大网络包
网络包在发送前要做的另外一个工作是 拆分大网络包。
路由器的端口并不只有以太网一种,也可以支持其他局域网或专线通信技术。不同的线路和局域网类型各自能传输的最大包长度也不同,因此输出端口的最大包长度可能会小于输入端口。即便两个端口的最大包长度相同,也可能会因为添加了一些头部数据而导致包的实际长度发生变化,ADSL、FTTH 等宽带接入技术中使用的 PPPoE 协议就属于这种情况。无论哪种情况,一旦转发的包长度超过了输出端口能传输的最大长度,就无法直接发送这个包了。
遇到这种情况,可以使用 IP 协议中定义的分片功能对包进行拆分,缩短每个包的长度。
数据发送
到这里,发送前的准备工作就完成了,接下来就会进入包发送出去。
网络包准备完成后,接下来会将其转换成电信号并通过端口发送出去。
然后经过层层转发,最后到达目的地。
参考文档
- 《网络是怎样连接的》—— 户根勤
往期文章
- 网络是怎样连接的(一)—— 浏览器访问 Web 服务器过程概览
- 网络是怎样连接的(二)—— 浏览器生成 HTTP 消息
- 网络是怎样连接的(三)—— 通过 DNS 服务器查询 IP 地址
- 网络是怎样连接的(四)—— DNS 服务器工作介绍
- 网络是怎样连接的(五)—— 委托操作系统进行收发消息过程概览
- 网络是怎样连接的(六)—— 协议栈内部探索步骤
- 网络是怎样连接的(七)—— 协议栈的内部结构
- 网络是怎样连接的(八)—— 探索套接字
- 网络是怎样连接的(九)—— 连接连的到底是啥
- 网络是怎样连接的(十)—— 连接操作的实际过程
- 网络是怎样连接的(十一)—— 协议栈发送数据特性
- 网络是怎样连接的(十二)—— 数据收发操作中重要标志位 ACK
- 网络是怎样连接的(十三)—— 从服务器断开并删除套接字
- 网络是怎样连接的(十四)—— 网络包传输概览(IP 模块视角)
- 网络是怎样连接的(十五)—— 网络包传输概览(IP 模块视角)
- 网络是怎样连接的(十六)—— 生成包含接收方 IP 地址的 IP 头部
- 网络是怎样连接的(十七)—— 生成以太网用的 MAC 头部
- 网络是怎样连接的(十八)—— 将服务器的响应包从 IP 传递给 TCP
- 网络是怎样连接的(十九)—— UDP协议的收发操作
- 网络是怎样连接的(二十)—— 信号在网线和集线器中传输
- 网络是怎样连接的(二十一)—— 交换机工作模式
- 网络是怎样连接的(二十二)—— 路由器的结构和基本原理