Virtio: marco de virtualización de entrada/salida para Linux

E/S paravirtualizada con KVM y lguest

El kernel Linux soporta una amplia gama de esquemas de virtualización que continúa creciendo a medida que la virtualización avanza y se descubren nuevos esquemas (por ejemplo, lguest). Pero con todos los esquemas de virtualización que se ejecutan sobre Linux, ¿cómo se logra explotar el kernel subyacente para la virtualización de E/S? La respuesta es virtio. Virtio proporciona una abstracción eficiente para hipervisores y un conjunto común de drivers de virtualización de E/S. Descubra virtio y sepa por qué Linux pronto será el hipervisor preferido.

Comparta su expertise: ¿Influye en su decisión de usar un hipervisor en particular el soporte de un esquema de E/S específico? Agregue sus comentarios a continuación.

M. Tim Jones, Consultant Engineer, Emulex Corp.

M. Tim JonesM. Tim Jones es arquitecto de firmware incrustado y es autor de Artificial Intelligence: A Systems Approach, GNU/Linux Application Programming (actualmente en su segunda edición), AI Application Programming (en su segunda edición) y BSD Sockets Programming from a Multilanguage Perspective. Sus antecedentes en la ingeniería abarcan desde el desarrollo de kernels para naves espaciales geosincrónicas hasta la arquitectura de sistemas incrustados y el desarrollo de protocolos de redes. Tim es Consultant Engineer de Emulex Corp. en Longmont, Colorado.



19-03-2010

Conéctese con Tim

Tim es uno de nuestros autores más populares y prolíficos. Navegue todos los artículos de Tim en developerWorks. Lea el perfil de Tim y conéctese con él y con otros autores y lectores en My developerWorks.

En síntesis, virtio es un nivel de abstracción sobre dispositivos en un hipervisor paravirtualizado. virtio fue desarrollado por Rusty Russell para soportar su propia solución de virtualización llamada lguest. Este artículo comienza con una introducción de la paravirtualización y los servicios emulados y luego analiza a virtio en detalle, centrándose en el marco virtio de la versión 2.6.30 del kernel.

Linux es el campo de juego del hipervisor. Como vimos en mi artículo sobre Linux como hipervisor, Linux ofrece una variedad de soluciones de hipervisor con diferentes atributos y ventajas. Algunas de estas son: Máquina virtual basada en el kernel (Kernel-based Virtual Machine - KVM), lguest y el modo de usuario de Linux. Tener todas estas soluciones de hipervisor distintas en Linux permite que los gravámenes sobre el sistema operativo se apliquen en base a las necesidades independientes de cada una. Uno de estos gravámenes es la virtualización de dispositivos. En lugar de depender de una serie de mecanismos de emulación de dispositivos (para redes, bloques y otros drivers), virtio proporciona un front-end común para las emulaciones de dispositivos que estandariza la interfaz y aumenta las posibilidades de reutilización del código en distintas plataformas.

Comparación entre virtualización total y paravirtualización

Únase a los grupos ecológicos en My developerWorks

Converse sobre distintos temas y comparta recursos sobre energía, eficiencia y medioambiente en el espacio GReen IT Report y el grupo Green computing en My developerWorks.

Comencemos con una breve descripción de dos tipos de esquemas de virtualización diferentes: la virtualización y la paravirtualización. En la virtualización total, el sistema operativo huésped se ejecuta sobre un hipervisor que se apoya en el metal base. El huésped no sabe que está siendo virtualizado y no necesita realizar cambios para trabajar en esta configuración. Por el contrario, en la paravirtualización, el sistema operativo huésped no sólo sabe que se está ejecutando en un hypervisor, sino que además incorpora código para mejorar la eficiencia de las transiciones del huésped al hipervisor (ver Figura 1).

En el esquema de virtualización total, el hipervisor debe emular el hardware del dispositivo, es decir, realizar la emulación en el nivel más bajo de la conversación (en un driver de red, por ejemplo). La abstracción en esta emulación es limpia, pero también es de alta complejidad y es la más ineficiente de todas. En el esquema de paravirtualización, el huésped y el hipervisor pueden cooperar para lograr una emulación eficiente. La desventaja del enfoque de paravirtualización consiste en que el sistema operativo sabe que está siendo virtualizado y requiere modificaciones para funcionar.

