Architecture et réseau¶
Version
Page écrite pour pupitre 0.1.35-1.
Cette page décrit une salle servie par pupitre, ce qui tourne dans la machine virtuelle pour chaque poste, les ports et les débits en jeu, puis le dimensionnement et les préconisations.
La salle¶
Le schéma montre une salle de dix postes : un commutateur, une liaison montante et une VM, dans la salle ou dans un local technique. Cliquez sur le schéma pour l'ouvrir en pleine taille.
Chaque poste est un Dell Wyse 1010 avec un écran VGA, un clavier et une souris USB (un récepteur sans fil convient), un casque et, au besoin, une clé USB. Le boîtier prend son adresse par DHCP sur le réseau de l'école ; pupitre ne sert pas de DHCP. Le serveur a une adresse fixe sur le même VLAN.
Pourquoi la couche 2 est obligatoire¶
Ce n'est pas une prudence, c'est le code :
- La découverte passe par la diffusion. Chaque boîtier s'annonce en diffusion UDP sur le port
- Le gestionnaire et les sièges écoutent ce port ; le siège répond en unicast depuis le port
52340 (
pupitre/main.py). Une diffusion ne traverse pas un routeur. - Le client de siège parle directement Ethernet.
fast_tcp2construit lui-même ses trames Ethernet avec la MAC du boîtier en destination, et rejette toute trame reçue d'une autre MAC (src/fast_tcp2/fast_tcp2.c). Derrière un routeur, la MAC source vue serait celle du routeur et chaque trame serait jetée.
Conséquences : la carte réseau de la VM est en pont sur le VLAN des boîtiers, jamais derrière un NAT, et aucun routeur ne s'intercale. Un relais DHCP ne remplace pas ce lien. Le Wi-Fi ne se ponte pas : l'hyperviseur doit être relié en filaire.
VM dans la salle ou VM déportée¶
- Montage de référence : une VM KVM/libvirt sur une machine reliée au réseau des boîtiers, avec une interface
macvtap sur la carte filaire (c'est ce que fait le démonstrateur
tools/demo-vm.sh). - Exigence pour déporter la VM dans une autre salle ou un local technique : le VLAN de la classe doit arriver tel quel, au niveau 2, jusqu'à l'hyperviseur, par exemple en 802.1Q de bout en bout sur les commutateurs intermédiaires.
- Latence : la vidéo avance par fenêtre de 14 336 octets et par accusé de fin de trame, son débit baisse donc quand l'aller-retour augmente. En réseau local, l'accusé revient en 0,4 ms environ. Gardez la VM sur un lien de faible latence ; avant de la déporter sur un lien de plusieurs millisecondes, vérifiez le débit vidéo d'un poste.
Ce qui tourne dans la VM¶
Cliquez sur le schéma pour l'ouvrir en pleine taille.
Les services communs¶
| Unité | Rôle |
|---|---|
pupitre-nft |
Une seule fois, en root : une table nftables ip pupitre qui jette les RST que le noyau enverrait vers les ports des boîtiers. Le noyau ne connaît pas les connexions TCP de fast_tcp2 et répondrait RST à chacun de leurs segments. Depuis 0.1.27, une mise à jour recharge la règle en place au lieu de la redémarrer, ce qui ne coupe plus les sièges. |
pupitre-manager |
Écoute les annonces UDP 52330, tient la table MAC vers siège (/var/lib/pupitre/seats.json), écrit /run/pupitre/seat-N.env (MAC, IP, interface) et démarre pupitre-seat@N. Un boîtier inconnu est enrôlé tout seul au plus petit numéro libre (enroll = yes, le défaut). |
pupitre-web |
La console d'administration, sur 127.0.0.1:8080 par défaut. Elle lit les écrans des sièges directement dans les framebuffers de Xvfb. |
lightdm |
Seulement en mode eleves (depuis 0.1.27) : un écran de connexion par siège, posé sur l'Xvfb du siège. |
Un siège : le côté session et le côté lien¶
pupitre-seat@N lance un script, /usr/lib/pupitre/pupitre-seat, qui reste root pour ce qui
l'exige et démarre le reste sous l'utilisateur du siège, pupitre-seat-N. Il sépare deux mondes,
et cette frontière explique le comportement quand un élève éteint son boîtier :
- Côté session, ce qui survit à une coupure du lien : Xvfb sur l'affichage
:(100+N)en 1280 × 1024, le bureau, le PulseAudio du siège et son pontparec, l'injecteur d'entrées. En modefixe, le bureau estxfce4-sessionsouspupitre-seat-N. En modeeleves, c'est l'écran de connexion puis la session de l'élève sous son propre compte. - Côté lien, ce qui est refait sans toucher la session :
pupitre.main, qui fait la poignée de main DCP et lancefast_tcp2, l'encodeur, le programme du curseur, et le veilleur de clé (pupitre-cle) avec son fichier FUSE, arrêtés avantfast_tcp2pour vider une clé montée.
Quand le boîtier disparaît, seul le côté lien est arrêté puis refait ; l'élève retrouve son bureau
tel qu'il l'a laissé (depuis 0.1.13). Sans lien depuis PUPITRE_GRACE secondes (600 par défaut), le
siège s'arrête. En mode eleves, la session de l'élève est fermée après PUPITRE_FERMETURE
secondes de boîtier éteint (600 par défaut).
fast_tcp2 n'a besoin que des capacités CAP_NET_RAW et CAP_SYS_NICE, posées par le paquet.
Il dort dans ppoll entre deux trames : 1,50 % d'un cœur par siège au lieu d'un cœur entier
(depuis 0.1.5).
Le chemin des données¶
Tous les tubes vivent dans /run/pupitre/seat-N/.
| Flux | Chemin |
|---|---|
| Image | Le bureau dessine dans Xvfb, qui écrit son framebuffer dans un fichier. encoder.py repère les zones modifiées, les code en RLE et les pousse dans le tube video. fast_tcp2 les envoie au boîtier sur TCP 1234 et 4321. Double tampon différé par défaut (depuis 0.1.20) : pas de déchirure, deux fois moins d'octets qu'un double tampon complet. |
| Curseur | curseur_x.py lit la forme et la position du pointeur par XFixes et les écrit dans le tube curseur ; le boîtier dessine lui-même le pointeur, sur le canal vidéo. Allumé par défaut depuis 0.1.14. |
| Son | Les applications jouent dans un puits PulseAudio nul nommé wyse, que parec lit en PCM 16 bits stéréo à 44,1 kHz vers le tube audio. fast_tcp2 l'envoie sur TCP 1235 et 4322, une unité de 1780 octets toutes les 10 ms. |
| Clavier et souris | Le boîtier remonte les rapports HID par le tunnel USB, TCP 4660. fast_tcp2 les écrit dans le tube input ; input_inject.py les rejoue dans Xvfb par XTEST, en codes de touche, et la disposition xkb du siège en fait des caractères. |
| Clé USB | fast_tcp2 parle à la clé par TCP 1237 et 4324 et la sert sur la socket cle.sock. wyse_cle_fuse en fait un fichier disque.img, que fusefatfs monte au double-clic dans le dossier « Clé USB ». Le noyau ne monte jamais la clé d'un élève. Port isolé du boîtier servi depuis 0.1.29. |
Ports et protocoles¶
Tous les canaux d'un boîtier passent par la même carte en pont. Les canaux TCP sont portés par
fast_tcp2 sur sa socket AF_PACKET ; le boîtier est le côté serveur des ports listés.
| Port | Protocole | Rôle | Sens principal |
|---|---|---|---|
| 52330 | UDP, diffusion | annonces DCP des boîtiers, toutes les 10 s | boîtier vers serveur |
| 52340 vers 52330 | UDP, unicast | réponse du siège à son boîtier | serveur vers boîtier |
| 4660 | TCP | tunnel USB : descripteurs, clavier, souris | dans les deux sens |
| 1234 et 4321 | TCP | vidéo et curseur : 1234 annonce, 4321 porte les données | serveur vers boîtier |
| 1235 et 4322 | TCP | son | serveur vers boîtier |
| 1237 et 4324 | TCP | clé USB (paire annoncée par le boîtier) | dans les deux sens |
| 1234 à 1241 et 4321 à 4328 | TCP | toutes les paires possibles, couvertes par la règle pupitre-nft |
|
| 8080 | TCP, HTTP | console web, sur 127.0.0.1 par défaut |
poste d'administration vers serveur |
Pupitre ne pose aucune règle d'entrée sur le serveur. Un pare-feu en entrée doit laisser passer l'UDP 52330 : c'est par là que les boîtiers s'annoncent, sans quoi ils ne sont pas découverts.
Débits¶
1 Mio/s vaut environ 8,4 Mbit/s.
| Usage d'un poste | Débit |
|---|---|
| Bureau au repos | négligeable (8 bandes en 60 s) |
| Frappe continue qui sature l'affichage | ≈ 0,29 Mio/s, soit ≈ 2,3 Mbit/s |
| Terminal qui défile vingt lignes par seconde | ≈ 0,28 Mio/s, soit ≈ 2,3 Mbit/s |
| Vidéo sans plafond (défaut depuis 0.1.17) | jusqu'à 6064 Kio/s, ≈ 50 Mbit/s (depuis 0.1.24) |
Vidéo plafonnée par PUPITRE_DEBIT_MAX=1024 |
1009 à 1038 Kio/s, ≈ 8,5 Mbit/s |
| Son en lecture | 178 000 o/s, ≈ 1,4 Mbit/s |
| Clé USB | ≈ 430 Kio/s en écriture, ≈ 900 Kio/s en lecture |
| Clavier et souris | négligeable |
Un port à 100 Mbit/s par boîtier suffit donc. La fiche Dell annonce un port Ethernet 10/100/1000.
Pour la salle, en additionnant :
| Cas | 10 postes | 13 postes |
|---|---|---|
| Tous en bureautique, frappe saturante | ≈ 23 Mbit/s | ≈ 30 Mbit/s |
| Tous en vidéo sans plafond, avec le son | ≈ 510 Mbit/s | ≈ 660 Mbit/s |
| Tous en vidéo plafonnée à 1024 Kio/s | ≈ 85 Mbit/s | ≈ 110 Mbit/s |
Le surcoût des en-têtes Ethernet, IP et TCP n'est pas compté. La clé et la vidéo d'un même siège ne s'additionnent pas en pointe : la vidéo attend la fin d'une commande de clé.
Latence en réseau local : environ 55 ms de la frappe au dernier octet de l'image sur le fil, dont 24 ms pour que X dessine, 4 ms d'encodage et 27 ms de transfert en médiane.
Dimensionner la VM¶
Tableau indicatif, pour une salle d'élèves qui ont chacun un bureau et Firefox ouvert :
| Sièges | vCPU | Mémoire | Disque | Débit maximal vers le serveur |
|---|---|---|---|---|
| 5 | 2 | 8 Go | 30 Go | ≈ 255 Mbit/s |
| 10 | 4 | 16 Go | 40 Go | ≈ 510 Mbit/s |
| 15 | 6 | 32 Go | 50 Go | ≈ 765 Mbit/s |
| 20 | 8 | 32 Go | 60 Go | ≈ 1 020 Mbit/s, au-delà d'un lien à 1 Gbit/s |
Le débit maximal est celui où tous les postes lisent une vidéo en même temps : environ 50 Mbit/s d'image plus 1,4 Mbit/s de son par poste. En bureautique, comptez environ 2,3 Mbit/s par poste.
La règle de calcul :
- Mémoire. 2 Go de réserve pour le système, plus environ 0,75 Go par élève : le bureau et Firefox ouvert sur une page, dont environ 590 Mio pour Firefox. Le total est arrondi au palier courant en gardant environ un quart de marge. Dimensionnez pour le navigateur, pas pour le bureau : un siège au repos ne coûte que 128 à 162 Mio.
- Processeur. L'encodeur fait environ 65 écrans complets par seconde et par vCPU, pour un
besoin de 8 par siège : un vCPU pour huit sièges, et autant pour Xfce, Firefox et LibreOffice,
arrondi au-dessus avec de la marge. Le client coûte 1,50 % d'un cœur par siège.
tools/bench_encode_n_seats.pyvérifie l'encodeur sur la VM cible. - Disque. 20 Go de système, 2,6 Go pour TuxBot et Wine, environ 1 Go par élève pour son dossier, arrondi avec de la marge.
- Au-delà de 15 sièges, le nombre par défaut depuis 0.1.35, réglez
seatsdans/etc/pupitre/pupitre.conf(seats = 0lève la limite). - Réseau. Le lien du serveur reste à 1 Gbit/s : à vingt postes qui lisent tous une vidéo, il sature.
- zram. Compressée en zstd, la mémoire anonyme d'un siège au repos passe de 155 à 28 Mio, soit
5,39 pour 1. zram et la limite souple par siège (
PUPITRE_MEMOIRE=1) sont livrés éteints : la procédure est dans Installation de zéro.
Préconisations¶
Réseau¶
- Mettre la VM et les boîtiers dans le même VLAN, la carte de la VM en pont, sans NAT ni routeur entre eux (imposé par le code).
- Donner au serveur une adresse fixe sur ce VLAN ; laisser les boîtiers en DHCP.
- Un port d'accès à 100 Mbit/s par boîtier suffit : un boîtier atteint environ 50 Mbit/s en vidéo.
- Le port de la VM et chaque liaison entre commutateurs jusqu'à elle : 1 Gbit/s dès que deux postes peuvent lire une vidéo en même temps (deux vidéos font ≈ 100 Mbit/s).
- Pour déporter la VM, étendre le VLAN de la classe au niveau 2 jusqu'à l'hyperviseur, puis vérifier le débit vidéo d'un poste avant de généraliser.
- Si le serveur a un pare-feu en entrée, y laisser passer l'UDP 52330.
Machine virtuelle¶
- Debian 13 uniquement : l'unité de siège exige systemd 254 ou plus.
- KVM/libvirt, avec une carte macvtap ou un pont sur le VLAN des boîtiers.
- Pour une salle de dix : 4 vCPU et 16 Go.
- Avec moins de 16 Go, activer zram et
PUPITRE_MEMOIRE=1.
Console d'administration¶
La console : sur la boucle locale, jointe par ssh ; sur le réseau, seulement avec un mot de passe (depuis 0.1.14) et sur un VLAN d'administration, car elle reste en HTTP clair et montre l'écran de chaque élève. Mise en place : Console web et son mot de passe.
Limites connues côté réseau¶
- DHCP : un boîtier qui démarre sans bail prend l'adresse de repli 169.254.10.10 et n'est pas servi : vérifiez le DHCP du VLAN, puis faites un cycle d'alimentation du boîtier.
- Clavier et souris se branchent boîtier éteint : le client ne les configure qu'à l'ouverture du lien. Branchés après, ils sont vus dans l'inventaire du boîtier mais pas servis de façon fiable, et le boîtier peut redémarrer au branchement. Un arrêt et une remise en marche du boîtier les fait prendre, bureau gardé ; un Relink revient au même, car il fait redémarrer le boîtier (une quarantaine de secondes). La clé USB, elle, se branche à chaud.