0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

如何更好的理解LWIP協(xié)議

恩智浦MCU加油站 ? 來源:恩智浦MCU加油站 ? 作者:恩智浦MCU加油站 ? 2022-10-27 09:13 ? 次閱讀

LWIP協(xié)議與網(wǎng)絡(luò)分層

LwIP(Light weight IP),是一種輕量化且開源的TCP/IP協(xié)議棧,它可以在有限的RAMROM條件下,實現(xiàn)一個完整的TCP/IP 協(xié)議棧。此外,LwIP既可以移植到操作系統(tǒng)上運行,也可以在無操作系統(tǒng)的情況下獨立運行。

TCP/IP協(xié)議棧的模型結(jié)構(gòu)如下圖所示,由于TCP/IP協(xié)議棧的出現(xiàn)時間較早,所以沒有按照傳統(tǒng)的7層OSI網(wǎng)絡(luò)模型進行設(shè)計,一共只分為了4層,分別為網(wǎng)絡(luò)接口層,網(wǎng)絡(luò)層,傳輸層以及應(yīng)用層,LwIP協(xié)議棧的網(wǎng)絡(luò)模型與之類似。

ccdbc404-5590-11ed-a3b6-dac502259ad0.png

網(wǎng)絡(luò)接口層主要通過雙絞線,光纖,無線等方式進行網(wǎng)絡(luò)上數(shù)據(jù)幀的發(fā)送和接收。網(wǎng)絡(luò)接口層將網(wǎng)絡(luò)層的數(shù)據(jù)組裝成自己特定的幀進行發(fā)送,同時也會接收數(shù)據(jù)幀進行解析,并將解析過后的數(shù)據(jù)發(fā)送給網(wǎng)絡(luò)層。

網(wǎng)絡(luò)層負責在主機之間的通信過程之中選擇數(shù)據(jù)包的傳輸路徑,并且在接收到傳入的數(shù)據(jù)報時會檢驗其有效性,并遞交給上層。

傳輸層主要提供應(yīng)用程序之間的通信服務(wù),它會系統(tǒng)的管理兩端數(shù)據(jù)之間的交互。

應(yīng)用層簡單來說就是利用傳輸層提供的功能發(fā)送自己的數(shù)據(jù)到對方。

LWIP協(xié)議棧初始化

在開始傳輸數(shù)據(jù)之前,首先要進行一系列的初始化操作,本文以i.MX RT1060 SDK中的Demo "evkmimxrt1060_lwip_udppecho_bm"為例,該代碼可以通過MCUXpresso IDE進行導(dǎo)入。

netif_add函數(shù)用來掛載網(wǎng)絡(luò)接口,并完成網(wǎng)絡(luò)通信之前的大部分初始化工作,包括PHY芯片的初始化,i.MX RT1060上ENET外設(shè)初始化,以及一些通信過程中用到的相關(guān)數(shù)據(jù)結(jié)構(gòu)的初始化。

PHY芯片的初始化是在ethernetif_phy_init之中完成,包括MDIO初始化,網(wǎng)口自動協(xié)商,網(wǎng)口連接等操作。

cd0108ae-5590-11ed-a3b6-dac502259ad0.png

ENET外設(shè)的初始化在ENET_SetMacController之中完成,這里進行了ENET外設(shè)的一些配置,例如設(shè)置接口速率,以及接口類型(mii,Rmii)等等。

cd236746-5590-11ed-a3b6-dac502259ad0.png

PHY初始化函數(shù)以及ENET初始化函數(shù)都在ethernetif0_init函數(shù)中被調(diào)用,并且該函數(shù)被作為一個實參傳入netif_add之中并被在其中被調(diào)用,因此netif_add不僅完成了網(wǎng)絡(luò)接口的掛載,還完成了接口相關(guān)的一系列初始化工作。

此外,在進行網(wǎng)絡(luò)接口相關(guān)初始化的同時,也完成了對一系列數(shù)據(jù)結(jié)構(gòu)的初始化,此處介紹一些在網(wǎng)絡(luò)通信過程中用到的結(jié)構(gòu)體。

