Objectifs pédagogiques

Les objectifs principaux de ce sujet de travaux pratiques sont :

  • de comprendre les principes de la mise en œuvre programmée d'un client NTP ;
  • d'apprendre à synchroniser sur l'UTC – le « temps Internet » – sur une carte Arduino en choisissant le paramétrage adéquat du client NTP ;
  • d'analyser le contenu d'un message NTP envoyé par un serveur de temps suite à une requête de synchronisation, et ce faisant de vérifier les éléments exposés dans le cours (chap. R2‑VI ).

Des objectifs secondaires sont :

  • d'exploiter les compétences de codage acquises en langages C/C++ (notamment les fonctions de manipulation de mots binaires) et de comprendre à quel point elles sont utiles pour l'exploitation des protocoles réseaux ;
  • de découvrir certaines bibliothèques de fonctions spécialisées pour les cartes à microcontrôleur de type Arduino.

Pour traiter ces exercices, il est recommandé d'avoir bien étudié le chapitre R2‑VI du cours. Des renvois aux principaux éléments de cours ou à des pages web d'information générale sont donnés au fur et à mesure des questions.

Mise en situation

Environnement et matériel

Les manipulations demandées sont à accomplir sur un réseau local utilisant la pile de protocoles TCP/IP, raccordé à l'Internet. On requiert le matériel ci‑dessous :

  • une carte Arduino Uno ou Mega, équipée d'un module d'extension shield Ethernet 2 ; cette association est l'architecture matérielle retenue pour implémenter le client NTP ;
  • une led externe, dont la cathode est soudée à un résistor de limitation de courant, pour signaler les pulsations de l'horloge mise en œuvre par le programme téléversé dans la carte.
  • un poste de travail (typiquement, un PC) qui servira :
    • de terminal de programmation de la carte via le logiciel Arduino IDE ;
    • de client ICMP (commande ping) pour tester la visibilité de la carte sur le réseau ;
    • d'horloge Internet via une page web pour vérifier la synchronisation de la carte avec le temps universel coordonné (UTC).

Ces deux machines doivent être l'une et l'autre raccordées réseau local – typiquement, via un switch comme sur la figure ci‑dessus – et se voir attribuer chacune une adresse IP sur le même segment pour pouvoir communiquer – ce qui est assuré avec la présence d'un serveur DHCP sur le réseau local et la configuration appropriée des machines (cf. chap R2‑II ). Évidemment, il faut connaître la plage d'adresses IP dynamiques paramétrée par l'administrateur du réseau pour pouvoir identifier les machines lors d'un scan du réseau.

Travail demandé

Effectuer les manipulations dans l'ordre indiqué et le codage des fonctions demandées en respectant les spécifications indiquées. Pour une bonne organisation, chaque programme est à placer dans un répertoire de projet distinct, et de réunir tous ces répertoires dans un répertoires de TP, typiquement nommé TP_R2-4, lui‑même placé dans le répertoire principal du module RESEAUX, lui‑même placé dans répertoire personnel d'étudiant.

