1 /**************************************************************************/ 2 /* */ 3 /* Copyright (c) Microsoft Corporation. All rights reserved. */ 4 /* */ 5 /* This software is licensed under the Microsoft Software License */ 6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */ 7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ 8 /* and in the root directory of this software. */ 9 /* */ 10 /**************************************************************************/ 11 12 13 /**************************************************************************/ 14 /**************************************************************************/ 15 /** */ 16 /** NetX Component */ 17 /** */ 18 /** Address Resolution Protocol (ARP) */ 19 /** */ 20 /**************************************************************************/ 21 /**************************************************************************/ 22 23 #define NX_SOURCE_CODE 24 25 26 /* Include necessary system files. */ 27 28 #include "nx_api.h" 29 #include "nx_arp.h" 30 #include "nx_packet.h" 31 32 #ifndef NX_DISABLE_IPV4 33 /**************************************************************************/ 34 /* */ 35 /* FUNCTION RELEASE */ 36 /* */ 37 /* _nx_arp_periodic_update PORTABLE C */ 38 /* 6.1 */ 39 /* AUTHOR */ 40 /* */ 41 /* Yuxin Zhou, Microsoft Corporation */ 42 /* */ 43 /* DESCRIPTION */ 44 /* */ 45 /* This function processes ARP periodic update requests by walking */ 46 /* through the dynamic ARP list to see if another ARP request needs to */ 47 /* be sent. */ 48 /* */ 49 /* INPUT */ 50 /* */ 51 /* ip_ptr Pointer to IP instance */ 52 /* */ 53 /* OUTPUT */ 54 /* */ 55 /* None */ 56 /* */ 57 /* CALLS */ 58 /* */ 59 /* _nx_arp_packet_send Send periodic ARP request out */ 60 /* _nx_packet_transmit_release Release queued packet */ 61 /* */ 62 /* CALLED BY */ 63 /* */ 64 /* _nx_ip_thread_entry IP helper thread */ 65 /* */ 66 /* RELEASE HISTORY */ 67 /* */ 68 /* DATE NAME DESCRIPTION */ 69 /* */ 70 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ 71 /* 09-30-2020 Yuxin Zhou Modified comment(s), */ 72 /* resulting in version 6.1 */ 73 /* */ 74 /**************************************************************************/ _nx_arp_periodic_update(NX_IP * ip_ptr)75VOID _nx_arp_periodic_update(NX_IP *ip_ptr) 76 { 77 78 TX_INTERRUPT_SAVE_AREA 79 80 ULONG i; 81 NX_ARP *arp_entry; 82 NX_PACKET *packet_ptr; 83 NX_PACKET *next_packet_ptr; 84 85 86 /* Pickup pointer to ARP dynamic list. */ 87 arp_entry = ip_ptr -> nx_ip_arp_dynamic_list; 88 89 /* Loop through the active ARP entries to see if they need updating. */ 90 for (i = 0; i < ip_ptr -> nx_ip_arp_dynamic_active_count; i++) 91 { 92 93 /* Check this ARP entry to see if it need updating. */ 94 if (arp_entry -> nx_arp_entry_next_update) 95 { 96 97 /* Decrement the next update field. */ 98 arp_entry -> nx_arp_entry_next_update--; 99 100 /* Determine if an ARP expiration is present. */ 101 if (!arp_entry -> nx_arp_entry_next_update) 102 { 103 104 /* Yes, an ARP expiration is present. */ 105 106 /* Determine if the retry counter has been exceeded. */ 107 if (arp_entry -> nx_arp_retries == NX_ARP_MAXIMUM_RETRIES) 108 { 109 110 /* The number of retries has been exceeded. The entry is removed 111 from the active list and any queued packet is released. */ 112 113 /* Disable interrupts. */ 114 TX_DISABLE 115 116 /* This ARP entry has expired, remove it from the active ARP list. Check to make 117 sure it is still active. */ 118 if (arp_entry -> nx_arp_active_list_head) 119 { 120 121 /* Determine if this is the only ARP entry on the list. */ 122 if (arp_entry == arp_entry -> nx_arp_active_next) 123 { 124 125 /* Remove the entry from the list. */ 126 *(arp_entry -> nx_arp_active_list_head) = NX_NULL; 127 } 128 else 129 { 130 131 /* Remove the entry from a list of more than one entry. */ 132 133 /* Update the list head pointer. */ 134 if (*(arp_entry -> nx_arp_active_list_head) == arp_entry) 135 { 136 *(arp_entry -> nx_arp_active_list_head) = arp_entry -> nx_arp_active_next; 137 } 138 139 /* Update the links of the adjacent ARP entries. */ 140 (arp_entry -> nx_arp_active_next) -> nx_arp_active_previous = 141 arp_entry -> nx_arp_active_previous; 142 (arp_entry -> nx_arp_active_previous) -> nx_arp_active_next = 143 arp_entry -> nx_arp_active_next; 144 } 145 146 /* Decrease the number of active ARP entries. */ 147 ip_ptr -> nx_ip_arp_dynamic_active_count--; 148 149 /* Clear the active head pointer. */ 150 arp_entry -> nx_arp_active_list_head = NX_NULL; 151 } 152 153 /* Determine if this is the only ARP entry on the dynamic list. */ 154 if (arp_entry != arp_entry -> nx_arp_pool_next) 155 { 156 157 /* No. Place the ARP entry at the end of the dynamic ARP pool, which is where new 158 ARP requests are allocated from. */ 159 160 /* Remove the entry from a list of more than one entry. */ 161 /* Update the links of the adjacent ARP dynamic pool entries. */ 162 (arp_entry -> nx_arp_pool_next) -> nx_arp_pool_previous = 163 arp_entry -> nx_arp_pool_previous; 164 (arp_entry -> nx_arp_pool_previous) -> nx_arp_pool_next = 165 arp_entry -> nx_arp_pool_next; 166 167 /* Update the list head pointer. */ 168 if (ip_ptr -> nx_ip_arp_dynamic_list == arp_entry) 169 { 170 ip_ptr -> nx_ip_arp_dynamic_list = arp_entry -> nx_arp_pool_next; 171 } 172 173 174 /* Add ARP entry to the end of the list. */ 175 arp_entry -> nx_arp_pool_next = 176 ip_ptr -> nx_ip_arp_dynamic_list; 177 arp_entry -> nx_arp_pool_previous = 178 (ip_ptr -> nx_ip_arp_dynamic_list) -> nx_arp_pool_previous; 179 ((ip_ptr -> nx_ip_arp_dynamic_list) -> nx_arp_pool_previous) -> nx_arp_pool_next = 180 arp_entry; 181 (ip_ptr -> nx_ip_arp_dynamic_list) -> nx_arp_pool_previous = arp_entry; 182 } 183 184 /* Pickup the queued packets head pointer. */ 185 next_packet_ptr = arp_entry -> nx_arp_packets_waiting; 186 187 /* Clear the queued packets head pointer. */ 188 arp_entry -> nx_arp_packets_waiting = NX_NULL; 189 190 /* Restore interrupts. */ 191 TX_RESTORE 192 193 /* Loop to remove all queued packets. */ 194 while (next_packet_ptr) 195 { 196 197 /* Pickup the packet pointer at the head of the queue. */ 198 packet_ptr = next_packet_ptr; 199 200 /* Move to the next packet in the queue. */ 201 next_packet_ptr = next_packet_ptr -> nx_packet_queue_next; 202 203 /* Clear the next packet queue pointer. */ 204 packet_ptr -> nx_packet_queue_next = NX_NULL; 205 206 #ifndef NX_DISABLE_IP_INFO 207 208 /* Increment the IP send packets dropped count. */ 209 ip_ptr -> nx_ip_send_packets_dropped++; 210 #endif 211 212 /* Release the packet that was queued for the expired ARP entry. */ 213 _nx_packet_transmit_release(packet_ptr); 214 } 215 } 216 else 217 { 218 219 /* We haven't yet had a response to this ARP request so send it again! */ 220 221 /* Increment the ARP retry counter. */ 222 arp_entry -> nx_arp_retries++; 223 224 /* Setup the ARP update rate to the maximum value again. */ 225 arp_entry -> nx_arp_entry_next_update = NX_ARP_UPDATE_RATE; 226 227 /* Send the ARP request out. */ 228 _nx_arp_packet_send(ip_ptr, arp_entry -> nx_arp_ip_address, arp_entry -> nx_arp_ip_interface); 229 } 230 } 231 } 232 233 /* Move to the next ARP entry. */ 234 arp_entry = arp_entry -> nx_arp_pool_next; 235 } 236 237 238 /* Reduce the defend timeout of interfaces. */ 239 for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i++) 240 { 241 if (ip_ptr -> nx_ip_interface[i].nx_interface_valid == NX_FALSE) 242 { 243 continue; 244 } 245 246 if (ip_ptr -> nx_ip_interface[i].nx_interface_arp_defend_timeout == 0) 247 { 248 continue; 249 } 250 251 ip_ptr -> nx_ip_interface[i].nx_interface_arp_defend_timeout--; 252 } 253 } 254 #endif /* !NX_DISABLE_IPV4 */ 255 256