HelloX操作系統網絡功能簡介及使用和開發指南

HelloX網絡功能簡介及使用和開發指南

HelloX網絡功能簡介

作爲物聯網操作系統,網絡功能是必備的核心功能之一。按照規劃,HelloX實現了兩個不同類型的TCP/IP協議棧,一個面向資源受限的嵌入式應用,移植了業界成熟使用的lwIP協議棧。該協議棧簡潔明瞭,功能相對簡單,同時專門面向嵌入式領域進行設計和優化,對硬件資源要求很低。另外一個協議棧來自BSD操作系統的協議棧,面向複雜的網絡功能豐富的應用場景,比如家庭網關,物聯網網關等。爲了適應HelloX本身的機制,對BSD協議棧做了一些更改和優化,當然,這是在BSD License允許的範圍之內。

目前lwIP協議棧已經成熟穩定運行,面向複雜場景的BSD協議棧正在移植當中。不論採用哪個協議棧,都提供相同的,符合BSD規範的socket API,因此對應用程序來說,協議棧都是透明的。對網卡驅動來說,HelloX本身設計了一套網卡驅動機制,向上屏蔽了不同的IP協議棧之間的差異,因此不論安裝的是lwIP協議棧還是BSD協議棧,網卡驅動也都是相同的。

本文對HelloX的網絡功能的使用和開發方法,進行簡單描述。

在虛擬機上使用網絡功能

HelloX V1.78實現了一個PCNet FastEthernet III的網卡驅動程序(對應的網卡控制芯片是AMD的AM79C973)。大部分虛擬機都支持這個網卡,因此有比較廣泛的通用性。如果您想試驗其它的網卡驅動程序,則需要手工編寫一個網卡驅動了。

以Virtual Box虛擬機爲例,在虛擬機的“設置”界面中,選擇“網絡”,這時候會列舉出四個網卡。選擇“網卡1”,按下圖所示進行配置:


 注意,“連接方式”選擇“橋接網卡”。如果選擇其它連接類型,我沒有試過,不知道行不行。選擇橋接網卡的含義,就是把你的PC機的物理網卡,與虛擬機的“網卡1”,用二層的方式連接了起來。可以想象VirtualBox虛擬了一個以太網交換機,然後把你的電腦的物理網卡,以及虛擬機的網卡1,都連接在了這個虛擬的以太網交換機上。

“界面名稱”中,選擇你的計算機的物理網卡名稱。注意,這個網卡一定是可以用的網卡,最好是你當前上網用的網卡,如果有多個網卡的話。

點開“高級”選項,“控制芯片”一行,按照上圖所示進行選擇。如果選擇其它的控制芯片,就需要編寫對應控制芯片的驅動程序了。這是一項很有意思的工作,只要拿到對應芯片的data sheet,基本很快就可以編寫出來。如果你能夠成功的編寫一個網卡驅動,那麼恭喜你,應聘任何一家通信類或者嵌入式開發類公司,保準可以通過。有興趣的朋友可以試試。

點擊確定之後,用最新的HelloX版本啓動虛擬機即可。注意,缺省情況下,HelloX是通過DHCP方式獲取IP地址的,因此與HelloX虛擬機關聯的物理網卡,也必須是通過DHCP方式獲取IP地址。

當然,如果不是DHCP獲取IP地址,也可以手工配置,參考本文下面的network命令部分。

啓動虛擬機之後,就可以用network程序,來查看和診斷網絡了。比如,可以用iflist命令,來查看獲取到的IP地址,用ping命令,來試試網絡連接是否正常。下面是在我的計算機上的運行結果:


在這裏,簡單介紹一下用ping命令診斷網絡連接是否正常的方法。這些方法,一般在《網絡基礎》課程裏面都會涉及到。如果要考MCSE,CCNA等證書,這些內容是必考內容。

首先,ping一下環回地址,即127.0.0.1。如果這個地址能ping通,說明TCP/IP協議棧已經正常工作了。如果ping不通,那麼就是TCP/IP協議棧都沒有起來;

如果環回地址ping通了,再ping一下網絡接口的本地地址,也就是網卡地址。在上圖中,是10.129.73.4。如果這個地址能夠ping通,說明網卡已經被TCP/IP協議棧成功識別和管理。如果這個地址都ping不通,那麼說明網卡與IP協議棧沒有關聯起來;

在本地地址ping通的情況下,再ping缺省網關,在上圖中,就是10.129.73.1這個地址。如果這個地址能ping通,說明計算機與路由器之間的通信是正常的。後面如果有網絡問題,基本上可以排除是本地計算機問題。如果ping不通,則說明本機與路由器沒有正常通信,這時候需要檢查網線等物理連接。

在缺省網關ping通的情況下,就可以ping目標服務器了。這時候如果ping通了,就萬事大吉了。如果ping不通,那麼很可能就是目標服務器的問題,或者是目標服務器與本地路由器之間的問題了。

HelloX的Network程序使用指南

HelloX實現了一個network字符界面應用程序,可以對網絡功能進行調試。同時實現了一個抽象的以太網管理框架(Ethernet Framework),實現了一套標準的網絡驅動程序接口,屏蔽了不同網絡驅動程序之間的差異。這樣,不同的硬件,其驅動代碼是不同的,但是隻要遵循這一套標準的接口規範,就可以無縫掛接到HelloX內核中。

下面簡要介紹V1.78版的網絡調試程序network,在此基礎上,簡要介紹一下HelloX的網絡驅動程序編寫方法。

在字符shell模式下,輸入network並回車,即可進入network應用程序。該程序提供瞭如下一些網絡相關命令:

scan命令

該命令用於掃描所有可用的WiFi熱點,前提是需要有WLAN硬件支持。該命令會列出所有掃描到的AP熱點,如下:

[network-view]scan

Available WiFi list:

 -----------------------------

 00:BSSID = 20004E9C, RSSI = 76, SSID = 'HelloX_HGW_AP', channel = 1

 01:BSSID = 2000508C, RSSI = 15, SSID = 'Celleden_Map1600', channel = 6

 

如果發現想要連接的熱點不在上述列表中,可多執行幾次scan命令,很多情況下,一次scan是無法掃描到所有熱點的。

注意,要使用scan命令,必須具備WLAN網卡,否則無效。

 

assoc命令

assoc用於跟某個指定的WiFi熱點相關聯。Scan只是掃描出一些可用的熱點,但是如果需要跟某個熱點進行連接,則必須使用assoc命令。如下:

 

[network-view]assoc HelloX_HGW_AP

 

上述命令用於連接到名字爲“HelloX_HGW_AP”的WiFi熱點。注意,該WiFi熱點必須是開放的不加密熱點,因爲上述命令沒有指定連接密碼。

如果是要連接一個加密的WiFi熱點,則可以用/k參數指定連接的密碼:

 

[network-view]assoc HelloX_HGW_AP/k0123456789012

 

後面是密碼。當前只支持WEP加密,因此密碼必須是13個字節。

再次說明一下,當前值支持開放不加密的WiFi熱點,以及基於WEP加密的WiFi熱點,尚不支持WPA加密熱點,因此要希望連接成功,必須修改WiFi熱點的配置,修改爲開放不加密,或者使用WEP加密(密碼要設置爲13位數字)。

 

showint命令

該命令用於顯示出系統中所有網絡接口的統計信息,比如接收報文個數,發送報文個數等。下列是一個簡單的輸出例子:

 

[network_view]showint

 Statistics information for interface'Marvel_WLAN_Int':

  Send frame #       : 17

  Success send #     : 17

  Send bytes size    : 2946

  Receive frame #    : 14

   Success recv #     : 14

  Receive bytes size : 1778

 

各輸出字段的含義是自解釋的。

 

iflist命令

能夠則列舉出系統中所有的網絡接口,與其對應的IP地址等信息。與showint不同的是,iflist顯示的是網絡接口的靜態信息(IP地址/掩碼/缺省網關等),而showint顯示的則是網絡接口的動態信息。

下面是iflist的一個輸出例子:

 

[network_view]iflist

 --------------------------------------

 Inetface name : Ma

    IPv4 address   : 192.168.43.173

     IPv4 mask     : 255.255.255.0

    IPv4 gateway   : 192.168.43.1

    Interface MTU  : 1500

 --------------------------------------

 Inetface name : lo

    IPv4 address   : 127.0.0.1

    IPv4 mask      : 255.0.0.0

    IPv4 gateway   : 127.0.0.1

    Interface MTU  : 0

 

上面顯示了兩個網絡接口,第一個是WLAN接口,名字只包含了起始的2個字節。

 

setif命令

setif命令則用於修改接口的靜態配置參數。比如,可以通過下列方式,爲一個網絡接口設置靜態的IP地址:

 

setif Marvel_WLAN_Int /a 192.168.0.100 /m255.255.255.0 /g 192.168.0.1

 

