精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

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

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

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

深入了解IP數(shù)據(jù)報(bào)發(fā)送的過(guò)程

汽車(chē)電子技術(shù) ? 來(lái)源:物聯(lián)網(wǎng)IoT開(kāi)發(fā) ? 作者:杰杰mcu ? 2023-02-14 10:24 ? 次閱讀

IP協(xié)議的功能

回顧一下前面寫(xiě)的關(guān)于IP協(xié)議的文章:

IP協(xié)議基礎(chǔ)掃盲班

IP地址相關(guān)知識(shí)深入了解~

IP數(shù)據(jù)報(bào)分析

IP數(shù)據(jù)報(bào)結(jié)構(gòu)、IP分片的原理與處理

IP數(shù)據(jù)報(bào)的收發(fā)

回顧一下前面的文章所提及的知識(shí)點(diǎn),總結(jié)一下IP協(xié)議的功能,得到以下結(jié)論:

  1. 編址(目標(biāo)端的IP地址),數(shù)據(jù)傳輸?shù)倪^(guò)程當(dāng)中就必須表明要發(fā)送目標(biāo)端的IP地址
  2. 尋址和路由(根據(jù)對(duì)方的IP地址,尋找最佳路徑傳輸信息);
  3. 數(shù)據(jù)報(bào)的分片和重組。
  4. 傳遞服務(wù)是不可靠的(IP協(xié)議只是盡自己最大努力去傳輸數(shù)據(jù)包),它也是無(wú)連接的協(xié)議

IP數(shù)據(jù)報(bào)發(fā)送

IP協(xié)議是網(wǎng)絡(luò)層的主要協(xié)議,在上層傳輸協(xié)議(如TCP/UDP)需要發(fā)送數(shù)據(jù)時(shí),會(huì)將數(shù)據(jù)封裝起來(lái),然后傳遞到IP層,IP協(xié)議首先會(huì)根據(jù)上層協(xié)議的目標(biāo)IP地址選擇一個(gè)合適的網(wǎng)卡進(jìn)行發(fā)送數(shù)據(jù)( 路由),然后IP協(xié)議將再次封裝數(shù)據(jù)形成IP數(shù)據(jù)報(bào),主要的操作就是填寫(xiě)IP數(shù)據(jù)報(bào)首部對(duì)應(yīng)的各個(gè)字段:目標(biāo)IP地址、源IP地址、協(xié)議類(lèi)型、生存時(shí)間等,最后在IP層通過(guò)回調(diào)函數(shù)netif->output(即etharp_output()函數(shù))將IP數(shù)據(jù)報(bào)投遞給ARP,再調(diào)用網(wǎng)卡底層發(fā)送函數(shù)進(jìn)行發(fā)送,這樣子自上而下的數(shù)據(jù)就發(fā)送出去,IP協(xié)議以目標(biāo)IP地址作為目標(biāo)主機(jī)的身份地址。

  1. /**

  2. * ip_output_if的簡(jiǎn)化版接口。它找到發(fā)送數(shù)據(jù)包的netif網(wǎng)絡(luò)接口并調(diào)用ip_output_if來(lái)完成實(shí)際工作。

  3. *

  4. * @param p 要發(fā)送的數(shù)據(jù)包(p->payload(有效負(fù)載)指向數(shù)據(jù),如果dest == LWIP_IP_HDRINCL,則p已包含IP頭和p->有效負(fù)載指向該IP頭)

  5. * @param src 要發(fā)送的源IP地址(如果src == IP4_ADDR_ANY,則用發(fā)送的netif綁定的IP地址用作源地址)

  6. * @param dest 目的IP地址

  7. * @param ttl 要在IP標(biāo)頭中設(shè)置的TTL值(生存時(shí)間)

  8. * @param tos 用于在IP標(biāo)頭中設(shè)置的TOS值

  9. * @param proto 將在IP頭中設(shè)置對(duì)應(yīng)的上層協(xié)議

  10. * @return ERR_OK 如果數(shù)據(jù)包發(fā)送正常就返回ok,

  11. * 如果p沒(méi)有足夠的空間用于IP /LINK標(biāo)頭,則為ERR_BUF

  12. * 其他則返回netif->output返回的錯(cuò)誤

  13. * @return ERR_RTE如果沒(méi)有找到路線

  14. * 請(qǐng)參閱ip_output_if()以獲取更多返回值

  15. */

  16. err_t

  17. ip4_output(struct pbuf *p,constip4_addr_t*src,constip4_addr_t*dest,

  18. u8_t ttl,u8_t tos,u8_t proto)

  19. {

  20. struct netif *netif;


  21. LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p);


  22. //根據(jù)目標(biāo)IP地址找到對(duì)應(yīng)的網(wǎng)卡發(fā)送數(shù)據(jù)

  23. if((netif = ip4_route_src(src, dest))== NULL){

  24. LWIP_DEBUGF(IP_DEBUG,("ip4_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\\n",

  25. ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest)));

  26. IP_STATS_INC(ip.rterr);

  27. return ERR_RTE;

  28. }


  29. return ip4_output_if(p, src, dest, ttl, tos, proto, netif);

  30. }

