Старое
название интерфейсов, такое как к примеру
eth0, кануло в лету (ну почти, иногда старые
имена можно встретить). В RHEL7 используются
следующие варианты схем наименования
сетевого интерфейса, в порядке применения:
-
Имя, предоставляемое аппаратным обеспечением (Firmware или BIOS), включающее порядковый номер, для устройств, расположенных на материнской плате, к примеру eno1. Если выбор имени не произведен, используется схема 2.
-
Имя, предоставляемое аппаратным обеспечением (Firmware или BIOS), включающее порядковый номер слота PCI Express, к примеру ens1. Если выбор не произведен, используется схема 3.
-
Имя формируется из физического положения точки подключения устройства, к примеру enp2s0. Иначе используется схема 5.
-
Имя включает MAC устройства, к примеру enx94de80a44f0c. Эта схема по умолчанию не используется.
-
Старая схема, где имя присваивается ядром в порядке обнаружения интерфейса, к примеру eth0 и т.д.
Это
поведение по умолчанию.
Новые
имена сами по себе содержат полезную
информацию. Принятое соглашение о
наименовании следующее: первые два
символа отражают тип интерфейса:
-
en — Ethernet.
-
wl — беспроводная локальная сеть, WLAN.
-
ww — беспроводная глобальная сеть, WWAN.
Далее
следует тип, отражающий схему наименования,
описанную выше:
-
o<index> — индекс для устройств расположенных на материнской плате.
-
s<slot>[f<function>][d<dev_id>] — сначала идет номер PCI Express слота, далее f<function> - номер функции у многофункционального PCI устройства (я не встречал таких плат) и последним идет идентификатор устройства.
-
p<bus>s<slot>[f<function>][d<dev_id>] — расположение устройства на PCI шине. Домен PCI (p<bus>) указывается только если он отличен от нулевого (это можно увидеть в больших системах). Номер функции и номер устройства аналогично предыдущему примеру.
-
p<bus>s<slot>[f<function>][u<port>][..][c<config>][i<interface>] — расположение устройства на USB шине, причем учитывается вся цепочка портов.
-
x<MAC> — MAC адрес.
Нужно
отметить, что имя не может быть более
15 символов, это ограничение ядра.
В
случае использования VLAN добавляется
следующее соглашение о имени интерфейса:
-
vlan<vlanid> — имя с полным номером vlanid, к примеру vlan0012 или имя с сокращенным vlanid — vlan12
-
device_name.<vlanid> - имя интерфейса и VLAN ID в полном или сокращенном виде, к примеру ens3.0012 или ens3.12
Как
бы глупо это не звучало, но помимо
описанных соглашений о наименовании,
есть еще одно, используемое при помощи
утилиты udev — biosdevname (насколько я понял,
возникло это соглашение по инициативе
DELL и используется на их серверах). Оно
имеет силу только при наличии установленного
пакета biosdevname и при указании biosdevname=1 при
загрузке системы. Переименования будут
производится только для встроенных
интерфейсов. При этом:
-
Встроенные интерфейсы будут иметь имя типа em[123...]
-
Интерфейсы, подключенные по шине PCI — p<slot>p<ethernet port>, к примеру p3p4
Чтобы
окончательно не запутаться в теоретической
части, рассмотрим более глубоко процесс
присваивания имени интерфейсу по шагам.
Ниже пример того что происходит, когда
в системе появляется новый интерфейс:
#
udevadm monitor
...
KERNEL[27783.869667]
add
/devices/pci0000:00/0000:00:14.0/usb1/1-7/1-7.4/1-7.4:1.0/net/eth0
(net)
...
KERNEL[27783.879674]
move
/devices/pci0000:00/0000:00:14.0/usb1/1-7/1-7.4/1-7.4:1.0/net/enp0s20u7u4
(net)
UDEV
[27783.892038] add
/devices/pci0000:00/0000:00:14.0/usb1/1-7/1-7.4/1-7.4:1.0/net/enp0s20u7u4
(net)
...
Т.е.
сначала интерфейс появился со старым,
знакомым именем eth0, а далее стал
enp0s20u7u4. Нетрудно заметить, что новое имя
сразу отображает что это адаптер Ethernet
(en), подключенный к USB шине через usb хаб
(в имени два usb порта u7u4). Достаточно
удобно.
Посмотрим,
что выполняет udev над интерфейсом:
-
Шаг первый:
#
udevadm test
/sys/devices/pci0000:00/0000:00:14.0/usb1/1-7/1-7.4/1-7.4:1.0/net/enp0s20u7u4
...
PROGRAM
'/lib/udev/rename_device' /usr/lib/udev/rules.d/60-net.rules:1
starting
'/lib/udev/rename_device'
Что
происходит: правило udev
/usr/lib/udev/rules.d/60-net.rules при помощи
/lib/udev/rename_device, просматривает конфигурационные
файлы сетевых интерфейсов -
/etc/sysconfig/network-scripts/ifcfg-*, и если есть
соответствие MAC адреса добавляемого
интерфейса и адреса в директиве HWADDR, то
имя интерфейса устанавливается в
соответствии с директивой DEVICE.
Сейчас
воспользуемся небольшой хитростью,
чтобы процесс применения правил udev был
более наглядным. Создадим конфигурационный
файл ifcfg-tstif0 с именем tstif0 для нашего
адаптера и вставим адаптер. Интерфейс
в системе станет tstif0. Теперь удалим
конфигурационный файл, и посмотрим на
обработку правил еще раз, но уже для
интерфейса tstif0, в конечном итоге мы
должны будем получить имя enp0s20u7u4.
Запустим
еще раз, первое правило не отработает,
т.к. конфигурационный файл мы удалили:
PROGRAM
'/lib/udev/rename_device' /usr/lib/udev/rules.d/60-net.rules:1
starting
'/lib/udev/rename_device'
'/lib/udev/rename_device'
[5023] exit with return code 0
-
Шаг второй, смотрим дальше:
PROGRAM
'/sbin/biosdevname --policy physical -i tstif0'
/usr/lib/udev/rules.d/71-biosdevname.rules:22
starting
'/sbin/biosdevname --policy physical -i tstif0'
'/sbin/biosdevname
--policy physical -i tstif0' [5024] exit with return code 2
Правило
/usr/lib/udev/rules.d/71-biosdevname.rules реализует выше
рассмотренное соглашение о именах при
использовании biosdevname. Уточнение, это
правило работает, если в системе
установлен biosdevname, при загрузке не был
использован параметр biosdevname=0, и если
имя не было назначено на предыдущем
шаге.
-
Шаг третий:
IMPORT
builtin 'net_id' /usr/lib/udev/rules.d/75-net-description.rules:6
IMPORT
builtin skip 'usb_id'
/usr/lib/udev/rules.d/75-net-description.rules:8
IMPORT
builtin 'hwdb' /usr/lib/udev/rules.d/75-net-description.rules:8
На
этом этапе правилом
/usr/lib/udev/rules.d/75-net-description.rules, заполняются
следующие директивы описания устройства:
ID_NET_NAME_ONBOARD, ID_NET_NAME_SLOT, ID_NET_NAME_PATH и
ID_NET_NAME_MAC. Не все директивы могут быть
заполнены, поскольку не все устройства
могут иметь требуемую информацию.
-
Шаг четвертый:
IMPORT
builtin 'path_id' /usr/lib/udev/rules.d/80-net-setup-link.rules:5
IMPORT
builtin 'net_setup_link'
/usr/lib/udev/rules.d/80-net-setup-link.rules:9
Config
file /usr/lib/systemd/network/99-default.link applies to device
tstif0
NAME
'enp0s20u7u4' /usr/lib/udev/rules.d/80-net-setup-link.rules:11
Вот
оно правило, которое устанавливает имя
для интерфейса в данном случае -
/usr/lib/udev/rules.d/80-net-setup-link.rules. Что по этому
правило происходит: если интерфейс не
был переименован на предыдущих шагах,
и если не задан параметр ядра net.ifnames=0,
то имя интерфейса устанавливается в
соответствии с порядком по приоритету
из полученных ранее директив:
ID_NET_NAME_ONBOARD, ID_NET_NAME_SLOT, ID_NET_NAME_PATH. Если ни
одна из директив не определена, то
интерфейс остается не переименованным,
т.е. старый вариант именования — eth0.
Для
понимания, посмотреть возможные имена
можно так:
#
udevadm info /sys/class/net/tstif0 | grep ID_NET_NAME
E:
ID_NET_NAME=enp0s20u7u4
E:
ID_NET_NAME_MAC=enx00101402bca7
E:
ID_NET_NAME_PATH=enp0s20u7u4
Можно
заметить, что почти все пункты (за
исключением 5 — старого именования) из
стандартного соглашения о наименовании
реализуются в правилах udev:
75-net-description.rules и 80-net-setup-link.rules. Можно
возразить, а где наименование по MAC
адресам? Включение его можно произвести
правкой правила 80-net-setup-link.rules. Скопируйте
его:
#
cp /usr/lib/udev/rules.d/80-net-name-slot.rules /etc/udev/rules.d
И
добавьте строку выделенную курсивом
на листинге:
#
grep -v "^#\|^$" /etc/udev/rules.d/80-net-name-slot.rules
ACTION!="add",
GOTO="net_name_slot_end"
SUBSYSTEM!="net",
GOTO="net_name_slot_end"
NAME!="",
GOTO="net_name_slot_end"
IMPORT{cmdline}="net.ifnames"
ENV{net.ifnames}=="0",
GOTO="net_name_slot_end"
NAME=="",
ENV{ID_NET_NAME_MAC}!="", NAME="$env{ID_NET_NAME_MAC}"
NAME=="",
ENV{ID_NET_NAME_ONBOARD}!="",
NAME="$env{ID_NET_NAME_ONBOARD}"
NAME=="",
ENV{ID_NET_NAME_SLOT}!="", NAME="$env{ID_NET_NAME_SLOT}"
NAME=="",
ENV{ID_NET_NAME_PATH}!="", NAME="$env{ID_NET_NAME_PATH}"
LABEL="net_name_slot_end"
Не
уверен, что данный вариант именования
удобен.
Итак,
мы обсудили несколько соглашений о
наименовании сетевых интерфейсов,
рассмотрели по шагам, как происходит
выбор имени, попутно узнали, что
net.ifnames=0 отключает новую схему наименования,
и последнее замечание: не используйте
имена из пространства ядра - ethX в схеме
с присвоением имен через файлы ifcfg-*.