其中Marvel_WLAN_Int是接口的名字(showint命令可以顯示),後面分別是該接口的IP地址/子網掩碼/缺省網關。需要注意的是,缺省情況下,接口上是啓動DHCP功能的,試圖自動獲取IP地址。一旦通過上述命令設置靜態IP地址,則會同時把該接口上的DHCP功能關閉。

如果要重新打開DHCP功能,則使用如下命令:

 

setif Marvel_WLAN_Int /d enable

 

而下列命令,則用於重新啓動接口上的DHCP功能:

 

setif Marvel_WLAN_Int /d enable

 

重啓DHCP功能的目的,是爲了立即在接口上發出DHCP請求。缺省情況下,DHCP功能是以指數退避方式來發送DHCP請求報文的,即當接口剛剛使能的時候,會發送DHCP請求,如果沒有收到響應,則會在2秒後再發一次,然後是4秒,然後是8秒…以此類推。如果想立即在接口上重新發出DHCP請求,則使用上述命令restart一下即可。

 

Ping命令

這是最常用的診斷命令,後面直接跟IP地址即可。下面是一個簡單的輸出例子:

 

[network_view]ping 192.168.43.1

 Ping192.168.43.1 with 64 bytes packet:

 [0]Reply from 192.168.43.1,size = 64,time = 40(ms)

 [1]Reply from 192.168.43.1,size = 64,time = 180(ms)

 [2]Reply from 192.168.43.1,size = 64,time = 180(ms)

 pingstatistics: total send = 3,received = 3,0 loss.

 

如果希望改變缺省的ping報文長度,則可以增加一個參數:

 

ping 192.168.43.1 /l 1024

 

上述命令以1024字節爲ping報文長度。缺省情況下,會連續ping三個報文,然後結束。如果希望ping更多的報文,則使用下列命令:

 

ping 192.168.43.1 /c 1000

 

上述命令可以ping1000個報文。當然,l參數和c參數可以一起使用。

 

HelloX網絡驅動程序編寫方法

HelloX實現了一個基於線程輪詢機制的以太網驅動程序框架,系統中有一個叫做eth_thread的線程,定時(每隔100ms)輪詢網卡驅動程序,試圖接收數據幀。如果有合適的數據幀到達,則eth_thread會把這個數據幀遞交到IP層處理。

因此,要實現一個以太網驅動程序,需要遵循HelloX的以太網驅動框架,具體來說,就是要實現下列函數:

 

初始化函數

原型如下,這個函數在以太網驅動程序被加載的時候,會被HelloX調用,用於完成硬件的初始化功能。當然,如果不需要初始化,完全可以寫成下列形式:

 

static BOOLInt_Init(__ETHERNET_INTERFACE*pInt)

{

       returnTRUE;

}

 

硬件的初始化,還可以放在驅動程序的入口函數中,下面會提及。

 

報文發送函數

原型如下:

 

static BOOLSendFrame(__ETHERNET_INTERFACE*pInt);

 

在IP層試圖發送報文的時候,以太網驅動框架會調用這個函數。所發送的數據幀已經在IP層面準備好(包括源MAC地址/目的MAC地址等),存放在pInt對象的一個緩衝區中(如下代碼),驅動程序只需要發送即可。

 

typedef struct tag__ETHERNET_INTERFACE{

      char                   ethName[MAX_ETH_NAME_LEN +1];

      char                   ethMac[ETH_MAC_LEN];

      char                   SendBuff[ETH_DEFAULT_MTU];//Sending buffer.

      int                    buffSize;                

      __ETH_INTERFACE_STATE  ifState;     

      LPVOID                 pL3Interface;

      LPVOID                 pIntExtension; //Privateinformation.

      ……

}__ETHERNET_INTERFACE;

 

其中SendBuff是存放待發送數據幀的緩衝區,buffSize是數據幀的長度,必須小於ETH_DEFAULT_MTU(1500)。

在SendFrame函數中,只需要操作硬件,把SendBuff中的內容送到物理網絡上,然後返回即可。

 

數據幀接收函數

該函數原型如下,會被HelloX的以太網管理框架週期性的調用,以判斷是否有數據幀到達:

 

static structpbuf*RecvFrame(__ETHERNET_INTERFACE* pInt);

 

在這個函數中,硬件判斷有數據幀到達,則需要創建一個pbuf,把數據幀從硬件緩衝區中拷貝到pbuf裏面,然後返回這個pbuf。比如下面的實例代碼:

 

static struct pbuf*Marvel_RecvFrame(__ETHERNET_INTERFACE*pInt)

{

struct eth_packet  *rx_pkt   =&pgmarvel_priv->rx_pkt;

