本文皆是作者工作學習中的理解或感悟,歡迎大家提出問題,一起討論!!
一.問題提出
一般的主板上都帶有兩個網卡接口,linux系統啟動后一般命名為eth0,eth1,當然如果我們不對eth0與eth1進行后期處理的話,每次開機eth0與eth1的位置也不會固定。所以當外置網卡時,更會出現端口混亂的問題(端口名與端口的pci位置不固定,每次啟動都可能變換,內核對網絡端口的命名順序是根據檢測到網卡的先后順序來的),特別是不同驅動的網卡。
二.問題分析
1、首先我們需要了解內核給網絡端口命名的執行流程:
1)linux內核一般會在rc.sysinit里執行/sbin/udevd -d開始執行udev程序
2)執行udev的過程中會檢測所有設備,並根據不同的設備來加載不同的驅動
3)加載完相應設備的驅動后,udev會收到一個該設備的內核事件,udev會根據相應的事件來匹配相應的規則,或者是執行某些腳本修改設備名重新書寫規則(rules)
4)當規則生成后,當再次產生此設備的內核事件時,則首先會匹配這些規則
這里要注意udev的兩點:
1)我們可以通過udev來修改任何設備的名字
2)在我們沒修改名字之前,內核已經給給設備分配了名字(值得注意這點,否則修改的名字和內核給其他設備分配的名字沖突,則會修改失敗)
2、不同的網卡設備
目前為止我已知的網卡有如下幾種(都是intel的):
網卡型號 所用驅動
8086:1502 e1000e
8086:10d3 e1000e
8086:150e igb
8086:105e e1000e
8086:1521 igb
這只是我接觸的幾種網卡,不同種類的驅動對網卡端口的命名還是會有影響的
3.pci接口的bus id號
-bash-3.2# lspci -n -D | grep 0200
0000:00:19.0 0200: 8086:1502 (rev 05)
0000:01:00.0 0200: 8086:150e (rev 01)
0000:01:00.1 0200: 8086:150e (rev 01)
0000:01:00.2 0200: 8086:150e (rev 01)
0000:01:00.3 0200: 8086:150e (rev 01)
0000:03:00.0 0200: 8086:105e (rev 06)
0000:03:00.1 0200: 8086:105e (rev 06)
0000:04:00.0 0200: 8086:10d3
我們通過lspci -n -D可以查看所有的連在pci接口上的設備的busid號(第一列)和設備型號(最后一列)的對應列表,這里的0200代表的是網卡設備,通過大量的實驗發現,無論網口的名字(eth*)怎么變化,在同一台機器上,他們的busid號是不變的。這里的8086:1502,8086:10d3是主板自帶的兩個端口,8086:150e是一個4口的Intel網卡,8086:105e是一個兩口的intel網卡。由此,在這一型號的機器上,這一型號的網卡上,可已通過busid號,網卡型號來固定網口名。
三、問題處理
1)首先我們在udev的一個和網絡有關的規則文件里添加了如下代碼:
KERNEL=="eth*|ath*|wlan*|ra*|sta*", DRIVERS=="?*",IMPORT{program}="A.sh $attr{address} %b"
當有網卡的內核事件的時候,會匹配這條規則,執行A.sh這個腳本,並且將mac地址($attr{address}),busid號(%b)作為參數傳給腳本
2)A.sh的功能就是根據mac地址和busid兩個參數,來修改端口名,最終將新規則輸出到一個新的規則文件B中。具體方法:
a)先列出一個busid和網絡端口名的對應表如下:
0000:04:00.0 8086:10d3 eth0
0000:00:19.0 8086:1502 eth1
0000:01:00.0 8086:150e eth2
0000:01:00.1 8086:150e eth3
0000:01:00.2 8086:150e eth4
0000:01:00.3 8086:150e eth5
0000:03:00.0 8086:105e eth6
0000:03:00.1 8086:105e eth7
b)根據busid和這個表,來查找最終的端口名
c)根據mac地址和最終的端口名,生成新的規則,如下:
# PCI device 0x8086:0x150e (igb)
BUS=="net", DRIVER=="?*", SYSFS{address}=="90:e2:ba:52:8e:b2", NAME="eth4"
# PCI device 0x8086:0x1502 (e1000e)
BUS=="net", DRIVER=="?*", SYSFS{address}=="0c:c4:7a:06:03:f3", NAME="eth1"
# PCI device 0x8086:0x150e (igb)
BUS=="net", DRIVER=="?*", SYSFS{address}=="90:e2:ba:52:8e:b3", NAME="eth5"
# PCI device 0x8086:0x10d3 (e1000e)
BUS=="net", DRIVER=="?*", SYSFS{address}=="0c:c4:7a:06:03:f2", NAME="eth0"
# PCI device 0x8086:0x150e (igb)
BUS=="net", DRIVER=="?*", SYSFS{address}=="90:e2:ba:52:8e:b0", NAME="eth2"
#PCI device 0x8086:0x105e (e1000e)
BUS=="net", DRIVER=="?*", SYSFS{address}=="68:05:ca:12:e0:c5", NAME="eth7"
# PCI device 0x8086:0x150e (igb)
BUS=="net", DRIVER=="?*", SYSFS{address}=="90:e2:ba:52:8e:b1", NAME="eth3"
# PCI device 0x8086:0x105e (e1000e)
BUS=="net", DRIVER=="?*", SYSFS{address}=="68:05:ca:12:e0:c4", NAME="eth6"
d)之后的udev事件則通過規則B文件來匹配,故完成了重命名
3)做完2之后,進行了大量的測試,發現存在了一個問題,概率很大:也就是重命名失敗了,原因是和系統分配的端口名相同,起沖突了
分析這個沖突問題:
1)首先我們有三塊網卡,兩種驅動
2)udev開啟,掃描設備,加載驅動,內核給設備命名
3)假如內核命名的eth0 驅動是e1000e,進入了udev的規則,我們要給它改成eth3
4)但是在eth0進入udev沒修改成eth3的時候,內核又將一個網絡端口設備命名為eth3
5)則我們將eth0修改為eth3的時候,就會沖突,eth0 變成了eth3_rename
4)針對3)的問題,在init.d的網絡服務啟動之前(network),即在network腳本里靠前部分,加入一段代碼,用於處理_rename問題。
1)通過ifconfig查找當前的端口名(顯示全部 加參數-a)
2)通過1)查找的端口名和規則B進行比對,出現問題,則進行修改
四、以上就是對於外置網卡的處理過程,歡迎大家一起討論。轉載請注明出處!!http://www.cnblogs.com/yuzhaoxin/p/4083760.html