%%
# 纲要
> 主干纲要、Hint/线索/路标
# Q&A
#### 已明确
#### 待明确
> 当下仍存有的疑惑
**❓<font color="#c0504d"> 有什么问题?</font>**
我的困惑在于,"路由转发" 这个功能,到底应该放在 "网络设备-路由器" 这一笔记中去说,还是放在这里说?
- "网络设备-路由器" 作为一个独立笔记? √
- 里面引用 "**路由转发**" 功能即可。
- 结构:
- 路由器的功能
- 两个核心功能:
- **路由转发**:转发源主机与目的主机之间传送的数据
- **路由表**:路由表字段、**路由类型**
- **路由器中的 ARP 表**
- **路由选择**:根据路由选择协议,路由器之间彼此交换路由信息,**构建维护各自的路由表**。
- 附加功能:
- NAT
- DHCP
- "路由转发" 同样作为一个独立笔记,介绍**网络层的 "转发" 功能**。
网络层,路由器的两个核心功能:
- **路由转发**
- **路由选择**
%%
# 路由转发
「**路由转发**」是**网络层(也即路由器)** 的两个核心功能之一,即 "**转发数据包**" 的功能。
每台路由器中都存储有一张 "**==路由表==**",**当路由器接收到了一个数据包**时,其根据网络包 **IP 头部**中的 "**目的 IP 地址**" 查询该 **路由表**,从而**确定将该数据包发往目的地址,需要从该路由器的哪一个接口转发出去**,实现 "**==转发==**" 过程。
![[_attachment/02-开发笔记/07-计算机网络/网络层/路由转发.assets/IMG-路由转发-71B3F6DFC31D8A97733C9D7FF14D51AB.png|578]]
<br>
## 路由转发的工作流程
路由转发过程可分为下列步骤:
1. **数据包接收**——**链路层帧解封装,拆卸 MAC 头部**
2. **查询路由表**
3. **更新 TTL**
4. **数据包封装——链路层帧封装,封装 MAC 头部(可能涉及 ARP 查询)**
> [!summary] 路由转发过程中的 "查表"
> 在路由转发过程中:
>
> - 路由器首先以 "**目的 IP 地址**" 查询 "**路由表**",明确「**用以==转发==该数据包的接口**」 以及 「**==下一跳设备==的 IP 地址**」;
> - 路由器进而以 "**下一跳设备 IP 地址**" 查询 "**ARP 表**",获取「**下一跳设备的 ==MAC 地址==**」,从而封装 MAC 头部,进行转发。
> ^gjiwo4
> [!example] 路由转发示例
> ![[_attachment/02-开发笔记/07-计算机网络/网络层/路由转发.assets/IMG-路由转发-8DC104B39DB7AE38F15E9C2774BADE99.png|826]]
<br>
### (1)数据包接收
路由器接收到数据包,进行 "**链路层帧解封装**",并根据**末尾 FCS 进行错误校验**,而后**检查 MAC 头部的==接收方 MAC 地址==**:
- 若是发给自己的,则**去除 MAC 头部,将有效载荷放入缓冲区**;
- 否则,**丢弃整个数据包**。
随后,路由器**检查 IP 数据包头部**:
- (1)检查 **IP 头部校验和**,确认是否有损坏,若存在错误则丢弃。
- (2)检查 "**源 IP 地址与目的 IP 地址**" 是否位于同一网段(来自**路由器同一端口**),若是则丢弃数据包,不进行转发。
> [!caution] 路由器只会 "跨网段" 进行转发,**不会在同一子网内进行路由**。
>
> 当路由器收到**来自同一子网的数据包**时,该数据包**本应==由源设备直接发送给目的设备==,而不应该经过路由器**。
> 因此数据包中的 "**==目的 MAC 地址==**" 并不匹配 **==路由器接口的 MAC 地址==**,故路由器会丢弃该数据包,
>
> 例如下图情况:该数据包可能是由集线器广播传来的。
>
> 
>
> ^8ss3i1
<br>
### (2)查询路由表
路由器获取数据包**IP 头部**中的 "**目标 IP 地址**",用以与 "**路由表**" 中各项条目的 "**子网掩码**" 进行**按位与**,
检查所得的 "**网络前缀**" 是否与路由条目中的 "**目的网络地址**" 相匹配——此过程中,遵循 "**==最长前缀匹配原则==**"。
- 若存在 "**==有效匹配项==**" 或 "**==默认路由==**",则进入下一步,**重新封装 MAC 头部**,从对应的路由器接口转发出数据包。
- 否则,**丢弃该数据包**,通过 **ICMP 消息**返回 "**不可达消息**"。

