Exportando dispositivos PCI a una VM con Xen y Debian Lenny

Por lo general en un entorno virtualizado, el hypervisor se encarga de gestionar el acceso a los recursos de hardware de las distintas máquinas virtuales; sin embargo, en algunas ocasiones deseamos que una VM (máquina virtual) tenga acceso *directamente* a un dispositivo físico (PCI-USB) de nuestra máquina.

Usando PCI-back

PCI back es un módulo del kernel Xen que nos permite “ocultar” un dispositivo al dom0 (máquina base) para ser “expuesto” o “exportado” a alguna de las máquinas o VM (de manera exclusiva).

PCI-Back no es un módulo que se encuentre activo (al menos en la versión de kernel que tengo de Xen para Debian Lenny), pero activarlo es bastante fácil.

Habilitando PCIback en Debian Lenny

Para habilitar PCIback bastará con agregar este módulo a la lista de módulos gestionados por el initramfs:

echo pciback >> /etc/initramfs-tools/modules

Luego, creamos un nuevo initrd, esta vez con pciback habilitado, de manera que podamos obviamente, arrancar sin PCIback:

mkinitramfs -o /boot/initrd.img-`uname -r`-pciback `uname -r`

Esto, generó un initrd llamado:

initrd.img-2.6.26-2-xen-amd64-pciback

y edito el menu.lst (en grub2 sería el grub.cfg o editar las reglas correspondientes):
de:

module /boot/vmlinuz-2.6.26-2-xen-amd64 root=/dev/sda1 ro console=tty0
module /boot/initrd.img-2.6.26-2-xen-amd64

a:

module /boot/vmlinuz-2.6.26-2-xen-amd64 root=/dev/sda1 ro console=tty0
module /boot/initrd.img-2.6.26-2-xen-amd64-pciback

Al reiniciar el dom0, ya tendremos habilitado PCIback.

Y reiniciamos el dom0.

Exportando una tarjeta de red en exclusiva para un VM

En mi caso, tengo una infraestructura para un servidor de correo, como la planteada en la figura:

No hemos creado un bridge con la eth1, ya que disponemos de una sola IP asignada por el ISP a través de un Frame Relay y no se compartirá dicha interfaz, para optimizar el rendimiento (un 35% mejor) y otras razones, la eth1 se “ocultará” y será entregada a la dom1 (que será un servidor de correo, con dos interfaces, una pública y otra privada).

Creando nuestro archivo pcibind:

Vamos a crear un archivo PCIbind, que se ejecutará al inicio, con este, podremos configurar qué dispositivos PCI se ocultarán, además podemos “apagar” la configuración en cualquier momento (a diferencia de usar pciback.hidden() en el grub, que requiere reiniciar el equipo dom0).

El archivo tiene la siguiente forma:

#!/bin/bash
# /etc/init.d/pcibind  <graham@vpac.org> Nov 2008. Rev: 20081202
#
# description: Bind a device to the PCI Backend's list

case "$1" in
 start) cat /etc/pcibind.conf 2>/dev/null |
 awk '{if ($1 !~ /#/) if($NF > 1) print $0}' |
 while read PCI ; do
 SLOT=`echo "$PCI" | awk '{print $1}'`
 DRVR=`echo "$PCI" | awk '{print $2}'`
 echo -n $SLOT > /sys/bus/pci/drivers/$DRVR/unbind
 echo -n $SLOT > /sys/bus/pci/drivers/pciback/new_slot
 echo -n $SLOT > /sys/bus/pci/drivers/pciback/bind
 done                                                   ;;
 stop ) cat /etc/pcibind.conf 2>/dev/null |
 awk '{if ($1 !~ /#/) if($NF > 1) print $0}' |
 while read PCI ; do
 SLOT=`echo "$PCI" | awk '{print $1}'`
 DRVR=`echo "$PCI" | awk '{print $2}'`
 echo -n $SLOT > /sys/bus/pci/drivers/pciback/unbind
 echo -n $SLOT > /sys/bus/pci/drivers/pciback/remove_slot
 echo -n $SLOT > /sys/bus/pci/drivers/$DRVR/bind
 done                                                   ;;
 * ) echo "Usage: $0 {start|stop}"; exit 2                  ;;
esac
exit 0

El archivo va en /etc/init.d/pcibind y busca un archivo de configuración en /etc/pcibind.conf.

Luego de creado, le damos privilegios a root sobre el archivo, lo hacemos ejecutable y lo agregamos a rc.d

chmod 0750 /etc/init.d/pcibind
update-rc.d pcibind defaults

Con esto, ya tenemos pcibind listo para “ocultar” los dispositivos PCI que le indiquemos.

Descubriendo las NIC Ethernet

