M1-nw-project/report/report.tex

160 lines
6.1 KiB
TeX

% 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.
\end{document}