路由過(guò)程的實(shí)現(xiàn)

路由(routing)就是通過(guò)互聯(lián)的網(wǎng)絡(luò)把信息從源地址傳輸?shù)侥康牡刂返幕顒?dòng),發(fā)送端必然需要找到一個(gè)網(wǎng)卡將數(shù)據(jù)報(bào)發(fā)送出去,而實(shí)現(xiàn)這個(gè)過(guò)程的函數(shù)就是 ip4_route_src()

其實(shí)lwip對(duì) ip4_route_src()函數(shù)進(jìn)行了重新定義,實(shí)際上是調(diào)用了 ip4_route()函數(shù)。這個(gè)函數(shù)的原理就是根據(jù)指定的IP地址找到合適的網(wǎng)卡 netif,然后返回,前面的文章也提到過(guò),lwip的網(wǎng)卡是通過(guò) netif_list列表管理的,那么找網(wǎng)卡的操作也必然是遍歷網(wǎng)卡列表 netif_list,判斷網(wǎng)卡是否已經(jīng)掛載并且IP地址是否有效,如果連網(wǎng)卡都找不到,那就不用發(fā)送數(shù)據(jù)了,返回null。

  1. #define ip4_route_src(src, dest) ip4_route(dest)

  1. /**

  2. *為給定的IP地址查找適當(dāng)?shù)木W(wǎng)絡(luò)接口。

  3. *它搜索網(wǎng)絡(luò)接口列表。找到匹配項(xiàng)

  4. *

  5. *@param dest 要查找路由的目標(biāo)IP地址

  6. *@return 發(fā)送到達(dá)目的地的網(wǎng)卡 netif

  7. */

  8. struct netif *

  9. ip4_route(constip4_addr_t*dest)

  10. {

  11. #if!LWIP_SINGLE_NETIF

  12. struct netif *netif;


  13. LWIP_ASSERT_CORE_LOCKED();


  14. #if LWIP_MULTICAST_TX_OPTIONS

  15. /*默認(rèn)使用管理選擇的接口進(jìn)行多播*/

  16. if(ip4_addr_ismulticast(dest)&& ip4_default_multicast_netif){

  17. return ip4_default_multicast_netif;

  18. }

  19. #endif /* LWIP_MULTICAST_TX_OPTIONS */


  20. /* bug #54569: in case LWIP_SINGLE_NETIF=1 and LWIP_DEBUGF() disabled, the following loop is optimized away */

  21. LWIP_UNUSED_ARG(dest);


  22. /*遍歷網(wǎng)卡列表netif_list */

  23. NETIF_FOREACH(netif){

  24. /* 如果網(wǎng)卡已經(jīng)掛載并且IP地址是有效的 */

  25. if(netif_is_up(netif)&& netif_is_link_up(netif)&&!ip4_addr_isany_val(*netif_ip4_addr(netif))){

  26. /* 網(wǎng)絡(luò)掩碼匹配? */

  27. if(ip4_addr_netcmp(dest, netif_ip4_addr(netif), netif_ip4_netmask(netif))){

  28. /* 返回找到的網(wǎng)卡netif */

  29. return netif;

  30. }

  31. /* 網(wǎng)關(guān)在非廣播接口上匹配?(即在點(diǎn)對(duì)點(diǎn)接口中對(duì)等) */

  32. if(((netif->flags & NETIF_FLAG_BROADCAST)==0)&& ip4_addr_cmp(dest, netif_ip4_gw(netif))){

  33. /* 返回找到的網(wǎng)卡netif */

  34. return netif;

  35. }

  36. }

  37. }


  38. #if LWIP_NETIF_LOOPBACK &&!LWIP_HAVE_LOOPIF /**如果打開(kāi)環(huán)回地址的宏定義 */

  39. /* loopif is disabled, looopback traffic is passed through any netif */

  40. if(ip4_addr_isloopback(dest)){

  41. /*不檢查環(huán)回流量的鏈接*/

  42. if(netif_default != NULL && netif_is_up(netif_default)){

  43. return netif_default;

  44. }

  45. /*默認(rèn)netif沒(méi)有啟動(dòng),只需使用任何netif進(jìn)行環(huán)回流量*/

  46. NETIF_FOREACH(netif){

  47. if(netif_is_up(netif)){

  48. return netif;

  49. }

  50. }

  51. return NULL;

  52. }

  53. #endif /* LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF */


  54. #ifdef LWIP_HOOK_IP4_ROUTE_SRC

  55. netif = LWIP_HOOK_IP4_ROUTE_SRC(NULL, dest);

  56. if(netif != NULL){

  57. return netif;

  58. }

  59. #elif defined(LWIP_HOOK_IP4_ROUTE)

  60. netif = LWIP_HOOK_IP4_ROUTE(dest);

  61. if(netif != NULL){

  62. return netif;

  63. }

  64. #endif

  65. #endif /* !LWIP_SINGLE_NETIF */


  66. if((netif_default == NULL)||!netif_is_up(netif_default)||!netif_is_link_up(netif_default)||

  67. ip4_addr_isany_val(*netif_ip4_addr(netif_default))|| ip4_addr_isloopback(dest)){

  68. /*找不到匹配的netif,默認(rèn)的netif不可用。建議使用LWIP_HOOK_IP4_ROUTE()*/

  69. LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,("ip4_route: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\\n",

  70. ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest)));

  71. IP_STATS_INC(ip.rterr);

  72. MIB2_STATS_INC(mib2.ipoutnoroutes);

  73. return NULL;

  74. }


  75. return netif_default;

  76. }

