% vim: spelllang=fr \documentclass[11pt,a4paper]{article} \usepackage[utf8]{inputenc} \usepackage[francais]{babel} %% FRENCH, FIXME if typing in english \usepackage[T1]{fontenc} \usepackage{amsmath} \usepackage{amsfonts} \usepackage{amssymb} \usepackage{graphicx} \usepackage[left=2cm,right=2cm,top=2cm,bottom=2cm]{geometry} % Custom packages \usepackage{my_listings} \usepackage{math} \author{Théophile \textsc{Bastian}} \title{Rapport~: projet réseau} \date{\today} \begin{document} \maketitle \begin{abstract} L'implémentation du protocole en C++ respecte la spécification sur tous les cas observés. De plus, les paquets sont agrégés tant que possible pour éviter une surcharge du réseau, l'inondation est un peu optimisée et n'interrompt pas le reste du protocole et le programme affiche ses informations dans la console sur demande. Toutefois, il n'est pas possible de modifier dynamiquement les données propagées. Le support de l'IPv4 et de l'IPv6 à la fois devrait être possible, mais n'a pas pu être testé. \end{abstract} \section{Utilisation} \subsection{Dépendances} Seuls un compilateur C++ supportant C++14 et la bibliothèque pthread sont nécessaires au fonctionnement du programme sur un environnement POSIX standard. \subsection{Compilation} \lstbash{make} suffit à compiler. Il est éventuellement possible d'utiliser un autre compilateur C++ en éditant le \texttt{Makefile}. \subsection{Utilisation} Le programme fourni prend en argument le chemin vers un fichier de configuration, dont chaque ligne commence par un mot-clé suivi de ses arguments. \begin{itemize} \item \lstbash{id [ID du programme]}~: laisser vide par défaut, sera généré automatiquement. \item \lstbash{bootstrap [ID du nœud] [adresse IPv6 du nœud] [port]}~: déclare le nœud comme nœud de bootstrap. L'adresse peut être IPv4-mapped, eg. \texttt{::FFFF:42.42.42.42}. \item \lstbash{data [donnée]}~: déclare une donnée à propager. La donnée peut contenir des espaces, et s'étend jusqu'à la fin de la ligne. \end{itemize} Le programme, à l'initialisation, lit le fichier puis le réécrit avec éventuellement des données tirées au hasard si nécessaire (eg. ID du nœud). \subsection{Entrée/sortie} Le programme produit des logs verbeux mais humainement lisibles sur sa sortie d'erreur (stderr). Le programme affiche son état actuel (voisins + infos sur eux, données + infos sur elles) lors d'un appui sur \textsc{return}. Un \textsc{sigint} (ctrl+C) permet l'arrêt propre du programme. %%%%%%%%%%%%%%%%%%%%%%%%%% \section{Implémentation} Tout d'abord, mon code est très --- trop --- long pour le programme demandé. J'ai manqué de temps pour ce projet (beaucoup de choses à faire en parallèle) et j'ai donc plus produit du code rapidement qu'intelligemment\ldots \subsection{Classes et fichiers} \begin{itemize} \item \lstcpp{Bytes}~: utilisé pour stocker des paquets. Permet une extraction/insertion facile de types \og{}classiques~\fg~: \lstcpp{u8}, \lstcpp{u16}, \ldots \item \lstcpp{ConfigFile}~: lit et écrit le fichier de configuration. \item \lstcpp{DataStore}~: stocke les données inondées et les maintient à jour. \item \lstcpp{Flooder}~: inonde une donnée vers une liste de pairs, en réessayant un nombre de fois défini (ici, 3). \item \lstcpp{Neighbours}~: gère les voisins du nœud courant, leur changement de type (potentiel, unidirectionnel, symétrique) et l'envoi de paquets nécessaires (IHU, \ldots). \item \lstcpp{PacketParser}~: reçoit les paquets entrants et les traite. \item \lstcpp{Protocol}~: gère le réseau de \og{}bas niveau~\fg, permet l'envoi de paquets de types donnés et gère le thread de réception de paquets. \item \lstcpp{data.h}~: définit les types de données et structures utiles un peu partout. \item \lstcpp{nw\_constants.h}~: définit les constantes relatives au réseau et au protocole. \end{itemize} \subsection{Threads} Le programme contient deux threads~: \begin{itemize} \item thread principal, gérant la plupart des choses~; \item thread de lecture des paquets, réceptionnant les paquets et les stockant dans une file pour que le thread principal puisse les analyser. \end{itemize} Des mutexes sont utilisées quand nécessaire (accès à la file, en particulier). \subsection{Lecture de l'entrée standard} Pour éviter d'être bloquant sur la lecture de l'entrée standard, j'utilise dans \texttt{main.cpp} \lstc{select} pour mettre un timeout d'une seconde sur \lstc{getchar}. Ceci remplace \lstc{sleep} dans la boucle principale. \subsection{Agrégation des paquets} L'idée suggérée est implémentée~: la fonction \lstcpp{Protocol::sendBody} agrège les TLVs qu'on lui donne dans une map de paquets (sans headers, \ie{} une suite de TLVs), mappant les IDs de nœuds sur leur paquet en cours d'envoi. Lorsqu'elle souhaite agréger plus d'un MTU~$- 12$ dans un paquet (\ie{} MTU~$-$~taille des headers), le paquet dans la map est envoyé, vidé, puis on agrèg le TLV qu'on souhaitait insérer. À la fin de chaque itération de la boucle principale, tous les paquets en cours sont envoyés, garantissant ainsi un délai inférieur à une seconde --- acceptable compte-tenu des délais prévus dans le protocole. \subsection{Amélioration de l'inondation} Lorsqu'un premier IHU est reçu d'un pair, on inonde immédiatement la donnée. \subsection{Inondation non-bloquante} L'objet \lstcpp{DataStore} décide périodiquement de republier ses données. Dans ce cas, il met à jour la donnée stockée, puis met à jour un champ demandant la propagation d'une certaine donnée. Ce champ est récupéré régulièrement par l'objet \lstcpp{Neighbours}, pouvant lui aussi décider d'inonder une donnée vers \emph{un} pair lorsque celui-ci envoie son premier IHU\@. Lorsque \lstcpp{Neighbours} reçoit, d'une manière ou d'une autre, une requête d'inondation, il crée un objet \lstcpp{Flooder} pour l'ID de la donnée à inonder initialisé avec la liste des voisins vers qui on souhaite inonder. Régulièrement, \lstcpp{Flooder::update} est appelé, et se charge d'inonder plusieurs fois la donnée vers chaque pair de l'ayant pas encore acquittée. \subsection{Problèmes remarqués} J'ai récemment remarqué que la manière dont je gère les seqno, à savoir prendre pour seqno la valeur de \lstcpp{time(NULL)}, me rend d'autant plus % chktex 36 vulnérable aux attaques par republication de données fausses~: mon programme ne se rend pas compte que sa donnée a été \og{}effacée~\fg, et --- pire --- si le seqno utilisé est assez grand, mes republications n'auront aucun effet du point de vue des autres nœuds pendant longtemps~: la donnée republiée semble obsolète, est donc ignorée, puis la donnée stockée finit par expirer\ldots \end{document}