OSFP原理:a.每台路由器学习激活的直接相连的网络。
b.每台路由器和直接相连的路由器互交,发送Hello报文,建立邻居关系。
c.每台路由器构建包含直接相连的链路状态的LSA(Link-State Advertisement,链路状态通告)。链路状态通告(LSA)中记录了所有相关的路由器,包括邻路由器的标识、链路类型、带宽等。
d.每台路由器泛洪链路状态通告(LSA)给所有的邻路由器,并且自己也在本地储存邻路由发过来的LSA,然后再将收到的LSA泛洪给自己的所有邻居,直到在同一区域中的所有路由器收到了所有的LSA。每台路由器在本地数据库中保存所有收到的LSA副本,这个数据库被称作”链路状态数据库(LSDB,Link-State Database)”
e.每台路由器基于本地的”链路状态数据库(LSDB)”执行”最短路径优先(SPF)”算法,并以本路由器为根,生成一个SPF树,基于这个SPF树计算去往每个网络的最短路径,也就得到了最终的路由表。
代码:
def dijkstra(packets, node_route): # Dijkstra算法
table = [] # 节点node_route的路由表
for key in packets[node_route]: # 初始化table
if packets[node_route][key] != float('Inf'):
row = [key, packets[node_route][key], key, False]
else:
row = [key, packets[node_route][key], '无', False]
table.append(row)
count = 0
while count < len(table):
temp = 0 # temp用于保存当前table中距离最小的下标
min = float('Inf') # min用于记录当前的距离最小值
for i in range(len(table)):
if table[i][3] == False and table[i][1] < min:
min = table[i][1]
temp = i
table[temp][3] = True # 把temp对应的节点加入到已经找到的最短路径的集合中
count = count + 1
for i in range(len(table)):
if (table[i][3] == False and packets[table[temp][0]][table[i][0]] != float('Inf') and (
table[temp][1] + packets[table[temp][0]][table[i][0]] < table[i][1])):
# 如果新得到的边可能影响其它未访问的节点,那就更新它的最短距离和下一跳路由器
table[i][1] = table[temp][1] + packets[table[temp][0]][table[i][0]]
table[i][2] = table[temp][2]
table.sort(key=lambda x: x[0])
return table
def main():
packets = {} # 所有的链路状态分组
nodes = [] # 所有的节点
node = input('请输入节点,以#结束:')
while node != '#':
if node not in nodes:
nodes.append(node)
else:
print('节点%s的链路状态分组已存在!' % node)
node = input('请输入节点,以#结束:')
continue
per = {}
row = input('请输入节点%s的链路状态分组(相邻路由器,度量),以空格隔开,以*结束:' % node)
while row != '*':
row = row.split() # 以空格分割输入的字符串
row = [int(x) if x.isdigit() == True else x for x in row] # 把度量置为整型
if row[1] <= 0: # 检查输入是否合理
print('输入违规!')
row = input('请输入节点%s的链路状态分组(相邻路由器,度量),以空格隔开,以*结束:' % node)
continue
if (row[0] in per): # 避免重复
print('节点%s的链路状态分组中已有此项!' % node)
row = input('请输入节点%s的链路状态分组(相邻路由器,度量),以空格隔开,以*结束:' % node)
continue
per[row[0]] = row[1] # 向节点node的链路状态分组中添加表项
row = input('请输入节点%s的链路状态分组(相邻路由器,度量),以空格隔开,以*结束:' % node)
packets[node] = per # 向所有的链路状态分组中添加节点node的链路状态分组
node = input('请输入节点,以#结束:')
# 将与每一节点未直接相邻的节点的度量置为无穷大(自身除外)
for key in packets:
for i in nodes:
if (i != key and (i not in packets[key].keys())):
packets[key][i] = float('Inf')
while True:
node_route = input('请输入你想查看路由表的节点:')
table = dijkstra(packets, node_route)
print('节点%s的路由表如下:' % node_route)
print('目的网络 距离 下一跳路由器')
for row in table:
print(' ' + row[0] + ' ' + str(row[1]) + ' ' + row[2])
if __name__ == '__main__':
main()