Archives de catégorie : Uncategorized

Installer Debian sur un portable Asus X73SL

En voulant installer une distribution Linux sur un ordinateur portable de marque Asus, modèle X73SL je me suis heurté à plusieurs problèmes. ll m’a semblé intéressant de les consigner ici, avec les sources que j’ai utilisé pour les résoudres.

Les solutions que je vais donner ici peuvent probablement être appliquées à d’autres distributions Linux (Ubuntu, Fedora, etc) mais nécessiteront peut être un peu d’adaptation. Par ailleurs, il semblerait qu’Asus ai basé plusieurs modèle de portables sur la même carte mère, il se pourrait donc que ces solutions fonctionnent aussi pour les modèles X70, X71, X72, X73 (avec des lettres derrière cette dénomination, voir ici).

TL;DR

Pour les lecteurs (expérimentés ou non qui voudraient un solution rapide) voici les ajustements que j’ai fait :

  • La carte mère ne supporte pas le interruptions MSI, il faut les désactiver pour le noyau dans son ensemble et le driver nouveau en ajoutant les paramètres pci=nomsi et nouveau.config=NvMSI=0 à la ligne de commande du noyau. Soit en live au moment du boot, soit de manière permanente les ajoutant à la variable GRUB_CMD_LINUX en éditant /etc/default/grub, puis en lançant update-grub.
  • Le chipset ethernet SiS191 ne supporte pas un MTU supérieur à 1496, il faut donc éditer votre configuration réseau (par un menu ou une configuration NetworkManager) pour définir sa valeur à 1496

Point de départ

Mon objectif était d’installer une distribution Linux sur un vieux portable Asus (de 2009) histoire de lui donner une seconde jeunesse. Le PC est un Asus X73SL-TY024C avec la configuration suivante :

  • Intel Pentium Dual CPU T3400 @ 2.16GHz (1Mo de cache, bus à 667Mhz)
  • Carte mère avec un chipset SiS 671MX
  • 4 Go de DDR2 à 667Mhz
  • 2 disques dur SATA de 250 Go, 5400 t/min
  • GeForce 9300M GS
  • Controleur ethernet SiS191
  • Carte Wi-Fi AR5B91 (chipset Atheros AR928X) mini PCI-E

Je souhaitais au départ installer Ubuntu car elle a une joli interface qui aurait été facile d’usage pour un néophyte, mais il était impossible de démarrer l’installateur, l’écran restait noir après le passage de Grub (22.04 ou 23.04 même combat). J’ai donc décidé de me rabattre sur une Debian Bullseye (la version stable à l’heure où j’écris ces lignes). Cette fois-ci, l’installation se passe correctement. Je redémarre, passe Grub, je vois les premières lignes de logs du noyau, et ensuite plus rien, écran noir. C’est là que les problèmes commencent.

Dans les sections qui suivent, je vais détailler la méthode que j’ai utilisé pour isoler les problèmes, et les solutions que j’ai trouvé. Dans la suite de cet article je vais partir. du principe qu’une distribution (Debian) est installée et qu’elle ne démarre pas.

Ça démarre pas, je fais quoi ?

La première étape c’est d’arriver à cerner à quel moment le boot est bloqué. Dans mon cas, Grub s’affiche, je peux lancer Debian, il me dit :

Loading Linux 5.10.0-23-amd64 ...
Loading initial ramdisk ...

puis l’écran devient noir avec qui un curseur clignote en haut à gauche de l’écran. Plus tard un changement semble se produire sur l’écran, puis plus rien, tout reste noir. C’est donc à un moment, après le démarrage de Linux, que quelque chose coince.

Dans ce cas, la première étape c’est de désactiver un maximum de périphériques dans le BIOS. Sur ce modèle il faut redémarrer, aller dans le BIOS avec F2, puis Advanced et I/O interface security. On peut alors désactiver un maximum de périphériques en les passant de UNLOCKED à LOCKED. Ensuite on enregistre avec F10 et on redémarre.

