Correction : TP RIP Graphes
Classe Routeur
D'après le principe utilisé dans le protocole RIP, un routeur va "explorer" la table de routage de ses voisins directs :
- si il découvre un voisin qui n'est pas dans sa table de routage, il l'y ajoute en lui donnant
Nonecomme passerelle ( le lien est direct ), et un nombre de saut de 1. - sinon ( si le voisin est déjà dans sa table de routage ), le routeur parcourt la table de routage reçue du voisin :
- si le routeur découvre une destination qui n'est pas encore dans sa propre table, il y créé une entrée pour cette destination, en lui associant comme passerelle le routeur voisin, et un nombre de saut égal à celui du voisin vers cette destination, plus 1 saut.
- si la destination existe déjà dans la table de routage du routeur, alors, si le nombre de sauts du voisin vers cette destination plus 1 saut est plus petite que celle qui est déjà stockée dans la table de routage du routeur, celui-ci met cette distance à jour.
Il faut bien entendu, vérifier que la destination n'est pas le routeur lui-même : un routeur n'apparaît pas dans sa propre table de routage !
class Routeur:
def __init__(self, nom: str):
self.nom = nom
self.table = {}
def get_nom(self)->str:
return str(self.nom)
def get_table(self)->dict:
return self.table
def maj_table(self, voisin):
nom_voisin = voisin.get_nom()
"""Voisin pas encore dans la table :
Nouvelle entrée :
voisin: ['', 1]
"""
if nom_voisin not in self.table:
self.table[nom_voisin] = ['', 1]
"""sinon, récupération de la table de routage
du routeur, et maj des distances
si nécessaire
"""
else:
table_voisin = voisin.get_table()
for destination in table_voisin:
"""pour les entrées qui ne concernent pas le routeur
lui-même
"""
if destination != self.nom:
"""Découverte d'une nouvelle destination :
Nouvelle entrée dans la table de routage :
destination: [routeur voisin, sauts depuis le voisin + 1]
Le nombre de sauts vers une destination est le 2ème élément
du tableau d'une destination dans la table de routage.
"""
if destination not in self.table:
self.table[destination] = [nom_voisin, table_voisin[destination][1]+1]
"""sinon ( la destination est déjà dans la table ),
maj de la distance si celle-ci est plus petite
que celle dans la table
"""
else:
nv_distance = table_voisin[destination][1]+1
if nv_distance < self.table[destination][1]:
self.table[destination] = [nom_voisin, nv_distance]
On remarque que c'est bien un objet Routeur que prend la méthode maj_table comme paramètre, pas seulement le nom d'un routeur...
Fonction rip
Rien de compliqué : on parcourt la liste des routeurs du réseau, et on envoie chacun de leurs voisins comme argument à leur méthode maj_table :
def rip(reseau):
for routeur in reseau: # pour chaque routeur dans le réseau
for voisin in reseau[routeur]: # pour chacun de ces voisins
routeur.maj_table(voisin) # on envoie le voisin en argument au routeur courant
Création du réseau et lancement du protocole
Bien se souvenir qu'un routeur est un objet, à stocker dans une variable pour pouvoir ensuite le réutiliser :
r1 = Routeur('R1')
r2 = Routeur('R2')
r3 = Routeur('R3')
r4 = Routeur('R4')
r5 = Routeur('R5')
r6 = Routeur('R6')
r7 = Routeur('R7')
reseau = {
r1: [r2, r3],
r2: [r1, r3, r4],
r3: [r1, r2, r5],
r4: [r2, r5, r6],
r5: [r3, r4, r6, r7],
r6: [r4, r5, r7],
r7: [r5, r6]
}
for i in range(3):
print(f"RIP n°{i+1}")
print('-----------------')
for r in reseau:
print(r.get_nom(), ':')
for dest, ligne in r.get_table().items():
print(dest, ':', ligne)
print()
print('-----------------')
print()
rip(reseau)
Les tables de routage se stabilisent très vite ( le réseau est petit...).
Simulation d'un incident
def incident(reseau, defaut):
reseau[defaut] = [] # on supprime tous les liens depuis le routeur en défaut
nom_defaut = defaut.get_nom()
for routeur in reseau: # pour chaque routeur dans le réseau
if defaut in reseau[routeur]: # si le routeur en défaut est dans la liste d'adjacence du routeur courant,
reseau[routeur].remove(defaut) # on supprime le routeur en défaut de cette liste.
for destination in routeur.table: # pour chaque destination dans la table de routage du routeur courant,
if destination == nom_defaut or routeur.table[destination][0] == nom_defaut: # si le routeur en défaut est la destination, ou si la destination passe par lui,
routeur.table[destination][1] = 16 # alors on met la distance à 16.
Après avoir simulé un incident, par exemple en désactivant R5, on observe bien la mise à jour des tables de routage, qui passent maintenant par R6.