CentOS7におけるNIC命名ルール
前回、CentOS6におけるNICの命名ルールを記載しましたが、CentOS7では少し(?)変更されています。ということで今回はCentOS7のNIC命名規則ならびに固定に必要な手続きについて記載します。
前回同様に、簡単にまとめると以下の流れでデバイスが作成されます。
- ifcfg-XXXに記載されているMACアドレスと実アドレスを比較して、マッチすればファイルに記載されているデバイス名を設定する。
- 71-biosdevname.rulesからbioddevnameコマンドが実行され、SMBIOS(System Management BIOS)から読み取った情報を用いて、デバイス名を設定(変更)する。
- 75-net-description.rulesからNICの属性情報(実装位置やMACアドレスなど)を取得する。
- 80-net-name-slot.rulesからNICの実装位置に基づいてデバイス名を設定(変更)する。
- 99-systemd.rulesから最終的なデバイス名を設定する。
Predictable Network Interface Names
CentOS5.xや6.xではNICデバイス名はethXという名称が使われるのが一般的でしたが、udevのバージョン197より予測可能なネットワークインタフェース名に設定されるようになり、enoXやenpXが使われるようになりました。デバイス名は接頭語ならびにデバイス種別によって決まります。
接頭語の例
接頭語 | 値 |
---|---|
Ethernet | en |
Wireless LAN | wl |
Wireless WAN | ww |
デバイス種別の例(上のものが優先される)
デバイス種別 | 値 |
---|---|
オンボード | o<index> |
ホットプラグ | s<slot>[f<function>][d<dev_id>] |
PCIデバイス | p<bus>s<slot>[f<function>][d<dev_id>] |
USBデバイス | p<bus>s<slot>[f<function>][u<port>][..][c<config>][i<interface>] |
MACアドレス | x<MAC> |
詳しい内容はfreedesktop.orgのPredictableNetworkInterfaceNamesやRed Hatの8.3. Understanding the Predictable Network Interface Device Namesに記載されてます。
CentOS7におけるNICの命名規則
CentOS7.xのNICのデバイス命名付与規則は以下のようになっています。
(1) /usr/lib/udev/rules.d/60-net.rules
ACTION=="add", SUBSYSTEM=="net", DRIVERS=="?*", ATTR{type}=="1", PROGRAM="/lib/udev/rename_device", RESULT=="?*", NAME="$result"
Cent6.xとの違いはローカルループバック(lo)やホットプラグに関する挙動が異なっていますが、/lib/udev/rename_deviceが実行され、/etc/sysconfig/network-scripts/ifcfg-XXXに記載されているMACアドレス(HWADDR)を比較し、マッチすれば該当するデバイス名(DEVICE)を付与するという挙動は同じです。
(2) /lib/udev/rules.d/71-biosdevname.rules
SUBSYSTEM!="net", GOTO="netdevicename_end" ACTION!="add", GOTO="netdevicename_end" NAME=="?*", GOTO="netdevicename_end" ATTR{type}!="1", GOTO="netdevicename_end" ENV{DEVTYPE}=="?*", GOTO="netdevicename_end" # whitelist all Dell systems ATTR{[dmi/id]sys_vendor}=="Dell*", ENV{UDEV_BIOSDEVNAME}="1" # kernel command line "biosdevname={0|1}" can turn off/on biosdevname IMPORT{cmdline}="biosdevname" ENV{biosdevname}=="?*", ENV{UDEV_BIOSDEVNAME}="$env{biosdevname}" # ENV{UDEV_BIOSDEVNAME} can be used for blacklist/whitelist # but will be overwritten by the kernel command line argument ENV{UDEV_BIOSDEVNAME}=="0", GOTO="netdevicename_end" ENV{UDEV_BIOSDEVNAME}=="1", GOTO="netdevicename_start" # off by default GOTO="netdevicename_end" LABEL="netdevicename_start" # using NAME= instead of setting INTERFACE_NAME, so that persistent # names aren't generated for these devices, they are "named" on each boot. SUBSYSTEMS=="pci", PROGRAM="/sbin/biosdevname --smbios 2.6 --nopirq --policy physical -i %k", NAME="%c" OPTIONS+="string_escape=replace" LABEL="netdevicename_end"
biosdevnameコマンドの実行結果をデバイス名の変数に設定します。このとき、/proc/cmdlineからbiosdevnameの値を読み取ってます。従って、biosdevnameによる命名を無効化するには以下の値をgrub2のconfigに追記することで可能です。
- biosdevname=0 (0は無効、1は有効を指します)
(3) /udev/rules.d/75-net-description.rules
# do not edit this file, it will be overwritten on update ACTION=="remove", GOTO="net_end" SUBSYSTEM!="net", GOTO="net_end" IMPORT{builtin}="net_id" SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id", IMPORT{builtin}="hwdb --subsystem=usb" SUBSYSTEMS=="usb", GOTO="net_end" SUBSYSTEMS=="pci", ENV{ID_BUS}="pci", ENV{ID_VENDOR_ID}="$attr{vendor}", ENV{ID_MODEL_ID}="$attr{device}" SUBSYSTEMS=="pci", IMPORT{builtin}="hwdb --subsystem=pci" LABEL="net_end"
デバイスのサブシステムの種類(USBデバイス or PCIデバイス)から必要な情報を読み取っています。
この情報を基に80-net-name-slot.rulesによってデバイス名が変更されます。
(4) /lib/udev/rules.d/80-net-name-slot.rules
# do not edit this file, it will be overwritten on update 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_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"
71-biosdevname.rulesで実行したbiosdevnameの実行結果が空の場合、オンボード、スロット、パスの順(優先)でデバイス名の変数に値が設定されます。このとき、/proc/cmdlineからnet.ifnamesの値を読み取ってます。従って、このルールによる命名を無効化するには以下の値をgrub2のconfigに追記することで可能です。
- net.ifnames=0 (0は無効、1は有効を指します)
(5) /lib/udev/rules.d/99-systemd.rules
# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. ACTION=="remove", GOTO="systemd_end" SUBSYSTEM=="tty", KERNEL=="tty[a-zA-Z]*|hvc*|xvc*|hvsi*|ttysclp*|sclp_line*|3270/tty[0-9]*", TAG+="systemd" KERNEL=="vport*", TAG+="systemd" SUBSYSTEM=="block", KERNEL!="ram*", TAG+="systemd" SUBSYSTEM=="block", KERNEL!="ram*", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}=="1", ENV{SYSTEMD_READY}="0" # Ignore encrypted devices with no identified superblock on it, since # we are probably still calling mke2fs or mkswap on it. SUBSYSTEM=="block", KERNEL!="ram*", ENV{DM_UUID}=="CRYPT-*", ENV{ID_PART_TABLE_TYPE}=="", ENV{ID_FS_USAGE}=="", ENV{SYSTEMD_READY}="0" # Ignore raid devices that are not yet assembled and started SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", KERNEL=="md*", TEST!="md/array_state", ENV{SYSTEMD_READY}="0" SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", KERNEL=="md*", ATTR{md/array_state}=="|clear|inactive", ENV{SYSTEMD_READY}="0" # Ignore nbd devices in the "add" event, with "change" the nbd is ready ACTION=="add", SUBSYSTEM=="block", KERNEL=="nbd*", ENV{SYSTEMD_READY}="0" # Ignore loop devices that don't have any file attached ACTION=="add|change", KERNEL=="loop[0-9]*", TEST!="loop/backing_file", ENV{SYSTEMD_READY}="0" # We need a hardware independent way to identify network devices. We # use the /sys/subsystem path for this. Current vanilla kernels don't # actually support that hierarchy right now, however upcoming kernels # will. HAL and udev internally support /sys/subsystem already, hence # it should be safe to use this here, too. This is mostly just an # identification string for systemd, so whether the path actually is # accessible or not does not matter as long as it is unique and in the # filesystem namespace. # # http://cgit.freedesktop.org/systemd/systemd/tree/src/libudev/libudev-enumerate.c#n922 SUBSYSTEM=="net", KERNEL!="lo", TAG+="systemd", ENV{SYSTEMD_ALIAS}+="/sys/subsystem/net/devices/$name" SUBSYSTEM=="bluetooth", TAG+="systemd", ENV{SYSTEMD_ALIAS}+="/sys/subsystem/bluetooth/devices/%k" SUBSYSTEM=="bluetooth", TAG+="systemd", ENV{SYSTEMD_WANTS}+="bluetooth.target" ENV{ID_SMARTCARD_READER}=="*?", TAG+="systemd", ENV{SYSTEMD_WANTS}+="smartcard.target" SUBSYSTEM=="sound", KERNEL=="card*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="sound.target" SUBSYSTEM=="printer", TAG+="systemd", ENV{SYSTEMD_WANTS}+="printer.target" SUBSYSTEM=="usb", KERNEL=="lp*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="printer.target" SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ENV{ID_USB_INTERFACES}=="*:0701??:*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="printer.target" # Apply sysctl variables to network devices (and only to those) as they appear. ACTION=="add", SUBSYSTEM=="net", KERNEL!="lo", RUN+="/usr/lib/systemd/systemd-sysctl --prefix=/proc/sys/net/ipv4/conf/$name --prefix=/proc/sys/net/ipv4/neigh/$name --prefix=/proc/sys/net/ipv6/conf/$name --prefix=/proc/sys/net/ipv6/neigh/$name" # Pull in backlight save/restore for all firmware backlight devices SUBSYSTEM=="backlight", ATTR{type}=="firmware", TAG+="systemd", ENV{SYSTEMD_WANTS}+="systemd-backlight@$name.service" # Asynchronously mount file systems implemented by these modules as # soon as they are loaded. SUBSYSTEM=="module", KERNEL=="fuse", TAG+="systemd", ENV{SYSTEMD_WANTS}+="sys-fs-fuse-connections.mount" SUBSYSTEM=="module", KERNEL=="configfs", TAG+="systemd", ENV{SYSTEMD_WANTS}+="sys-kernel-config.mount" LABEL="systemd_end"
# Apply sysctl variables ~の箇所でデバイス名に基づいた設定がされています。71-biosdevname.rulesならびに80-net-name-slot.rulesからデバイス名が取得できない場合は、CentOS6.xなどでもおなじみのethXが振られることになります。
NICを固定するにはどうすれば...
Predictable Network Interface Namesによって、デバイスの実装位置によってデバイス名が設定されるため、物理実装位置を変えない限り不変となります。ただ、USBNICとかを用いる場合は、刺すポートによってデバイス名が変わることになってしまいますが…。
ethXが使いたいのだけど...
Predictable Network Interface Namesが導入されてから、ethXは上記の命名則が使えない場合に利用されます。ただし、biosdevnameならびにnet.ifnamesの値をあらかじめ設定することで、ethXを使うことができます。
grub2のデフォルト状態の設定ファイルを編集する。
CMDLINE_LINUXにbiosdevname=0 net.ifnames=0を追加します。
# 編集前 [root@localhost ~]# vi /etc/default/grub GRUB_TIMEOUT=5 GRUB_DEFAULT=saved GRUB_DISABLE_SUBMENU=true GRUB_TERMINAL_OUTPUT="console" GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=centos/swap rd.lvm.lv=centos/root rhgb quiet" GRUB_DISABLE_RECOVERY="true" # 編集後 [root@localhost ~]# vi /etc/default/grub GRUB_TIMEOUT=5 GRUB_DEFAULT=saved GRUB_DISABLE_SUBMENU=true GRUB_TERMINAL_OUTPUT="console" GRUB_CMDLINE_LINUX="crashkernel=auto biosdevname=0 net.ifnames=0 rd.lvm.lv=centos/swap rd.lvm.lv=centos/root rhgb quiet" GRUB_DISABLE_RECOVERY="true"
grub2設定ファイルの出力
コマンドを実行することで/boot/grub2/grub.cfgに先ほどの変更が反映されます。
[root@localhost ~]# grub2-mkconfig -o /boot/grub2/grub.cfg Generating grub configuration file ... Found linux image: /boot/vmlinuz-3.10.0-229.el7.x86_64 Found initrd image: /boot/initramfs-3.10.0-229.el7.x86_64.img Found linux image: /boot/vmlinuz-0-rescue-0df2ba0c301649e081ae8a621c3b9d04 Found initrd image: /boot/initramfs-0-rescue-0df2ba0c301649e081ae8a621c3b9d04.img done [root@localhost ~]# cat /boot/grub2/grub.cfg | grep "biosdevname=0 net.ifnames=0" linux16 /vmlinuz-3.10.0-229.el7.x86_64 root=/dev/mapper/centos-root ro crashkernel=auto biosdevname=0 net.ifnames=0 rd.lvm.lv=centos/swap rd.lvm.lv=centos/root rhgb quiet linux16 /vmlinuz-0-rescue-0df2ba0c301649e081ae8a621c3b9d04 root=/dev/mapper/centos-root ro crashkernel=auto biosdevname=0 net.ifnames=0 rd.lvm.lv=centos/swap rd.lvm.lv=centos/root rhgb quiet
NIC設定ファイル名の変更
設定ファイルはインストール時を除き、自動で生成されませんので、適宜リネームまたは作成します。
[root@localhost ~]# mv /etc/sysconfig/network-scripts/ifcfg-enp0s3 /etc/sysconfig/network-scripts/ifcfg-eth0
再起動
再起動することでデバイス名がethXに変更されます。
#変更前 [root@localhost ~]# ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 08:00:27:b6:5e:b2 brd ff:ff:ff:ff:ff:ff inet 192.168.56.102/24 brd 192.168.56.255 scope global dynamic enp0s3 valid_lft 995sec preferred_lft 995sec inet6 fe80::a00:27ff:feb6:5eb2/64 scope link valid_lft forever preferred_lft forever # 変更後 [root@localhost ~]# ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 08:00:27:b6:5e:b2 brd ff:ff:ff:ff:ff:ff inet 192.168.56.102/24 brd 192.168.56.255 scope global dynamic eth0 valid_lft 1161sec preferred_lft 1161sec inet6 fe80::a00:27ff:feb6:5eb2/64 scope link valid_lft forever preferred_lft forever
インストール時に反映する場合
そもそもインストール時に設定したい場合、インストーラ起動前にTabキーを押下し、biosdevname=0 net.ifnames=0を追加すればethXで認識します。