enet_rx_bd_struct_t, 該結(jié)構(gòu)體一般用來定義buffer descriptor,網(wǎng)絡(luò)接口層接收到的數(shù)據(jù)一般就封裝在buffer descriptor之中。
結(jié)構(gòu)體定義如下圖所示,其中l(wèi)ength代表buffer descriptor之中數(shù)據(jù)的長度,control之中會存儲一些與buffer descriptor相關(guān)的狀態(tài)信息,并且支持enhanced buffer descriptor。

cd43a5ce-5590-11ed-a3b6-dac502259ad0.png

enet_rx_bd_ring_t結(jié)構(gòu)體,如下圖所示,每一條ring都是由buffer descriptor組成的。
cd78c3c6-5590-11ed-a3b6-dac502259ad0.pngRing結(jié)構(gòu)體中的rxBdBase成員就是第一個buffer descriptor的地址,rxGenIdx指的是當前buffer descriptor的序號,rxRingLen指的是這條Ring中共有幾個buffer descriptor。
cd892108-5590-11ed-a3b6-dac502259ad0.png

pbuf結(jié)構(gòu)體,pbuf結(jié)構(gòu)體是用來描述lwip協(xié)議棧中數(shù)據(jù)包的結(jié)構(gòu)體。它是以鏈表的形式存在的,pbuf之中會存在指針指向下一個pubf 。

由于在case之中,使用的是UDP通信,因此還需要進行一些UDP相關(guān)的初始化設(shè)置。例如調(diào)用udp_bind函數(shù),對UDP控制塊中的local_port,local_ip等參數(shù)進行綁定,以及調(diào)用udp_recv在udp控制塊上進行一些回調(diào)函數(shù)的綁定等等,至于什么是UDP控制塊,在后面會進行介紹。

LWIP網(wǎng)絡(luò)接口層

網(wǎng)絡(luò)接口層數(shù)據(jù)接收

在udpecho demo之中是通過輪詢的方法來實現(xiàn)數(shù)據(jù)接收,使用的是raw/callback api, 除了這種api之外lwip還提供socket api等,不過需要操作系統(tǒng)的支持。

在while循環(huán)中首先會去調(diào)用ethernetif_input函數(shù),該函數(shù)中會調(diào)用ethernetif_linkinput函數(shù),在ethernetif_linkinput之中又會去調(diào)用ENET_GetRxFrame和ethernetif_rx_frame_to_pbufs函數(shù)。

在ENET_GetRxFrame函數(shù)中會把網(wǎng)絡(luò)接口中接收到的數(shù)據(jù)搬運到RxFrame之中,然后ethernetif_rx_frame_to_pbufs函數(shù)又會把RxFrame之中的數(shù)據(jù)搬運到pbufs之中,接下來就會調(diào)用ethernet_input函數(shù),在lwip源碼之中的ethernet.c文件中被定義,主要用于無操作系統(tǒng)時候網(wǎng)絡(luò)層去處理接收到的數(shù)據(jù)幀,然后往上層遞交,對于不同的數(shù)據(jù)包進行不同的處理,如果是 ARP包,則調(diào)用etharp_input函數(shù);如果是 IP 包,則調(diào)用 ip4_input函數(shù),通過這些函數(shù)將數(shù)據(jù)包遞交給 IP 層處理。

cdab6308-5590-11ed-a3b6-dac502259ad0.png

網(wǎng)絡(luò)接口層數(shù)據(jù)發(fā)送

在網(wǎng)絡(luò)層發(fā)送數(shù)據(jù)時,會調(diào)用網(wǎng)絡(luò)接口層的ethernet_output函數(shù),ethernet_output函數(shù)之中又會去調(diào)用ethernetif_linkoutput函數(shù),當數(shù)據(jù)較大需要用多個pbuf進行存儲的時候,pbuf以鏈表的形式存在,所以需要將這些鏈表中的數(shù)據(jù)進行合并,如下圖所示。

ce720378-5590-11ed-a3b6-dac502259ad0.png

操作完成后通過ENET_SendFrame函數(shù)來完成數(shù)據(jù)的發(fā)送;最后數(shù)據(jù)會通過網(wǎng)絡(luò)接口傳輸出去。