Cuando ejecutamos:

ifconfig -a

Vemos la información de la eth1:

eth1      Link encap:Ethernet  HWaddr 00:ab:fe:85:25:55  
 inet6 addr: fe80::218:feff:fe83:2450/64 Scope:Link
 UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
 RX packets:10779 errors:0 dropped:0 overruns:0 frame:0
 TX packets:56975 errors:0 dropped:0 overruns:0 carrier:0
 collisions:0 txqueuelen:1000 
 RX bytes:698027 (681.6 KiB)  TX bytes:3653233 (3.4 MiB)
 Interrupt:26

Nos interesa la MAC Address de la tarjeta de red; ahora descubriremos su PCI-id y el módulo del kernel que la gestiona:

para ello ejecutamos:

lspci -v

Y en su salida encontraremos algo como esto:

03:02.0 Ethernet controller: Broadcom Corporation NetXtreme BCM5703 Gigabit Ethernet (rev 10)
 Subsystem: Compaq Computer Corporation NC7771 Gigabit Server Adapter (PCI-X, 10,100,1000-T)
 Flags: bus master, 66MHz, medium devsel, latency 64, IRQ 29
 Memory at fdde0000 (64-bit, non-prefetchable) [size=64K]
 [virtual] Expansion ROM at c4210000 [disabled] [size=64K]
 Capabilities: [40] PCI-X non-bridge device
 Capabilities: [48] Power Management version 2
 Capabilities: [50] Vital Product Data <?>
 Capabilities: [58] Message Signalled Interrupts: Mask- 64bit+ Queue=0/3 Enable-
 Kernel driver in use: tg3
 Kernel modules: tg3

Si desean, pueden ejecutar primero con lspci -v | grep Ethernet

03:02.0 Ethernet controller: Broadcom Corporation NetXtreme BCM5703  Gigabit Ethernet (rev 10)

El primer valor (en negrillas) es el PCI-id

Con esto descubrimos que la tarjeta eth1 es una Broadcom, PCI-id: 03:02.0 y la gestiona el módulo del kernel tg3.

Ocultando la tarjeta al dom0

Para ocultar cualquier dispositivo PCI, simplemente lo agregamos como un línea en el archivo /etc/pcibind.conf:

# /etc/pcibind.conf
# SLOT        DRIVER

0000:03:02.0  tg3  # MAC=00:ab:fe:85:25:55

Hemos puesto el PCI-id (slot PCI), el módulo del kernel (tg3) y como comentario recordatorio, la mac-address de la tarjeta.

Al ejecutar

/etc/init.d/pcibind start

Veremos que el dispositivo eth1 “desaparece” y ya no es accedido por el equipo local.

Si deseamos “reaparecerlo” (la VM que lo tenga asignado debe estar apagada) simplemente ejecutamos:

/etc/init.d/pcibind stop

Asignado el recurso PCI a una VM

Para asignar el recurso a una VM debemos editar el archivo /etc/network/interfaces (antes que nada) para que la máquina al reiniciar pueda hacer uso de la tarjeta NIC, simplemente agregamos:

hwaddress ether 00:AB:FE:85:25:55

Quedando:

iface eth1 inet static
address 200.105.240.254
netmask 255.255.255.248
gateway 200.105.240.249
dns-search cantv.net
dns-nameservers 200.44.32.12
hwaddress ether 00:AB:FE:85:25:55

Apagamos la VM luego de agregar esa opción en el /etc/network/interfaces

Luego, en el archivo de configuración de la VM en Xen (/etc/xen/vmcorreo.cfg) agregamos la siguiente opción:

pci = [ “03:02.0” ]

Que representa el dispositivo (o los dispositivos) PCI que vamos a asignar a la VM:

Quedando:

#
#  Networking
#
vif         = [ 'ip=172.16.80.20,mac=00:16:3E:CF:3F:AA,bridge=brlocal' ]
pci         = [ "03:02.0" ]

Cuando iniciemos la VM (xm create vmcorreo.cfg) veremos que tendremos 2 interfaces de red, una virtual (eth0) que sale por el bridge del dom0, y una eth1, que será físicamente nuestra interfaz a Internet.

Como nota adicional, recuerden instalar todos los módulos en su domU:

apt-get install linux-modules-`uname -r`

Sobre todo si tienen una NIC u otro hardware PCI que requiera módulos especiales del kernel para ser detectado.

Acerca de phenobarbital

http://about.me/phenobarbital

Publicado el 26 marzo 2010 en Cultura Libre, Linux, PlanetaLinux, trucos de la abuela, Weyu y etiquetado en , , , , , , , , , , , . Guarda el enlace permanente. Deja un comentario.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: