<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                如果在ARP緩存表中沒有找到目標IP地址對應的表項,那么ARP協議就會創建一個表項,這也是ARP協議的核心處理,對于剛創建的表項,它在初始化網卡信息后會被設置為ETHARP\_STATE\_PENDING狀態,與此同時一個ARP請求包將被廣播出去,這個時候的表項是無法發送數據的,只有等待到目標主機回應了一個ARP應答包才能發送數據,那么這些數據在這段時間中將被掛到表項的等待隊列上,在ARP表項處于ETHARP\_STATE\_STABLE狀態完成數據的發送,函數源碼具體見代碼清單 10?13。 ``` 1 err_t 2 etharp_query(struct netif *netif, 3 const ip4_addr_t *ipaddr, 4 struct pbuf *q) 5 { 6 struct eth_addr *srcaddr = (struct eth_addr *)netif->hwaddr; 7 err_t result = ERR_MEM; 8 int is_new_entry = 0; 9 s16_t i_err; 10 netif_addr_idx_t i; 11 12 /* 檢是否為單播地址 */ 13 if (ip4_addr_isbroadcast(ipaddr, netif) || 14 ip4_addr_ismulticast(ipaddr) || 15 ip4_addr_isany(ipaddr)) 16 { 17 return ERR_ARG; 18 } 19 20 /* 在ARP緩存中查找表項,如果沒有則嘗試創建表項 */ 21 i_err = etharp_find_entry(ipaddr, ETHARP_FLAG_TRY_HARD, netif);(1) 22 23 /* 沒有發現表項或者沒有創建表項成功 */ 24 if (i_err < 0) 25 { 26 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 27 ("etharp_query: could not create ARP entry\n")); 28 if (q) 29 { 30 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 31 ("etharp_query: packet dropped\n")); 32 ETHARP_STATS_INC(etharp.memerr); 33 } 34 return (err_t)i_err; //返回錯誤代碼 35 } 36 LWIP_ASSERT("type overflow", (size_t)i_err < NETIF_ADDR_IDX_MAX); 37 38 //找到對應的表項或者創建表項成功 39 i = (netif_addr_idx_t)i_err; 40 41 /* 將新表項標記為待處理 */ 42 if (arp_table[i].state == ETHARP_STATE_EMPTY) 43 { 44 is_new_entry = 1; 45 arp_table[i].state = ETHARP_STATE_PENDING; 46 /* 記錄網絡接口 */ 47 arp_table[i].netif = netif; (2) 48 } 49 50 /* 是否有新的表項 */ 51 if (is_new_entry || (q == NULL)) (3) 52 { 53 /* 發送ARP請求包*/ 54 result = etharp_request(netif, ipaddr); 55 if (result != ERR_OK) 56 { 57 /* 無法發送ARP請求 */ 58 } 59 if (q == NULL) 60 { 61 return result; (4) 62 } 63 } 64 65 LWIP_ASSERT("q != NULL", q != NULL); 66 /* 表項狀態是否穩定 */ 67 if (arp_table[i].state >= ETHARP_STATE_STABLE) 68 { 69 ETHARP_SET_ADDRHINT(netif, i); 70 /* 發送數據包 */ 71 result = ethernet_output(netif, q, 72 srcaddr, 73 &(arp_table[i].ethaddr), 74 ETHTYPE_IP); (5) 75 } 76 /* 如果表項是ETHARP_STATE_PENDING狀態 */ 77 else if (arp_table[i].state == ETHARP_STATE_PENDING) 78 { 79 /* 將給數據包'q'排隊 */ 80 struct pbuf *p; 81 int copy_needed = 0; 82 /* 如果q包含必須拷貝的pbuf,請將整個鏈復制到一個新的PBUF_RAM */ 83 p = q; 84 while (p) 85 { 86 LWIP_ASSERT("no packet queues allowed!", 87 (p->len != p->tot_len) || (p->next == 0)); 88 if (PBUF_NEEDS_COPY(p)) (6) 89 { 90 //需要拷貝 91 copy_needed = 1; 92 break; 93 } 94 p = p->next; 95 } 96 if (copy_needed) 97 { 98 /* 將整個數據包復制到新的pbuf中 */ 99 p = pbuf_clone(PBUF_LINK, PBUF_RAM, q); (7) 100 } 101 else 102 { 103 /* 引用舊的pbuf就足夠了 */ 104 p = q; 105 pbuf_ref(p); 106 } 107 108 if (p != NULL) 109 { 110 /* 如果使用隊列 */ 111 #if ARP_QUEUEING 112 struct etharp_q_entry *new_entry; 113 /* 分配一個新的arp隊列表項 */ (8) 114 new_entry = (struct etharp_q_entry *)memp_malloc(MEMP_ARP_QUEUE); 115 if (new_entry != NULL) 116 { 117 unsigned int qlen = 0; 118 new_entry->next = 0; 119 new_entry->p = p; 120 if (arp_table[i].q != NULL) 121 { 122 /* 隊列已經存在,將新數據包插入隊列后面 */ 123 struct etharp_q_entry *r; 124 r = arp_table[i].q; 125 qlen++; 126 while (r->next != NULL) 127 { 128 r = r->next; 129 qlen++; 130 } 131 r->next = new_entry; (9) 132 } 133 else 134 { 135 /* 隊列不存在,數據包就是隊列的第一個節點 */ 136 arp_table[i].q = new_entry; (10) 137 } 138 #if ARP_QUEUE_LEN 139 if (qlen >= ARP_QUEUE_LEN) 140 { 141 struct etharp_q_entry *old; 142 old = arp_table[i].q; 143 arp_table[i].q = arp_table[i].q->next; 144 pbuf_free(old->p); 145 memp_free(MEMP_ARP_QUEUE, old); 146 } 147 #endif 148 result = ERR_OK; 149 } 150 else 151 { 152 /* 申請內存失敗 */ 153 pbuf_free(p); 154 result = ERR_MEM; 155 } 156 #else 157 /* 如果只是掛載單個數據包,那么始終只為每個ARP請求排隊一個數據包, 158 就需要釋放先前排隊的數據包 */ 159 if (arp_table[i].q != NULL) 160 { 161 pbuf_free(arp_table[i].q); (11) 162 } 163 arp_table[i].q = p; 164 result = ERR_OK; 165 166 #endif 167 } 168 else 169 { 170 ETHARP_STATS_INC(etharp.memerr); 171 result = ERR_MEM; 172 } 173 } 174 return result; 175 } ``` (1)(2):函數的處理邏輯是很清晰的,首先調用etharp_find_entry()函數在ARP緩存表中查找表項,如果沒有找到就嘗試創建表項并且返回表項的索引,當然ARP緩存表中可能存在表項,可能為新創建的表項(ETHARP_STATE_EMPTY),也可能為ETHARP_STATE_PENDING或者ETHARP_STATE_STABLE狀態。如果是新創建的表項,那么表項肯定沒有其他信息,LwIP就會初始化一些信息,如網卡,然后就將表項設置為ETHARP_STATE_PENDING狀態。 (3):如果表項是剛創建的或者數據包是空的,那么就會調用etharp_request()函數發送一個ARP請求包。 (4):如果數據包是空的,直接返回結果 (5):如果表項的狀態大于等于 ETHARP_STATE_STABLE,表示表項已經是穩定狀態了,就調用ethernet_output()函數發送數據包。 (6):通過宏定義PBUF_NEEDS_COPY(p)對數據包的類型進行判斷,如果需要拷貝則將變量copy_needed設置為1,表示需要拷貝。 (7):將整個數據包復制到新的pbuf中。 (8):如果ARP_QUEUEING宏定義為1,則表示使用隊列,那么LwIP會分配一個新的ARP數據包隊列節點,然后插入隊列中。 (9):如果隊列已經存在,將新數據包插入隊列后面。 (10):如果隊列不存在,數據包就是隊列的第一個節點。 (11):如果只是掛載單個數據包,就需要釋放先前排隊的數據包,然后再掛載新的數據包。 掛載的這些數據在等待到目標主機產生ARP應答的時候會發送出去,此時的發送就是延時了,所以在沒有ARP表項的時候,發送數據會產生延時,在指定等待ARP應答時間內如果等不到目標主機的應答,那么這個表項將被系統回收,同時數據也無法發送出去。 上層數據包通過ARP協議進行發送數據的流程示意圖具體見圖 10 10。 ![](https://box.kancloud.cn/7be7cb313de98579977fa8d30e419390_862x768.png) 整個ARP協議運作示意圖具體見圖 10?11。 ![](https://box.kancloud.cn/d0498f6171fe0c5e644cc791a2174e26_1162x752.png)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看