網路卡之命名

English version

還記得,不久以前,NIC (網路卡) 的名稱是 eth0,eth1,等。使用檔案 /etc/udev/rules.d/70-persistent-net.rules,NIC 的 MAC 位址跟名稱,例 eth0 ,可以連在一起。 所以如你的電腦有多個 NIC 的話,將電腦啟動或重新啟動後你會得到一個可預測的和一致的名稱。eth0 就是 eth0,eth1 就是 eth1 等。

然後 systemd 進入攪局。現在當你啟動或重新啟動電腦你無法得到可預測的或一致的 NIC 名稱。原來的 eth0 現在可能被稱為 eth2 而原來的 eth1 現在可能被稱為 eth0。真的一塌糊塗! 結果,沒有一個人可以上網了。檔案 /etc/udev/rules.d/70-persistent-net.rules:

SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:0c:f1:73:93:51", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:26:5a:79:b5:9c", ATTR{type}=="1", KERNEL=="eth*", NAME="eth1"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:17:9a:bb:4e:7a", ATTR{type}=="1", KERNEL=="eth*", NAME="eth2"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:19:5b:2e:fd:47", ATTR{type}=="1", KERNEL=="eth*", NAME="eth3"

已經沒有效了而有項目  HWADDR=<mac-address> 的 /etc/sysconfig/network-scripts/ifcfg.eth0 檔案也沒有用了。

每次我重新啟動伺服器就祈求天主保佑,希望至少 eth0 會被設定好。這樣我可以 ssh 到伺服器然後才解決其他的問題。但平常得不到所期望的結果。

所以開發者提供建議如何得到一個 可預測的網路介面名稱。簡單的說,不要用 eth 這個名稱了。 你可以使用如同 wan0, lan1 名稱或依 NIC 在主機板的位置,一個糟糕的名稱 enp5s0。我拒絕接受這建議因為我建的 iptables 的規矩都使用 eth0,eth1,eth2 和 eth3 這些名稱。

我使用的是 Fedora 20,所以我以下所描述可能在別的發行版不能用。

我的伺服器是當學生區域網路的路由器。我用四個 NIC:

eth0 是連線到網際網路
eth1 (192.168.1.0/24) 用 NAT 連接到 eth0
eth2 (192.168.2.0/24) 用 NAT 連接到 eth0
eth3 (192.168.3.0/24) 用 NAT 連接到 eth0

所以你看的到,如果 eth0,eth1,eth2 和 eth3 名稱被搞亂的話,沒有人可以連線到網際網路。

很幸運因為 eth0 是使用 e1000 核心模組而其他都使用 skge。所以我建一個檔案,命名為 nic.conf。內容是:

blacklist skge

然後把這檔案放在 /etc/modprobe.d/。這會把核心模組放在黑名單。意思是說,啟動電腦時不會載入 skge 這個模組。現在我只有一個 NIC,所以 eth0 會被正確的設定。每次我重新啟動電腦至少我現在可以 ssh 到電腦。ssh 到電腦之後我可以解決其他 NIC 的問題。但是,這仍然是一個非常繁瑣的工作要做。

我已讀了不少網際網路的文章有關如何解決這個問題。我試過不同的建議但沒有找到任何有效的方法。最後我找到這文章。 我讀了又讀很多次直到我找到描述有關「Using the ethtool and ip programs」。起初,我沒有理會,因為我不認為這是可行的。但是,這給了我下一步該怎麼做的想法。

依這個建議,我寫了一個 bash 腳本命名為 reneth。首先這腳本把 eth1 改名為 not_eth1,eth2 改名為 not_eth2 和 eth3 改名為 not_eth3。然後按照每個 NIC 的 MAC address, 我又改名為 eth1, eth2 或 eth3。最後,運作正常了。要自動化這過程,我在 /etc/rc.d/rc.local 執行這個腳本。

腳本::

#!/bin/bash
#
# Module skge for eth1, eth2 and eth3 is blacklisted in /etc/modprobe.d/nic.conf
# to ensure that after a reboot, eth0 (using module e1000) is setup correctly.
# At least I can ssh to NATcr!
# The following script is named reneth.
# To automate this process after every reboot, execute this script from /etc/rc.d/rc.local.
# Get MAC address of current eth1, eth2 and eth3.
# Then rename:
# eth1 ==> not_eth1
# eth2 ==> not_eth2
# eth3 ==> not_eth3
# Based on the MAC address, find which MAC belongs to eth1, eth2 or eth3.
# and rename the NIC accordingly to eth1, eth2 or eth3.
#
# Fr. Visminlu Vicente L. Chua, S.J.
# 2014/07/23
#
# Install NIC module skge
#
/usr/sbin/modprobe skge

#
# Get current MAC address of eth1, eth2 and eth3.
#
eth_1=`grep -H . /sys/class/net/eth1/address`
eth_2=`grep -H . /sys/class/net/eth2/address`
eth_3=`grep -H . /sys/class/net/eth3/address`

#
# The correct MAC address of eth1, eth2 and eth3
#
eth1Mac="00:26:5a:79:b5:9c"
eth2Mac="00:17:9a:bb:4e:7a"
eth3Mac="00:19:5b:2e:fd:47"

#
# Rename eth1, eth2 and eth3 to not_eth1, not_eth2 and not_eth3
#
/usr/sbin/ip link set dev eth1 name not_eth1
/usr/sbin/ip link set dev eth2 name not_eth2
/usr/sbin/ip link set dev eth3 name not_eth3

#
# find eth1
#
if [[ $eth_1 == *$eth1Mac* ]] ; then
   /usr/sbin/ip link set dev not_eth1 name eth1
elif [[ $eth_1 == *$eth2Mac* ]] ; then
   /usr/sbin/ip link set dev not_eth2 name eth1
elif [[ $eth_1 == *$eth3Mac* ]] ; then
   /usr/sbin/ip link set dev not_eth3 name eth1
fi

#
# find eth2
#
if [[ $eth_2 == *$eth1Mac* ]] ; then
   /usr/sbin/ip link set dev not_eth1 name eth2
elif [[ $eth_2 == *$eth2Mac* ]] ; then
   /usr/sbin/ip link set dev not_eth2 name eth2
elif [[ $eth_2 == *$eth3Mac* ]] ; then
   /usr/sbin/ip link set dev not_eth3 name eth2
fi

#
# find eth3
#
if [[ $eth_3 == *$eth1Mac* ]] ; then
   /usr/sbin/ip link set dev not_eth1 name eth3
elif [[ $eth_3 == *$eth2Mac* ]] ; then
   /usr/sbin/ip link set dev not_eth2 name eth3
elif [[ $eth_3 == *$eth3Mac* ]] ; then
   /usr/sbin/ip link set dev not_eth3 name eth3
fi

這解決了我的問題。真希望這也可以幫你解決你的問題。

蔡由世神父
2014/07/26