LWIP網(wǎng)絡(luò)層

IP協(xié)議

IP協(xié)議是一種經(jīng)典的網(wǎng)絡(luò)層協(xié)議,IP協(xié)議(Internet Protocol),又稱之為網(wǎng)際協(xié)議,IP 協(xié)議處于IP層工作,它是整個TCP/IP協(xié)議棧的核心協(xié)議,上層協(xié)議都要依賴IP協(xié)議提供的服務(wù),IP協(xié)議負責將數(shù)據(jù)報從源主機發(fā)送到目標主機,并通過IP地址作為唯一識別碼。簡單來說,不同主機之間的IP地址是不一樣的,在發(fā)送數(shù)據(jù)報的過程中,IP協(xié)議還可能對數(shù)據(jù)報進行分片處理,同時在接收數(shù)據(jù)報的時候,還可能需要對分片的數(shù)據(jù)報進行重裝等等。

IP協(xié)議是一種無連接的不可靠數(shù)據(jù)報交付協(xié)議,協(xié)議本身不提供任何的錯誤檢查與恢復(fù)機制,需要傳輸層協(xié)議來完成這些功能。

IP地址

在TCP/IP設(shè)計過程中,設(shè)計人員為每一臺主機分配一個32bit的IP地址,只有具有有效的IP地址的主機才能接入互聯(lián)網(wǎng)中與其他主機進行通信。

IP數(shù)據(jù)報

IP數(shù)據(jù)包一般由IP首部和數(shù)據(jù)組成,首部一般有20-60字節(jié),其中有40字節(jié)是可選的,一般首部僅由20字節(jié)組成,IP數(shù)據(jù)報結(jié)構(gòu)如下圖所示。

ce9b5048-5590-11ed-a3b6-dac502259ad0.png

為了方便對IP首部進行讀取或?qū)懭氩僮?,在lwip源碼之中定義了ip_hdr結(jié)構(gòu)體來表示ip數(shù)據(jù)報首部。

ceb0838c-5590-11ed-a3b6-dac502259ad0.png

IP層數(shù)據(jù)接收

在上文提到,對于不同的數(shù)據(jù)包進行不同的處理,如果是ARP包,則調(diào)用etharp_input函數(shù)去處理;如果是IP包,則交給IP相關(guān)函數(shù)去處理。

在udpecho demo中使用的是IPV4協(xié)議,因此,會調(diào)用ip4_input函數(shù)。

在ip4_input函數(shù)中會對ip數(shù)據(jù)報的相關(guān)字段進行檢驗,例如長度,校驗和,版本號等等,也會判斷該數(shù)據(jù)包是否是發(fā)送給本地的,如果不是發(fā)送給本地的數(shù)據(jù)包,可能還要對其進行轉(zhuǎn)發(fā)或者丟棄,如果數(shù)據(jù)報沒有問題,IP層就會根據(jù)傳輸層的協(xié)議類型將數(shù)據(jù)包傳送到不同的入口函數(shù)之中,例如udp_input, tcp_input函數(shù)等。

ced31398-5590-11ed-a3b6-dac502259ad0.png

IP層數(shù)據(jù)發(fā)送

在傳輸層協(xié)議需要通過IP層來發(fā)送數(shù)據(jù)時,在上層函數(shù)之中會調(diào)用ip4_output_if_src函數(shù),在該函數(shù)中,又會去調(diào)用ip4_output_if_opt_src函數(shù),它會將傳輸數(shù)據(jù)封裝到ip數(shù)據(jù)報之中,填寫數(shù)據(jù)報之中的目標IP地址,源IP地址,協(xié)議類型等相關(guān)信息。然后再去調(diào)用etharp_output(),它會解析MAC地址,組裝以太網(wǎng)幀并并發(fā)送。在etharp_output()函數(shù)之中,最終會去調(diào)用網(wǎng)絡(luò)接口層的相關(guān)發(fā)送函數(shù)。

cf050934-5590-11ed-a3b6-dac502259ad0.png

LWIP傳輸層與應(yīng)用層

