28 окт. 2010 г.

Инкрементное возрастание имени сетевого интерфейса при загрузке ОС

Столкнулся со странной и очень неприятной проблемой: сетевая карта на нвидиевском чипе:
00:07.0 Bridge: nVidia Corporation MCP61 Ethernet (rev a2)
При загрузке системы сетевка определяется и udev-ом ей назначается имя eth0, все хорошо. Однако при следующей загрузке сетевка по каким-то неведомым причинам получает другой MAC и, соответственно, udev считает ее новым устройством и дает имя eth1. И так далее... На одном из форумов (ссылка где то утерялась) вычитал предпололжение, что на некоторых материнских платах некоторых производителей на NIC назначается какой-то "неправильный" с точки зрения модуля forcedeth MAC-адрес. Он, модуль, сему не верит, и присваивает некий свой, или что-то в этом роде. Короче, правда это, или сказки, но жопа имеет место быть. Лечение, предложенное там же, выглядит как добавление в строку привязки устройства аттрибутов ATTR{device} и ATTR{vendor}, которые неизменны. Узнать оные для сетевки можно так (X - номер интерфейса):
cat /sys/class/net/ethX/device/device
cat /sys/class/net/ethX/device/vendor
Или глянуть в файл /etc/udev/rules.d/70-persistent-net.rules, в закомментированном поле после PCI Device как раз указываются нужные параметры в порядке vendor:device
 cat /etc/udev/rules.d/70-persistent-net.rules | grep '#'
# PCI device 0x10de:0x03ef (forcedeth)
Однако, если убрать меняющийся мак из 70-persistent-net.rules и внести ATTR{device} и ATTR{vendor}, то есть, примерно так:
# PCI device 0x10de:0x03ef (forcedeth)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*",  ATTR{device}="0x03ef", ATTR{vendor}="0x10de", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"
 То... ничего не изменяется, и после ребута снова появляется еще одна строчка в 70-persistent-net.rules с новым именем нашего интерфейса. В итоге, решение нашлось в следующем: так как мак меняется только по вторым трем байтам, то можно использовать маску: ATTR{address}=="00:00:6c:*". Однако, аттрибуты ATTR{device} и ATTR{vendor} лучше все же оставить, потому что если окажется в системе еще один сетевой интерфейс, удовлетворяющий маске, udev может "сойти с ума", назначив обоим одно имя или не назначив вовсе. 
Таким образом, окончательный вид файла 70-persistent-net.rules получился таким:
cat /etc/udev/rules.d/70-persistent-net.rules
# PCI device 0x10de:0x03ef (forcedeth)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:00:6c:*", ATTR{device}="0x03ef", ATTR{vendor}="0x10de", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"
 P.S.: Описанные действия проводились в Ubuntu 8.04 LTS, однако проблема в принципе может проявиться и в других дистрибутивах. Решение будет работоспособно и там, разве что имя файла persistent-net.rules может различаться.