ip4_output_if函數(shù)

找到網(wǎng)卡之后就調(diào)用 ip4_output_if()函數(shù)將數(shù)據(jù)發(fā)送出去,這個(gè)函數(shù)會(huì)指定發(fā)送數(shù)據(jù)的網(wǎng)卡,同時(shí)會(huì)將來(lái)自上層協(xié)議(tcp、udp)的數(shù)據(jù)進(jìn)行封裝,組成IP數(shù)據(jù)報(bào)再發(fā)送,不過(guò)這個(gè)函數(shù)層層調(diào)用,比較麻煩,具體如下:。

  1. /**

  2. * 在網(wǎng)絡(luò)接口上發(fā)送IP數(shù)據(jù)包。這個(gè)函數(shù)構(gòu)造IP數(shù)據(jù)包首部并計(jì)算IP頭校驗(yàn)和,

  3. * 如果源IP地址為NULL,在發(fā)送的時(shí)候就填寫(xiě)發(fā)送網(wǎng)卡的IP地址為源IP地址

  4. * 如果目標(biāo)IP地址是LWIP_IP_HDRINCL,則假定pbuf已經(jīng)存在包括IP頭和有效負(fù)載指向它而不是數(shù)據(jù)。

  5. *

  6. * @param p 要發(fā)送的數(shù)據(jù)包(p->payload(有效負(fù)載)指向數(shù)據(jù),如果dest == LWIP_IP_HDRINCL,則p已包含IP頭和p->有效負(fù)載指向該IP頭)

  7. * @param src 要發(fā)送的源IP地址(如果src == IP4_ADDR_ANY,則用發(fā)送的netif綁定的IP地址用作源地址)

  8. * @param dest 目的IP地址

  9. * @param ttl 要在IP標(biāo)頭中設(shè)置的TTL值(生存時(shí)間)

  10. * @param tos 用于在IP標(biāo)頭中設(shè)置的TOS值

  11. * @param proto 將在IP頭中設(shè)置對(duì)應(yīng)的上層協(xié)議

  12. * @param netif 發(fā)送此數(shù)據(jù)包的netif

  13. * @return ERR_OK 如果數(shù)據(jù)包發(fā)送正常就返回ok,

  14. * 如果p沒(méi)有足夠的空間用于IP /LINK標(biāo)頭,則為ERR_BUF

  15. * 其他則返回netif->output返回的錯(cuò)誤

  16. *

  17. * @note ip_id:RFC791“某些主機(jī)可能只需使用

  18. * 獨(dú)立于目的地的唯一標(biāo)識(shí)符“

  19. */

  20. err_t

  21. ip4_output_if(struct pbuf *p,constip4_addr_t*src,constip4_addr_t*dest,

  22. u8_t ttl,u8_t tos,

  23. u8_t proto,struct netif *netif)

  24. {

  25. #if IP_OPTIONS_SEND

  26. return ip4_output_if_opt(p, src, dest, ttl, tos, proto, netif, NULL,0);

  27. }

  1. /**

  2. * 與ip_output_if()相同,但可以包含IP選項(xiàng):

  3. *

  4. * @param ip_options指向IP選項(xiàng)的指針,復(fù)制到IP頭中

  5. * @param optlen ip_options的長(zhǎng)度

  6. */

  7. err_t

  8. ip4_output_if_opt(struct pbuf *p,constip4_addr_t*src,constip4_addr_t*dest,

  9. u8_t ttl,u8_t tos,u8_t proto,struct netif *netif,void*ip_options,

  10. u16_t optlen)

  11. {

  12. #endif /* IP_OPTIONS_SEND */

  13. constip4_addr_t*src_used = src;

  14. if(dest != LWIP_IP_HDRINCL){

  15. if(ip4_addr_isany(src)){

  16. src_used = netif_ip4_addr(netif);

  17. }

  18. }


  19. #if IP_OPTIONS_SEND

  20. return ip4_output_if_opt_src(p, src_used, dest, ttl, tos, proto, netif,

  21. ip_options, optlen);

  22. #else/* IP_OPTIONS_SEND */

  23. return ip4_output_if_src(p, src_used, dest, ttl, tos, proto, netif);

  24. #endif /* IP_OPTIONS_SEND */

  25. }