Dans une perspective de consolidation des connaissances, il est recommandé de bien comprendre le codage des fonctions employées pour la mise en œuvre ou l'étude du protocole NTP.

  1. Travail préparatoire
    1. Avant d'assembler le shield Ethernet sur la carte Arduino, relever l'adresse MAC inscrite sur l'étiquette collée sur la face inférieure du shield.
    2. Assembler le shield Ethernet sur la carte Arduino avec soin, sans forcer, en faisant bien coïncider toutes les broches mâles/femelles correspondantes, y compris celles au centre de la carte, formant le connecteur ICSP  (cf. la partie entourée en orange sur la figure ci‑contre).
    3. Introduire les broches du montage led‑résistor dans le port numérique de la carte (cf. la photo ci‑contre), de sorte que :
      • l'anode de la led soit dans une broche non utilisée par le shield Ethernet – par exemple, 37 ou 39 sur une carte Mega ;
      • la broche du résistor soit reliée au pôle GND de la carte.
    4. Raccorder le shield Ethernet au réseau local du poste de travail et mettre en service la carte en liaison USB au poste de travail.
    5. Sur le poste de travail, télécharger le code source du programme de test du système fourni via ce lien . Sans modifier son nom, le placer dans un répertoire de projet homonyme, à créer préalablement dans le répertoire de TP.
    6. Ouvrir ce programme avec le logiciel Arduino IDE. Avant de le téléverser dans la carte, il faut configurer quelques éléments :
      • Coder comme valeur de la constante TIME_LED_PIN le numéro de broche à laquelle la led externe est reliée (cf. la question c supra).
      • Coder comme valeur de la constante SPI_SS_ETHERNET_PIN le numéro de broche de sélection – celui désigné par le sigle SS, pour slave select – du shield Ethernet sur le bus SPI W utilisé dans les communications entre la carte Arduino et le port Ethernet du shield (cf. chap. R1‑III  ainsi que la page de référence A).
      • Coder les octets de l'adresse MAC du shield Ethernet relevés précédemment.
      • Modifier le code pour configurer la connexion au réseau local en mode DHCP (cf. chap. R2‑II ).
      De plus, vérifier que le module de bibliothèque requis par le programme, nommé Ethernet, est disponible dans l'IDE – sinon procéder à son installation à l'aide du gestionnaire de bibliothèques du logiciel (cf. chap. C1‑III ) – et sachant que le module SPI est inclus par défaut lors de l'installation d'Arduino IDE.
    7. Mettre sous tension la carte Arduino et raccorder le shield Ethernet au réseau local.
    8. Téléverser le programme dans la carte et attendre que sa led intégrée clignote avec une période de 1 s (cette led est aussi implémentée sur le shield juste à côté du connecteur RJ45). Lire les commentaires sur le fichier du code source pour plus de détails.
    9. Sur le poste de travail :
      • Ouvrir le moniteur série intégré à l'IDE Arduino en réglant la même vitesse de transmission (baud rate) que celle codée dans le programme.
      • Dans la fenêtre d'affichage du moniteur série, relever les informations de connexion – adresse IP, passerelle par défaut, etc. générées par le programme.
      • À l'aide d'un logiciel de scan réseau (cf. chap. R1‑II ), vérifier que la carte est détectée et retrouver son adresse IP.
      • Par ailleurs, l'état des ports logiciels de la carte est‑il renseigné ? Un nom d'hôte est‑il attribué ? Pourquoi non ?
      • Dans un terminal de commandes en ligne, vérifier que cette adresse IP répond à la commande ping (cf. chap. R1‑IV ).
  2. Mise en place et configuration d'un client NTP
    1. Sur le poste de travail, télécharger le programme de client NTP fourni via ce lien . Il s'agit d'un fichier d'archive, à déplacer puis extraire dans le répertoire de TP.
    2. Attention ! Il est réparti sur plusieurs fichiers et codé avec les concepts de la programmation orientée objet (cf. chap. C1‑I ) et de la compilation conditionnelle (cf. chap. C4‑III ).
      Ouvrir ce programme avec le logiciel Arduino IDE. Comme pour l'exercice précédent, il est nécessaire de configurer quelques éléments, sachant que ces derniers sont placés et codés différemment. Il faut notamment repérer :
      • le choix de la technologie de connexion au réseau (ici, Ethernet, pas Wi‑Fi) ;
      • les octets de l'adresse MAC du shield Ethernet ;
      • le choix d'une configuration dynamique (DHCP) pour la connexion au réseau ;
      • la vitesse de transmission sur la liaison au moniteur série ;
      • le numéro de la broche à laquelle est reliée la led externe pour signaler les pulsations de l'horloge ;
      • le numéro de broche de sélection du shield Ethernet sur le bus SPI ;
      • le choix des options de débogage avec le moniteur série, tant pour la connexion au réseau que pour le client NTP (il y a deux directives #define à décommenter).
      De plus, il faut vérifier que les modules de bibliothèque supplémentaire requis par le programme (Time A et Timezone A) sont installés dans l'IDE. Sinon, procéder à leur installation à l'aide du gestionnaire de bibliothèques du logiciel (cf. chap. C1‑III ).
    3. Téléverser le programme dans la carte Arduino et vérifier le bon fonctionnement en ouvrant le moniteur série (régler la même vitesse de transmission – le baud rate – que celle codée dans le programme).
    4. Comparer la date et l'heure affichées par la carte Arduino avec celui d'une page web d'horloge comme celle de ce lien . À quelle zone horaire cet affichage correspond‑il ?
    5. Dans le fichier d'en‑tête NTPclient.h coder les deux règles de changement d'heure DST pour la zone horaire de la France métropolitaine (cf. le cours, chap. C2‑VI, pour la détermination des dates de changement  et pour la syntaxe de codage des règles ).
    6. Téléverser le programme ainsi modifié et vérifier l'affichage de la date et de l'heure dans le moniteur série avec celui de la page web précédente, paramétrée pour Paris .
    7. Dans le moniteur série, observer le fonctionnement du programme durant plusieurs minutes puis répondre aux questions suivantes, en consultant si nécessaire le code source du programme (pour cela, les pseudo‑constantes de débogage doivent impérativement être définies – cf. la question 2.a supra ).
      • Comment est géré l'intervalle de temps entre deux synchronisations au serveur (polling interval) ? Quelle est la méthode qui code cet aspect du système ? Quelle est la plus grande valeur possible pour cet intervalle ?
      • Quels sont les numéros de port logiciel utilisés dans la couche transport pour identifier les messages du protocole NTP, côté client et serveur ? (cf. le cours, chap. R2‑VI  et ce lien externe )
      • Quelle est la taille en octets de l'en‑tête des messages NTP en provenance du serveur qui sont lus par le programme ? (cf. le cours, chap. R2‑VI )
      • À quoi sert la constante UNIX_EPOCH et à quelle durée sa valeur correspond‑elle ? (cf. le cours, chap. R2‑VI )
  3. Décodage de messages NTP
    1. Sur le poste de travail, télécharger le programme d'étude du protocole NTP fourni via ce lien . Déplacer l'archive dans le répertoire de TP puis l'extraire et l'ouvrir avec le logiciel Arduino IDE.
    2. Ce programme adopte la même base que celui de l'exercice 2 mais inclut davantage de méthodes pour afficher les informations contenues dans les différents champs d'un message NTP envoyés par le serveur de temps. Le présent exercice consiste à coder certaines de ces fonctions.
    3. En étudiant attentivement la constitution d'un message NTP (cf. le cours, chap. R2‑VI ), et en employant les opérateurs de manipulation de bits (décalage, masquage, cf. le chap. C3‑III ), compléter le codage des fonctions dans le fichier auxiliaire d'implémentation NTPstudy.cpp :
      • la méthode decodeVN qui retourne la valeur du champ VN (version number) ;
      • la méthode decodeMode qui retourne la valeur du champ mode ;
      • la méthode decodeStratum qui retourne la valeur du champ stratum ;
      • la méthode decodePoll qui retourne la durée en secondes de l'intervalle entre deux requêtes, codée en logarithme à base 2 dans le champ poll ;
      • la méthode decodePrecision qui retourne la précision du serveur exprimée en fraction de seconde et codée en logarithme à base 2 dans le champ precision.
      Remarque : pour le codage de toutes ces méthode, on pourra s'inspirer du code de la méthode decodeLI qui retourne la valeur du champ LI (leap indicator).
      Toujours dans le fichier d'implémentation NTPstudy.cpp, en s'inspirant du code de la méthode decodeReference, compléter celui de la méthode decodeString qui retourne la chaîne de caractères codée dans le champ reference id. / kiss of death (KOD).
      Téléverser le programme dans la carte Arduino et vérifier son bon fonctionnement : chaque champ décodé du message NTP doit avoir une valeur conforme à ce qui est attendu.
    4. Laisser le programme fonctionner durant quelques minutes et observer les caractéristiques des serveurs de temps répondant aux requêtes, notamment le stratum et la précision, ainsi que le numéro de version du protocole NTP.
    5. Dans le fichier d'en‑tête NTPstudy.h, remplacer le nom de domaine du serveur de temps par celui d'un pool de serveurs qui optimise les temps de requêtes en France métropolitaine (cf. le cours, chap. R2‑VI ).
      Recompiler et téléverser le programme ainsi modifié et observer à nouveau les caractéristiques des serveurs de temps répondant aux requêtes.
    6. * Dans le fichier d'implémentation NTPstudy.cpp, compléter le code des méthodes dateIsoString, timeIsoString et dateAndTimeString pour obtenir un affichage conforme à la norme ISO 8601 (cf. le cours, chap. R2‑VI ).
    7. Pour cela, on pourra s'inspirer du code des méthodes dateWithDayNameString et timeWithTZstring.
      Pour tester ces modifications et ainsi vérifier que l'affichage est conforme aux attentes, recompiler et téléverser le programme dans la carte pour la zone horaire de Paris puis celle de Los Angeles.