Ensuite, il faut modifier (temporairement) la ligne de commande du noyau passée par Grub, de manière à laisser le noyau afficher des traces à l’écran, on saura alors ce qui se passe. Pour ça, au moment où Grub s’affiche et propose des options, il faut presser Control+X pour obtenir l’éditeur et retirer le paramètre quiet de la ligne :

linux	/boot/vmlinuz-5.10.0-23-amd64 root=UUID=[...] ro quiet

Ensuite Linux démarre, affiche des traces dans la console. Puis au moment de passer la console en mode frame buffer (console de haute résolution), l’image disparait de nouveau, et j’ai un écran noir. Il y a donc sans doute un problème avec la carte graphique ou son driver nouveau.

GeForce 9300M et Nouveau

Pour en avoir le coeur net, je redémarre, j’édite de nouveau la ligne de commande du noyau pour retirer quiet et j’ajoute nouveau.modeset=0 pour désactiver le remplacement de la console :

linux	/boot/vmlinuz-5.10.0-23-amd64 root=UUID=[...] ro quiet nouveau.modeset=0

Je redémarre et … miracle, j’obtiens une invite de login et je peux me connecter en tant qu’utilisateur root. Je décide de démarrer le serveur d’affichage (serveur X) pour voir ce qui se passe et dans le logs je trouve :

(EE) NVIDIA(GPU-0): The NVIDIA kernel module does not appear to be receiving
(EE) NVIDIA(GPU-0):     interrupts generated by the NVIDIA GPU at PCI:1:0:0. 
(EE) NVIDIA(GPU-0):     Please see Chapter 8: Common Problems in the README for additional information.

Le driver ne reçoit pas les interruptions ? En regardant la liste des options du driver nouveau j’ai remarqué un paramètres NvMSI :

NvMSI: Use MSI interrupts, on by default on the chipsets that support it

C’est exactement ce qu’il nous faut. En effet Un périphérique PCI-E n’est pas obligé d’utiliser les interruptions matériels (reliées directement au contrôleur d’interruptions du processeur) mais peut envoyer un message à travers le bus PCI-E pour faire générer un interruption par le contrôleur de bus. C’est ce qu’on appelle les Message Signaled Interrupts ou MSI. Or cette fonctionnalité n’a pas été introduite immédiatement dans PCI-Express, l’ordinateur étant un peu âgé, il se peut qu’il ne les supporte pas.

On peut donc modifier de nouveau ligne de commande du noyau depuis Grub pour voir si ça fonctionne :

linux	/boot/vmlinuz-5.10.0-23-amd64 root=UUID=[...] ro quiet nouveau.config=NvMSI=0

Un petit reboot et hop ça fonctionne, le gestionnaire de login graphique s’affiche ! Il suffit maintenant de rendre cette option permanente. Pour ça j’ai ajouté le paramètre à la configuration de Grub :

