Avec ses fonctionnalités de virtualisation intégrées, Solaris 10 se devait de revoir la couche réseau, a minima pour permettre aux zones de communiquer correctement sur du hardware partagé. Au final, ces possibilités sont beaucoup plus développées, allant jusqu'à une virtualisation complète des interfaces réseaux des zones qui n'est pas sans rappeler ce qu'IBM propose sur sa gamme pSeries ...

Un peu d'historique

Les STREAMS

Depuis l'apparition de Solaris 2.x, la pile IP de l'OS est basée sur le framework STREAMS. En pratique, ce framework permet de transférer de manière simple des messages d'un module STREAMS à un autre module STREAMS. La gestion des connexions réseaux s'en est retrouvée très répartie, entre les threads utilisateurs qui exécutaient des appels système, le thread du driver, et les différents threads STREAMS. Cette répartition a imposé l'utilisation de nombreux verrous (les mutex) sur les structures de données en mémoire, pour assurer un multi-threading sain où personne ne se marcherait sur les pieds.

Ce modèle a fini par montrer ses limites, par le biais de deux inconvénients majeurs (qui n'en étaient pas au départ, mais se sont révélés au fur et à mesure de l'évolution de la technologie) :

  • Le coût de mise en oeuvre d'un STREAM est élevé. Ca ne posait pas de problèmes particuliers au départ, car il y avait généralement peu de connexions, et elles duraient longtemps. Dans un environnement de type web, en revanche, caractérisé par un grand nombre de connexions très brèves, ce système est pénalisant.
  • Ce système ne tenait absolument pas compte du positionnement des données en mémoire vis-à-vis des processeurs. Dans des environnements majoritairement mono-processeurs, cela ne posait pas de problèmes. Avec l'explosion des systèmes multi-processeurs, le fait d'avoir des paquets arrivant sur différents processeurs génère une charge supplémentaire de déplacement de contexte d'un processeur à un autre.

Les drivers

Pour ce qui est de la gestion des interfaces physiques (ou NIC, pour Network Interface Card), les versions de Solaris avant la 10 utilisaient des drivers appelés DLPI (Data Link Provider Interface). Ces drivers pouvaient se présenter de deux façons différentes.

Soit le driver était monolithique, implémentant lui-même toutes les fonctions requises :

Soit le driver était partiel, s'appuyant sur la Generic Driver Library v2 (GLDv2), une bibliothèque de fonctions standards évitant à chaque fabricant de réinventer la roue à chaque fois :

L'implémentation Solaris 10

L'approche FireEngine

L'idée retenue pour la pile réseau de Solaris 10 a été de fusionner toutes les couches protocolaires au sein d'un seul module STREAMS, lui-même multi-threadé. Au lieu de protéger les structures de données elles-mêmes, FireEngine propose un mécanisme de synchronisation par processeur, appelée une squeue. Chaque squeue est liée à un processeur, et chaque connexion est liée à une squeue. Cela garantit que les paquets d'une connexion donnée ne seront plus dispatchés sur plusieurs processeurs (c'est un mécanisme généralement connu sous le nom de CPU affinity). Par ailleurs, la squeue garantit l'exclusion mutuelle de l'accès aux ressources de manière satisfaisante : seul un thread à la fois peut accéder à une connexion donnée.

Les drivers GLDv3

La nouvelle architecture, vers laquelle ont été portés la plupart des drivers importants, introduit des couches d'abstraction dans la communication avec une NIC. Par ailleurs, contrairement aux versions précédentes, ce modèle n'est plus basé sur les STREAMS, mais sur une interface du kernel appelée Data-Link Services (DLS). Pour garantir la compatibilité avec les modules STREAMS qui ne seraient pas conscients de cette couche, une interface spécifique a été développée, le Data-Link Driver (DLD).

Les drivers des fournisseurs en eux-mêmes sont assez similaires aux versions précédentes, mais s'appuient sur une couche supplémentaire, le MAC Services Module.

Virtualisation réseau : CrossBow

Le principe

Le projet CrossBow, en version bêta depuis mars 2008, offre des fonctionnalités de virtualisation réseau (et de gestion de ressources, en intégrant les aspects QoS directement dans la pile, mais nous n'aborderons pas ce sujet ici), en permettant le découpage d'une NIC en interfaces virtuelles, les VNIC. Cette fonctionnalité peut s'appuyer ou non sur la capacité de la NIC à découper sa mémoire embarquée en segments et en queues (classification matérielle), qui pourront avoir leurs propres canaux DMA et leurs propres interruptions.

Chacun de ces ensembles sera rattaché à une squeue qui lui est propre, et on pourra optionnellement affecter à chacun une adresse MAC et une VNIC, permettant de l'administrer depuis l'OS exactement comme une interface physique. Typiquement, la création d'une VNIC ne se fera que dans un environnement virtualisé (containers, xVM, LDoms).

Enfin, la communication inter-VNIC (sur une même NIC physique) se fait intégralement en mémoire, par le biais d'un switch virtuel.

Virtualisation sans interface physique

Une option intéressante de cette architecture est la possibilité de créer un réseau virtuel sans la moindre interface physique (à l'instar de ce qui existe depuis de nombreuses années chez VMWare). Pour ce faire, on s'appuie sur un type spécial de VNIC, appelé VNIC anchor, non rattachée à une interface physique, mais sur laquelle on peut en revanche attacher d'autres VNIC.

Une application particulière : zones ip-exclusive

A l'avenir, cette option permettra également de dédier des VNIC à des zones non-globales, avec l'option ip-exclusive (voir ce billet pour plus de détails), offrant les avantages des NIC dédiées tout en partageant une même ressource physique.