ip4_output_if_opt_src

首先看看這個(gè)函數(shù)到底做了什么吧:在上層協(xié)議遞交數(shù)據(jù)包后,通過(guò)層層調(diào)用,最終到 ip4_output_if_opt_src()函數(shù)中處理,它的處理如下:圖片代碼的實(shí)現(xiàn)如下:注釋非常豐富。主要過(guò)程就是:

  1. 判斷是否填寫(xiě)好IP數(shù)據(jù)報(bào)首部?若目標(biāo)IP地址為L(zhǎng)WIPIPHDRINCL表示已經(jīng)填寫(xiě)好IP數(shù)據(jù)報(bào)首部,且payload指針也指向了IP數(shù)據(jù)報(bào)首部。
  2. 如果沒(méi)有填寫(xiě)IP數(shù)據(jù)報(bào)首部,調(diào)用 pbuf_add_header()函數(shù)調(diào)整數(shù)據(jù)區(qū)域指針以指向IP數(shù)據(jù)報(bào)首部。
  3. 填寫(xiě)IP數(shù)據(jù)報(bào)中的生存時(shí)間、服務(wù)類(lèi)型、上層協(xié)議、目標(biāo)IP地址、版本號(hào)與首部長(zhǎng)度、數(shù)據(jù)報(bào)總長(zhǎng)度、標(biāo)志位和分片偏移量、標(biāo)識(shí)、源IP地址等內(nèi)容,總之就是將IP數(shù)據(jù)報(bào)首部的內(nèi)容該填的都填上。
  4. 如果目標(biāo)IP地址是自己的網(wǎng)卡IP地址,調(diào)用環(huán)回輸入函數(shù) netif_loop_output()發(fā)送IP數(shù)據(jù)報(bào)給自己,這種處理一般是用于測(cè)試代碼。
  5. 如果IP數(shù)據(jù)報(bào)太大,數(shù)據(jù)報(bào)總長(zhǎng)度大于網(wǎng)卡的MTU,則需要進(jìn)行分片處理,調(diào)用 ip4_frag()函數(shù)進(jìn)行發(fā)送。
  6. 直接調(diào)用注冊(cè)的 netif->output接口傳遞給ARP,實(shí)際上就是調(diào)用 etharp_output()函數(shù),在這里它會(huì)將IP地址解析成對(duì)應(yīng)的 MAC地址,并且調(diào)用網(wǎng)卡發(fā)送函數(shù)進(jìn)行發(fā)送。
  1. /**

  2. * 與ip4_output_if_opt()相同,當(dāng)源地址是'IP4_ADDR_ANY'時(shí),'src'地址不會(huì)被netif地址替換

  3. */

  4. err_t

  5. ip4_output_if_opt_src(struct pbuf *p,constip4_addr_t*src,constip4_addr_t*dest,

  6. u8_t ttl,u8_t tos,u8_t proto,struct netif *netif,void*ip_options,

  7. u16_t optlen)

  8. {

  9. #endif /* IP_OPTIONS_SEND */

  10. struct ip_hdr *iphdr;

  11. ip4_addr_t dest_addr;

  12. #if CHECKSUM_GEN_IP_INLINE

  13. u32_t chk_sum =0;

  14. #endif /* CHECKSUM_GEN_IP_INLINE */


  15. LWIP_ASSERT_CORE_LOCKED();

  16. LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p);


  17. MIB2_STATS_INC(mib2.ipoutrequests);


  18. /* 應(yīng)該要構(gòu)建IP首部還是已經(jīng)包含在pbuf中了?如果是要構(gòu)建IP數(shù)據(jù)報(bào)首部 */

  19. if(dest != LWIP_IP_HDRINCL){

  20. u16_t ip_hlen = IP_HLEN;

  21. #if IP_OPTIONS_SEND

  22. u16_t optlen_aligned =0;

  23. if(optlen !=0){

  24. #if CHECKSUM_GEN_IP_INLINE

  25. int i;

  26. #endif /* CHECKSUM_GEN_IP_INLINE */

  27. if(optlen >(IP_HLEN_MAX - IP_HLEN)){

  28. /* 選項(xiàng)字段太長(zhǎng) */

  29. LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,("ip4_output_if_opt: optlen too long\\n"));

  30. IP_STATS_INC(ip.err);

  31. MIB2_STATS_INC(mib2.ipoutdiscards);

  32. return ERR_VAL;

  33. }

  34. /* 選項(xiàng)字段按照4字節(jié)對(duì)齊 */

  35. optlen_aligned =(u16_t)((optlen +3)&~3);

  36. ip_hlen =(u16_t)(ip_hlen + optlen_aligned);

  37. /* 首先寫(xiě)入IP選項(xiàng)字段 */

  38. if(pbuf_add_header(p, optlen_aligned)){

  39. LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,("ip4_output_if_opt: not enough room for IP options in pbuf\\n"));

  40. IP_STATS_INC(ip.err);

  41. MIB2_STATS_INC(mib2.ipoutdiscards);

  42. return ERR_BUF;

  43. }

  44. MEMCPY(p->payload, ip_options, optlen);

  45. if(optlen < optlen_aligned){

  46. /* 剩余字節(jié)清零 */

  47. memset(((char*)p->payload)+ optlen,0,(size_t)(optlen_aligned - optlen));

  48. }

  49. #if CHECKSUM_GEN_IP_INLINE

  50. for(i =0; i < optlen_aligned /2; i++){

  51. chk_sum +=((u16_t*)p->payload)[i];

  52. }

  53. #endif /* CHECKSUM_GEN_IP_INLINE */

  54. }

  55. #endif /* IP_OPTIONS_SEND */

  56. /* 生成IP頭 */

  57. if(pbuf_add_header(p, IP_HLEN)){

  58. LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,("ip4_output: not enough room for IP header in pbuf\\n"));


  59. IP_STATS_INC(ip.err);

  60. MIB2_STATS_INC(mib2.ipoutdiscards);

  61. return ERR_BUF;

  62. }


  63. iphdr =(struct ip_hdr *)p->payload;

  64. LWIP_ASSERT("check that first pbuf can hold struct ip_hdr",

  65. (p->len >=sizeof(struct ip_hdr)));


  66. IPH_TTL_SET(iphdr, ttl);

  67. IPH_PROTO_SET(iphdr, proto);

  68. #if CHECKSUM_GEN_IP_INLINE

  69. chk_sum += PP_NTOHS(proto |(ttl <<8));

  70. #endif /* CHECKSUM_GEN_IP_INLINE */


  71. /* 構(gòu)建目的IP地址,此處的目的IP地址不能為NULL */

  72. ip4_addr_copy(iphdr->dest,*dest);

  73. #if CHECKSUM_GEN_IP_INLINE

  74. chk_sum += ip4_addr_get_u32(&iphdr->dest)&0xFFFF;

  75. chk_sum += ip4_addr_get_u32(&iphdr->dest)>>16;

  76. #endif /* CHECKSUM_GEN_IP_INLINE */


  77. IPH_VHL_SET(iphdr,4, ip_hlen /4);

  78. IPH_TOS_SET(iphdr, tos);

  79. #if CHECKSUM_GEN_IP_INLINE

  80. chk_sum += PP_NTOHS(tos |(iphdr->_v_hl <<8));

  81. #endif /* CHECKSUM_GEN_IP_INLINE */

  82. IPH_LEN_SET(iphdr, lwip_htons(p->tot_len));

  83. #if CHECKSUM_GEN_IP_INLINE

  84. chk_sum += iphdr->_len;

  85. #endif /* CHECKSUM_GEN_IP_INLINE */

  86. IPH_OFFSET_SET(iphdr,0);

  87. IPH_ID_SET(iphdr, lwip_htons(ip_id));

  88. #if CHECKSUM_GEN_IP_INLINE

  89. chk_sum += iphdr->_id;

  90. #endif /* CHECKSUM_GEN_IP_INLINE */

  91. ++ip_id;


  92. if(src == NULL){

  93. ip4_addr_copy(iphdr->src,*IP4_ADDR_ANY4);/** 構(gòu)建源IP地址 */

  94. }else{

  95. /* 此處的源IP地址不能為NULL */

  96. ip4_addr_copy(iphdr->src,*src);

  97. }


  98. #if CHECKSUM_GEN_IP_INLINE

  99. chk_sum += ip4_addr_get_u32(&iphdr->src)&0xFFFF;

  100. chk_sum += ip4_addr_get_u32(&iphdr->src)>>16;

  101. chk_sum =(chk_sum >>16)+(chk_sum &0xFFFF);

  102. chk_sum =(chk_sum >>16)+ chk_sum;

  103. chk_sum =~chk_sum;

  104. IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_IP){

  105. iphdr->_chksum =(u16_t)chk_sum;/* network order */

  106. }

  107. #if LWIP_CHECKSUM_CTRL_PER_NETIF

  108. else{

  109. IPH_CHKSUM_SET(iphdr,0);

  110. }

  111. #endif /* LWIP_CHECKSUM_CTRL_PER_NETIF*/

  112. #else/* CHECKSUM_GEN_IP_INLINE */

  113. IPH_CHKSUM_SET(iphdr,0);

  114. #if CHECKSUM_GEN_IP

  115. IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_IP){

  116. IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, ip_hlen));

  117. }

  118. #endif /* CHECKSUM_GEN_IP */

  119. #endif /* CHECKSUM_GEN_IP_INLINE */

  120. }else{

  121. /* IP頭已包含在pbuf中 */

  122. if(p->len < IP_HLEN){

  123. /** pbuf的長(zhǎng)度小于IP數(shù)據(jù)報(bào)首部長(zhǎng)度(20字節(jié)) */

  124. LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,("ip4_output: LWIP_IP_HDRINCL but pbuf is too short\\n"));

  125. IP_STATS_INC(ip.err);

  126. MIB2_STATS_INC(mib2.ipoutdiscards);

  127. return ERR_BUF;

  128. }

  129. iphdr =(struct ip_hdr *)p->payload;/** 直接從數(shù)據(jù)區(qū)域獲取IP數(shù)據(jù)報(bào)首部 */

  130. ip4_addr_copy(dest_addr, iphdr->dest);/** 獲取目的IP地址 */

  131. dest =&dest_addr;

  132. }


  133. IP_STATS_INC(ip.xmit);


  134. LWIP_DEBUGF(IP_DEBUG,("ip4_output_if: %c%c%"U16_F"\\n", netif->name[0], netif->name[1],(u16_t)netif->num));

  135. ip4_debug_print(p);


  136. #if ENABLE_LOOPBACK /** 換回接口 */

  137. if(ip4_addr_cmp(dest, netif_ip4_addr(netif))

  138. #if!LWIP_HAVE_LOOPIF

  139. || ip4_addr_isloopback(dest)

  140. #endif /* !LWIP_HAVE_LOOPIF */

  141. ){

  142. /* 數(shù)據(jù)包是給自己的,將其放入環(huán)回接口 */

  143. LWIP_DEBUGF(IP_DEBUG,("netif_loop_output()"));

  144. return netif_loop_output(netif, p);

  145. }

  146. #if LWIP_MULTICAST_TX_OPTIONS

  147. if((p->flags & PBUF_FLAG_MCASTLOOP)!=0){

  148. netif_loop_output(netif, p);

  149. }

  150. #endif /* LWIP_MULTICAST_TX_OPTIONS */

  151. #endif /* ENABLE_LOOPBACK */

  152. #if IP_FRAG

  153. /** 要發(fā)送的數(shù)據(jù)報(bào)大于mtu,需要分片,此處的前提是使能了IP_FRAG (IP分片) */

  154. if(netif->mtu &&(p->tot_len > netif->mtu)){

  155. return ip4_frag(p, netif, dest);/** 調(diào)用IP數(shù)據(jù)報(bào)分片函數(shù)將數(shù)據(jù)報(bào)分片發(fā)送出去 */

  156. }

  157. #endif /* IP_FRAG */


  158. LWIP_DEBUGF(IP_DEBUG,("ip4_output_if: call netif->output()\\n"));

  159. return netif->output(netif, p, dest);/** 如果不需要分片就直接通過(guò)網(wǎng)卡發(fā)送出去,netif->output() */

  160. }