# vim /etc/default/grub
[...]
GRUB_DEFAULT=0
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`
GRUB_CMDLINE_LINUX_DEFAULT="quiet"
GRUB_CMDLINE_LINUX="nouveau.config=NvMSI=0"
[...]

puis mise à jour de Grub :

# /sbin/update-grub
Generating grub configuration file ...
Found background image: /usr/share/images/desktop-base/desktop-grub.png
Found linux image: /boot/vmlinuz-5.10.0-23-amd64
Found initrd image: /boot/initrd.img-5.10.0-23-amd64
Found linux image: /boot/vmlinuz-5.10.0-21-amd64
Found initrd image: /boot/initrd.img-5.10.0-21-amd64
Warning: os-prober will be executed to detect other bootable partitions.
Its output will be used to detect bootable binaries on them and create new boot entries.
Found Windows Boot Manager on /dev/sda1@/efi/Microsoft/Boot/bootmgfw.efi
Adding boot menu entry for UEFI Firmware Settings ...
done

Après redémarrage tout va bien.

Un peu de réseau ?

Ethernet – SiS191

J’ai réactivé un par un les périphériques dans le BIOS et le problème suivant est apparu avec la carte ethernet SiS191. En effet, au bout d’un moment la connexion au réseau cesse de fonctionner, toutes les requêtes font des timeouts et le réseau devient inaccessible.

En cherchant des informations sur le support de ce chip dans Linux, j’ai découvert que ce chip a une taille maximum de MTU (Maximum Transmission Unit) de 1496 octets là ou Linux configure cette taille à 1500 octets par défaut. Ce qui fait que lorsqu’un paquet dépasse 1496 octets, la fin du paquet est tronquée, et le paquet envoyé sur le réseau est invalide. Le problème est documenté dans un bug sur le bug tracker du noyau Linux On peut vérifier le MTU défini pour une interface avec la commande :

# ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: enp0s4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether 00:e8:4c:68:44:71 brd ff:ff:ff:ff:ff:ff
3: wlp2s0: <BROADCAST,ALLMULTI,PROMISC,NOTRAILERS,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether 48:45:20:e1:0e:e7 brd ff:ff:ff:ff:ff:ff

Pour corriger le problème, il suffit de dire à NetworkManager (le gestionnaire de connexions) que toutes les connexions qui utilisent cette interface doivent définir un MTU à 1496. Pour cela on va créer un fichier de configuration :

# vim /etc/NetworkManager/conf.d/enp0s4-mtu.conf
[connection-enp0s4-mtu]
match-device=interface-name:enp0s4
ethernet.mtu=1496

Dans le fichier ci-dessus, n’oubliez pas de changer enp0s4 par le nom de votre interface ethernet. Puis on relance NetworkManager :

# systemctl restart NetworkManager

Wi-Fi

L’étape suivante c’est de ré-activer la carte Wi-Fi depuis le BIOS, et là c’est le drame. Lors du reboot, le système gèle pendant le démarrage, et impossible d’en sortir autrement que par un redémarrage à la dure.

La carte Wi-Fi installée dans le PC est une AR5B91 mini PCI-Express munie d’un chip Atheros qui est en théorie bien supportée par le driver ath9k. Le problème se situe donc sans doute ailleurs. Et en effet, la carte est elle aussi sur le bus PCI-Express, elle est donc soumise au même problème que la carte graphique : il faut désactiver le support des MSIs pour que cela fonctionne.

Il suffit de rajouter l’option pci=nomsi à la ligne de commande du noyau de la même manière qu’on l’a fait pour la carte graphique :

# vim /etc/default/grub
[...]
GRUB_DEFAULT=0
GRUB_TIMEOUT=5 GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`
GRUB_CMDLINE_LINUX_DEFAULT="quiet" GRUB_CMDLINE_LINUX="nouveau.config=NvMSI=0 pci=nomsi"
[...]

# /sbin/update-grub
Generating grub configuration file ...
Found background image: /usr/share/images/desktop-base/desktop-grub.png
Found linux image: /boot/vmlinuz-5.10.0-23-amd64
Found initrd image: /boot/initrd.img-5.10.0-23-amd64
Found linux image: /boot/vmlinuz-5.10.0-21-amd64
Found initrd image: /boot/initrd.img-5.10.0-21-amd64
Warning: os-prober will be executed to detect other bootable partitions.
Its output will be used to detect bootable binaries on them and create new boot entries.
Found Windows Boot Manager on /dev/sda1@/efi/Microsoft/Boot/bootmgfw.efi
Adding boot menu entry for UEFI Firmware Settings ...
done

Un reboot, et le tour est joué !

Conclusion

Après cet ensemble de changements, le système fonctionne plutôt très bien. En revanche, on peut pas dire que l’installation soit aisée.

Références

Multimedia : buffers dynamiques et gestion de latence grace au « inter-arrival jitter »

