上篇博文介紹了無線mesh網絡和adhoc網絡的區別,這篇文章將介紹無線mesh網絡的骨干網節點的組建過程。首先需要介紹下骨干網節點的設計方案:每個骨干網節點都是由一塊友善之臂的tiny6410 arm開發板+兩塊TP-LINK TL-WN721N USB無線網卡+linux 2.6.38系統組成的,其中一塊網卡工作在adhoc模式下,用來和其他骨干網節點進行無線連接(自組織形式連接,而不是wifi接入點方式),另一塊網卡工作在wifi的master模式下,也就是說需要在這塊網卡上創建wifi熱點,供用戶的終端設備連接。即,骨干網節點之間采用自組網方式互連,而用戶終端設備和骨干網之間采用wifi接入方式。
1.linux內核的裁剪
由於骨干網節點之間采用自組織方式進行連接,因此將來需要運行adhoc網絡的路由協議(aodv或者別的自組網協議),工作在adhoc模式下的那張網卡需要參與該協議的運行。本實驗采用的aodv協議是由開源社區提供的aodv-uu-0.9.6協議。該協議是基於linux的Netfilter框架實現的。因此在進行linux內核裁剪時,需要加入Netfilter框架。本實驗使用的linux內核是友善之臂tiny6410開發板所帶的光盤中的linux-2.6.38-20120828.tgz,文件系統使用光盤中提供的rootfs_qtopia_qt4-mlc2.ubi。另外,內核裁剪時,使用了linux-2.6.38-20120828.tgz源碼根目錄下的config_linux_mini6410作為內核的原始配置文件。mv config_linux_mini6410 .config即可。
該配置文件中沒有加入Netfilter框架,因此需要手動去添加,筆者使用make menuconfig在圖形化界面中進行內核裁剪。
(1)打開內核配置界面首頁后,進入Networking support選項,如下圖:
(2)接着進入Networking options選項,如下圖:
(3)接着選擇Network packet filtering framework (Netfilter) 選項,並進入其中。所謂選擇,就是將該選項前的[]變為[*],將該選項對應的功能編譯進內核。如下圖:
(4)接着進入Core Netfilter Configuration選項,如下圖:
(5)按照下圖所示,選擇相應的選項。沒有在圖中出現的選項一律不管。
(6)退出當前選項,然后進入IP: Netfilter Configuration選項,如下圖:
(7)按照如下圖示,進行配置。不在圖中的選項不用管。
至此,Netfilter框架和iptables工具就配置進了內核中。iptables是用來設置linux防火牆的工具,我們在后邊要使用其設置一些過濾規則,因此將其一塊編譯進內核。之后可以使用make zImage && make install 編譯和安裝內核,並將編譯好的內核燒寫到arm開發板中。
2.將網卡A配置為adhoc模式
將兩張網卡中的任意一張(假設為網卡A)設置為adhoc模式,使用到的命令下面列出。筆者在實驗過程中,發現usb無線網卡插入開發板后,只能引起usb驅動做出響應,並不能激活無線網卡驅動。因此無法使用ifconfig,iwconfig對插入的無線網卡進行設置(此時設置會提示不存在wlan0設備)。筆者使用了tiny 6410 linux自帶的scan-wifi命令來加載網卡驅動(可能比較笨,不過很有效)。所有命令列出如下:
scan-wifi //此命令本用來搜索wifi熱點的,筆者使用它激活網卡驅動,笨笨噠~~
ifconfig //該命令可以查看所有網卡的配置情況,包括以太網卡和無線網卡,使用過scan-wifi操作后,在該命令下就會發現wlan0網卡的信息。
ifconfig wlan0 down //使用scan-wifi命令后,接着需要使用該命令停止wlan0網卡工作(該操作並未停止無線網卡驅動哦~),然后才能使用iwconfig命令對無線網卡的工作模式進行設置,否則如果不停止無線網卡的工作,使用iwconfig命令時將提示設備正忙。。。
iwconfig wlan0 mode ad-hoc //將網卡wlan0的工作模式設置為ad-hoc
iwconfig wlan0 essid “自定義的name” //設置該網卡所在的adhoc網絡的名稱,設置完成后,當其他的無線網卡也將其essid設置為相同名稱后,這些網卡將處於同一個adhoc網絡中。因此essid實際上是用來區分不同網絡的。
iwconfig wlan0 //該命令專門用來查看無線網卡的配置信息。此時,就會看到wlan0網卡工作模式為adhoc,essid為所設置的名稱,cell為當前網絡的詳細標志。
ifconfig wlan0 X.X.X.X //配置網卡wlan0的ip地址
ifconfig wlan0 up //啟動網卡wlan0
至此,無線網卡wlan0配置完畢,工作完成一半了。
3.重新編譯無線網卡驅動ath9k_htc
其實當配置完內核,加入Netfilter框架和iptables工具后,在使用scan-wifi命令時,內核會報出oops錯誤並導致arm板宕機。筆者懶於重現該錯誤,因此沒有錯誤截圖,很抱歉。但是錯誤的大概意思就是Unable to handle kernel NULL pointer dereference,不能操作空指針。筆者經過分析后,發現是無線網卡驅動ath9k_htc導致了該錯誤發生。由於我們在新內核中使用的仍然是友善之臂提供的舊無線網卡驅動,而新內核的虛擬地址空間有所變動,可能會導致舊的無線網卡驅動中某些虛擬地址已經不再被映射到正確的地方,因此出現了這種錯誤。解決辦法就是在新內核下重新編譯ath9k_htc無線網卡驅動,具體操作步驟下面給出。重新編譯后問題得以解決,進而驗證了筆者的猜測。
(1)用make menuconfig重新配置內核。在首頁中進入Networking support ----> Wireless選項中,選擇cfg80211 - wireless configuration API選項及其子選項。將cfg80211選為模塊來編譯,即將[]變為[M]。此外也將Generic IEEE 802.11 Networking Stack (mac80211)選項選擇為模塊來編譯,如下圖。
(2)退回配置文件的首頁,進入Device Driver ----> Netword device support選項中,選擇Wireless Lan選項並進入,如下圖:
(3)進入后,按照下圖所示進行選擇。
(4)進入Atheros Wireless Cards選項,並按下圖進行選擇。
至此,無線網卡驅動配置完畢,使用make modules && make modules_install對網卡驅動進行編譯與安裝。最后將/lib/modules/2.6.38-FriendlyARM/kernel/drivers/net/wireless/ath/,/lib/modules/2.6.38-FriendlyARM/kernel/net/mac80211/,
/lib/modules/2.6.38-FriendlyARM/kernel/net/wireless/路徑下的內容拷貝到arm linux的/lib中的相應路徑中,覆蓋掉原先的這些文件。宿主機系統和arm linux系統的這些路徑大體上是一致的,可能稍有不同,仔細找下,很容易找到相應的目錄。重新啟動arm linux系統,一切ok。
4.iptables安裝
上面1中linux內核裁剪時,提到了iptables已經編譯進了內核。其實iptables包含了兩個部分,上面的只是將內核部分搞定了,還需要對用戶態部分進行編譯和安裝。iptables的編輯比較簡單,只是需要注意,執行configure命令時,用prefix指定的安裝目錄,一定要與將來移植到arm linux系統中的路徑完全一致。例如,configure -prefix=/usr/local/iptables,那么編譯完后執行make install命令,iptables將被安裝在宿主機的/usr/local/iptables目錄下。之后也要將iptables目錄下的所有內容移植到arm linux的/usr/local/iptables下,不能移到其他路徑,否則iptables命令使用時將出錯,很難排查。筆者在這里花費了不少時間。
5.aodv協議的編譯和安裝
打開aodv-uu-0.9.6根目錄下的Makefile文件,找到CC=gcc處,將其改為CC=arm-linux-gcc(交叉編譯器),然后進行編譯。編譯完后生成aodvd和kaodv.ko兩個文件,kaodv.ko為內核模塊,aodvd為用戶態的可執行程序,將二者拖入arm linux系統中,先插入kaodv.ko模塊,然后再執行aodvd程序,aodv協議就成功運行了。當然這一切都要在上面的1、2、3步驟之后才能進行。也就是要有無線網卡工作在adhoc模式下,該路由協議才能發揮作用。
4.host Ap的安裝
此處較為簡單,以后再寫。
5.使用iptables配置網絡地址轉換方式
筆者使用上圖所示的拓撲測試了網絡的連通性,發現如果計算機A和計算B是win系統的話,則需要在1、2兩個節點上執行iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE命令,也就是說,要在節點1的POSTROUTING處為筆記本B做網絡地址轉換(對源地址做NAT),這樣B才能ping通A;同理,在節點2的POSTROUTING處為筆記本A做網絡地址轉換(對源地址做NAT),這樣A才能ping通B。但是如果計算機A和B為linux系統的話,就不需要做NAT。因此筆者猜測win系統和linux在處理包轉發或包回復時機制是不同的,至於是不是這樣,還有待於研究。
6.激活路由轉發模塊
普通的pc linux或arm linux的網絡層默認情況下,是沒有開啟路由轉發功能的,當系統收到的數據包不是發給本機的,會將數據包丟棄;因此當pc或者開發版作為路由器時,必須要激活路由轉發模塊。命令為:echo “1” > /proc/sys/net/ipv4/ip_forward。這樣就激活了主機的路由轉發模塊。
題外話
通過實驗,筆者對網絡的很多概念,包括ip地址、默認網關、路由表、arp表、路由表項、arp表項等等有了更深一步的認識。筆者覺得,ip地址雖然進行了A/B/C/D/E類划分,甚至划分了公網ip和局域網ip,可是就ip地址本身而言,它們之間沒有任何本質區別,在這種自組織的ip地址分配中,可以任意使用所有ip地址。因此筆者在對全網進行ip地址規划時,將mesh骨干網的所有節點的ip地址划為一個網段,將連接在某個骨干網節點的所有客戶端划為一個網段,並稱其為“局域網”,連接在不同骨干網節點上的若干個局域網之間絕不能處於同一個網段,也不能和骨干網處於同一網段。示意圖如下:
盡管骨干網是無自組織網絡,使用了aodv路由協議,但其mac層依然使用的是802.11協議。試想下,如果局域網1和局域網2處於處於同一網段,那么它們二者之間還能否進行通信??筆者認為,這種情況下,只有使用端口映射才能通信,那么局域網1和局域網2中都有若干台終端設備,那么還怎樣映射呢?因此不同局域網之間必須處於不同網段,這些相互之間才能通信。
細心的實驗者還應該發現,當不運行aodv協議時,這些節點之間有時也是可以連通的。其實這是對的,如果骨干網的所有節點都處於同一網段,那么arp協議會自動獲取本網段內所有節點的ip地址和mac地址,並初始化節點的arp表和路由表,使得本網段的主機可以直接通信;這就和以太網內所有主機處於同一網段,也可以互相通信是一個道理。如果骨干網內的所有節點並不在同一網段的時候,就需要aodv協議來進行路由探索了。另外,骨干網內,信號不能相互覆蓋的節點(即不是鄰居節點),也需要aodv協議進行路由探索,aodv協議一旦探索成功路由,並將路由信息更新至內核的路由表中,其就失去作用了(可以粗略這么理解)。
aodv協議的作用本身就只是探索路由並更新路由表,除此之外,別無它用。
最后,還要更正網上一些同類文章中錯誤的概念。他們認為節點上的兩張無線網卡需要使用NAT方式連通,這屬於概念性錯誤。其實在linux系統中,無論你插入多少張無線網卡,只要安裝好了網卡驅動,這些網卡本身就是連通的,也就是說,每個網卡的ip地址和Mac地址都會被記錄到路由表和arp表中,ip協議可以正確的將數據包通過相應的網卡發送出去。這和NAT方式壓根沒任何關系,NAT用來做網絡地址轉換,也就是說它會修改數據包的源地址或目的地址(對源地址做轉換或對目的地址做轉換,具體要根據需求來定),將其改為所設置的ip地址。NAT的作用在於,假如某些內網主機要通過一台連接在公網上的主機去上網,如果不做NAT,內網主機發送到互聯網上的數據包,互聯網站點是無法返回數據包的(返回的那些主機是內網主機,其ip地址為內網地址),所以這些內網主機是無法上網的;因此需要在連接到公網的那台主機上對這些內網主機數據包的源地址做NAT,將源地址轉換為公網主機的ip地址,這時內網主機發送到互聯網上的數據包,互聯網可以做應答的,將應答包發送給這台公網主機,該主機再逆向根據NAT規則,將應答包交給某個內網主機。因此內網主機就可以上網了。