nForce network controller woes

The Linux server machine I have been using here at home for the last 6 years or so is equipped with an Asus A7N8X Deluxe motherboard. Although the motherboard was supposed to be "deluxe" with many extra components, using those components frankly has often been a lot of trouble.

Besides the intractable SATA controller, I have been particularly annoyed by the two on-board network controllers manufactured by 3Com and nVidia. A few years after I had bought the Asus motherboard, I managed to get the 3Com controller to work (if I remember correctly by simultaneously doing a BIOS upgrade and compiling a Linux kernel with the proper module), but the nVidia controller remained an elusive beast.

Today has seen my most recent attempt at getting the nVidia NIC to work, and this time I am proud to announce my final triumph! :-)

Analysis of the current situation

The nVidia network interface controller (NIC) is provided by the nForce chipset integrated on the Asus motherboard. The Linux kernel has support for the NIC by way of the forcedeth.c driver, which originally was a reverse engineered driver but has since seen semi-official support by nVidia (see this story).

When I look at my boot log I see that forcedeth.c currently detects that the NIC has an invalid MAC address (00:00:00:00:00:00, which is, I agree with the driver, quite invalid) and then proceeds to configure the NIC with a random MAC address. Yuck!

When the system is finally up and running, ifconfig -a shows me a network interface which is strangely named eth2_rename and which ifup refuses to bring up. The unhelpful message displayed by ifup: "Ignoring unknown interface".


Seeing that a random MAC address is used, I no longer wondered why the nForce NIC does not work - I assumed that any number of programs simply cannot handle the case of a constantly changing MAC address.

I now saw two possible options: 1) Either give the NIC a static MAC address, or 2) find those parts of the system responsible for setting up the network interface and convince them to work with random MAC addresses. Although at first I thought that solution 1 would be easier, it turned out that solution 2 was the way to go.


Googling around gave me this post which hints at the udev system being responsible for assigning the network interface name (e.g. "eth0") to the actual kernel device.

Googling some more led me to the file /etc/udev/rules.d/70-persistent-net.rules. Indeed I saw that it contained definitions for "eth0" and "eth1", but unlike I expected it had no reference to "eth2_rename". What it did contain, though, was many lines referring to a device that constantly changed its MAC address - the nForce NIC! Interestingly, that device was named "eth1", which on my system is the name of a network interface in good working order. So it appears that udev would have liked to assign "eth1" to the nForce NIC, but couldn't because there already was such an interface, and therefore somehow fell back to "eth2_rename".

This post gave me the final solution to my problem: It seems to be possible to tell udev to assign a network interface name based not on the MAC address, but on the PCI device ID. According to the post's instructions, I then tried the command

udevinfo --attribute-walk --path /sys/class/net/eth2_rename

to get at the PCI device address, and finally added the following rule to 70-persistent-net.rules:

SUBSYSTEM=="net", DRIVERS=="?*", ATTRS{vendor}=="0x10de", ATTRS{device}=="0x0066", NAME="eth2"

Note that the "0x" prefix is important! Unfortunately, it seems to be impossible to let the rule become active without either reloading the network driver's kernel module, or rebooting the system. Since forcedeth.c is not a module on my system, I had to reboot :-(

Nevertheless, I am still happy to finally have the nForce NIC working. It only took me about 6 years to get there :-). For additional information about writing udev rules, it may be interesting to read this well-written article.

Post Scriptum

I finally figured out why ifup refused to bring up "eth2_rename": The simple reason is that the interface was not defined in /etc/network/interfaces. Had I changed that file and then tried to bring the interface up, it would have worked perfectly.

So another thing that I learned today was that /etc/network/interfaces and tools like ifconfig, ifup and ifdown have no "mysterious" effect on how network interfaces are named. They simply use references to interface names that have already been pre-determined by a system such as udev, or the older devfs.