En travaillant sur le contrôle et la réduction de la latence dans une application multi-media temps réel, j’ai découvert que le premier problème que j’avais était du aux variations de latence introduites par le réseau. La principale difficulté a été d’arriver a estimer le désordre produit par le réseau sur un flux RTP entrant sans pouvoir utiliser RTCP ou n’importe que autre canal de feed-back. Dans l’article suivant, nous allons nous intéresser a la méthode que j’ai utilisé pour estimer le désordre et déduire une taille optimale de buffers pour les conditions courantes.

Contexte

Partons d’une application qui transmet un flux audio et/ou vidéo temps reel à un receveur. Par temps réel, on entend que le contenu envoyé peut être interactif, ne peut pas être envoyé à l’avance au receveur (un appel audio ou vidéo par exemple). Il faut donc trouver un compromis entre l’interactivité (une latence faible) et un contenu diffusé de manière fluide (une latence plus élevée du à l’usage d’un tampon).

La source émet un flux à travers le réseau en direction du receveur. Souvent le contenu encodé (compressé) est découpé en de petites « access units » qui seront encapsulées dans des paquets RTP et envoyées par UDP. Pour simplifier nous considèrerons que la source se contente d’envoyer un flux video en utilisant RTP par dessus UDP en direction de la cible.

La cible reçoit les paquets RTP sur un port UDP choisi aléatoirement, et les obtiens a travers une socket comme d’habitude. Tel que défini dans RTP, chaque paquet a un marqueur de temps (timestamp) qui décrit l’heure de presentation de l’access unit (consultez la RFC3550 pour plus de details sur RTP). Étant donné qu’une access unit peut être plus volumineuse que ce que peut contenir le paquet RTP, elle peut être découpée en de multiples paquets RTP. La manière de le faire dépend du codec utilisé. Pour éviter de complexifier nous considèrerons que le receveur a un assembleur qui délivre chaque access unit ré-assemblée avec son marqueur temporel.

Dans les paragraphes suivants, nous nous intéresserons aux access units et a leur marqueurs de temps avant/apres qu’il soit passe par le transport reseau. Cela revient quasiment a étudier directement les paquets RTP et simplifie le raisonnement, c’est donc une hypothèse raisonnable.

Le problème : réseau et references de temps

Du cote émetteur, les access units sont produites de manière régulière. Pour une vidéo a 30 images par secondes, l’encodeur produit en général une access unit toutes les 33 millisecondes (ms). En réalité cela dépend du codec, mais nous ferons avec. L’illustration ci-dessous montre un flux d’access units émises en suivant une période de 33 ms (30 images par secondes).

Image 1 : des access units produites régulièrement.

Si le réseau était parfait, nous devrions recevoir exactement le même flux (avec le même intervalle de temps entre les access units), mais décalé d’un délai du à l’emission, la transmission, la réception et l’opération d’assemblage (voir l’illustration ci-dessous).

Image 2 : délai de transmission dans un réseau parfait.

Mais dans le monde réel, le délai introduit par le réseau n’est pas constant. Il y a bien évidement un délai incompressible du au temps de propagation physique de l’information et au traitement des données, mais il y a aussi une part variable du à la congestion du réseau. Le véritable résultat a donc l’allure de l’illustration suivante.

Image 3 : delais dans le monde reel.

Chaque access unit est délivrée au receveur avec un délai relatif à son horloge de départ, qui varie en fonction des conditions du réseau. La latence d’une access unit peut être représentée comme suit :

\Delta_{frame}(n) = \Delta_{network} + \delta_n

Faisons un petit résume de la situation du receveur :

  • il reçoit un flux d’access units avec leur marqueur de temps,
  • les access units ne sont pas délivrées de manière régulière à cause de la congestion dans le réseau,
  • les conditions du réseau évoluent au court du temps,
  • la seule référence de temps disponible est le marqueur de temps disponible dans les paquets RTP.

Le défi est donc de trouver un moyen d’estimer la taille idéale de buffer (tampon) nécessaire pour jouer le contenu en minimisant l’impact des aléas du réseau tout en préservant l’interactivité.

Le « inter-arrival jitter » comme estimateur de l’état du réseau

