路由表与下一跳决策

假设本机 IP 是 192.168.12.170/26,现在要分别给 192.168.12.180 和 192.168.12.210 发数据。这两个目标 IP 的前三段都是 192.168.12,看起来很像“同一个网段”,但在发包时走的路完全不同。

判断目标是否在本地子网

前面算过,本机所在的子网是 192.168.12.128/26,范围从 .128 到 .191。所以 .180 在本地子网里,而 .210 已经超出了本地子网。

在操作系统内部,协议栈会把目标 IP 和本机子网掩码做按位与(AND)运算(两个二进制位都是 1 结果才为 1,否则为 0),看算出来的网络号跟本机是不是一样:

                 地址最后一组二进制      与掩码 11000000 做按位与
本机自身 .170     10101010               10000000 = 128(本机网络号)
目标地址 .180     10110100               10000000 = 128(同一子网,直接发)
目标地址 .210     11010010               11000000 = 192(不在本子网,交给网关)

网络号相同,说明目标就在同一个局域网里,直接通过本地交换机发过去就行;网络号不同,说明目标在外部网络,必须把包交给默认网关(Default Gateway)去转发。

判断本地目标

模拟实验

使用发送方的前缀,选择所有落在其本地子网内的目标。完成后再换一个前缀,观察同样的 IP 地址为什么会得到不同判断。

点击此处启动:

默认网关与路由表

默认网关通常就是本局域网里那台路由器的接口 IP(具体是哪个地址由网络配置决定,不一定是 .1)。在 Linux 终端里运行 ip route 可以看到本机的路由表:

crow@laptop:~$ ip route
default via 192.168.12.129 dev enp1s0
192.168.12.128/26 dev enp1s0 proto kernel scope link src 192.168.12.170
  • 192.168.12.128/26 dev enp1s0 ...:发往本地子网 192.168.12.128/26 的包,直接从网卡 enp1s0 往本地链路上发。
  • default via 192.168.12.129 dev enp1s0:其他所有目标(默认路由 0.0.0.0/0),统统从 enp1s0 交给下一跳网关 192.168.12.129。

最长前缀匹配

如果路由表里还多了一条更具体的路由:

192.168.20.0/24 via 192.168.12.130 dev enp1s0

这时访问 192.168.20.10,它会同时匹配默认路由 0.0.0.0/0(前缀长度 0)和 192.168.20.0/24(前缀长度 24)。查路由表遵循最长前缀匹配(Longest Prefix Match):前缀匹配的位数越长,说明写得越具体,优先级越高。所以发往 192.168.20.10 的包不会走默认网关 .129,而是优先交给 .130。

路由表里的条目通常有三种来源:网卡配好 IP 后内核自动生成的直连路由、管理员手动添加的静态路由,以及大型网络里路由器之间通过 OSPF、BGP 等动态路由协议自动交换学到的路由。每台路由器收到包后都只查自己的路由表决定“下一跳交给谁”,不需要提前知道从起点到终点的完整路径。