Figura 1. Emulación de dispositivos en entornos de virtualización total y paravirtualización
Device emulation in full virtualization and paravirtualization environments

El hardware se mantiene en constante cambio en relación con la virtualización. Los nuevos procesadores incorporan instrucciones avanzadas para mejorar la eficiencia de las transiciones de hipervisores y sistemas operativos huéspedes. Además, el hardware continúa cambiando para posibilitar la virtualización de entrada/salida (E/S) (ver la sección de Recursos para saber más acerca del passthrough Peripheral Controller Interconnect [PCI] y la virtualización de E/S de raíz única y multi-raíz).

Alternativas de virtio

virtio no está completamente solo en este espacio. Xen proporciona drivers de dispositivos paravirtualizados y VMware aporta las denominadas Guest Tools (herramientas de huéspedes)

Sin embargo, en entornos de virtualización total tradicionales, el hipervisor debe capturar las solicitudes y luego emular los comportamientos del hardware real. Aunque esto brinda una mayor flexibilidad (a saber, ejecución en un sistema operativo sin realizar modificaciones), también suma ineficiencia (ver el sector izquierdo de la Figura 1). El sector derecho de la Figura 1 muestra un caso de paravirtualización. En éste, el sistema operativo huésped sabe que se está ejecutando en un hipervisor e incluye drivers que actúan como front-end. El hipervisor implementa los drivers de back-end para cada emulación de dispositivo en particular. virtio participa en estos drivers de front-end y back-end proporcionando una interfaz estandarizada que permite el desarrollo de acceso a dispositivos emulados para propagar la reutilización del código y aumentar la eficiencia.


Abstracción para huéspedes de Linux

Como vimos en la sección anterior, virtio es una abstracción para un conjunto de dispositivos emulados comunes en un hipervisor paravirtualizo. Este diseño permite al hipervisor exportar un conjunto común de dispositivos y ponerlos a disposición a través de una API (Interfaz de Programación de Aplicaciones). La Figura 2 muestra por qué esto resulta importante. Con los hipervisores paravirtualizos, los huéspedes implementan un conjunto común de interfaces y la emulación de dispositivos particulares se realiza detrás de un conjunto de drivers de back-end. No es necesario que los drivers de back-end sean comunes, siempre y cuando estos implementen los comportamientos requeridos por el front-end.

Figura 2. Abstracciones de drivers con virtio
Driver abstractions with virtio

Tome en cuenta que, en realidad, la emulación de dispositivos (si bien no se requiere) ocurre en el espacio de usuario usando QEMU, a fin de que los drivers de back-end se comuniquen dentro del espacio de usuario del hipervisor para facilitar la E/S a través de QEMU. QEMU es un emulador de sistemas que, además de brindar una plataforma de virtualización de sistemas operativos, proporciona emulación para sistemas completos (controladores de host de PCI, discos, redes, hardware de video, controladores USB y otros elementos de hardware).

La API de virtio usa una abstracción de buffer simple para encapsular las necesidades de comandos y datos del huésped. Repasemos los componentes internos de la API de virtio.


Arquitectura de virtio

Además de los drivers de front-end (implementados en el sistema operativo huésped) y los drivers de back-end (implementados en el hipervisor), virtio define dos capas para soportar la comunicación del huésped al hipervisor. En el nivel superior (denominado virtio) encontramos la interfaz de cola virtual que adjunta conceptualmente los drivers de front-end a los drivers de back-end. Los drivers puede usar colas o no, dependiendo de las necesidades de cada uno. Por ejemplo, el driver de red virtio usa dos colas virtuales (una de recepción y otra de transmisión), mientras que el driver de bloques virtio usa una sola. Las colas virtuales, por el hecho de ser virtuales, se implementan en realidad como anillos que efectúan transversalmente la transición del huésped al hipervisor. Esto podría implementarse de varias maneras, siempre que el huésped y el hipervisor compartan la forma de implementación.

Figura 3. Arquitectura de nivel superior del marco virtio
High-level architecture