Pour estimer la congestion du réseau, puis calculer une taille de tampon adéquate, nous avons besoin d’un indicateur. En cherchant des articles sur le sujet, j’ai trouvé le brouillon d’une RFC : Google Congestion Control Algorithm for Real-Time Communication. Cet algorithme déduit une « estimation du débit maximum du récepteur » (Receiver Estimated Maximum Bitrate ou REMB) en utilisant le inter-arrival jitter. Calculer un débit n’est pas exactement ce que nous cherchons mais il utilise uniquement les paquets RTP entrants et leur marqueurs de temps pour faire l’estimation. C’est déjà un bon point.

Inter-arrival jitter

Les marqueurs de temps des paquets reçus ne sont pas suffisants pour calculer la latence en valeur absolue de ce flux. Mais grâce à eux, nous avons une information de valeur : le délai théorique entre deux images qui se suivent. Il est équivalent au délai entre l’émission de deux images par l’émetteur. La différence entre ces deux marqueurs de temps T des images n et n-1 est nommé inter-departure time (délai inter-départs) et s’exprime de la manière suivante :

T(n) - T(n-1)

De l’autre coté, en tant que récepteur, nous pouvons enregistrer pour chaque image, son heure arrivée locale et calculer le délai t qui sépare deux images consécutives n et n-1. C’est ce que l’on appelle inter-arrival time (délai inter-arrivées) et s’exprime de la façon suivante :

t(n) - t(n-1)

Si l’on compare les délais inter-arrivée et inter-départ pour deux images consécutives, nous avons un indicateur de la congestion du réseau. Dans un réseau parfait il devrait être nul, en pratique il varie. On peut l’exprimer formellement comme suit :

J(n) = t(n) - t(n-1) - (T(n) - T(n-1))

Plus de détails sont disponible dans la RFC mentionnée précédemment.

Estimations

Observer le jitter est un bon indicateur de l’état du réseau car il représente la distance entre la situation idéale (le délai entre deux images au départ) et la réalité (le délai entre deux images à l’arrivée). Plus le jitter est éloigné de 0, plus le réseau est dérangé.

Le premier estimateur que l’on peut calculer est le jitter moyen. Il fourni une estimation du désordre au cours du temps, mais pour refléter correctement la réalité cette moyenne doit être glissante, avec une fenêtre de temps relativement courte. Dans l’implémentation de GCC dans Chromium, une moyenne glissante exponentielle est utilisée. Elle permet de conserver l’influence des échantillons mesurés récemment tout en lissant les fortes variations.

