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.

Committer:
Benoit
Date:
Sun Jun 12 19:17:11 2011 +0000
Revision:
1:f4040665bc61
Child:
5:3cd83fcb1467
Frames are now received using an interrupt handler

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Benoit 1:f4040665bc61 1 /*
Benoit 1:f4040665bc61 2 * $Id: ARP.c 29 2011-06-11 14:53:08Z benoit $
Benoit 1:f4040665bc61 3 * $Author: benoit $
Benoit 1:f4040665bc61 4 * $Date: 2011-06-11 16:53:08 +0200 (sam., 11 juin 2011) $
Benoit 1:f4040665bc61 5 * $Rev: 29 $
Benoit 1:f4040665bc61 6 *
Benoit 1:f4040665bc61 7 *
Benoit 1:f4040665bc61 8 *
Benoit 1:f4040665bc61 9 *
Benoit 1:f4040665bc61 10 *
Benoit 1:f4040665bc61 11 */
Benoit 1:f4040665bc61 12
Benoit 1:f4040665bc61 13 #include "ARP.h"
Benoit 1:f4040665bc61 14 #include "Ethernet.h"
Benoit 1:f4040665bc61 15 #include "Debug.h"
Benoit 1:f4040665bc61 16 #include "IPv4.h"
Benoit 1:f4040665bc61 17 #include <string.h>
Benoit 1:f4040665bc61 18
Benoit 1:f4040665bc61 19
Benoit 1:f4040665bc61 20 #define DEBUG_CURRENT_MODULE_NAME "ARP"
Benoit 1:f4040665bc61 21 #define DEBUG_CURRENT_MODULE_ID DEBUG_MODULE_ARP
Benoit 1:f4040665bc61 22
Benoit 1:f4040665bc61 23
Benoit 1:f4040665bc61 24 enum ARP_EntryStatus
Benoit 1:f4040665bc61 25 {
Benoit 1:f4040665bc61 26 ARP_Entry_Free = 0,
Benoit 1:f4040665bc61 27 ARP_Entry_PendingReply,
Benoit 1:f4040665bc61 28 ARP_Entry_Dynamic,
Benoit 1:f4040665bc61 29 ARP_Entry_Expired,
Benoit 1:f4040665bc61 30 ARP_Entry_Static,
Benoit 1:f4040665bc61 31 ARP_Entry_Count,
Benoit 1:f4040665bc61 32 };
Benoit 1:f4040665bc61 33 typedef enum ARP_EntryStatus ARP_EntryStatus_t;
Benoit 1:f4040665bc61 34
Benoit 1:f4040665bc61 35
Benoit 1:f4040665bc61 36 const char *arpEntryStatusText[ARP_Entry_Count] =
Benoit 1:f4040665bc61 37 {
Benoit 1:f4040665bc61 38 "free",
Benoit 1:f4040665bc61 39 "pending",
Benoit 1:f4040665bc61 40 "dynamic",
Benoit 1:f4040665bc61 41 "expired",
Benoit 1:f4040665bc61 42 "static",
Benoit 1:f4040665bc61 43 };
Benoit 1:f4040665bc61 44
Benoit 1:f4040665bc61 45 struct ARP_CacheEntry
Benoit 1:f4040665bc61 46 {
Benoit 1:f4040665bc61 47 IPv4_Addr_t ipv4Addr;
Benoit 1:f4040665bc61 48 Ethernet_Addr_t ethernetAddr;
Benoit 1:f4040665bc61 49 NetIF_t *netIF;
Benoit 1:f4040665bc61 50 uint16_t age;
Benoit 1:f4040665bc61 51 ARP_EntryStatus_t status;
Benoit 1:f4040665bc61 52 RTOS_Mutex_t mutex;
Benoit 1:f4040665bc61 53 };
Benoit 1:f4040665bc61 54 typedef struct ARP_CacheEntry ARP_CacheEntry_t;
Benoit 1:f4040665bc61 55
Benoit 1:f4040665bc61 56
Benoit 1:f4040665bc61 57 #pragma push
Benoit 1:f4040665bc61 58 #pragma pack(1)
Benoit 1:f4040665bc61 59 static struct
Benoit 1:f4040665bc61 60 {
Benoit 1:f4040665bc61 61 Ethernet_Header_t ethernetHeader;
Benoit 1:f4040665bc61 62 ARP_Header_t arpHeader;
Benoit 1:f4040665bc61 63 ARP_IPv4Data_t ipv4ARPData;
Benoit 1:f4040665bc61 64 } arp_FullIPv4Packet;
Benoit 1:f4040665bc61 65 #pragma pop
Benoit 1:f4040665bc61 66
Benoit 1:f4040665bc61 67
Benoit 1:f4040665bc61 68 static void Init(void);
Benoit 1:f4040665bc61 69 static void Handler(NetIF_t *netIF, Packet_t *packet);
Benoit 1:f4040665bc61 70 static void PeriodicFunction(void);
Benoit 1:f4040665bc61 71 static ARP_CacheEntry_t *GetReusableEntry(void);
Benoit 1:f4040665bc61 72 static ARP_CacheEntry_t *GetEntryByIPv4Address(IPv4_Addr_t address);
Benoit 1:f4040665bc61 73
Benoit 1:f4040665bc61 74
Benoit 1:f4040665bc61 75 static ARP_CacheEntry_t arp_CacheTable[ARP_CACHE_MAX_ENTRIES];
Benoit 1:f4040665bc61 76
Benoit 1:f4040665bc61 77
Benoit 1:f4040665bc61 78 Protocol_Handler_t arp =
Benoit 1:f4040665bc61 79 {
Benoit 1:f4040665bc61 80 PROTOCOL_INDEX_NOT_INITIALIZED, /* Always PROTOCOL_INDEX_NOT_INITIALIZED at initialization */
Benoit 1:f4040665bc61 81 Protocol_ID_ARP, /* Protocol ID */
Benoit 1:f4040665bc61 82 htons(ETHERNET_PROTO_ARP), /* Protocol number */
Benoit 1:f4040665bc61 83 Init, /* Protocol initialisation function */
Benoit 1:f4040665bc61 84 Handler, /* Protocol handler */
Benoit 1:f4040665bc61 85 NULL, /* Protocol registration function */
Benoit 1:f4040665bc61 86 NULL, /* API registration function */
Benoit 1:f4040665bc61 87 };
Benoit 1:f4040665bc61 88
Benoit 1:f4040665bc61 89
Benoit 1:f4040665bc61 90 static void Init(void)
Benoit 1:f4040665bc61 91 {
Benoit 1:f4040665bc61 92 int32_t index;
Benoit 1:f4040665bc61 93
Benoit 1:f4040665bc61 94 DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Initializing ARP layer"));
Benoit 1:f4040665bc61 95 memset(arp_CacheTable, 0, sizeof(arp_CacheTable));
Benoit 1:f4040665bc61 96 for (index = 0; index < ARP_CACHE_MAX_ENTRIES; index++)
Benoit 1:f4040665bc61 97 {
Benoit 1:f4040665bc61 98 arp_CacheTable[index].mutex = RTOS_MUTEX_CREATE();
Benoit 1:f4040665bc61 99 }
Benoit 1:f4040665bc61 100 NetIF_RegisterPeriodicFunction("ARP cache", PeriodicFunction, ARP_FUNCTION_PERIOD);
Benoit 1:f4040665bc61 101 }
Benoit 1:f4040665bc61 102
Benoit 1:f4040665bc61 103
Benoit 1:f4040665bc61 104 static void Handler(NetIF_t *netIF, Packet_t *packet)
Benoit 1:f4040665bc61 105 {
Benoit 1:f4040665bc61 106 static ARP_Type_t type;
Benoit 1:f4040665bc61 107 static ARP_Protocol_t protocol;
Benoit 1:f4040665bc61 108 static ARP_Operation_t operation;
Benoit 1:f4040665bc61 109 static ARP_IPv4Data_t *ipv4ARP;
Benoit 1:f4040665bc61 110 static ARP_Header_t *arpHeader;
Benoit 1:f4040665bc61 111 static Ethernet_Addr_t *ourHWAddress;
Benoit 1:f4040665bc61 112 static Ethernet_Header_t *ethernetHeader;
Benoit 1:f4040665bc61 113 static ARP_CacheEntry_t *entry;
Benoit 1:f4040665bc61 114
Benoit 1:f4040665bc61 115 arpHeader = (ARP_Header_t *)packet->data;
Benoit 1:f4040665bc61 116 type = ntohs(arpHeader->type);
Benoit 1:f4040665bc61 117 protocol = ntohs(arpHeader->protocol);
Benoit 1:f4040665bc61 118 operation = ntohs(arpHeader->operation);
Benoit 1:f4040665bc61 119
Benoit 1:f4040665bc61 120 if (type != ARP_HW_TYPE_ENET) goto Exit; /* not an ethernet ARP, ignore */
Benoit 1:f4040665bc61 121 if (protocol != ETHERNET_PROTO_IPV4) goto Exit; /* Not an IPv4 ARP, ignore */
Benoit 1:f4040665bc61 122
Benoit 1:f4040665bc61 123 ipv4ARP = (ARP_IPv4Data_t *)(arpHeader + 1);
Benoit 1:f4040665bc61 124
Benoit 1:f4040665bc61 125 switch(operation)
Benoit 1:f4040665bc61 126 {
Benoit 1:f4040665bc61 127 case ARP_OPERATION_REQUEST:
Benoit 1:f4040665bc61 128 if (ipv4ARP->ipDest.addr == netIF->ipv4Address.addr) /* Does it match our hw address? */
Benoit 1:f4040665bc61 129 {
Benoit 1:f4040665bc61 130 DEBUG_BLOCK(DEBUG_LEVEL_VERBOSE0)
Benoit 1:f4040665bc61 131 {
Benoit 1:f4040665bc61 132 ARP_DumpHeader("Got ", arpHeader);
Benoit 1:f4040665bc61 133 }
Benoit 1:f4040665bc61 134
Benoit 1:f4040665bc61 135 ourHWAddress = (Ethernet_Addr_t *)netIF->driverParameter;
Benoit 1:f4040665bc61 136
Benoit 1:f4040665bc61 137 arpHeader->operation = htons(ARP_OPERATION_REPLY);
Benoit 1:f4040665bc61 138
Benoit 1:f4040665bc61 139 ipv4ARP->hwDest = ipv4ARP->hwSource;
Benoit 1:f4040665bc61 140 ipv4ARP->ipDest.addr = ipv4ARP->ipSource.addr;
Benoit 1:f4040665bc61 141 ipv4ARP->hwSource = *ourHWAddress;
Benoit 1:f4040665bc61 142 ipv4ARP->ipSource = netIF->ipv4Address;
Benoit 1:f4040665bc61 143
Benoit 1:f4040665bc61 144 NetIF_ProtoPop(packet);
Benoit 1:f4040665bc61 145
Benoit 1:f4040665bc61 146 ethernetHeader = (Ethernet_Header_t *)packet->data;
Benoit 1:f4040665bc61 147 ethernetHeader->destination = ethernetHeader->source;
Benoit 1:f4040665bc61 148 ethernetHeader->source = *ourHWAddress;
Benoit 1:f4040665bc61 149
Benoit 1:f4040665bc61 150 DEBUG_BLOCK(DEBUG_LEVEL_VERBOSE0)
Benoit 1:f4040665bc61 151 {
Benoit 1:f4040665bc61 152 ARP_DumpHeader("Replying ", arpHeader);
Benoit 1:f4040665bc61 153 }
Benoit 1:f4040665bc61 154
Benoit 1:f4040665bc61 155 netIF->driver->Write(packet->data, packet->length);
Benoit 1:f4040665bc61 156 }
Benoit 1:f4040665bc61 157
Benoit 1:f4040665bc61 158 break;
Benoit 1:f4040665bc61 159
Benoit 1:f4040665bc61 160 case ARP_OPERATION_REPLY:
Benoit 1:f4040665bc61 161 /* Check if it matches an entry we requested */
Benoit 1:f4040665bc61 162 DEBUG_BLOCK(DEBUG_LEVEL_VERBOSE0)
Benoit 1:f4040665bc61 163 {
Benoit 1:f4040665bc61 164 ARP_DumpHeader("Got ", arpHeader);
Benoit 1:f4040665bc61 165 }
Benoit 1:f4040665bc61 166
Benoit 1:f4040665bc61 167 entry = GetEntryByIPv4Address(ipv4ARP->ipSource);
Benoit 1:f4040665bc61 168 if (entry == NULL) break; /* fake arp request */
Benoit 1:f4040665bc61 169
Benoit 1:f4040665bc61 170 entry->status = ARP_Entry_Dynamic;
Benoit 1:f4040665bc61 171 entry->ethernetAddr = ipv4ARP->hwSource;
Benoit 1:f4040665bc61 172 entry->netIF = netIF;
Benoit 1:f4040665bc61 173 entry->age = 0;
Benoit 1:f4040665bc61 174
Benoit 1:f4040665bc61 175 RTOS_MUTEX_UNLOCK(entry->mutex);
Benoit 1:f4040665bc61 176
Benoit 1:f4040665bc61 177 DEBUG_BLOCK(DEBUG_LEVEL_VERBOSE0)
Benoit 1:f4040665bc61 178 {
Benoit 1:f4040665bc61 179 DEBUG_RAW(("Adding entry %d.%d.%d.%d at %02x:%02x:%02x:%02x:%02x:%02x",
Benoit 1:f4040665bc61 180 ipv4ARP->ipSource.IP0,
Benoit 1:f4040665bc61 181 ipv4ARP->ipSource.IP1,
Benoit 1:f4040665bc61 182 ipv4ARP->ipSource.IP2,
Benoit 1:f4040665bc61 183 ipv4ARP->ipSource.IP3,
Benoit 1:f4040665bc61 184 ipv4ARP->hwSource.MA0,
Benoit 1:f4040665bc61 185 ipv4ARP->hwSource.MA1,
Benoit 1:f4040665bc61 186 ipv4ARP->hwSource.MA2,
Benoit 1:f4040665bc61 187 ipv4ARP->hwSource.MA3,
Benoit 1:f4040665bc61 188 ipv4ARP->hwSource.MA4,
Benoit 1:f4040665bc61 189 ipv4ARP->hwSource.MA5
Benoit 1:f4040665bc61 190 ));
Benoit 1:f4040665bc61 191 }
Benoit 1:f4040665bc61 192 break;
Benoit 1:f4040665bc61 193 }
Benoit 1:f4040665bc61 194
Benoit 1:f4040665bc61 195 Exit:
Benoit 1:f4040665bc61 196 return;
Benoit 1:f4040665bc61 197 }
Benoit 1:f4040665bc61 198
Benoit 1:f4040665bc61 199
Benoit 1:f4040665bc61 200 static void PeriodicFunction(void)
Benoit 1:f4040665bc61 201 {
Benoit 1:f4040665bc61 202 int32_t index;
Benoit 1:f4040665bc61 203 ARP_CacheEntry_t *entry;
Benoit 1:f4040665bc61 204
Benoit 1:f4040665bc61 205 for (index = 0; index < ARP_CACHE_MAX_ENTRIES; index++)
Benoit 1:f4040665bc61 206 {
Benoit 1:f4040665bc61 207 entry = arp_CacheTable + index;
Benoit 1:f4040665bc61 208 RTOS_MUTEX_LOCK(entry->mutex);
Benoit 1:f4040665bc61 209 switch(entry->status)
Benoit 1:f4040665bc61 210 {
Benoit 1:f4040665bc61 211 case ARP_Entry_Dynamic:
Benoit 1:f4040665bc61 212 entry->age += ARP_FUNCTION_PERIOD;
Benoit 1:f4040665bc61 213 if (entry->age > ARP_MAX_ENTRY_AGE)
Benoit 1:f4040665bc61 214 {
Benoit 1:f4040665bc61 215 entry->status = ARP_Entry_Expired;
Benoit 1:f4040665bc61 216 entry->age = 0;
Benoit 1:f4040665bc61 217 }
Benoit 1:f4040665bc61 218 break;
Benoit 1:f4040665bc61 219
Benoit 1:f4040665bc61 220 case ARP_Entry_PendingReply:
Benoit 1:f4040665bc61 221 entry->age += ARP_FUNCTION_PERIOD;
Benoit 1:f4040665bc61 222 if (entry->age > ARP_MAX_ENTRY_AGE)
Benoit 1:f4040665bc61 223 {
Benoit 1:f4040665bc61 224 entry->status = ARP_Entry_Free;
Benoit 1:f4040665bc61 225 entry->age = 0;
Benoit 1:f4040665bc61 226 }
Benoit 1:f4040665bc61 227 break;
Benoit 1:f4040665bc61 228 }
Benoit 1:f4040665bc61 229 RTOS_MUTEX_UNLOCK(entry->mutex);
Benoit 1:f4040665bc61 230 }
Benoit 1:f4040665bc61 231 }
Benoit 1:f4040665bc61 232
Benoit 1:f4040665bc61 233
Benoit 1:f4040665bc61 234 static ARP_CacheEntry_t *GetReusableEntry(void)
Benoit 1:f4040665bc61 235 {
Benoit 1:f4040665bc61 236 int32_t index,
Benoit 1:f4040665bc61 237 oldestEntryIndex, oldestEntryAge;
Benoit 1:f4040665bc61 238 ARP_CacheEntry_t *entry;
Benoit 1:f4040665bc61 239
Benoit 1:f4040665bc61 240 /* First look for a free entry */
Benoit 1:f4040665bc61 241 for (index = 0; index < ARP_CACHE_MAX_ENTRIES; index++)
Benoit 1:f4040665bc61 242 {
Benoit 1:f4040665bc61 243 entry = arp_CacheTable + index;
Benoit 1:f4040665bc61 244 RTOS_MUTEX_LOCK(entry->mutex);
Benoit 1:f4040665bc61 245
Benoit 1:f4040665bc61 246 if (entry->status == ARP_Entry_Free)
Benoit 1:f4040665bc61 247 {
Benoit 1:f4040665bc61 248 break;
Benoit 1:f4040665bc61 249 }
Benoit 1:f4040665bc61 250
Benoit 1:f4040665bc61 251 RTOS_MUTEX_UNLOCK(entry->mutex);
Benoit 1:f4040665bc61 252 entry = NULL;
Benoit 1:f4040665bc61 253 }
Benoit 1:f4040665bc61 254
Benoit 1:f4040665bc61 255 if (entry != NULL) goto Exit; /* A free entry was found, return it */
Benoit 1:f4040665bc61 256
Benoit 1:f4040665bc61 257 /* Now look for an expired entry */
Benoit 1:f4040665bc61 258 oldestEntryIndex = -1;
Benoit 1:f4040665bc61 259 oldestEntryAge = -1;
Benoit 1:f4040665bc61 260 for (index = 0; index < ARP_CACHE_MAX_ENTRIES; index++)
Benoit 1:f4040665bc61 261 {
Benoit 1:f4040665bc61 262 entry = arp_CacheTable + index;
Benoit 1:f4040665bc61 263 RTOS_MUTEX_LOCK(entry->mutex);
Benoit 1:f4040665bc61 264
Benoit 1:f4040665bc61 265 if (entry->age > oldestEntryAge)
Benoit 1:f4040665bc61 266 {
Benoit 1:f4040665bc61 267 oldestEntryIndex = index;
Benoit 1:f4040665bc61 268 oldestEntryAge = entry->age;
Benoit 1:f4040665bc61 269 }
Benoit 1:f4040665bc61 270
Benoit 1:f4040665bc61 271 if (entry->status == ARP_Entry_Expired)
Benoit 1:f4040665bc61 272 {
Benoit 1:f4040665bc61 273 break;
Benoit 1:f4040665bc61 274 }
Benoit 1:f4040665bc61 275
Benoit 1:f4040665bc61 276 RTOS_MUTEX_UNLOCK(entry->mutex);
Benoit 1:f4040665bc61 277 entry = NULL;
Benoit 1:f4040665bc61 278 }
Benoit 1:f4040665bc61 279
Benoit 1:f4040665bc61 280 if (entry != NULL) goto Exit; /* An expired entry was found, return it */
Benoit 1:f4040665bc61 281
Benoit 1:f4040665bc61 282 /* Last possibility, return the oldest non static entry */
Benoit 1:f4040665bc61 283 entry = arp_CacheTable + oldestEntryIndex;
Benoit 1:f4040665bc61 284 RTOS_MUTEX_LOCK(entry->mutex);
Benoit 1:f4040665bc61 285
Benoit 1:f4040665bc61 286 Exit:
Benoit 1:f4040665bc61 287 return entry;
Benoit 1:f4040665bc61 288 }
Benoit 1:f4040665bc61 289
Benoit 1:f4040665bc61 290
Benoit 1:f4040665bc61 291 static ARP_CacheEntry_t *GetEntryByIPv4Address(IPv4_Addr_t address)
Benoit 1:f4040665bc61 292 {
Benoit 1:f4040665bc61 293 int32_t index;
Benoit 1:f4040665bc61 294 ARP_CacheEntry_t *entry = NULL;
Benoit 1:f4040665bc61 295
Benoit 1:f4040665bc61 296 for (index = 0; index < ARP_CACHE_MAX_ENTRIES; index++)
Benoit 1:f4040665bc61 297 {
Benoit 1:f4040665bc61 298 entry = arp_CacheTable + index;
Benoit 1:f4040665bc61 299 RTOS_MUTEX_LOCK(entry->mutex);
Benoit 1:f4040665bc61 300
Benoit 1:f4040665bc61 301 if (entry->ipv4Addr.addr == address.addr)
Benoit 1:f4040665bc61 302 {
Benoit 1:f4040665bc61 303 break;
Benoit 1:f4040665bc61 304 }
Benoit 1:f4040665bc61 305 RTOS_MUTEX_UNLOCK(entry->mutex);
Benoit 1:f4040665bc61 306 entry = NULL;
Benoit 1:f4040665bc61 307 }
Benoit 1:f4040665bc61 308
Benoit 1:f4040665bc61 309 return entry;
Benoit 1:f4040665bc61 310 }
Benoit 1:f4040665bc61 311
Benoit 1:f4040665bc61 312
Benoit 1:f4040665bc61 313 int32_t ARP_ResolveIPv4Address(NetIF_t *netIF, IPv4_Addr_t address, Ethernet_Addr_t *ethernetAddr)
Benoit 1:f4040665bc61 314 {
Benoit 1:f4040665bc61 315 int32_t result = -1;
Benoit 1:f4040665bc61 316 Ethernet_Addr_t *hwAddress;
Benoit 1:f4040665bc61 317 ARP_CacheEntry_t *entry;
Benoit 1:f4040665bc61 318
Benoit 1:f4040665bc61 319 DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Resolving %d.%d.%d.%d",
Benoit 1:f4040665bc61 320 address.IP0,
Benoit 1:f4040665bc61 321 address.IP1,
Benoit 1:f4040665bc61 322 address.IP2,
Benoit 1:f4040665bc61 323 address.IP3
Benoit 1:f4040665bc61 324 ));
Benoit 1:f4040665bc61 325
Benoit 1:f4040665bc61 326 /* Look if entry is already available in table */
Benoit 1:f4040665bc61 327 entry = GetEntryByIPv4Address(address);
Benoit 1:f4040665bc61 328 if (entry != NULL) /* Found entry, look its status */
Benoit 1:f4040665bc61 329 {
Benoit 1:f4040665bc61 330 switch(entry->status)
Benoit 1:f4040665bc61 331 {
Benoit 1:f4040665bc61 332 case ARP_Entry_Static:
Benoit 1:f4040665bc61 333 DEBUG_MODULE(DEBUG_LEVEL_VERBOSE0, ("Found static entry"));
Benoit 1:f4040665bc61 334 if (ethernetAddr != NULL) *ethernetAddr = entry->ethernetAddr;
Benoit 1:f4040665bc61 335 RTOS_MUTEX_UNLOCK(entry->mutex);
Benoit 1:f4040665bc61 336 result = 0;
Benoit 1:f4040665bc61 337 break;
Benoit 1:f4040665bc61 338
Benoit 1:f4040665bc61 339 case ARP_Entry_Dynamic:
Benoit 1:f4040665bc61 340 DEBUG_MODULE(DEBUG_LEVEL_VERBOSE0, ("Found dynamic entry"));
Benoit 1:f4040665bc61 341 if (ethernetAddr != NULL) *ethernetAddr = entry->ethernetAddr;
Benoit 1:f4040665bc61 342 entry->age = 0;
Benoit 1:f4040665bc61 343 RTOS_MUTEX_UNLOCK(entry->mutex);
Benoit 1:f4040665bc61 344 result = 0;
Benoit 1:f4040665bc61 345 break;
Benoit 1:f4040665bc61 346
Benoit 1:f4040665bc61 347 case ARP_Entry_Expired:
Benoit 1:f4040665bc61 348 DEBUG_MODULE(DEBUG_LEVEL_VERBOSE0, ("Found expired entry, reactivating it"));
Benoit 1:f4040665bc61 349 if (ethernetAddr != NULL) *ethernetAddr = entry->ethernetAddr;
Benoit 1:f4040665bc61 350 entry->status = ARP_Entry_Dynamic;
Benoit 1:f4040665bc61 351 entry->age = 0;
Benoit 1:f4040665bc61 352 RTOS_MUTEX_UNLOCK(entry->mutex);
Benoit 1:f4040665bc61 353 result = 0;
Benoit 1:f4040665bc61 354 break;
Benoit 1:f4040665bc61 355
Benoit 1:f4040665bc61 356 case ARP_Entry_PendingReply:
Benoit 1:f4040665bc61 357 DEBUG_MODULE(DEBUG_LEVEL_VERBOSE0, ("Found pending entry"));
Benoit 1:f4040665bc61 358 entry->age = 0;
Benoit 1:f4040665bc61 359 RTOS_MUTEX_UNLOCK(entry->mutex);
Benoit 1:f4040665bc61 360 break;
Benoit 1:f4040665bc61 361
Benoit 1:f4040665bc61 362 default:
Benoit 1:f4040665bc61 363 DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Default?!"));
Benoit 1:f4040665bc61 364 break;
Benoit 1:f4040665bc61 365 }
Benoit 1:f4040665bc61 366 }
Benoit 1:f4040665bc61 367
Benoit 1:f4040665bc61 368 if (result == 0) goto Exit; /* Resolution was successfull, exit */
Benoit 1:f4040665bc61 369
Benoit 1:f4040665bc61 370
Benoit 1:f4040665bc61 371 /* Entry not found, send a request */
Benoit 1:f4040665bc61 372 result = -1;
Benoit 1:f4040665bc61 373 DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Sending ARP resolution request for %d.%d.%d.%d",
Benoit 1:f4040665bc61 374 address.IP0,
Benoit 1:f4040665bc61 375 address.IP1,
Benoit 1:f4040665bc61 376 address.IP2,
Benoit 1:f4040665bc61 377 address.IP3
Benoit 1:f4040665bc61 378 ));
Benoit 1:f4040665bc61 379
Benoit 1:f4040665bc61 380 /* Update entry, setting its status to Pending reply */
Benoit 1:f4040665bc61 381 entry = GetReusableEntry();
Benoit 1:f4040665bc61 382 if (entry != NULL)
Benoit 1:f4040665bc61 383 {
Benoit 1:f4040665bc61 384 entry->status = ARP_Entry_PendingReply;
Benoit 1:f4040665bc61 385 entry->ipv4Addr.addr = address.addr;
Benoit 1:f4040665bc61 386 entry->netIF = netIF;
Benoit 1:f4040665bc61 387 entry->age = 0;
Benoit 1:f4040665bc61 388 RTOS_MUTEX_UNLOCK(entry->mutex);
Benoit 1:f4040665bc61 389 }
Benoit 1:f4040665bc61 390 /* Send ARP who-has */
Benoit 1:f4040665bc61 391 hwAddress = (Ethernet_Addr_t *)netIF->driverParameter;
Benoit 1:f4040665bc61 392
Benoit 1:f4040665bc61 393 arp_FullIPv4Packet.ethernetHeader.destination = ethernet_Addr_Broadcast;
Benoit 1:f4040665bc61 394 arp_FullIPv4Packet.ethernetHeader.source = *hwAddress;
Benoit 1:f4040665bc61 395 arp_FullIPv4Packet.ethernetHeader.protocol = htons(ETHERNET_PROTO_ARP);
Benoit 1:f4040665bc61 396
Benoit 1:f4040665bc61 397 arp_FullIPv4Packet.arpHeader.type = htons(ARP_HW_TYPE_ENET);
Benoit 1:f4040665bc61 398 arp_FullIPv4Packet.arpHeader.protocol = htons(ETHERNET_PROTO_IPV4);
Benoit 1:f4040665bc61 399 arp_FullIPv4Packet.arpHeader.operation = htons(ARP_OPERATION_REQUEST);
Benoit 1:f4040665bc61 400 arp_FullIPv4Packet.arpHeader.hardAddrLen = 6;
Benoit 1:f4040665bc61 401 arp_FullIPv4Packet.arpHeader.protoAddrLen = 4;
Benoit 1:f4040665bc61 402
Benoit 1:f4040665bc61 403 arp_FullIPv4Packet.ipv4ARPData.hwSource = *hwAddress;
Benoit 1:f4040665bc61 404 arp_FullIPv4Packet.ipv4ARPData.ipSource = netIF->ipv4Address;
Benoit 1:f4040665bc61 405 arp_FullIPv4Packet.ipv4ARPData.hwDest = ethernet_Addr_Null;
Benoit 1:f4040665bc61 406 arp_FullIPv4Packet.ipv4ARPData.ipDest = address;
Benoit 1:f4040665bc61 407
Benoit 1:f4040665bc61 408 DEBUG_BLOCK(DEBUG_LEVEL_VERBOSE0)
Benoit 1:f4040665bc61 409 {
Benoit 1:f4040665bc61 410 ARP_DumpHeader("Sending ", &arp_FullIPv4Packet.arpHeader);
Benoit 1:f4040665bc61 411 }
Benoit 1:f4040665bc61 412
Benoit 1:f4040665bc61 413 netIF->driver->Write((uint8_t *)&arp_FullIPv4Packet, sizeof(arp_FullIPv4Packet));
Benoit 1:f4040665bc61 414
Benoit 1:f4040665bc61 415 Exit:
Benoit 1:f4040665bc61 416 return result;
Benoit 1:f4040665bc61 417 }
Benoit 1:f4040665bc61 418
Benoit 1:f4040665bc61 419
Benoit 1:f4040665bc61 420 int32_t ARP_AddStaticEntry(NetIF_t *netIF, IPv4_Addr_t address, const Ethernet_Addr_t *ethernetAddr)
Benoit 1:f4040665bc61 421 {
Benoit 1:f4040665bc61 422 int32_t result = 0;
Benoit 1:f4040665bc61 423 ARP_CacheEntry_t *entry;
Benoit 1:f4040665bc61 424
Benoit 1:f4040665bc61 425 entry = GetReusableEntry();
Benoit 1:f4040665bc61 426 if (entry == NULL)
Benoit 1:f4040665bc61 427 {
Benoit 1:f4040665bc61 428 result = -1;
Benoit 1:f4040665bc61 429 goto Exit;
Benoit 1:f4040665bc61 430 }
Benoit 1:f4040665bc61 431 entry->netIF = netIF;
Benoit 1:f4040665bc61 432 entry->status = ARP_Entry_Static;
Benoit 1:f4040665bc61 433 entry->ipv4Addr.addr = address.addr;
Benoit 1:f4040665bc61 434 entry->ethernetAddr = *ethernetAddr;
Benoit 1:f4040665bc61 435 entry->age = 0;
Benoit 1:f4040665bc61 436 RTOS_MUTEX_UNLOCK(entry->mutex);
Benoit 1:f4040665bc61 437
Benoit 1:f4040665bc61 438 Exit:
Benoit 1:f4040665bc61 439 return result;
Benoit 1:f4040665bc61 440 }
Benoit 1:f4040665bc61 441
Benoit 1:f4040665bc61 442
Benoit 1:f4040665bc61 443 int32_t ARP_RemoveEntry(const NetIF_t *netIF, IPv4_Addr_t address)
Benoit 1:f4040665bc61 444 {
Benoit 1:f4040665bc61 445 int32_t result = 0;
Benoit 1:f4040665bc61 446
Benoit 1:f4040665bc61 447
Benoit 1:f4040665bc61 448
Benoit 1:f4040665bc61 449 return result;
Benoit 1:f4040665bc61 450 }
Benoit 1:f4040665bc61 451
Benoit 1:f4040665bc61 452
Benoit 1:f4040665bc61 453 void ARP_FlushCache(Bool_t flushStaticEntries)
Benoit 1:f4040665bc61 454 {
Benoit 1:f4040665bc61 455 int32_t index;
Benoit 1:f4040665bc61 456 ARP_CacheEntry_t *entry;
Benoit 1:f4040665bc61 457
Benoit 1:f4040665bc61 458 for (index = 0; index < ARP_CACHE_MAX_ENTRIES; index++)
Benoit 1:f4040665bc61 459 {
Benoit 1:f4040665bc61 460 entry = arp_CacheTable + index;
Benoit 1:f4040665bc61 461 RTOS_MUTEX_LOCK(entry->mutex);
Benoit 1:f4040665bc61 462 if ((entry->status == ARP_Entry_Static) && (!flushStaticEntries))
Benoit 1:f4040665bc61 463 {
Benoit 1:f4040665bc61 464 RTOS_MUTEX_UNLOCK(entry->mutex);
Benoit 1:f4040665bc61 465 continue;
Benoit 1:f4040665bc61 466 }
Benoit 1:f4040665bc61 467 entry->status = ARP_Entry_Free;
Benoit 1:f4040665bc61 468 entry->ipv4Addr = ipv4_Addr_Any;
Benoit 1:f4040665bc61 469 entry->ethernetAddr = ethernet_Addr_Null;
Benoit 1:f4040665bc61 470 entry->age = 0;
Benoit 1:f4040665bc61 471 RTOS_MUTEX_UNLOCK(entry->mutex);
Benoit 1:f4040665bc61 472 }
Benoit 1:f4040665bc61 473 }
Benoit 1:f4040665bc61 474
Benoit 1:f4040665bc61 475
Benoit 1:f4040665bc61 476 void ARP_DisplayCache(void)
Benoit 1:f4040665bc61 477 {
Benoit 1:f4040665bc61 478 int32_t index;
Benoit 1:f4040665bc61 479 ARP_CacheEntry_t *entry = NULL;
Benoit 1:f4040665bc61 480
Benoit 1:f4040665bc61 481 DEBUG_RAW(("ARP cache"));
Benoit 1:f4040665bc61 482 DEBUG_RAW(("index dev MAC address type age IPv4 address"));
Benoit 1:f4040665bc61 483 DEBUG_RAW(("----------------------------------------------------------"));
Benoit 1:f4040665bc61 484 /* en0 00:11:22:33:44:55 dyn 10 163.157.128.131 */
Benoit 1:f4040665bc61 485 for (index = 0; index < ARP_CACHE_MAX_ENTRIES; index++)
Benoit 1:f4040665bc61 486 {
Benoit 1:f4040665bc61 487 entry = arp_CacheTable + index;
Benoit 1:f4040665bc61 488
Benoit 1:f4040665bc61 489 DEBUG_RAW(("%2d %s%c %02x:%02x:%02x:%02x:%02x:%02x %8s %4d %d.%d.%d.%d",
Benoit 1:f4040665bc61 490 index,
Benoit 1:f4040665bc61 491 entry->status != ARP_Entry_Free ? entry->netIF->name : "--",
Benoit 1:f4040665bc61 492 entry->status != ARP_Entry_Free ? entry->netIF->index + '0' : '-',
Benoit 1:f4040665bc61 493 entry->ethernetAddr.MA0,
Benoit 1:f4040665bc61 494 entry->ethernetAddr.MA1,
Benoit 1:f4040665bc61 495 entry->ethernetAddr.MA2,
Benoit 1:f4040665bc61 496 entry->ethernetAddr.MA3,
Benoit 1:f4040665bc61 497 entry->ethernetAddr.MA4,
Benoit 1:f4040665bc61 498 entry->ethernetAddr.MA5,
Benoit 1:f4040665bc61 499
Benoit 1:f4040665bc61 500 arpEntryStatusText[entry->status],
Benoit 1:f4040665bc61 501 entry->age,
Benoit 1:f4040665bc61 502
Benoit 1:f4040665bc61 503 entry->ipv4Addr.IP0,
Benoit 1:f4040665bc61 504 entry->ipv4Addr.IP1,
Benoit 1:f4040665bc61 505 entry->ipv4Addr.IP2,
Benoit 1:f4040665bc61 506 entry->ipv4Addr.IP3
Benoit 1:f4040665bc61 507 ));
Benoit 1:f4040665bc61 508 }
Benoit 1:f4040665bc61 509 }
Benoit 1:f4040665bc61 510
Benoit 1:f4040665bc61 511 void ARP_DumpHeader(const char *prefix, ARP_Header_t *arpHeader)
Benoit 1:f4040665bc61 512 {
Benoit 1:f4040665bc61 513 ARP_IPv4Data_t *ipv4ARP = NULL;
Benoit 1:f4040665bc61 514
Benoit 1:f4040665bc61 515 if (arpHeader->protocol == htons(ETHERNET_PROTO_IPV4))
Benoit 1:f4040665bc61 516 {
Benoit 1:f4040665bc61 517 ipv4ARP = (ARP_IPv4Data_t *)(arpHeader + 1);
Benoit 1:f4040665bc61 518
Benoit 1:f4040665bc61 519 switch(ntohs(arpHeader->operation))
Benoit 1:f4040665bc61 520 {
Benoit 1:f4040665bc61 521 case ARP_OPERATION_REQUEST:
Benoit 1:f4040665bc61 522 DEBUG_RAW(("%sARP who-has %d.%d.%d.%d tell %02x:%02x:%02x:%02x:%02x:%02x",
Benoit 1:f4040665bc61 523 prefix != NULL ? prefix : "",
Benoit 1:f4040665bc61 524
Benoit 1:f4040665bc61 525 ipv4ARP->ipDest.IP0,
Benoit 1:f4040665bc61 526 ipv4ARP->ipDest.IP1,
Benoit 1:f4040665bc61 527 ipv4ARP->ipDest.IP2,
Benoit 1:f4040665bc61 528 ipv4ARP->ipDest.IP3,
Benoit 1:f4040665bc61 529
Benoit 1:f4040665bc61 530 ipv4ARP->hwSource.MA0,
Benoit 1:f4040665bc61 531 ipv4ARP->hwSource.MA1,
Benoit 1:f4040665bc61 532 ipv4ARP->hwSource.MA2,
Benoit 1:f4040665bc61 533 ipv4ARP->hwSource.MA3,
Benoit 1:f4040665bc61 534 ipv4ARP->hwSource.MA4,
Benoit 1:f4040665bc61 535 ipv4ARP->hwSource.MA5
Benoit 1:f4040665bc61 536 ));
Benoit 1:f4040665bc61 537 break;
Benoit 1:f4040665bc61 538
Benoit 1:f4040665bc61 539 case ARP_OPERATION_REPLY:
Benoit 1:f4040665bc61 540 DEBUG_RAW(("%sARP %d.%d.%d.%d is-at %02x:%02x:%02x:%02x:%02x:%02x",
Benoit 1:f4040665bc61 541 prefix != NULL ? prefix : "",
Benoit 1:f4040665bc61 542
Benoit 1:f4040665bc61 543 ipv4ARP->ipSource.IP0,
Benoit 1:f4040665bc61 544 ipv4ARP->ipSource.IP1,
Benoit 1:f4040665bc61 545 ipv4ARP->ipSource.IP2,
Benoit 1:f4040665bc61 546 ipv4ARP->ipSource.IP3,
Benoit 1:f4040665bc61 547
Benoit 1:f4040665bc61 548 ipv4ARP->hwSource.MA0,
Benoit 1:f4040665bc61 549 ipv4ARP->hwSource.MA1,
Benoit 1:f4040665bc61 550 ipv4ARP->hwSource.MA2,
Benoit 1:f4040665bc61 551 ipv4ARP->hwSource.MA3,
Benoit 1:f4040665bc61 552 ipv4ARP->hwSource.MA4,
Benoit 1:f4040665bc61 553 ipv4ARP->hwSource.MA5
Benoit 1:f4040665bc61 554 ));
Benoit 1:f4040665bc61 555 break;
Benoit 1:f4040665bc61 556
Benoit 1:f4040665bc61 557 default:
Benoit 1:f4040665bc61 558 break;
Benoit 1:f4040665bc61 559 }
Benoit 1:f4040665bc61 560 }
Benoit 1:f4040665bc61 561 else
Benoit 1:f4040665bc61 562 {
Benoit 1:f4040665bc61 563 DEBUG_RAW(("%sARP: unsupported protocol %d",
Benoit 1:f4040665bc61 564 prefix != NULL ? prefix : "",
Benoit 1:f4040665bc61 565 arpHeader->protocol
Benoit 1:f4040665bc61 566 ));
Benoit 1:f4040665bc61 567 }
Benoit 1:f4040665bc61 568 }