En la Figura 3 se listan cinco drivers de front-end para dispositivos de bloques (como discos), dispositivos de red, emulación PCI, un balloon driver (para la gestión dinámica del uso de memoria de huésped), y un driver de consola. A cada driver de front-end le corresponde un driver de back-end del hipervisor.

Jerarquía conceptual

Definiremos la jerarquía de objetos mostrada en la Figura 4 desde la perspectiva del huésped. En primer lugar se encuentra virtio_driver, que representa el driver de front-end en el huésped. Los dispositivos que coinciden con este driver aparecen encapsulados por virtio_device(representación del dispositivo en el huésped), el cual se refiere a la estructura virtio_config_ops (que define las operaciones de configuración del dispositivo virtio). virtio_deviceaparece referido en la virtqueue (que incluye una referencia al virtio_device que atiende). Finalmente, cada objeto de virtqueue referencia al objeto virtqueue_ops, el cual define las operaciones de cola subyacentes para gestionar el driver del hipervisor. Si bien las operaciones de la cola son el núcleo de la API de virtio, a continuación proporcionaré un breve análisis y luego profundizaré en las operaciones de virtqueue_ops.

Figura 4. Jerarquía de objetos del front-end de virtio
Object hierarchy of the Virtio front end

El proceso comienza con la creación de un virtio_driver y el posterior registro a través de register_virtio_driver. La estructura de virtio_driver define el driver de dispositivo de nivel superior, una lista de ID de dispositivos soportados por el driver, una tabla de características (de acuerdo con el tipo de dispositivo) y una lista de funciones de devolución de llamada. Cuando el hipervisor identifica la presencia de un nuevo dispositivo que coincide con un ID de dispositivo de la lista de dispositivos, se llama a la función probe (proporcionada en el objeto virtio_driver) para dejar pasar el objeto virtio_device. Este objeto se almacena en caché con los datos de gestión del dispositivo (de acuerdo con el driver). Dependiendo del tipo de driver, pueden invocarse funciones virtio_config_ops para obtener o establecer opciones específicas al dispositivo (por ejemplo, obtener el estado lectura/escritura del disco en un dispositivo virtio_blk o establecer el tamaño del bloque de un dispositivo de bloques).

Observe que virtio_device no incluye ninguna referencia a virtqueue(pero virtqueue sí referencia a virtio_device). Para identificar las virtqueue s que se asocian con este virtio_device se usa el objeto virtio_config_ops con la función find_vq. Este objeto devuelve las colas virtuales asociadas con esta instancia virtio_device. La función find_vq también permite la especificación de una función de devolución de llamada de virtqueue (ver la estructura virtqueue de la Figura 4), lo cual sirve para notificar al huésped sobre buffers de respuesta del hipervisor.

virtqueue es una estructura simple que identifica: una función de devolución de llamada opcional (a la cual se llama cuando el hipervisor consume los buffers), una referencia a virtio_device, una referencia a las operaciones de virtqueue y una referencia priv especial que indica la implementación subyacente a usar. Aunque la devolución de llamada o callback es opcional, es posible activar o desactivar devoluciones de llamadas dinámicamente.

Pero el núcleo de esta jerarquía es virtqueue_ops, que define la forma en que los comandos y los datos se mueven entre el huésped y el hipervisor. Primero analicemos el objeto que se agrega o elimina de virtqueue.

Buffers de virtio

Los drivers huéspedes (front-end) se comunican con drivers del hipervisor (back-end) a través de buffers. En una E/S, el huésped proporciona uno o más buffers que representan la solicitud. Por ejemplo, se podrían proporcionar tres buffers, de los cuales el primero represente una solicitud de Read (Leer) y los dos siguientes representen los datos de respuesta. Internamente, esta configuración se representa como una lista de dispersión/agrupación (cada entrada de la lista representa una dirección y una longitud).

API central