網(wǎng)絡(luò)層已經(jīng)通過IP協(xié)議等完成了數(shù)據(jù)報在各臺主機之間傳輸?shù)牡墓δ?,但是?shù)據(jù)還沒有到達最終目的地—主機上的某個特定應(yīng)用程序。

IP層通過傳輸層的協(xié)議將數(shù)據(jù)包遞交給應(yīng)用程序,常用的傳輸層協(xié)議有UDP協(xié)議,TCP協(xié)議等。

此處以UDP協(xié)議為例,它是一種較為簡單的傳輸層協(xié)議,經(jīng)常應(yīng)用于局域網(wǎng)環(huán)境以及視頻播放領(lǐng)域,以UDP為例結(jié)合SDK代碼講解一下傳輸層是如何實現(xiàn)數(shù)據(jù)交互的。

UDP報文

在使用UDP傳輸數(shù)據(jù)時,它會將數(shù)據(jù)封裝在UDP報文之中,在IP層又會將數(shù)據(jù)包封裝在IP報文之中,在物理層又會將IP數(shù)據(jù)包封裝在物理數(shù)據(jù)幀之中。

一份用戶數(shù)據(jù)在被發(fā)送時共經(jīng)歷了三次封裝。

cf27e6ca-5590-11ed-a3b6-dac502259ad0.png

UDP相關(guān)數(shù)據(jù)結(jié)構(gòu)

在LWIP源碼的udp.h之中,定義了報文首部數(shù)據(jù)結(jié)構(gòu)以及UDP控制塊。

LwIP報文首部數(shù)據(jù)結(jié)構(gòu)為udp_hdr, 定義了 UDP 報文首部的各個字段, 分別為16位源端口號src, 16位目標端口號dest, 16位用戶數(shù)據(jù)報總長度, 以及16位的校驗和。

cf531d90-5590-11ed-a3b6-dac502259ad0.png

LwIP還定義了UDP控制塊,記錄與UDP通信的所有相關(guān)信息,如源端口號、目標端口號、源IP地址、目標IP地址以及收到數(shù)據(jù)時的回調(diào)函數(shù)等等,系統(tǒng)會為每一個基于UDP協(xié)議的進程創(chuàng)建一個UDP控制塊,并且將其與對應(yīng)的端口綁定,并將所有的UDP控制塊用一個鏈表連接起來。當UDP接收到一個報文的時候,會去遍歷鏈表上的所有控制塊,通過端口號來找到匹配的控制塊,并將數(shù)據(jù)通過回調(diào)函數(shù)傳遞到上層應(yīng)用。

cf8a2fce-5590-11ed-a3b6-dac502259ad0.png

UDP報文接收

在IP層,當接收到一個包含UDP報文的數(shù)據(jù)報時,udp_input函數(shù)就會被調(diào)用,該函數(shù)之中進行了一些報文合法性的檢測,然后根據(jù)報文中的端口信息查找UDP控制塊,最后通過UDP控制塊之中的回調(diào)函數(shù)recv_udp將數(shù)據(jù)傳遞到應(yīng)用層,如果找不到對應(yīng)的端口,那么會返回一個端口不可達數(shù)據(jù)包。

cfc46bf8-5590-11ed-a3b6-dac502259ad0.png

UDP報文發(fā)送

UDP報文發(fā)送依靠IP層提供的服務(wù),用戶在發(fā)送數(shù)據(jù)時需要在應(yīng)用程序之中調(diào)用udp_send或者是udp_sendto,應(yīng)用程序之中將用戶數(shù)據(jù)填到pbuf數(shù)據(jù)區(qū)域,并將pubf作為參數(shù)傳入udp_send或udp_sendto之中。

cfe8112a-5590-11ed-a3b6-dac502259ad0.png

udp_send和udp_sendto之間的區(qū)別就是udp_sendto將數(shù)據(jù)發(fā)送到指定的ip地址和端口號,udp_send將數(shù)據(jù)發(fā)送到UDP控制塊之中定義的ip地址和端口號。udp_send實際上也是調(diào)用udp_sendto來進行數(shù)據(jù)的發(fā)送,最終這兩個函數(shù)都是會去調(diào)用udp_sendto_if。

