Projet de fin d'année Logiciel
< Cahier des charges < > Mise en oeuvre > |
Nous disposions au début du projet des sources et du rapport de programmation du groupe ayant travaillé l'an dernier sur ce sujet. La première étape a été la familiarisation avec ce code.
Le code source initial était réparti dans deux répertoires, un par application:
treeb
: collecte des informations relatives aux équipements du
réseau à l'aide du protocole SNMP, stockage de ces informations dans une
base de données, construction de l'arbre de la topologie qui est lui-même
stocké dans la base de données.
psnmp
: application graphique de présentation de la topologie
(qui est lue dans la base de données), et d'interrogation dynamique
(affichage des débits par exemple).
Nous allons donc décrire ici l'analyse réalisée sur ce code et les conséquences que nous en avons tirées et qui ont influencées le travail réalisé.
Une des premières choses que l'on a remarquée est la duplication de plusieurs fichiers entre les deux répertoires. Malgré une partie commune relativement importante (mais pas toujours parfaitement identique), des fonctions avaient été ajoutées dans une des versions et pas dans l'autre. Visiblement, le manque de temps et de communication dans le groupe ayant travaillé sur ce projet l'année dernière est la cause de ce problème de structuration.
Afin de comprendre l'organisation des modules qui n'était pas documentée, nous avons utilisé l'outil cxref pour construire le graphe des appels entre les différentes fonctions. Ainsi, pour chaque fonction, on sait d'une part quelles fonctions elle appelle, et d'autre part quelles fonctions l'appellent. Le rapport de cxref nous a beaucoup aidé dans l'analyse des dépendances. Une des conclusions de ce travail a été la mise en évidence de très nombreuses dépendances croisées: il n'y a pas d'organisation en couche.
Pour chaque requête SNMP, il y a un certain nombre d'opérations à faire autour de la requête elle-même si bien que le code nécessaire à une simple interrogation fait une trentaine de lignes. Les requêtes sont assez nombreuses et quasiment toutes du même type mais plutôt que de factoriser le code commun, celui-ci a été copié/collé un grand nombre de fois. Ceci pose plusieurs problèmes. Tout d'abord les fonctions perdent énormément en lisibilité. Par exemple, une simple fonction du type ``récupérer A; si A vérifie un test, récupérer B sinon récupérer C'' prend quasiment cent lignes. D'autre part, les améliorations effectuées sur une interrogation au niveau du code commun ne profitent pas aux autres. Ainsi la maintenabilité est réduite.
Il y avait un problème semblable au niveau des requêtes MySQL bien que le code autour de chaque requête soit moins volumineux que celui des interrogations SNMP.
La qualité de la programmation était plutôt médiocre.
malloc()
n'étaient quasiment jamais
testées.
/opt/jumble
).
.h
) se faisaient manifestement sans réflexion
mais avec des méthodes du type ``ça marche pas, on en ajoute jusqu'à ce
que ça compile''.
Quant à la partie du code correspondant à l'interface graphique en GTK,
elle avait été à l'origine développée avec un générateur de code visuel
(Glade) puis retouchée à la main. Le code que génère Glade est très
difficile à maintenir pour plusieurs raisons. Tout d'abord, les noms des
différents composants graphiques (fenêtres, boutons, etc.) ne sont
pas du tout explicites (Windows3
, Button34
, etc.).
D'autre part, le code n'est pas divisé de manière logique: tout est groupé
dans deux fichiers.
Le code initial que nous avons repris était très peu maintenable à cause de ses problèmes de structuration. Même si on peut être tenté de repartir de zéro devant un tel projet, nous avons choisi de ne pas le faire pour les raisons suivantes:
Nous avons donc choisi de restructurer le code par étape en s'assurant de la non regression de l'application à chaque étape.
Le premier travail a été la fusion des fichiers communs entre les deux
parties (treeb
et psnmp
,
cf , page ).
Ensuite nous avons décidé de mettre en place des scripts pour faciliter la
compilation du logiciel à l'aide des outils classiques GNU
autoconf
et automake
.
Lors de notre analyse du code, nous avons constaté que l'algorithme de construction de la topologie était assez obscur et quasiment pas documenté. Nous avons donc décidé de l'étudier précisément afin d'en comprendre le fonctionnement. Ceci était d'autant plus nécessaire que nous avions à le modifier pour qu'il prenne en charge les réseaux virtuels. Le résultat de l'analyse de l'algorithme est présenté à l'annexe , page .
Nous avons également effectué des recherches sur des algorithmes de ce type. Et nous avons trouvé un document de qualité qui s'intéressait précisément à la découverte des topologies de réseaux Ethernet: [18]. L'intérêt de ce document est qu'il présente le problème d'une manière formelle, en cherchant à le résoudre mathématiquement (avec des théorèmes démontrés). De plus, il cherche à trouver un algorithme fonctionnant le mieux possible même lorsque l'information est partielle. Ceci est très important dans le cadre de notre projet, car nous n'avons aucune garantie de disposer d'une information complète (voir , page ). On notera qu'il existe très peu d'informations à ce sujet; la plupart des gens ayant travaillé sur des systèmes de découverte de topologie de réseaux se sont intéressés au cas des réseaux IP (découverte des routeurs), pour lesquels le problème est complètement différent.
Ayant alors deux algorithmes, celui du code repris d'une part - implémenté et fonctionnant a priori - et d'autre part celui de [18] - prouvé, nous avons analysé l'un par rapport à l'autre avec pour objectif l'amélioration de la solution implémentée dont on dispose.
Ici, nous considérons qu'un réseau logique correspond à un VLAN. Une entité logique est donc un equipement réseau, plus particulièrement l'ensemble de ses interfaces qui appartiennent à un VLAN donné. Un même équipement réseau peut donc être scindé en sous ensembles d'interfaces suivant les VLANs sur lesquels elles sont configurées.
De plus, si sur un réseau Ethernet classique nous avons la garantie qu'il n'y a pas de boucle, cela n'est plus vrai lorsque des réseaux virtuels sont définis. Nous avons alors analysé les conséquences de ceci sur l'algorithme de construction de la topologie. Aussi bien l'algorithme implémenté dans le projet de l'année dernière que celui du document [18] ne fonctionnent que si on suppose la non existence de boucle. Ainsi, nous nous sommes dirigés vers la solution suivante: les informations récupérées pour les différents VLANs sont isolées et l'algorithme est exécuté indépendamment sur chaque VLAN. Nous obtenons alors autant d'arbres que de VLANs. Pour conserver l'affichage global de l'ensemble du réseau (tous réseaux virtuels confondus), nous avons choisi alors de développer un module de fusion d'arbres. On notera que la fusion n'est pas toujours possible, dans le sens où son résultat n'est pas forcément un arbre. L'affichage d'un graphe général étant beaucoup plus délicat que celui d'un arbre, nous limiterons la fusion au cas où son résultat reste un arbre. Ainsi, on peut afficher simultanément plusieurs VLANs lorsque la fusion de leurs arbres respectifs ne crée pas de boucle.
L'affichage graphique était très lent avec la représentation d'origine qui ne comportait que peu de machines; nous avons donc analysé l'implémentation de l'affichage des éléments de la carte pour l'optimiser afin qu'une représentation plus complète soit possible sans décupler le temps nécessaire à son calcul.
Projet de fin d'année Logiciel
< Cahier des charges < > Mise en oeuvre > |