\alpha \text{ est le coefficient de la moyenne glissante} \\
J(n) \text{ est le inter-arrival jitter pour l'image } n \\
J_{avg}(n) \text{ est la moyenne glissante pour l'image } n \\
J_{avg}(n) = \alpha * J(n) + (1 - \alpha) * J_{avg}(n-1)

Le paramètre de lissage α doit être choisi en fonction du cas d’utilisation et de l’implémentation. Si l’on joue un flux à 30 images par seconde, une value de 0,1 pour α signifie que la moyenne s’applique sur 10 inter-arrival jitter, elle tient donc compte des 10 * 33ms = 330 dernières millisecondes.

La moyenne est un bon indicateur de départ, mais se révèle en fait relativement faible utilisé seul car elle est fortement sensible aux variations et ne fourni aucune véritable information sur la distribution du jitter. Pour être précis, on ne s’intéresse pas à la taille de buffer qui satisfait le jitter moyen, mais plutôt à celle qui permet de prendre en compte le jitter de la majorité des images. N’oublions pas que le but est d’avoir une expérience de lecture fluide de notre vidéo.

Nous cherchons donc un indicateur qui permette d’estimer une durée de buffer idéale afin de lisser l’impact du réseau pour la majorité des images. En disant cela on se rapproche de la solution : il nous faut un taille de buffer associée à un intervalle de confiance. En calculant l’écart type σ à partir des jitters mesurés, nous pouvons construite un intervalle autour du jitter moyen qui nous fournira la durée de buffer idéale pour 68% (la moyenne plus σ), 95% (la moyenne plus 2σ) voir même 99,7% (la moyenne plus 3σ) des images entrantes. Pour en savoir plus sur l’écart type et les intervalles de confiance, rendez-vous ici.

Nous pouvons donc calculer calculer une variance mobile sur les jitters en utilisant la moyenne exponentielle :

V(n) = \alpha * (J_{avg}(n) - J(n))^2 + (1 - \alpha) * V(n-1)

Puis en déduire l’écart type :

\sigma(n) = \sqrt{V(n)}

Prenons un exemple ! Après quelques secondes de streaming, le jitter moyen est de 15 ms et l’écart type de 37 ms. Si l’on considère un intervalle de confiance de 3σ, le calcul de la durée optimale du buffer est :

D_{buf}(n) = J_{avg}(n) + 3 * \sigma(n) = 15 + 3 * 37 = 126 \text{ ms}

En utilisant cette durée de buffer, nous savons couvrir 99,7% du jitter des images. Cette durée peut être ré-estimée régulièrement au cours du temps afin de toujours conserver le délai optimal. Ce faisant, la latence est conservée à sa valeur minimum tout en préservant une expérience de lecture fluide.

Conclusion

Calculer quelques indicateurs à partir du inter-arrival jitter est le procédé le plus simple que j’ai trouvé dans la littérature au cours de mes recherches sur le sujet. Il permet de fournir une expérience de lecture fluide tout en préservant une latence minimum. Il requiert, par ailleurs, peu d’information en entrée pour un indicateur fiable.

Remerciements

  • Tristan Braud pour m’avoir aidé à comprendre les concepts derrière le jitter et les statistiques menant au calcul de taille de buffer.
  • Rémi Peuvergne  pour ses conseils sur l’article et ses illustrations.

Références

Du compost sur ma terrasse !

Fatigué de devoir descendre une poubelle à moitié pleine parce qu’elle était trop odorante, et un peu poussé par un sentiment d’écologisme, j’ai décidé de faire mon propre compost. Oui mais … j’habite en appartement, autant dire que le bac au fond du jardin c’était perdu d’avance.

Un ami m’a donné l’idée de faire mon compost dans un seau sur la terrasse, nous avons réalisé ce petit projet ensemble. L’idée était que ce soit fonctionnel, mais aussi un peu esthétique. Voici le matériel utilisé :

  • Seau de 15l (seau à mélanges, Castorama, environ 3€),
  • Un dessous pour pot de fleur nettement plus large que le fond du seau (environ 7 €),
  • Du terreau, suffisement pour remplir le dessous,
  • Un peu de gazon à semer, ou d’autres plantes pour garnir le tour.

Photo du matériel initial.

Fournitures initiales

Dans un premier temps il faut percer le fond du saut de petits trous qui permettront au liquide généré par votre compost de s’évacuer. Puis, garnir le dessous de pot de terreau.

compost-first-step

Quelques trous dans le seau et un peu de terreau !

Posez ensuite le seau sur le lit de terreau et semez vos plantes, ici du gazon, autour. Cela permettra de décorer l’ensemble, et aussi de consommer ce que votre compost émètra dans la terre.

compost-final-step

L’ensemble, prêt à composter.

Vous pouvez mettre un peu de terre au fond du seau si vous le souhaitez, ça le rend plus facile à nettoyer. Entreposez ensuite le tout dans un endroit à l’abri des fortes pluies et fermez le couvercle. Vous n’aurez ainsi pas d’odeurs. Après quelques semaines, les plantes semées poussent et votre bac à compost pour balcon devient sortable.

compost-with-grass

Quelques semaines plus tard, avec de l’herbe et une collection d’épluchures !

Ça vaut ce que ça vaut, mais j’ai trouvé un compromis entre mon problème de poubelles et ma petite conscience écologique 😉 A vos outils !