最后提個(gè)醒

此外:上層協(xié)議是不會(huì)直接調(diào)用 ip4_output()函數(shù)的,lwip是通過(guò)宏定義將 ip4_output()函數(shù)進(jìn)行重新定義:

  1. #define ip_output(p, src, dest, ttl, tos, proto) ip4_output(p, src, dest, ttl, tos, proto

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • IP協(xié)議
    +關(guān)注

    關(guān)注

    3

    文章

    85

    瀏覽量

    21636
  • 傳輸協(xié)議
    +關(guān)注

    關(guān)注

    0

    文章

    78

    瀏覽量

    11439
  • 網(wǎng)絡(luò)層
    +關(guān)注

    關(guān)注

    0

    文章

    40

    瀏覽量

    10290
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    深入了解示波器

    深入了解示波器
    發(fā)表于 11-14 22:32

    專(zhuān)家開(kāi)講:深入了解電池技術(shù)──Part 3

    資深工程師 Ivan Cowie 的「深入了解電池技術(shù)」專(zhuān)欄Part 3來(lái)啰!這次要介紹的是鉛酸電池(lead-acidbatteries)技術(shù)。鉛酸電池是在1859年由法國(guó)物理學(xué)家Gaston
    發(fā)表于 08-18 09:37

    單片機(jī)的深入了解

    項(xiàng)目名稱(chēng):?jiǎn)纹瑱C(jī)的深入了解!項(xiàng)目是否開(kāi)源:否申請(qǐng)開(kāi)發(fā)板數(shù)量:1 塊申請(qǐng)人團(tuán)隊(duì)介紹:我們團(tuán)隊(duì)由五個(gè)人組成,我們打算開(kāi)始著手單片機(jī)的程序改編,設(shè)計(jì)一些比較特殊新穎的東西!希望給以支持!
    發(fā)表于 10-12 20:00

    深入了解LabVIEW FPGA資料分享

    深入了解LabVIEW FPGA
    發(fā)表于 05-27 08:35

    深入了解獨(dú)立式數(shù)據(jù)采集系統(tǒng)CompactDAQ

    深入了解獨(dú)立式數(shù)據(jù)采集系統(tǒng)CompactDAQ
    發(fā)表于 05-11 07:10

    請(qǐng)問(wèn)網(wǎng)絡(luò)中IP數(shù)據(jù)報(bào)傳輸?shù)?b class='flag-5'>過(guò)程是怎樣的?

    請(qǐng)問(wèn)網(wǎng)絡(luò)中IP數(shù)據(jù)報(bào)傳輸?shù)?b class='flag-5'>過(guò)程是怎樣的?
    發(fā)表于 10-27 07:03

    如何使用Winpcap接收和發(fā)送IP數(shù)據(jù)報(bào)文?

    如何使用Winpcap接收和發(fā)送IP數(shù)據(jù)報(bào)文?如何解決在Windows上配置雙協(xié)議棧的一些問(wèn)題?
    發(fā)表于 12-24 06:15

    介紹IP數(shù)據(jù)報(bào)的格式及IP相關(guān)功能在Lwip中的實(shí)現(xiàn)方式

    1、IP報(bào)文基礎(chǔ)及其在Lwip的實(shí)現(xiàn)IP協(xié)議是TCP/IP協(xié)議中最為核心的協(xié)議,所有的TCP、UDP、ICMP及IGMP數(shù)據(jù)都已IP
    發(fā)表于 08-23 17:38

    示波器的深入了解

    示波器的深入了解 引言自然界運(yùn)行著各種形式的正弦波,比如海浪、地震、聲波、爆破、空氣中傳播的聲音,或者身體運(yùn)轉(zhuǎn)的自然節(jié)律。物理世界里,能
    發(fā)表于 11-04 11:53 ?52次下載
    示波器的<b class='flag-5'>深入了解</b>

    深入了解示波器入門(mén)手冊(cè)

    深入了解示波器入門(mén)手冊(cè)
    發(fā)表于 03-27 17:43 ?241次下載
    <b class='flag-5'>深入了解</b>示波器入門(mén)手冊(cè)

    深入了解電路噪聲的那些事

    模擬電子的相關(guān)知識(shí)學(xué)習(xí)教材資料——深入了解電路噪聲的那些事
    發(fā)表于 09-27 15:19 ?0次下載

    深入了解電感與磁珠的異同

    模擬電子的相關(guān)知識(shí)學(xué)習(xí)教材資料——深入了解電感與磁珠的異同
    發(fā)表于 09-27 15:19 ?0次下載

    帶你深入了解示波器

    帶你深入了解示波器
    發(fā)表于 02-07 14:26 ?19次下載

    深入了解安全光柵

    深入了解安全光柵
    的頭像 發(fā)表于 06-25 13:53 ?1169次閱讀
    <b class='flag-5'>深入了解</b>安全光柵

    深入了解 GaN 技術(shù)

    深入了解 GaN 技術(shù)
    的頭像 發(fā)表于 12-06 17:28 ?6090次閱讀
    <b class='flag-5'>深入了解</b> GaN 技術(shù)