cff9e260-5590-11ed-a3b6-dac502259ad0.png

udp_sendto_if函數(shù)之中會完成udp報文的組裝和發(fā)送,最終會調(diào)用Ip層的發(fā)送函數(shù)去發(fā)送報文。

LWIP應(yīng)用層

在應(yīng)用層一般會通過調(diào)用傳輸層的一些函數(shù)來編寫特定的應(yīng)用程序,從而實現(xiàn)數(shù)據(jù)的傳遞,在udpecho demo之中,當接收到數(shù)據(jù)之后,在udp控制塊中綁定的接收回調(diào)函數(shù)中又會去調(diào)用udp_sendto函數(shù)。

d0093ed6-5590-11ed-a3b6-dac502259ad0.png

除了上面介紹的一些協(xié)議外,LWIP還支持ICMP、IGMP、PPP、DHCP等協(xié)議,并且SOCKET API以及NETCONN API使用起來更加簡單,但是RAW/Callback API的使用有助于更好的理解LWIP協(xié)議。

對LWIP協(xié)議棧感興趣的讀者可自行深入了解。

審核編輯:彭靜
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • UDP
    UDP
    +關(guān)注

    關(guān)注

    0

    文章

    325

    瀏覽量

    33941
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4331

    瀏覽量

    62622
  • LwIP協(xié)議
    +關(guān)注

    關(guān)注

    0

    文章

    11

    瀏覽量

    8914

原文標題:在i.MX RT中使用LwIP協(xié)議棧淺析

