两台各查各的
同一个目的地,两台各选各的下一站
站的位置不同,交出去的方向就不同
(这一节多了逐跳模拟:NODES 里每个节点有接口地址和一张小路由表;next_hop 在某节点上查表,owner 找哪个节点持有某个地址,trace 从起点一跳跳走到目标,交回 (路径, 结果)。)
贯穿拓扑:
主机 192.168.10.5/24
└─ R1 192.168.10.1 | 10.0.1.1
└─ R2 10.0.1.2 | 10.0.2.1
└─ R3 10.0.2.2 | 172.16.0.1
└─ 目标 172.16.0.9/24对同一个目标,在 R1 和 R3 上各查一次下一跳;再对回程的目标 192.168.10.5 查一次:
def to_int(ip):
a, b, c, d = [int(x) for x in ip.split(".")]
return (a << 24) | (b << 16) | (c << 8) | d
def mask(prefix):
return (0xFFFFFFFF << (32 - prefix)) & 0xFFFFFFFF
def contains(cidr, ip):
net, p = cidr.split("/")
return to_int(net) & mask(int(p)) == to_int(ip) & mask(int(p))
NODES = {
"主机": (["192.168.10.5/24"], [("0.0.0.0/0", "192.168.10.1")]),
"R1": (["192.168.10.1/24", "10.0.1.1/24"], [("172.16.0.0/16", "10.0.1.2"), ("0.0.0.0/0", "10.0.1.2")]),
"R2": (["10.0.1.2/24", "10.0.2.1/24"], [("172.16.0.0/16", "10.0.2.2"), ("192.168.10.0/24", "10.0.1.1")]),
"R3": (["10.0.2.2/24", "172.16.0.1/24"], [("192.168.10.0/24", "10.0.2.1")]),
"目标": (["172.16.0.9/24"], [("0.0.0.0/0", "172.16.0.1")]),
}
def owner(nodes, ip):
for name, (addrs, _) in nodes.items():
if any(a.split("/")[0] == ip for a in addrs):
return name
return None
def next_hop(nodes, name, target):
addrs, table = nodes[name]
for a in addrs:
if contains(a, target):
return "直连"
best = None
for cidr, via in table:
if contains(cidr, target):
plen = int(cidr.split("/")[1])
if best is None or plen > best[0]:
best = (plen, via)
return best[1] if best else None
def trace(nodes, start, target, ttl=16):
path = [start]
cur = start
while ttl > 0:
hop = next_hop(nodes, cur, target)
if hop is None:
return path, "无路可走"
if hop == "直连":
dst = owner(nodes, target)
if dst is None:
return path, "同段但无人应答"
path.append(dst)
return path, "到达"
cur = owner(nodes, hop)
if cur is None:
return path, "下一跳不存在"
path.append(cur)
ttl -= 1
return path, "TTL耗尽"
print(next_hop(NODES, "R1", "172.16.0.9") + "/" + next_hop(NODES, "R3", "172.16.0.9") + "|" + next_hop(NODES, "R1", "192.168.10.5") + "/" + next_hop(NODES, "R3", "192.168.10.5"))
全部评论