El vínculo entre el driver del huésped y el driver del hipervisor se efectúa a través de virtio_device y en general a través de virtqueue s. virtqueue soporta su propia API, la cual consta de cinco funciones. La primera función, add_buf se usa para proporcionar una solicitud al hipervisor. Esta solicitud tiene el formato de lista de dispersión/agrupación antes descripto. Para add_buf, el huésped proporciona la virtqueue donde debe colocarse la solicitud, la lista de dispersión/agrupación (arreglo de direcciones y longitudes), el número de buffers que funcionan como entradas salientes (destinadas al hypervisor subyacente), y el número de entradas entrantes (para las cuales el hipervisor almacenará datos y volverá al huésped). Cuando la solicitud realizada al hipervisor se efectúa a través de add_buf, el huésped puede notificar al hipervisor la nueva solicitud usando la función kick. Para un mejor rendimiento, el huésped deberá cargar la mayor cantidad de buffers posible en virtqueue antes de notificar a través de kick.

Las respuestas del hipervisor se realizan a través de la función get_buf. El huésped puede interrogar simplemente llamando a esta función o esperar la notificación a través de la función virtqueue callback proporcionada. Una vez que el huésped conoce que existen buffers disponibles, una llamada a get_buf devuelve los buffers completados.

Las dos últimas funciones de la API de virtqueue son enable_cb y disable_cb. Estas funciones se usan para activar o desactivar el proceso de devolución de llamada (mediante la función callback inicializada en virtqueue a través de la función find_vq). Tome en cuenta que la función de devolución de llamada y el hipervisor se encuentran en espacios de direcciones diferentes, por lo cual la llamada se realiza a través de una llamada de hipervisor indirecta (como, por ejemplo, kvm_hypercall).

El formato, el orden y el contenido de los buffers sólo tienen significado para los drivers de front-end y back-end. El transporte interno (anillos, en esta implementación) se limita a mover buffers y no tiene conocimiento de su representación interna.


Drivers virtio de ejemplo

Encontrará la fuente de los distintos drivers de front-end dentro del subdirectorio ./drivers del kernel de Linux. El driver de red de virtio se encuentra en ./drivers/net/virtio_net.c y el driver de bloques de virtio se encuentra en ./drivers/block/virtio_blk.c. El subdirectorio ./drivers/virtio proporciona la implementación de las interfaces virtio (virtio dispositivo, driver, virtqueue y anillo). También se usó virtio en investigaciones de Computación de alto rendimiento (High-Performance Computing - HPC) para el desarrollo de comunicaciones entre máquinas virtuales (VM) a través de transmisión con memoria compartida. Específicamente, esto se implementó a través de una interfaz PCI virtualizada usando el driver PCI de virtio. Sepa más acerca de estos proyectos consultando la sección de Recursos.

Puede poner en práctica esta infraestructura de paravirtualización hoy mismo en el kernel de Linux. Lo único que necesitará es un kernel que actúe como hipervisor, un kernel huésped y QEMU para la emulación de dispositivos. Puede usar KVM (modulo existente en el kernel huésped) o lguest de Rusty Russell (kernel huésped de Linux modificado). Ambas soluciones de virtualización soportan virtio (además de QEMU para emulación de sistemas y libvirt para gestión de la virtualización).

El trabajo de Rusty aportó una base de código más sencilla para los drivers paravirtualizados y una emulación más rápida de los dispositivos virtuales. Pero, por sobre todo, se ha comprobado que virtio proporciona un mejor rendimiento (2 a 3 veces mejor en E/S de redes) que las soluciones comerciales actuales. Esta mejora del rendimiento tiene sus costos, pero bien vale la pena cuando se usa Linux como hipervisor y huésped.


En el futuro

Si bien probablemente nunca desarrolle drivers de front-end o back-end para virtio, éste implementa una arquitectura interesante y vale la pena comprenderlo con mayor profundidad. virtio abre nuevas oportunidades de eficiencia en entornos de E/S paravirtualizada y se basa en trabajos anteriores realizados en Xen. Linux sigue demostrando ser un hipervisor de producción y una plataforma de investigación para nuevas tecnologías de virtualización. virtio es un ejemplo más de las fortalezas que posee Linux y de cuán abierto es.

Recursos