文章出處:【微信號:NXP_SMART_HARDWARE,微信公眾號:恩智浦MCU加油站】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    STM32之LWIP網(wǎng)絡(luò)協(xié)議棧移植步驟與方案

    LwIP是Light Weight(輕型)IP 協(xié)議,有無操作系統(tǒng)的支持都可以運行。LwIP 實現(xiàn)的重點是在保持TCP協(xié)議 主要功能的基礎(chǔ)上減少對RAM的占用。
    的頭像 發(fā)表于 06-01 08:35 ?1.3w次閱讀
    STM32之<b class='flag-5'>LWIP</b>網(wǎng)絡(luò)<b class='flag-5'>協(xié)議</b>棧移植步驟與方案

    LwIP中TCP協(xié)議是如何實現(xiàn)的

    與其他協(xié)議一樣,為了描述`TCP`協(xié)議LwIP定義了一個名字叫`tcp_pcb`的結(jié)構(gòu)體,可以稱之為`TCP控制塊`,其內(nèi)定義了大量的成員變量,基本定義了整個TCP協(xié)議運作過程的所有
    的頭像 發(fā)表于 02-14 10:39 ?3056次閱讀

    lwip協(xié)議棧代碼分析

    lwIP(Lightweight IP)是一個為嵌入式系統(tǒng)設(shè)計的輕量級TCP/IP協(xié)議棧。
    的頭像 發(fā)表于 10-29 17:37 ?2002次閱讀
    <b class='flag-5'>lwip</b><b class='flag-5'>協(xié)議</b>棧代碼分析

    嵌入式TCPIP協(xié)議LWIP的內(nèi)部結(jié)構(gòu)

    分析了嵌入式 TCPIP協(xié)議棧主要對LWIP的基本結(jié)構(gòu),介紹了嵌入式TCPIP協(xié)議LWIP的內(nèi)存管理方式,同時給出了對UDP、TCP、IP等協(xié)議
    發(fā)表于 02-17 15:55 ?76次下載
    嵌入式TCPIP<b class='flag-5'>協(xié)議</b>棧<b class='flag-5'>LWIP</b>的內(nèi)部結(jié)構(gòu)

    Lwip協(xié)議棧的設(shè)計方案

    LWIP是TCP/IP協(xié)議棧的一種實現(xiàn)。LWIP的主要目的是減少存儲器利用量和代碼尺寸,使LWIP適合應(yīng)用于小的、資源有限的處理器如嵌入式系統(tǒng)。為了減少處理器和存儲器要求,
    發(fā)表于 09-16 15:18 ?33次下載
    <b class='flag-5'>Lwip</b><b class='flag-5'>協(xié)議</b>棧的設(shè)計方案

    基于ARM的LwIP協(xié)議棧研究與移植

    提出基于ARM的LwIP協(xié)議棧研究與移植
    發(fā)表于 10-14 17:50 ?65次下載
    基于ARM的<b class='flag-5'>LwIP</b><b class='flag-5'>協(xié)議</b>棧研究與移植

    lwip協(xié)議中文版

    LWIP是TCP/IP協(xié)議棧的一種實現(xiàn)。LWIP的主要目的是減少存儲器利用量和代碼尺寸,使LWIP適合應(yīng)用于小的、資源有限的處理器如嵌入式系統(tǒng)。為了減少處理器和存儲器要求,
    發(fā)表于 02-03 16:47 ?0次下載
    <b class='flag-5'>lwip</b><b class='flag-5'>協(xié)議</b>中文版

    LwIP編程指南

    LwIP編程指南,LwIP是Light Weight (輕型)IP協(xié)議,有無操作系統(tǒng)的支持都可以運行。LwIP實現(xiàn)的重點是在保持TCP協(xié)議
    發(fā)表于 11-09 18:28 ?47次下載

    LwIP協(xié)議詳解

    LwIP協(xié)議詳解,LwIP是Light Weight (輕型)IP協(xié)議,有無操作系統(tǒng)的支持都可以運行。LwIP實現(xiàn)的重點是在保持TCP
    發(fā)表于 11-09 18:25 ?49次下載

    TCPIP協(xié)議棧的實現(xiàn)lwip

    TCPIP協(xié)議棧的實現(xiàn)lwip方便初學者剛開始接觸lwip,有個大概的了解與認識。
    發(fā)表于 03-14 15:40 ?13次下載

    lwip協(xié)議棧源碼詳解說明

    lwip是瑞典計算機科學院(SICS)的Adam Dunkels 開發(fā)的一個小型開源的TCP/IP協(xié)議棧。實現(xiàn)的重點是在保持TCP協(xié)議主要功能的基礎(chǔ)上減少對RAM 的占用。
    發(fā)表于 12-11 15:27 ?3.7w次閱讀
    <b class='flag-5'>lwip</b><b class='flag-5'>協(xié)議</b>棧源碼詳解說明

    介紹tcp_ip協(xié)議lwip的特點

    簡介了嵌入式tcp_ip協(xié)議lwip的基本信息
    的頭像 發(fā)表于 07-03 13:05 ?3661次閱讀

    LWIP協(xié)議棧中Raw TCP中使用

    本文檔的主要內(nèi)容詳細介紹的是LWIP協(xié)議棧中Raw TCP中使用的資料免費下載
    發(fā)表于 11-05 17:36 ?17次下載
    <b class='flag-5'>LWIP</b><b class='flag-5'>協(xié)議</b>棧中Raw TCP中使用

    如何更好理解LWIP協(xié)議?

    網(wǎng)絡(luò)接口層主要通過雙絞線,光纖,無線等方式進行網(wǎng)絡(luò)上數(shù)據(jù)幀的發(fā)送和接收。網(wǎng)絡(luò)接口層將網(wǎng)絡(luò)層的數(shù)據(jù)組裝成自己特定的幀進行發(fā)送,同時也會接收數(shù)據(jù)幀進行解析,并將解析過后的數(shù)據(jù)發(fā)送給網(wǎng)絡(luò)層。
    發(fā)表于 05-04 10:22 ?6475次閱讀
    如何<b class='flag-5'>更好</b>的<b class='flag-5'>理解</b><b class='flag-5'>LWIP</b><b class='flag-5'>協(xié)議</b>?

    LwIP協(xié)議棧源碼詳解—TCP/IP協(xié)議的實現(xiàn)

    電子發(fā)燒友網(wǎng)站提供《LwIP協(xié)議棧源碼詳解—TCP/IP協(xié)議的實現(xiàn).pdf》資料免費下載
    發(fā)表于 07-03 11:22 ?3次下載