 struct pbuf         *p, *q;

 u16                 len        =0;

 int                 l          = 0;

 char                *buffer    = NULL;

 

  p=NULL;

 /*Obtain the size of the packet and put it into the "len"variable. */

 len= lbs_rev_pkt();

     

 if(len > 0){

              buffer= rx_pkt->data;

              /*We allocate a pbuf chain ofpbufs from the pool. */

              p= pbuf_alloc(PBUF_RAW, len,PBUF_POOL);

              if(p != NULL){

                     for(q = p; q != NULL; q =q->next){

                           memcpy((u8_t*)q->payload,(u8_t*)&buffer[l], q->len);

                            l= l + q->len;

          }  

        }

        else

              {

        }

  }

 return p;

}

 

如果硬件判斷沒有數據幀到達,則只需要返回NULL即可。

 

特定功能的控制函數

原型如下:

 

static BOOLEth_Ctrl(__ETHERNET_INTERFACE*pInt,DWORD dwOperation,LPVOID pData);

 

對於一些以太網的特定控制功能,比如設置MTU大小,修改速率,WiFi的掃描AP/附着AP等,通過這個函數實現。dwOperation指明瞭需要的操作。

如果沒有特殊需要,也可以不需要實現該函數。建議的實現方式是,實現一個只返回TRUE的空函數,比如:

 

staticBOOLMarvel_Ctrl(__ETHERNET_INTERFACE* pInt,DWORD dwOperation,LPVOID pData)

{

      returnTRUE;

}

 

實現驅動程序入口函數

實現完成上述函數之後,還需要實現一個以太網驅動程序的入口函數,這個入口函數會被HelloX的以太網管理框架調用,用於加載以太網驅動程序。在入口函數中,需要做系列工作:

1. 初始化硬件;

2. 調用AddEthernetInterface,向系統中註冊以太網接口。

下面是一個實現實例:

 

BOOL Marvel_Initialize(LPVOID pData)

{

      __ETHERNET_INTERFACE*pMarvelInt = NULL;

      char                 mac[ETH_MAC_LEN];

     

   //初始化硬件,獲得硬件的MAC地址,存放在mac數組中。

   //調用AddEthernetInterface,註冊接口。

      pMarvelInt= EthernetManager.AddEthernetInterface(

        MARVEL_ETH_NAME,  //以太網的名字,任意字符串,不能包含空格。

        &mac[0],               //MAC地址。

NULL,                 //初始化函數的參數。

Int_Init,               //接口初始化函數,對應上述Int_Init函數

SendFrame,             //數據幀發送函數

RecvFrame,             //數據幀接收函數

Eth_Ctrl);               //控制函數。

 

      if(NULL== pMarvelInt)

      {

              returnFALSE;

      }

      returnTRUE;

}

 

調用AddEthernetInterface的時候,需要使用上面實現的四個操作函數作爲參數。調用成功後,會返回一個以太網對象指針,可以保存起來,供後期卸載以太網接口的時候用。

 

在以太網驅動入口數組中增加一項

最後一步,就是在以太網驅動程序入口函數數組中增加一項,告訴操作系統以太網驅動程序的存在。這樣操作系統在初始化的時候,就會調用驅動程序入口函數,加載驅動程序。入口函數數組位於network/ethernet/ethentry.c文件中,下面是一個示例:

 

__ETHERNET_DRIVER_ENTRYEthernetDriverEntry[]=

{

#ifdef __CFG_NET_MARVELLAN

       {Marvel_Initialize,NULL},

#endif

 //Please add your ethernet driver's entryhere.

 {NULL,NULL}

};

 

其中Marvel_Initialize是驅動程序入口函數,NULL是入口函數的參數,可以是任意指針。注意,該數組中的第一個網絡接口,會被系統自動設置爲缺省網絡接口,即缺省網關所在的接口,或者HelloX默認路由所在的接口。

這樣以太網驅動程序就編寫完成了。建議把以太網驅動程序的代碼,存放在driver/STM32目錄下。重新編譯HelloX,即可實現以太網驅動程序的加載。

以太網驅動程序加載成功後,即可食用network程序,進行診斷和調試。如果命令級別的診斷無法發現問題,則可以啓用代碼級的調試。具體來說,在ethif.h文件中,打開以太網調試開關(__ETH_DEBUG),重新編譯並加載運行,即可輸出網絡運行過程中的更加詳細的信息。

 

HelloX V1.78的代碼,可以從github上下載:

github.com/hellox-project/HelloX_OS

有任何問題,歡迎加入QQ羣討論:38467832

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章