Aprender

  • Uno de los mejores recursos que brinda información técnica detallada acerca de virtio es "Virtio: towards a de factor standard for virtual I/O devices" de Rusty Russell. Este trabajo ofrece una explicación minuciosa de virtio y sus componentes internos.
  • Este artículo abordó dos mecanismos de virtualización: la virtualización total y la paravirtualización. Para saber más acerca de la variedad de mecanismos de virtualización en Linux, lea el artículo de Tim "Virtual Linux" (developerworks, diciembre de 2006).
  • La clave de virtio consiste en explotar la paravirtualización para mejorar el rendimiento general de E/S. Para saber más acerca del rol de Linux como hipervisor y en la emulación de dispositivos, lea los artículos de Tim "Anatomy of a Linux hypervisor" (developerWorks, mayo de 2009) y "Linux virtualization and PCI passthrough" (developerworks, octubre de 2009).
  • Este artículo se refirió a la emulación de dispositivos. Una de las principales aplicaciones que proporciona esta funcionalidad es QEMU (emulador de sistemas). Lea más acerca de QEMU en el artículo de Tim "System emulation with QEMU" (developerWorks, septiembre de 2007).
  • Xen también incluye el concepto de drivers paravirtualizados. Paravirtual Windows Drivers se refiere tanto a la paravirtualización como a la virtualización asistida por hardware (HVM) en particular.
  • Uno de los beneficios más importantes que ofrece virtio es el rendimiento en entornos paravirtualizados. Este mensaje de blog de btm.geek muestra la ventaja de rendimiento que brinda virtio usando KVM.
  • Este artículo se refirió a la intersección entre libvirt (API de virtualización abierta) y el marco virtio. El wiki de libvirt explica cómo especificar dispositivos virtio en libvirt.
  • Este artículo muestra dos soluciones de hipervisor que aprovechan el entorno de virtio: lguest, hypervisor x86 desarrollado por Rusty Russell y KVM, otro hypervisor basado en Linux que inicialmente se construyó dentro del kernel de Linux.
  • Un uso interesante que se dio a virtio fue el desarrollo de la transmisión de mensajes con memoria compartida para que VM pudieran comunicarse entre sí a través del hipervisor. Este trabajo de SpringerLink describe este uso.
  • En la zona Linux en developerWorks encuentre más recursos para desarrolladores Linux y dé una mirada a los artículos y tutoriales más populares.
  • Vea todos los tutoriales Linux y consejos Linux en developerWorks.
  • Manténgase al día con los eventos técnicos y transmisiones por Internet de developerWorks.
  • Siga a developerWorks en Twitter.

Obtener los productos y tecnologías

  • Con el software de prueba de IBM, disponible para su descarga directamente desde developerWorks, construya su próximo proyecto de desarrollo en Linux.

Comentar

  • Participe en la comunidad My developerWorks. Conéctese con otros usuarios de developerWorks y mire los blogs, foros, grupos y wikis orientados a los desarrolladores.

Comentarios

developerWorks: Ingrese

Los campos obligatorios están marcados con un asterisco (*).


¿Necesita un IBM ID?
¿Olvidó su IBM ID?


¿Olvidó su Password?
Cambie su Password

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

 


La primera vez que inicie sesión en developerWorks, se creará un perfil para usted. La información en su propio perfil (nombre, país/región y nombre de la empresa) se muestra al público y acompañará a cualquier contenido que publique, a menos que opte por la opción de ocultar el nombre de su empresa. Puede actualizar su cuenta de IBM en cualquier momento.

Toda la información enviada es segura.

Elija su nombre para mostrar



La primera vez que inicia sesión en developerWorks se crea un perfil para usted, teniendo que elegir un nombre para mostrar en el mismo. Este nombre acompañará el contenido que usted publique en developerWorks.

Por favor elija un nombre de 3 - 31 caracteres. Su nombre de usuario debe ser único en la comunidad developerWorks y debe ser distinto a su dirección de email por motivos de privacidad.

Los campos obligatorios están marcados con un asterisco (*).

(Por favor elija un nombre de 3 - 31 caracteres.)

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

 


Toda la información enviada es segura.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=90
Zone=Linux
ArticleID=476032
ArticleTitle=Virtio: marco de virtualización de entrada/salida para Linux
publish-date=03192010