Rewrite from scratch a TCP/IP stack for mbed. So far the following parts are usable: Drivers: - EMAC driver (from CMSIS 2.0) Protocols: - Ethernet protocol - ARP over ethernet for IPv4 - IPv4 over Ethernet - ICMPv4 over IPv4 - UDPv4 over IPv4 APIs: - Sockets for UDPv4 The structure of this stack is designed to be very modular. Each protocol can register one or more protocol to handle its payload, and in each protocol, an API can be hooked (like Sockets for example). This is an early release.
ARP.cpp
00001 /* 00002 * $Id: ARP.c 29 2011-06-11 14:53:08Z benoit $ 00003 * $Author: benoit $ 00004 * $Date: 2011-06-11 16:53:08 +0200 (sam., 11 juin 2011) $ 00005 * $Rev: 29 $ 00006 * 00007 * 00008 * 00009 * 00010 * 00011 */ 00012 00013 #include "ARP.h" 00014 #include "Ethernet.h" 00015 #include "Debug.h" 00016 #include "IPv4.h" 00017 #include <string.h> 00018 00019 #define DEBUG_CURRENT_MODULE_NAME "ARP" 00020 #define DEBUG_CURRENT_MODULE_ID DEBUG_MODULE_ARP 00021 00022 enum ARP_EntryStatus 00023 { 00024 ARP_Entry_Free = 0, 00025 ARP_Entry_PendingReply, 00026 ARP_Entry_Dynamic, 00027 ARP_Entry_Expired, 00028 ARP_Entry_Static, 00029 ARP_Entry_Count, 00030 }; 00031 typedef enum ARP_EntryStatus ARP_EntryStatus_t; 00032 00033 const char *arpEntryStatusText[ARP_Entry_Count] = 00034 { 00035 "free", 00036 "pending", 00037 "dynamic", 00038 "expired", 00039 "static", 00040 }; 00041 00042 struct ARP_CacheEntry 00043 { 00044 IPv4_Addr_t ipv4Addr; 00045 Ethernet_Addr_t ethernetAddr; 00046 NetIF_t *netIF; 00047 uint16_t age; 00048 ARP_EntryStatus_t status; 00049 RTOS_Mutex_t mutex; 00050 }; 00051 typedef struct ARP_CacheEntry ARP_CacheEntry_t; 00052 00053 #pragma push 00054 #pragma pack(1) 00055 static struct 00056 { 00057 Ethernet_Header_t ethernetHeader; 00058 ARP_Header_t arpHeader; 00059 ARP_IPv4Data_t ipv4ARPData; 00060 } arp_FullIPv4Packet; 00061 #pragma pop 00062 00063 static void Init(void); 00064 static void Handler(NetIF_t *netIF, NetPacket_t *packet); 00065 static void PeriodicFunction(void); 00066 static ARP_CacheEntry_t *GetReusableEntry(void); 00067 static ARP_CacheEntry_t *GetEntryByIPv4Address(IPv4_Addr_t address); 00068 00069 static ARP_CacheEntry_t arp_CacheTable[ARP_CACHE_MAX_ENTRIES]; 00070 00071 Protocol_Handler_t arp = 00072 { 00073 PROTOCOL_INDEX_NOT_INITIALIZED, /* Always PROTOCOL_INDEX_NOT_INITIALIZED at initialization */ 00074 Protocol_ID_ARP, /* Protocol ID */ 00075 htons(ETHERNET_PROTO_ARP), /* Protocol number */ 00076 Init, /* Protocol initialisation function */ 00077 Handler, /* Protocol handler */ 00078 NULL, /* Protocol registration function */ 00079 NULL, /* API registration function */ 00080 }; 00081 00082 static void Init(void) 00083 { 00084 int32_t index; 00085 00086 DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Initializing ARP layer")); 00087 memset(arp_CacheTable, 0, sizeof(arp_CacheTable)); 00088 for (index = 0; index < ARP_CACHE_MAX_ENTRIES; index++) 00089 { 00090 arp_CacheTable[index].mutex = RTOS_MUTEX_CREATE(); 00091 } 00092 NetIF_RegisterPeriodicFunction("ARP cache", PeriodicFunction, ARP_FUNCTION_PERIOD); 00093 } 00094 00095 00096 00097 00098 static void Handler(NetIF_t *netIF, NetPacket_t *packet) 00099 { 00100 static ARP_Type_t type; 00101 static ARP_Protocol_t protocol; 00102 static ARP_Operation_t operation; 00103 static ARP_IPv4Data_t *ipv4ARP; 00104 static ARP_Header_t *arpHeader; 00105 static Ethernet_Addr_t *ourHWAddress; 00106 static Ethernet_Header_t *ethernetHeader; 00107 static ARP_CacheEntry_t *entry; 00108 00109 arpHeader = (ARP_Header_t *)packet->data; 00110 type = ntohs(arpHeader->type); 00111 protocol = ntohs(arpHeader->protocol); 00112 operation = ntohs(arpHeader->operation); 00113 00114 if (type != ARP_HW_TYPE_ENET) goto Exit; /* not an ethernet ARP, ignore */ 00115 /* Not an IPv4 ARP, ignore */ 00116 if (protocol != ETHERNET_PROTO_IPV4) goto Exit; 00117 00118 ipv4ARP = (ARP_IPv4Data_t *)(arpHeader + 1); 00119 00120 switch(operation) 00121 { 00122 case ARP_OPERATION_REQUEST: 00123 /* Does it match our hw address? */ 00124 if (ipv4ARP->ipDest.addr == netIF->ipv4Address.addr) 00125 { 00126 DEBUG_BLOCK(DEBUG_LEVEL_VERBOSE0) 00127 { 00128 ARP_DumpHeader("Got ", arpHeader); 00129 } 00130 00131 ourHWAddress = (Ethernet_Addr_t *)netIF->driverParameter; 00132 00133 arpHeader->operation = htons(ARP_OPERATION_REPLY); 00134 00135 ipv4ARP->hwDest = ipv4ARP->hwSource; 00136 ipv4ARP->ipDest.addr = ipv4ARP->ipSource.addr; 00137 ipv4ARP->hwSource = *ourHWAddress; 00138 ipv4ARP->ipSource = netIF->ipv4Address; 00139 00140 NetIF_ProtoPop(packet); 00141 00142 ethernetHeader = (Ethernet_Header_t *)packet->data; 00143 ethernetHeader->destination = ethernetHeader->source; 00144 ethernetHeader->source = *ourHWAddress; 00145 00146 DEBUG_BLOCK(DEBUG_LEVEL_VERBOSE0) 00147 { 00148 ARP_DumpHeader("Replying ", arpHeader); 00149 } 00150 00151 netIF->driver->Write(packet->data, packet->length); 00152 } 00153 00154 break; 00155 00156 case ARP_OPERATION_REPLY: 00157 /* Check if it matches an entry we requested */ 00158 DEBUG_BLOCK(DEBUG_LEVEL_VERBOSE0) 00159 { 00160 ARP_DumpHeader("Got ", arpHeader); 00161 } 00162 00163 entry = GetEntryByIPv4Address(ipv4ARP->ipSource); 00164 if (entry == NULL) break; /* fake arp request */ 00165 00166 entry->status = ARP_Entry_Dynamic; 00167 entry->ethernetAddr = ipv4ARP->hwSource; 00168 entry->netIF = netIF; 00169 entry->age = 0; 00170 00171 RTOS_MUTEX_UNLOCK(entry->mutex); 00172 00173 DEBUG_BLOCK(DEBUG_LEVEL_VERBOSE0) 00174 { 00175 DEBUG_RAW(("Adding entry %d.%d.%d.%d at %02x:%02x:%02x:%02x:%02x:%02x", 00176 ipv4ARP->ipSource.IP0, 00177 ipv4ARP->ipSource.IP1, 00178 ipv4ARP->ipSource.IP2, 00179 ipv4ARP->ipSource.IP3, 00180 ipv4ARP->hwSource.MA0, 00181 ipv4ARP->hwSource.MA1, 00182 ipv4ARP->hwSource.MA2, 00183 ipv4ARP->hwSource.MA3, 00184 ipv4ARP->hwSource.MA4, 00185 ipv4ARP->hwSource.MA5 00186 )); 00187 } 00188 break; 00189 } 00190 00191 Exit: 00192 return; 00193 } 00194 00195 00196 00197 00198 static void PeriodicFunction(void) 00199 { 00200 int32_t index; 00201 ARP_CacheEntry_t *entry; 00202 00203 for (index = 0; index < ARP_CACHE_MAX_ENTRIES; index++) 00204 { 00205 entry = arp_CacheTable + index; 00206 RTOS_MUTEX_LOCK(entry->mutex); 00207 switch(entry->status) 00208 { 00209 case ARP_Entry_Dynamic: 00210 entry->age += ARP_FUNCTION_PERIOD; 00211 if (entry->age > ARP_MAX_ENTRY_AGE) 00212 { 00213 entry->status = ARP_Entry_Expired; 00214 entry->age = 0; 00215 } 00216 break; 00217 00218 case ARP_Entry_PendingReply: 00219 entry->age += ARP_FUNCTION_PERIOD; 00220 if (entry->age > ARP_MAX_ENTRY_AGE) 00221 { 00222 entry->status = ARP_Entry_Free; 00223 entry->age = 0; 00224 } 00225 break; 00226 } 00227 RTOS_MUTEX_UNLOCK(entry->mutex); 00228 } 00229 } 00230 00231 00232 00233 00234 static ARP_CacheEntry_t *GetReusableEntry(void) 00235 { 00236 int32_t index, 00237 oldestEntryIndex, oldestEntryAge; 00238 ARP_CacheEntry_t *entry; 00239 00240 /* First look for a free entry */ 00241 for (index = 0; index < ARP_CACHE_MAX_ENTRIES; index++) 00242 { 00243 entry = arp_CacheTable + index; 00244 RTOS_MUTEX_LOCK(entry->mutex); 00245 00246 if (entry->status == ARP_Entry_Free) 00247 { 00248 break; 00249 } 00250 00251 RTOS_MUTEX_UNLOCK(entry->mutex); 00252 entry = NULL; 00253 } 00254 00255 if (entry != NULL) goto Exit; /* A free entry was found, return it */ 00256 00257 /* Now look for an expired entry */ 00258 oldestEntryIndex = -1; 00259 oldestEntryAge = -1; 00260 for (index = 0; index < ARP_CACHE_MAX_ENTRIES; index++) 00261 { 00262 entry = arp_CacheTable + index; 00263 RTOS_MUTEX_LOCK(entry->mutex); 00264 00265 if (entry->age > oldestEntryAge) 00266 { 00267 oldestEntryIndex = index; 00268 oldestEntryAge = entry->age; 00269 } 00270 00271 if (entry->status == ARP_Entry_Expired) 00272 { 00273 break; 00274 } 00275 00276 RTOS_MUTEX_UNLOCK(entry->mutex); 00277 entry = NULL; 00278 } 00279 00280 if (entry != NULL) goto Exit; /* An expired entry was found, return it */ 00281 00282 /* Last possibility, return the oldest non static entry */ 00283 entry = arp_CacheTable + oldestEntryIndex; 00284 RTOS_MUTEX_LOCK(entry->mutex); 00285 00286 Exit: 00287 return entry; 00288 } 00289 00290 00291 00292 00293 static ARP_CacheEntry_t *GetEntryByIPv4Address(IPv4_Addr_t address) 00294 { 00295 int32_t index; 00296 ARP_CacheEntry_t *entry = NULL; 00297 00298 for (index = 0; index < ARP_CACHE_MAX_ENTRIES; index++) 00299 { 00300 entry = arp_CacheTable + index; 00301 RTOS_MUTEX_LOCK(entry->mutex); 00302 00303 if (entry->ipv4Addr.addr == address.addr) 00304 { 00305 break; 00306 } 00307 RTOS_MUTEX_UNLOCK(entry->mutex); 00308 entry = NULL; 00309 } 00310 00311 return entry; 00312 } 00313 00314 00315 00316 00317 int32_t ARP_ResolveIPv4Address(NetIF_t *netIF, IPv4_Addr_t address, Ethernet_Addr_t *ethernetAddr) 00318 { 00319 int32_t result = -1; 00320 Ethernet_Addr_t *hwAddress; 00321 ARP_CacheEntry_t *entry; 00322 00323 DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Resolving %d.%d.%d.%d", 00324 address.IP0, 00325 address.IP1, 00326 address.IP2, 00327 address.IP3 00328 )); 00329 00330 /* Look if entry is already available in table */ 00331 entry = GetEntryByIPv4Address(address); 00332 if (entry != NULL) /* Found entry, look its status */ 00333 { 00334 switch(entry->status) 00335 { 00336 case ARP_Entry_Static: 00337 DEBUG_MODULE(DEBUG_LEVEL_VERBOSE0, ("Found static entry")); 00338 if (ethernetAddr != NULL) *ethernetAddr = entry->ethernetAddr; 00339 RTOS_MUTEX_UNLOCK(entry->mutex); 00340 result = 0; 00341 break; 00342 00343 case ARP_Entry_Dynamic: 00344 DEBUG_MODULE(DEBUG_LEVEL_VERBOSE0, ("Found dynamic entry")); 00345 if (ethernetAddr != NULL) *ethernetAddr = entry->ethernetAddr; 00346 entry->age = 0; 00347 RTOS_MUTEX_UNLOCK(entry->mutex); 00348 result = 0; 00349 break; 00350 00351 case ARP_Entry_Expired: 00352 DEBUG_MODULE(DEBUG_LEVEL_VERBOSE0, ("Found expired entry, reactivating it")); 00353 if (ethernetAddr != NULL) *ethernetAddr = entry->ethernetAddr; 00354 entry->status = ARP_Entry_Dynamic; 00355 entry->age = 0; 00356 RTOS_MUTEX_UNLOCK(entry->mutex); 00357 result = 0; 00358 break; 00359 00360 case ARP_Entry_PendingReply: 00361 DEBUG_MODULE(DEBUG_LEVEL_VERBOSE0, ("Found pending entry")); 00362 entry->age = 0; 00363 RTOS_MUTEX_UNLOCK(entry->mutex); 00364 break; 00365 00366 default: 00367 DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Default?!")); 00368 break; 00369 } 00370 } 00371 00372 if (result == 0) goto Exit; /* Resolution was successfull, exit */ 00373 00374 /* Entry not found, send a request */ 00375 result = -1; 00376 DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Sending ARP resolution request for %d.%d.%d.%d", 00377 address.IP0, 00378 address.IP1, 00379 address.IP2, 00380 address.IP3 00381 )); 00382 00383 /* Update entry, setting its status to Pending reply */ 00384 entry = GetReusableEntry(); 00385 if (entry != NULL) 00386 { 00387 entry->status = ARP_Entry_PendingReply; 00388 entry->ipv4Addr.addr = address.addr; 00389 entry->netIF = netIF; 00390 entry->age = 0; 00391 RTOS_MUTEX_UNLOCK(entry->mutex); 00392 } 00393 /* Send ARP who-has */ 00394 hwAddress = (Ethernet_Addr_t *)netIF->driverParameter; 00395 00396 arp_FullIPv4Packet.ethernetHeader.destination = ethernet_Addr_Broadcast; 00397 arp_FullIPv4Packet.ethernetHeader.source = *hwAddress; 00398 arp_FullIPv4Packet.ethernetHeader.protocol = htons(ETHERNET_PROTO_ARP); 00399 00400 arp_FullIPv4Packet.arpHeader.type = htons(ARP_HW_TYPE_ENET); 00401 arp_FullIPv4Packet.arpHeader.protocol = htons(ETHERNET_PROTO_IPV4); 00402 arp_FullIPv4Packet.arpHeader.operation = htons(ARP_OPERATION_REQUEST); 00403 arp_FullIPv4Packet.arpHeader.hardAddrLen = 6; 00404 arp_FullIPv4Packet.arpHeader.protoAddrLen = 4; 00405 00406 arp_FullIPv4Packet.ipv4ARPData.hwSource = *hwAddress; 00407 arp_FullIPv4Packet.ipv4ARPData.ipSource = netIF->ipv4Address; 00408 arp_FullIPv4Packet.ipv4ARPData.hwDest = ethernet_Addr_Null; 00409 arp_FullIPv4Packet.ipv4ARPData.ipDest = address; 00410 00411 DEBUG_BLOCK(DEBUG_LEVEL_VERBOSE0) 00412 { 00413 ARP_DumpHeader("Sending ", &arp_FullIPv4Packet.arpHeader); 00414 } 00415 00416 netIF->driver->Write((uint8_t *)&arp_FullIPv4Packet, sizeof(arp_FullIPv4Packet)); 00417 00418 Exit: 00419 return result; 00420 } 00421 00422 00423 00424 00425 int32_t ARP_AddStaticEntry(NetIF_t *netIF, IPv4_Addr_t address, const Ethernet_Addr_t *ethernetAddr) 00426 { 00427 int32_t result = 0; 00428 ARP_CacheEntry_t *entry; 00429 00430 entry = GetReusableEntry(); 00431 if (entry == NULL) 00432 { 00433 result = -1; 00434 goto Exit; 00435 } 00436 entry->netIF = netIF; 00437 entry->status = ARP_Entry_Static; 00438 entry->ipv4Addr.addr = address.addr; 00439 entry->ethernetAddr = *ethernetAddr; 00440 entry->age = 0; 00441 RTOS_MUTEX_UNLOCK(entry->mutex); 00442 00443 Exit: 00444 return result; 00445 } 00446 00447 00448 00449 00450 int32_t ARP_RemoveEntry(const NetIF_t *netIF, IPv4_Addr_t address) 00451 { 00452 int32_t result = 0; 00453 00454 return result; 00455 } 00456 00457 00458 00459 00460 void ARP_FlushCache(Bool_t flushStaticEntries) 00461 { 00462 int32_t index; 00463 ARP_CacheEntry_t *entry; 00464 00465 for (index = 0; index < ARP_CACHE_MAX_ENTRIES; index++) 00466 { 00467 entry = arp_CacheTable + index; 00468 RTOS_MUTEX_LOCK(entry->mutex); 00469 if ((entry->status == ARP_Entry_Static) && (!flushStaticEntries)) 00470 { 00471 RTOS_MUTEX_UNLOCK(entry->mutex); 00472 continue; 00473 } 00474 entry->status = ARP_Entry_Free; 00475 entry->ipv4Addr = ipv4_Addr_Any; 00476 entry->ethernetAddr = ethernet_Addr_Null; 00477 entry->age = 0; 00478 RTOS_MUTEX_UNLOCK(entry->mutex); 00479 } 00480 } 00481 00482 00483 00484 00485 void ARP_DisplayCache(void) 00486 { 00487 int32_t index; 00488 ARP_CacheEntry_t *entry = NULL; 00489 00490 DEBUG_RAW(("ARP cache")); 00491 DEBUG_RAW(("index dev MAC address type age IPv4 address")); 00492 DEBUG_RAW(("----------------------------------------------------------")); 00493 /* en0 00:11:22:33:44:55 dyn 10 163.157.128.131 */ 00494 for (index = 0; index < ARP_CACHE_MAX_ENTRIES; index++) 00495 { 00496 entry = arp_CacheTable + index; 00497 00498 DEBUG_RAW(("%2d %s%c %02x:%02x:%02x:%02x:%02x:%02x %8s %4d %d.%d.%d.%d", 00499 index, 00500 entry->status != ARP_Entry_Free ? entry->netIF->name : "--", 00501 entry->status != ARP_Entry_Free ? entry->netIF->index + '0' : '-', 00502 entry->ethernetAddr.MA0, 00503 entry->ethernetAddr.MA1, 00504 entry->ethernetAddr.MA2, 00505 entry->ethernetAddr.MA3, 00506 entry->ethernetAddr.MA4, 00507 entry->ethernetAddr.MA5, 00508 00509 arpEntryStatusText[entry->status], 00510 entry->age, 00511 00512 entry->ipv4Addr.IP0, 00513 entry->ipv4Addr.IP1, 00514 entry->ipv4Addr.IP2, 00515 entry->ipv4Addr.IP3 00516 )); 00517 } 00518 } 00519 00520 00521 00522 00523 void ARP_DumpHeader(const char *prefix, ARP_Header_t *arpHeader) 00524 { 00525 ARP_IPv4Data_t *ipv4ARP = NULL; 00526 00527 if (arpHeader->protocol == htons(ETHERNET_PROTO_IPV4)) 00528 { 00529 ipv4ARP = (ARP_IPv4Data_t *)(arpHeader + 1); 00530 00531 switch(ntohs(arpHeader->operation)) 00532 { 00533 case ARP_OPERATION_REQUEST: 00534 DEBUG_RAW(("%sARP who-has %d.%d.%d.%d tell %02x:%02x:%02x:%02x:%02x:%02x", 00535 prefix != NULL ? prefix : "", 00536 00537 ipv4ARP->ipDest.IP0, 00538 ipv4ARP->ipDest.IP1, 00539 ipv4ARP->ipDest.IP2, 00540 ipv4ARP->ipDest.IP3, 00541 00542 ipv4ARP->hwSource.MA0, 00543 ipv4ARP->hwSource.MA1, 00544 ipv4ARP->hwSource.MA2, 00545 ipv4ARP->hwSource.MA3, 00546 ipv4ARP->hwSource.MA4, 00547 ipv4ARP->hwSource.MA5 00548 )); 00549 break; 00550 00551 case ARP_OPERATION_REPLY: 00552 DEBUG_RAW(("%sARP %d.%d.%d.%d is-at %02x:%02x:%02x:%02x:%02x:%02x", 00553 prefix != NULL ? prefix : "", 00554 00555 ipv4ARP->ipSource.IP0, 00556 ipv4ARP->ipSource.IP1, 00557 ipv4ARP->ipSource.IP2, 00558 ipv4ARP->ipSource.IP3, 00559 00560 ipv4ARP->hwSource.MA0, 00561 ipv4ARP->hwSource.MA1, 00562 ipv4ARP->hwSource.MA2, 00563 ipv4ARP->hwSource.MA3, 00564 ipv4ARP->hwSource.MA4, 00565 ipv4ARP->hwSource.MA5 00566 )); 00567 break; 00568 00569 default: 00570 break; 00571 } 00572 } 00573 else 00574 { 00575 DEBUG_RAW(("%sARP: unsupported protocol %d", 00576 prefix != NULL ? prefix : "", 00577 arpHeader->protocol 00578 )); 00579 } 00580 }
Generated on Wed Jul 13 2022 06:09:33 by 1.7.2