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 26 09:56:31 2011 +0000
Revision:
7:8e12f7357b9f
Parent:
5:3cd83fcb1467
Added IPv4 global broadcast address to processed frames inside IPv4 layer.

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