Persistent storage device names in Linux
October 11th, 2007
Recently I purchased two external USB hard-drives, one from LACIE and another one from IOMEGA, that I plugged into one of my Linux workstations. I wanted these drives to be auto-mounted during boot, so I created a couple of entries in /etc/fstab. The problem is that, somehow, the Linux kernel is not always able to enumerate devices on a bus in the same order between reboots. Thus, sometimes the LACIE hard disk gets /dev/sdb and IOMEGA gets /dev/sdc, and other times it is the other way around. In fact, it gets even worse as my machine as a built-in 6×1 card-reader, so I also have /dev/sd{d,e,f,g}.
Looking at /etc/udev/rules.d, I found that Ubuntu has a nice 65-persistent-disk.rules file with very smart and useful udev entries that create symlinks under /dev/disk by disk ID, disk label, device path and device UUID:
/dev/disk/by-idcontains one symlink per physical device and partition. The symlink name is built using the device’s ID./dev/disk/by-labelcontains one symlink per partition. The symlink name is built using the partition volume label./dev/disk/by-pathcontains one symlink per physical device and parition. The symlink name is built using the device bus name./dev/disk/by-uuidcontains one symlink per partition. The symlink name is built using the partition UUID.
For example:
$ tree /dev/disk
/dev/disk
|-- by-id
| |-- scsi-1ATA_WDC_WD1600JS-75NCB2_WD-WCANM44 -> ../../sda
| |-- scsi-1ATA_WDC_WD1600JS-75NCB2_WD-WCANM44-part1 -> ../../sda1
| |-- scsi-1ATA_WDC_WD1600JS-75NCB2_WD-WCANM44-part2 -> ../../sda2
| |-- scsi-1ATA_WDC_WD1600JS-75NCB2_WD-WCANM44-part5 -> ../../sda5
| |-- scsi-1ATA_WDC_WD1600JS-75NCB2_WD-WCANM44-part6 -> ../../sda6
| |-- usb-Generic_Flash_HS-CF_26020128B005 -> ../../sdd
| `-- usb-Generic_Flash_HS-COMBO_26020128B005 -> ../../sde
|-- by-label
| `-- DellUtility -> ../../sda1
|-- by-path
| |-- pci-0000:00:1f.1-scsi-0:0:0:0 -> ../../scd0
| |-- pci-0000:00:1f.2-scsi-0:0:0:0 -> ../../sda
| |-- pci-0000:00:1f.2-scsi-0:0:0:0-part1 -> ../../sda1
| |-- pci-0000:00:1f.2-scsi-0:0:0:0-part2 -> ../../sda2
| |-- pci-0000:00:1f.2-scsi-0:0:0:0-part5 -> ../../sda5
| |-- pci-0000:00:1f.2-scsi-0:0:0:0-part6 -> ../../sda6
| |-- usb-26020128B005:0:0:0 -> ../../sdd
| `-- usb-26020128B005:0:0:1 -> ../../sde
`-- by-uuid
|-- 07D6-0701 -> ../../sda1
|-- 29982b9e-63a4-4d3f-8b88-ebc9d000c09f -> ../../sda5
`-- 6aa8745b-dbe2-4386-9697-cc0c2dee27d4 -> ../../sda6
Basically, what I did is replacing the entries I previously created in /et/fstab using absolute device names, like /dev/sdb1, with /dev/disk/by-label/<VOLUME> instead.
Name stability and predictability across reboots for devices is quite a nice feature in Ubuntu Linux. And this can be easily ported to other Linux distributions simply by copying /etc/udev/rules.d/65-persistent-disk.rules.
Playing music remotely using MPD
July 16th, 2007
From the home page of MPD:
Music Player Daemon (MPD) allows remote access for playing music (MP3, Ogg Vorbis, FLAC, AAC, Mod, and wave files) and managing playlists. MPD is designed for integrating a computer into a stereo system that provides control for music playback over a local network. It is also makes a great desktop music player, especially if you are a console junkie, like frontend options, or restart X often.
The idea behind using MPD was to be able to set up a multimedia computer that I could manage either locally or remotely. When I mean remotely, I don’t mean via VNC or X11/NX. For example, I don’t need the overhead of a full X11 session just to play music over the sound card of my multimedia computer. I might do that using MPlayer over a SSH/screen session or a text-based, command-line music player, but sometimes I like GUI applications too!
Also, detaching the music player controller (the daemon) from the client allows me to use different clients from different computers. Sometimes I’m using one of my Apple computers. Sometimes I’m using one of Linux boxes. Using a client that matches natively my operating system is something that I really appreciate.
For Linux I use Sonata. For Mac OS X I use Theremin.
Installing MPD on Ubuntu Feisty Fawn
Installing MPD in Ubuntu Linux, as usual, it’s pretty straightforward:
sudo apt-get install mpd
By default, Ubuntu will install MPD, start it up and create the symbolic links under /etc/rc[0123456].d to make sure it gets started at the next system boot.
You might also want to edit MPD’s configuration file:
$EDITOR /etc/mpd.conf
In my case, the only thing I changed in this file is the bind_to_address directive to allow clients to connect remotely. It looks like this:
bind_to_address "0.0.0.0"
Installing Sonata on Ubuntu Feisty Fawn
Sonata is a nice Python-based, GTK+2.0-based MPD client. Thus, it’s multi-platform and can be run on Linux, *BSD, Solaris, Mac OS X and (I guess) even Windows.
To install Sonata on Ubuntu Linux, run apt-get as usual:
sudo apt-get install sonata
The first time you run Sonata, either from the command-line or from the menu, it will ask you where the MPD daemon is running. It defaults to localhost (and port 6600) so I changed that to point to the hostname of my multimedia computer.
Installing Sonata on Mac OS X
Installing Sonata on Mac OS X is a little bit more elaborated, since some of the components that Sonata requires are not installed by default on Mac OS X.
Sonata requires Python and, more concretely, PyGTK. Since I am already using MacPorts, getting PyGTK installed was a matter of running:
sudo /opt/local/bin/port install py-gtk2
The rest is pretty much the same as for Linux.
Installing Theremin.app on Mac OS X
Theremin.app is a nice, native Cocoa application for Mac OS X that sports Growl integration. For example, when MPD starts playing a new song, Theremin.app notifies the user via a Growl notification.
Download Theremin.app from Theremin’s Web site.
Extract it and run it:
tar jxvf Theremin_0.5.1.tbz open Theremin.app
Theremin.app can also be compiled from sources by downloading the source code from the Subversion repository and using Xcode to compile it. I must confess that I was lazy to that, so I chose to run the pre-compiled binaries.
QEMU, KQEMU and udev
February 8th, 2007
Now that KQEMU has switched to the GPL v2 license, I’m starting to get interested on it.
One problem with KQEMU is that modprobing the kernel module, kqemu.ko, doesn’t automatically create /dev/kqemu unless the proper udev rules are defined.
A cannonical udev rule file to get /dev/kqemu created automatically when kqemu.ko is loaded is:
# cat /etc/udev/rules.d/60-kqemu.rules KERNEL=="kqemu", NAME="%k", MODE="0666"'
Creating this file will tell udev to automatically create the corresponding special device file with permissions 0666 and owner root.root, but this can be easily changed to specify a different user group so that only a limited number of users, members of that group, can access KQEMU.
NetBSD 3.1 as a domU/guest on Xen
February 4th, 2007
Xen is one of the coolest pieces of software I have ever used. It allows me to partition my box into manageable pieces, for increased security and increased resource utilization. I have been playing extensively with Xen for more than a year and have also written some posts about it.
NetBSD is a lean, mean, fast free, open source operating system and is nicely supported under Xen, has nice features like the PF packet filter and the pkgsrc ports-like collection and runs in nearly every single hardware architecture on earth. Because of this, I decided to run NetBSD 3.1 on Xen. NetBSD can run either as the privileged domain (called dom0) or as an unprivileged guest (called domU) domain. Since I was already running Linux under Xen as a domU, I am mostly interested in running NetBSD 3.1 as a domU guest on Xen. dom0 can be either Red Hat Enterprise Linux 5.0 or Fedora Core 6, but feel free to use any other Linux distribution as most of them are Xen-ready.
As far as I know, there are some restrictions between the Xen hypervisor + dom0 kernel and domU kernel:
- You cannot mix PAE-enabled and non-PAE kernels.
For example, you cannot run a PAE-enabled dom0 kernel and/or PAE-enabled hypervisor and a non-PAE dom0/domU kernel.
This is currently a problem since Fedora Core 6 and Red Hat Enterprise Linux 5.0 both ship with a PAE-enabled Xen hypervisor and Xen-enabled kernels, but NetBSD does not currently ship a PAE-compatible, Xen-enabled kernel.
- You cannot mix 64-bit and 32-bit kernels.
You cannot run a 64-bit Xen hypervisor and 64-bit dom0 kernel and a 32-bit domU kernel.
Since both Fedora Core 6 and Red Hat Enterprise Linux 5.0 ship by default with a PAE-enabled (36-bit addressable memory space) Xen hypervisor and dom0 Xen-enabled Linux kernel, the first thing that I had to do in order to run NetBSD 3.1 as domU under Xen was to recompile the Linux kernel and the Xen hypervisor with PAE support completely disabled. This is described next.
Build Xen hypervisor and dom0 kernel without PAE
You can skip to the next section if you already have a non-PAE, working Xen installation.
The first thing I had to do is to downl the SRPM (source RPM) for the latest Linux kernel, for example kernel-2.6.19-1.2895.fc6.src.rpm, then install it by running:
# rpm -i kernel-2.6.19-1.2895.fc6.src.rpm
In file /usr/src/redhat/SPECS/kernel-2.6.spec replace the following:
%ifarch i686 %define buildpae 1 # we build always xen HV with pae %define xen_flags verbose=y crash_debug=y pae=y %endif
with:
%ifarch i686 %define buildpae 0 # we build always xen HV with pae %define xen_flags verbose=y crash_debug=y %endif
This will cause the Xen hypervisor to be built without PAE support. Additionally, no PAE-enabled extra kernels will be built. The Xen kernel, however, uses its specific configuration file that has to be changed in order to disable PAE support. To disable PAE support for the Xen kernel, I reconfigured the kernel with no PAE support by running:
# rpmbuild -bp /usr/src/redhat/SPECS/kernel-2.6.spec # cd /usr/src/redhat/BUILD/kernel-2.6.19/linux-2.6.19.i386 # cp configs/kernel-2.6.19-i686-xen.config .config # make menuconfig
Make sure PAE is disabled by navigating to Processor type and features, then High Memory Support is set to either off or 4GB (but not 64GB).
Next, I copied the updated configuration file back to /usr/src/redhat/SOURCES, where it belongs. Also, we need to insert # i386 at the beginning of the file so that the RPM build process can derive the exact processor architecture from the config file when building the RPMs:
# cat <(echo "# i386") .config > ../../../SOURCES/kernel-2.6.19-i686-xen.config
The processor architecture is supplied to make during the build process in the form of ARCH=i386.
Now, let’s build the RPMs:
# rpmbuild -ba --target i686 ../../../SPECS/kernel-2.6.spec
We need to specify i686 as the target architecture since Fedora and Red Hat don’t use i386 anymore for kernels themselves — i386 is now only used for some common RPMs like kernel-headers.
Once the RPMs have been built, check the files under /usr/src/redhat/RPMS/i686. At least there should be a file called kernel-xen-2.6.19-1.2895.i686.rpm. This RPM contains several files, but the ones that we are interested in are:
- /boot/config-2.6.19-1.2895xen
Contains the kernel configuration. Make sure either
CONFIG_X86_PAEis set tonor is undefined. - /boot/vmlinuz-2.6.19-1.2895xen
The Linux Xen-enabled kernel.
- /boot/xen.gz-2.6.19-1.2895
The Xen hypervisor. In the most recent versions of Fedora Core and Red Hat Enterprise Linux, the Xen hypervisor and the Xen-enabled kernel are packaged in the same RPM. This is the right thing to do since both are tightly coupled.
Install the new Xen kernel and hypervisor:
# rpm -ivh --force /usr/src/redhat/RPMS/i686/kernel-xen-2.6.19-1.2895.i686.rpm
Reboot:
# reboot
I assume the system will boot correctly and into the new Xen hypervisor and Xen-enabled Linux kernel. You can check that by running:
# uname -a Linux xen 2.6.19-1.2895xen #1 SMP Sat Feb 3 16:56:34 CET 2007 i686 i686 i386 GNU/Linux
The next step is installing NetBSD 3.1 as a domU. This is covered next.
Installing NetBSD 3.1
The first step is preparing the Xen’s domU configuration file and its corresponding storage backend. Xen can use file-backed storage for a domU or block-backed storage (i.e. a disk partition or logical volume). Typically, block-backed storage is faster than file-backed storage, so I set up a 10GiB logical volume for NetBSD:
# lvcreate -n netbsd xen -L 10G
I also used NetBSD’s Internet-based installation since it’s the easiest way to get a working NetBSD installation and the NetBSD community have built Xen-enabled NetBSD kernels:
- netbsd-INSTALL_XEN3_DOMU
A Xen-based, domU kernel used to install NetBSD.
- netbsd-XEN3_DOMU
A Xen-based, domU kernel used to run the installed system.
Both files can be downloaded from /pub/NetBSD/NetBSD-3.1/i386/binary/kernel. Download and uncompress both of them:
# wget ftp://ftp.netbsd.org/pub/NetBSD/NetBSD-3.1/i386/binary/kernel/netbsd-*XEN3_DOMU.gz # zcat netbsd-INSTALL_XEN3_DOMU.gz > /boot/netbsd-INSTALL_XEN3_DOMU # zcat netbsd-XEN3_DOMU.gz > /boot/netbsd-XEN3_DOMU
If you are running SELinux, you will need to relabel these files properly or xm will be unable to load them into memory:
# chcon root system_u:object_r:boot_t /boot/netbsd*
Next, create the Xen configuration file for NetBSD. In my case, it looked like this:
# cat /etc/xen/auto/netbsd kernel = "/boot/netbsd-INSTALL_XEN3_DOMU" memory = 256 name = "netbsd" vif = [ 'mac=00:16:3e:00:00:11, bridge=xenbr0' ] disk = [ 'phy:/dev/xen/netbsd,hda,w' ] on_poweroff = 'destroy' on_reboot = 'restart' on_crash = 'restart'
Now, we will install NetBSD by starting the domain:
# xm create -c /etc/xen/auto/netbsd
This will start the new domain and will attach to its console. You can follow the Example Installation NetBSD document to assist you in installing NetBSD and also Xensource NetBSDdomU Wiki page.
Once the installer has finished, do not reboot. At the end of the installation process, you’ll be brought back to the main install screen. Select e: Utility menu, then a: Run /bin/sh, then type the following at the shell:
mount /dev/xbd0a /mnt cp -pR /dev/rxbd* /mnt/dev cp -pR /dev/xbd* /mnt/dev halt -p
This will copy the required special device files and shut down the guest. Now, you will have to modify the domain config file in order to use the standard NetBSD domU kernel, /boot/netbsd-XEN3_DOMU. Edit /etc/xen/auto/netbsd and replace:
kernel = "/boot/netbsd-INSTALL_XEN3_DOMU"
with:
kernel = "/boot/netbsd-XEN3_DOMU"
And boot the domain again:
# xm create -c /etc/xen/auto/netbsd
During boot, you will see some errors like:
wsconscfg: /dev/ttyEcfg: Device not configured
This is due to the NetBSD guest only having access to one physical console. To kill those errors, edit /etc/ttys from within the NetBSD guest and turn off all terminals except "console", like:
console "/usr/libexec/getty Pc" vt100 on secure ttyE0 "/usr/libexec/getty Pc" vt220 off secure ttyE1 "/usr/libexec/getty Pc" vt220 off secure ttyE2 "/usr/libexec/getty Pc" vt220 off secure ttyE3 "/usr/libexec/getty Pc" vt220 off secure ...
Also, comment out all screens in /etc/wscons.conf:
#screen 0 - vt100 #screen 1 - vt100 #screen 2 - vt100 #screen 3 - vt100 #screen 4 - - #screen 4 80x25bf vt100
That’s all. Now we have a fully functional NetBSD 3.1 domU guest running on Xen
References
The information and instructions on this post are based on:
- NetBSDdomU — How to install NetBSD as a domU on a Linux host.
- Example Installation — NetBSD example installation.
Ubuntu Edgy, AIGLX y Beryl
November 1st, 2006
Modifying screen brightness on AC state changes
September 11th, 2006
The acpid daemon listens to the /proc/acpi/event socket. When the Linux kernel any ACPI-related event, like an AC state change, it sends a message to that socket.
When the Linux kernel detects AC power loss, it sends a message to the socket. acpid then runs the /etc/acpi/power.sh script which, in turn, invokes all the scripts under /etc/acpi/battery.d directory, orderly.
When the Linux detects that AC power has been restored, it sends a message to the socket. acpid then runs /etc/acpi/power.sh which, in turn, invokes all the scripts under /etc/acpi/ac.d directory, orderly.
To make the LCD brightness dim when AC power is lost and return the LCD brightness to its previous value once AC power has been restored, we can create two new scripts:
/etc/acpi/ac.d/01-brightness.sh/etc/acpi/battery.d/01-brightness.sh
Both of these scripts use a configuration file, located at /etc/default/brightness. A sample configuration file is shown below:
/etc/default/brightness
# Whether or not enable LCD brightness control depending
# on AC power state.
BRIGHTNESS_CONTROL="yes"
# Binary used to control LCD brightness.
BRIGHTNESS_PROGRAM="/usr/local/bin/bl1"
# Defines the brightness level when running on batteries.
BRIGHTNESS_LEVEL_ON_BATTERY="10"
# Defines the default brightness level for the system when
# running on AC power. This value is superseded by the value
# stored in the ${BRIGHTNESS_LAST_LEVEL_FILE} file.
BRIGHTNESS_LEVEL_ON_AC="15"
# Defines where to store the brightness level used the last
# time the system was running on AC power.
BRIGHTNESS_LAST_LEVEL_FILE="/var/tmp/brightness"
For MacBook Pro, these scripts depend use bl1, which can be found at Basic backlight support for MacBook Pro, for the BRIGHTNESS_PROGRAM, used to control the LCD brightness.
/etc/acpi/ac.d/01-brightness.sh
The following shell script restores the brightness level in use before losing AC power:
#!/bin/bash # Load configuration parameters . /etc/default/brightness exec 2> /dev/null if [ "${BRIGHTNESS_CONTROL}" = "yes" ]; then # Check the value stored in ${BRIGHTNESS_LAST_LEVEL_FILE} # holds a numeric value. OLD=$(cat ${BRIGHTNESS_LAST_LEVEL_FILE}) let NUM=${OLD}+1 let NUM=${NUM}-1 if [ "${OLD}" -eq "${NUM}" ] 2>/dev/null; then # If previously stored value is a number, set the brightness # level to that. VALUE=${OLD} else # If previously stored value is not a number, or undefined # restore the brightness to its default value for AC power. VALUE=${BRIGHTNESS_LEVEL_ON_AC} fi # Sets the new brightness and stores its value /usr/local/bin/bl1 ${VALUE} \ | sed 's/new value: //g' > ${BRIGHTNESS_LAST_LEVEL_FILE} fi
/etc/acpi/battery.d/01-brightness.sh
The following shell script stores the current brightness level in order to restore it once AC power is restored and, since AC power has just been lost, dims the LCD brightness:
#!/bin/bash # Load configuration parameters . /etc/default/brightness if [ "${BRIGHTNESS_CONTROL}" = "yes" ]; then # Gets current brightness level and stores it ${BRIGHTNESS_PROGRAM} \ | sed 's/Current value : //g' > ${BRIGHTNESS_LAST_LEVEL_FILE} # Sets the brightness level used when running on batteries ${BRIGHTNESS_PROGRAM} ${BRIGHTNESS_LEVEL_ON_BATTERY} fi
Basic backlight support for MacBook Pro
September 11th, 2006
I made some modifications to the original bl1.c program from Nicolas Boichat. In summary, this modifications allow:
Specify an absolute brightness value
Let x be the absolute brightness value, such that 0<x<16, that is, the value must between 1 and 15, where 1 is the minimum brightness level before turning off the screen, and 15 is the maximum brightness supported by the LCD screen.
For example:
./bl1 15
./bl1 1
Specify an increment or decrement (delta)
Let d be the delta, and x the current brightness value, then the new brightness value y is y=x+d, and 0<y<16.
y = min(max(1, x + d), 15)
Source code
/*
* Apple Macbook Pro LCD backlight control
*
* Copyright (C) 2006 Nicolas Boichat <nicolas @boichat.ch>
* Copyright (C) 2006 Felipe Alfaro Solana <felipe_alfaro @linuxmail.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <stdio .h>
#include <sys /io.h>
#include <stdlib .h>
void init()
{
if (ioperm(0xB2, 0xB3, 1) < 0)
{
perror("ioperm failed (you should be root).");
exit(2);
}
}
int get_current_value()
{
outb(0x03, 0xB3);
outb(0xBF, 0xB2);
char t = inb(0xB3) >> 4;
return t;
}
int calculate_new_value(const char *arg)
{
int val, new = atoi(arg);
if (arg[0] == '+' || arg[0] == '-')
val = new + get_current_value();
else
val = new;
if (val > 15)
val = 15;
else if (val < 1)
val = 1;
return val;
}
int main(int argc, char** argv)
{
if (argc > 2)
{
printf("Usage:\n");
printf("%s : read current value\n", argv[0]);
printf("%s value : write value [0-15]\n", argv[0]);
exit(1);
}
init();
if (argc < 2)
{
printf("Current value : %d\n", get_current_value());
exit(0);
}
if (argc == 2)
{
int value = calculate_new_value(argv[1]);
outb(0x04 | (value << 4), 0xB3);
outb(0xBF, 0xB2);
printf("new value: %d\n", value);
}
return 0;
}
Encrypted home on Ubuntu using dmcrypt
September 8th, 2006
Install crypsetup and dmsetup:
# apt-get install crypsetup dmsetup
Install pam_mount:
# apt-get install libpam-mount
Configure PAM to use pam_mount for authentication and session management. PAM authentication captures the user login password, while PAM session set ups the dmcrypt device and mounts it during log on, and unmounts the dmcrypt device during log off.
# echo “@include common-pammount” >> /etc/pam.d/common-auth
# echo “@include common-pammount” >> /etc/pam.d/common-session
Sets up some variables used to make the rest of the steps a little bit easier and more generic:
# USER=solana
# KEYSIZE=128
# DEVICE=/dev/whatever
The meaning of the previous variables is:
- USER defines the username.
- KEYSIZE defines the AES keysize used to encrypt the data. Valid keysizes are 128, 192 and 256.
- DEVICE defines the device that will hold the crypted volume. This can be standard partition, a LVM volume, a NBD, etc..
Generate an AES random encryption key, encrypts it with the user log on password and stores it:
# dd if=/dev/urandom bs=1c count=$((${KEYSIZE}/8)) | openssl enc -aes-${KEYSIZE}-ecb > /home/${USER}.key
When prompted for the passphrase, enter the user’s log on password.
Sets up the dmcrypt device:
# openssl enc -d -aes-${KEYSIZE}-ecb -in /home/${USER}.key | cryptsetup -c aes -s ${KEYSIZE} create crypt-${USER} ${DEVICE}
When asked for the passphrase, just enter the user’s log on password.
Make a new ext3 filesystem on top of the cryptoloop device:
# mkfs.ext3 /dev/mapper/crypt-${USER}
Change the owner, so the user will be able to write to this volume:
# mkdir /mnt/crypt-${USER}
# mount /dev/mapper/crypt-${USER} /mnt/crypt-${USER}
# chown ${USER} /mnt/crypt-${USER}
# umount /dev/mapper/crypt-${USER}
# rmdir /mnt/crypt-${USER}
Frees the dmcrypt device:
# dmsetup remove crypt-${USER}
To test whether mount.crypt and mount the encrypted volume:
# openssl enc -d -aes-${KEYSIZE}-ecb -in /home/${USER}.key | mount.crypt ${DEVICE} /home/${USER} -o keysize=${KEYSIZE}
Frees the dmcrypt device after the test:
# dmsetup remove _dev_mapper_${DEVICE}
Configure pam_mount:
# echo “volume ${USER} crypt – ${DEVICE} /home/${USER} keysize=${KEYSIZE} aes-${KEYSIZE}-ecb /home/${USER}.key” >> /etc/security/pam_mount.conf
Ubuntu Edgy, ATI’s fglrx, DRI, 3D acceleration and X.org Composite extension
September 6th, 2006
I think that Ubuntu Edgy Knot 2 is the first Linux distribution that enables the Composite extension by default for X.org. While this is really exciting, unfortunately it seems to negatively affect DRI and 3D acceleration when using ATI’s closed-source drivers, fglrx.
I don’t know exactly the reasons of this, but enabling Composite extensions disables ATI’s driver support for DRI and 3D acceleration. The X.org logs show DRI has been disabled, but they offer no clue on what’s going on, so I eventually found tout he answer while digging on the Ubuntu forums.
To disable Composite extensions, add the following lines to the end of /etc/X11/xorg.conf file:
Section "Extensions"
Option "Composite" "false"
EndSection
This will bring back support for DRI, 3D acceleration and, thus, OpenGL support.
Xen network configuration and multiple VLANs (II)
August 21st, 2006
Since I first write my first attempt at trying to get VLAN support working under Xen, I’ve received some reports for people stating that it doesn’t work as expected. And they are right.
At the end of the first article, I pointed out I was having problems with UDP traffic. In turn, it was worse than I ever expected, since it was affecting DNS name resolution, DHCP services and other services running as inside a domainU. This is the reason why I rethought the implementation and now have it working on a production machine acting, among as other things, as a DHCP server and DNS server.
In this second try I decided not to mess around with Xen’s default network configuration, so please undo all the changes you did so you end end up with a pristine Xen configuration. In this new scenario all the native traffic (tagged an untagged Ethernet frames) is being captured by Xen’s switch, xenbr0, and sent to the right network interface. If the traffic being received is a 802.11q tagged frame, the target will receive it tagged and thus will have to implement measures to untag and process it accordingly.
Introduction
So, let’s say we have the following logical network topology and virtual machines:
|
LAN
|
-------------------+----------------------------------
| | |
| peth0 ---- xen-br0 |
| | |
| ----------------------------- |
| | | |
| vif0.0 vif1.0 |
| | | |
| | +--------------+------------
| | | |
| | | ------------+------------
| | | | | |
| eth0 | | eth0 |
| | | | | |
| -------+------- | | ------+------- |
| | | | | | | |
| eth0.1000 eth0.10 | | eth0.2000 eth0.10 |
| | | | | | | |
| VLAN 1000 VLAN 10 | | VLAN 2000 VLAN 10 |
| | | | | | | |
| www ssh | | ftp ssh |
| | | |
| Domain0 | | DomainU |
--------------------------- -------------------------
The Xen’s switch configuration can be seen with the following command:
root@xen:~# brctl show
bridge name bridge id STP enabled interfaces
xenbr0 8000.feffffffffff no peth0
vif0.0
vif1.0
For each domain — this includes domain0 or any domainU — there is a vif|X|.|Y| interface attached to Xen’s bridge xen-br0, where |X| is the domain ID (0 for domain0 and a monotonically increasing number for every domainU). Then, we have every network interface card inside the domain, in the form of eth|Y|. Thus, if a domainU with ID #3 defines two network interfaces, eth0 and eth1, there will two corresponding virtual network interfaces in domain0, named vif3.0 and vif3.1.
Instead of trying to export VLAN interfaces to one or more domainUs, we export the whole, native (tagged or not) network interface to the domainU and, inside this domainU, we can configure VLAN subinterfaces if needed.
Sample scenario
Let’s say we want to offer the following services per VLAN:
- WWW server on VLAN 1000
- FTP server on VLAN 2000
- SSH access to administer the WWW sever, reachable only through the VLAN 10
- SSH server to administer the FTP server, reachable only through the VLAN 10
But we also want to partition the physical machine in two, so domain0 serves WWW traffic while domainU servers FTP traffic:
| WWW | FTP | SSH | |
|---|---|---|---|
| domain0 | VLAN 1000 | - | VLAN 10 |
| domainU | - | VLAN 2000 | VLAN 10 |
Thus, we need the following VLAN subinterfaces:
eth0.10andeth0.1000on domain0eth0.10andeth0.2000on domainU
Configuring VLAN subinterfaces in domainU is straight forward. However, it’s a little bit more difficult for domain0.
Configuring VLAN subinterfaces for domain0
First of all, make sure you are using bridging for your Xen configuration. Make sure the following line is uncommented in /etc/xen/xend-config.sxp:
(network-script network-bridge)
And comment any other network-script configuration lines, like:
(network-script network-nat)
or
(network-script network-route)
It seems we can’t bring up VLAN subinterfaces before Xen’s network script is fired up since Xen’s network scripts perform some black magic on the network interfaces, mainly renaming eth0 to peth0 and bringing up a dummy interface named eth0. Any subinterface related to the original eth0 seems to stop working after the renaming takes place.
Thus, I coded up an init script used to bring up the VLAN subinterfaces that gets invoked just after Xen’s network script has finished. Note that it’s targeted for RedHat-based distributions:
#!/bin/sh
#
# Init file for Network-VLAN
# STARTS AFTER XEN (which is S50 and K01)
#
# chkconfig: 2345 51 89
# description: VLAN networking
. /etc/init.d/functions
case "$1" in
start)
echo -n $"Configuring VLAN interfaces:"
if [ ! -f /var/lock/subsys/network-vlan ]; then
(
modprobe 8021q || exit 1
vconfig add eth0 10 || exit 2
ifconfig eth0.10 up 10.0.0.1 netmask 255.0.0.0 || exit 3
vconfig add eth0 1000 || exit 2
ifconfig eth0.1000 up 11.0.0.1 netmask 255.0.0.0 || exit 3
) > /dev/null 2>&1
RETVAL=$?
[ "$RETVAL" = 0 ] && ( success ;\\
touch /var/lock/subsys/network-vlan ) || failure
fi
echo
;;
stop)
echo -n $"Unconfiguring VLAN interfaces:"
if [ -f /var/lock/subsys/network-vlan ]; then
(
ifconfig eth0.10 down && vconfig rem eth0.10 ;
ifconfig eth0.1000 down && vconfig rem eth0.1000
) > /dev/null 2>&1
RETVAL=$?
[ "$RETVAL" = 0 ] && ( rm -f /var/lock/subsys/network-vlan ;\\
success ) || failure
fi
echo
esac
Save this script as /etc/init.d/network-vlan, then run:
chmod +x /etc/init.d/network-vlan chkconfig --add /etc/init.d/network-vlan
The script runs just after Xen’s init script has renamed the real Ethernet interface and has brought up a dummy interface called eth0. Then, the network-vlan script brings up two VLAN subinterfaces, one for VLAN 10 and another one for VLAN 1000, and then assigns each one its own IP address.
Additionally, these are the contents of /etc/sysconfig/network-scripts/ifcfg-eth0:
DEVICE=eth0 BOOTPROTO=static ONBOOT=yes TYPE=Ethernet
Note that eth0 in this context refers to the real Ethernet interface, since Xen’s init script has not been ran yet. I didn’t configure any IP address for this interface since I only want to process tagged traffic. Beware that on many switches — i.e., Cisco 2960 and 3560 —, VLAN1 is, by default, the native VLAN and traffic on the native VLAN doesn’t get tagged.
Configuring VLAN subinterfaces for domainU
These are the contents of /etc/sysconfig/network-scripts/ifcfg-eth0:
DEVICE=eth0 BOOTPROTO=static ONBOOT=yes TYPE=Ethernet
I didn’t configure any IP address for this interface since I only want to process tagged traffic. Read the note above on untagged frames and native VLANs.
These are the contents of /etc/sysconfig/network-scripts/ifcfg-eth0.10:
DEVICE=eth0.10 BOOTPROTO=static IPADDR=10.0.0.2 NETMASK=255.0.0.0 ONBOOT=yes TYPE=Ethernet VLAN=yes
These are the contents of /etc/sysconfig/network-scripts/ifcfg-eth0.2000:
DEVICE=eth0.2000 BOOTPROTO=static IPADDR=12.0.0.1 NETMASK=255.0.0.0 ONBOOT=yes TYPE=Ethernet VLAN=yes
Bonding
For those who desire to use bonding, it seems some tweaking of the networking scripts is required. I recommend them to look at this post on Bonding not working with network-bridge.
Conclusion
I’m sure there are better ways to configure VLAN subinterfaces in domain0, but it was in a hurry and couldn’t find of a better way to get it done.
If anyone out there has a different way of achieving this, please let me know