> [!info] **"==最长前缀匹配=="原则**:当查表存在多个匹配条目时,应选择 "**==网络前缀最长==**" 的一个条目(网络前缀越长,地址块越小,路由越具体)
>
> 
>
<br>
### (3)更新 TTL
明确匹配项后,路由器需要**更新 IP 头部中的 TTL 字段**,令其**值减 1**。
> [!info] TTL 字段表示 "Time to Live" 生存时间,包每经过一个路由器,该值就需要减 1,**减为 0 后就需要将包丢弃**。
<br>
### (4)数据包封装——重新封装 MAC 头部(可能涉及 APR 查询)
在转发出数据包之前,需要为其**重新封装 MAC 头部**,填入新的 "**==源 MAC 地址==**" 和 "**==目的 MAC 地址==**"。
- "**源 MAC 地址**" 即**该路由器将==用于转发该数据包的 "出接口" ==的 MAC 地址**。
- "**目的 MAC 地址**" 则根据**所匹配的路由表条目,有下列两种可能情况:
| | 说明 | 所需新封装的目的 MAC 地址 |
| ----------------- | ----------------------------------------------------------------------- | ----------------------------------------------- |
| **直连路由** <br><br> | 数据包所需发往的 "**目的地址**" 属于**路由器某接口所在网段** <br>("**网关/下一跳地址**" 字段为空 或 "在链路上") | **"==数据包 IP 头部中目标 IP 地址=="所对应的设备接口的 MAC 地址** |
| **非直连路由** | 数据包还需要**经过==下一跳==路由器转发** <br>("**网关/下一跳地址**" 字段非空)<br> | "**==网关/下一跳 IP 地址==**" 所对应的**下一跳路由器接口的 MAC 地址** |
**路由器需要查询其内部的 ==ARP 表==,获取上述情况中 ==IP 地址对应的设备接口的 MAC 地址==**,以此作为 "**目的 MAC 地址**"。
若 ARP 表中不存在对应条目,则**路由器需要根据 ARP 协议==广播 ARP 请求==**,从而获取应答。
完成 MAC 头部的封装后,根据匹配的路由项,从**对应路由器接口转发出数据包**。
## 路由转发示例

概述:
- HostA 要发送给 HostB,HostA 检查自身路由表发现不在同网段,于是发送给其默认网关即路由器 A 的 E0 端口。
- 路由器 A 的 E0 端口接收到后,检查自身路由表中也没有目标网段,因此发送给其默认网关,即路由器 B 的 E1 端口(即下一跳地址 10.1.1.2/8)。
- 路由器 B 的 E1 端口接收到后,检查自身路由表,目标地址的网段正好是其 E0 端口的直连网段,进而在获取 HostB 的 MAC 地址后,从 E0 端口发出,转发给 HostB。
HostA 向 HostB 发送数据包的通信过程:
- (1)**HostA 查询自身的路由表,得知 HostB 不在同网段,因此 HostA 将数据包发给默认网关——即路由器 A 的 E0 端口。**
1. **HostA 通过 ARP 广播请求获取网关路由 A 的 E0 接口的 MAC 地址**,同时存入 HostA 的 ARP 缓存表。
2. 而后,HostA在链路层**将路由器 E0 接口的 MAC 地址封装成 "目的 MAC 地址"**,而 "**源 MAC 地址**" 是 HostA 自身网卡的 MAC 地址。
- (2)路由器 A 从 E0 接口收到数据帧,去掉链路层封装后,**检查路由表**未匹配,则根据**默认路由**发送给其**默认网关**,对应**下一跳地址为`10.1.1.2/8`**(即**路由器 B 的 E1 接口**),**出接口为路由器 A 的E1 口**。
1) 若路由器 A 的 APR 缓存表中没有下一跳地址 `10.1.1.2/8` 对应的 MAC 地址,则其向 E1 接口所在的 `10.1.1.0/8` 网段发生 ARP 广播请求,**获取路由器 B 的 E1 接口的 MAC 地址**。
2) 数据在路由器 A 的 E1 口重新封装,**源 MAC 地址是路由器 A 的 E1 接口的 MAC 地址**,封装的**目标 MAC 地址则是路由器 2 的 E1 接口的 MAC 地址**。
- (3)路由器 B 的 E1 端口接收到后,检查自身路由表,**目标地址的网段正好是其 E0 端口的直连网段**,进而在**获取 HostB 的 MAC 地址后**,**从 E0 端口发出**,转发给 HostB。
- 数据包在路由器 B 的 E0 接口再次封装,源 MAC 地址是路由器 B 的 E0 接口的 MAC 地址,目标 MAC 地址是 HostB 的 MAC 地址。
<br><br><br>
# 路由表
**路由表**(Routing Table),也称 **==转发表==**(Forwarding Table)。
路由表中每一行称之 "**==路由条目==**",记录了将一个数据包**传输到特定网络**,所需经过的**下一跳地址**,以及**需要从当前路由器的哪个网络接口发出**等信息。
> [!NOTE] 电脑主机中也存在路由表
<br>
## 路由表字段说明
- **==目标地址==(Destination)**:**目的网络 IP 地址**,可以是一个**具体的主机地址**(子网掩码全 1)或**网络地址**
- **==子网掩码==(Netmask)**:即**目的网络 IP 地址**对应的**子网掩码**
- **==网关==**(**Gateway**):即 **"==下一跳地址== Next hop"**,表示**按该条路由转发**时,**网络包将被转发至的下一个 IP 地址**。
- **==接口==**(**Interface**):表示按该条路由转发时,**本设备用以发出网络包的==网络接口==(网卡)**,该值**指示了此接口的 IP 地址**。
- ==**跃点数**==(Metric):用于**衡量路由的“成本”或“优先级”** 的度量值。
- **==路由类型==**:指示该条路由条目的来源,例如**静态路由 Static**、**直连路由 Direct**、**动态路由**(RIP、OSPF、BGP 等)。
> [!NOTE] 网关/下一跳地址
>
> 网络包在传输途中的**每一次 "转发"** 都称之为**一 "跳(hop)"**,
> 因此 "**==下一跳地址==**(next hop)" 即是指**将该数据包送达目的地的途中,需要转发至的下一个路由器的 IP 地址**。
>
> 若**路由条目的网关字段为空**,说明**目的 IP 地址**就在 "**本地链路上**"(即该路由为直连路由),直接查询其 MAC 地址,发出即可。
<br>
## 路由表条目类型
路由表中存在几种条目类型:
- **==默认路由==**(Default Route):当数据包的**目的 IP 地址未能匹配其它任何路由条目**时,则按 "**默认路由**" 进行转发
- 特征:
- **目的 IP 地址** 、**子网掩码字段均为全 0**,即 `0.0.0.0/0`
- **网关**字段——为所配置的 "**==默认网关==**" 的 IP 地址。
- **==直连路由==**(Direclty Connected Routes):指向**路由器各个==接口所处网段的路由==**,表示该网段**直接连接于路由器接口**。
- 来源:由 **链路层协议发现**,当路由器接口接入一个网段,并**为该接口配置了该网段下的 IP 地址**时,路由器会自动生成直连路由。
- 特征:
- **网关**字段显示为 "**==在链路上==**" 或者**与 "==接口==" 字段 IP 相同**——表示 **"与本设备某个接口"** 位于同一物理链路上,**从该接口转发出即可**。
- **==静态路由==**(Static Routes)
- 来源:由网络管理员**手动配置的固定路由条目**,条目信息不会改变。
- **==动态路由==**(Dynamic Routes)
- 来源:通过**动态路由协议(如 RIP、OSPF、BGP 等)自动生成并更新**的路由条目。
- **==主机路由==**(Host Routes):指向**一台具体主机**的路由。
- 特征:子网掩码为 `255.255.255.255`,即网络前缀位数为 `/32`。
- **==本地路由==**(Local Routes):指向**该台路由器某一个接口的地址**,用于**确保路由器能够接收到发往其本地IP地址的数据包**
- 特征:如同主机路由,**子网掩码全 1**,而**目的 IP 地址为路由器某一接口的地址**。
- **==不可达路由==**(Unreachable Routes):用以**明确标识某个目标网络或主机不可到达**。
- 说明:
- 该条目通常表示网络中断、无法到达目标网络或出于安全或管理目的而设置的访问限制。
- 当路由器遇到这些路由条目时,通常会**向源设备返回 ICMP 不可达消息**。
> [!example] 示例:直连路由
>
> **设备自动产生直连路由的两个条件**:**接口接入一个网络**、**接口配上该网段内有效地址**。
>
> 下图中的三个网段 `10.1.1.0/24`,`10.1.2.0/24`,`10.1.3.0/24` 通过**一台路由器**直接相连,
> 因此**只需要配置好==路由器三个接口的 IP== 即可互相访问**,路由器表中将被自动添加 "**直连路由**"。
>
>
> 
>
<br>
## 路由表示例
### Windows 主机上的路由表
> [!NOTE] Windows下通过 `route print` 命令查看本机路由表

上图路由表中依次包含了:
- **默认路由**
- **环回地址相关的路由**(网段`127.0.0.0/8`,涵盖地址`127.0.0.0`~`127.255.255.255`)
- **源机的各个网络接口(网卡)所在网段的路由**
- **多播路由**(多播地址所在网段`224.0.0.0/4`,涵盖地址`224.0.0.0`~`239.255.255.255`)
- **广播路由**(`255.255.255.255`)
## 路由条目优先级
优先级值越小则路由越优。

### 路由协议开销
直连及静态路由的 Cost 为 0。
通过动态路由协议学习到的 Cost 则根据实际情况而定。不同的路由协议计算 Cost 的方法不同。
<br><br><br>
# 路由器中的 ARP 表
路由器上的 ARP 缓存表主要用于管理 **路由器与其直连设备** 之间的通信。
ARP 缓存表:存储网络接口上**直连设备**的 **IP 地址 -> MAC 地址** 的映射;
![[02-开发笔记/07-计算机网络/网络层/路由转发#^gjiwo4]]
<br><br>
# Buffer
## 闪念
> sudden idea
## 候选资料
> Read it later
# ♾️参考资料
[18张图带你详解IP路由表七大要素:路由前缀、协议类型、优先级等](https://zhuanlan.zhihu.com/p/405894469)
[网络原理-计算机网络详解-mac表、arp表、路由表](https://www.huaijiujia.com/2018/08/03/%E7%BD%91%E7%BB%9C%E5%8E%9F%E7%90%86-%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C%E8%AF%A6%E8%A7%A3-mac%E8%A1%A8%E3%80%81arp%E8%A1%A8%E3%80%81%E8%B7%AF%E7%94%B1%E8%A1%A8/)
# Footnotes