Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: oldheating gps motorhome heating
Diff: eth/ar6.cpp
- Revision:
- 48:952dddb74b8b
- Child:
- 49:1a6336f2b3f9
diff -r 73af5c0b0dc2 -r 952dddb74b8b eth/ar6.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/eth/ar6.cpp Tue Oct 31 21:25:09 2017 +0000
@@ -0,0 +1,233 @@
+#include "mbed.h"
+#include "log.h"
+#include "clock.h"
+#include "net.h"
+#include "mac.h"
+#include "ip6.h"
+#include "ns.h"
+#include "http-reply.h"
+
+bool Ar6Trace = false;
+
+#define CACHE_TIMEOUT 3600
+#define FREEZE_TIMEOUT 1800
+#define REPLY_TIMEOUT 2
+#define SEND_ATTEMPTS 3
+#define RECORDS_COUNT 20
+
+#define STATE_NONE 0
+#define STATE_WANT_MAC_FROM_IP 1
+#define STATE_SENT_MAC_FROM_IP 2
+#define STATE_VALID 3
+
+static uint32_t elapsed = 0;
+struct record
+{
+ uint32_t elapsed;
+ char ip[16];
+ uint8_t state;
+ uint8_t tries;
+ char mac[6];
+};
+static struct record records[RECORDS_COUNT];
+static int getExistingIp(char* ip)
+{
+ for (int i = 0; i < RECORDS_COUNT; i++)
+ {
+ if (records[i].state && Ip6IsSame(records[i].ip, ip)) return i;
+ }
+ return -1;
+}
+static int getOldest()
+{
+ int iN = 0;
+ uint32_t tN = 0xFFFFFFFF;
+ for (int i = 0; i < RECORDS_COUNT; i++)
+ {
+ if (!records[i].state) return i; //Found an empty slot so just return it
+ if (records[i].elapsed < tN)
+ {
+ tN = records[i].elapsed;
+ iN = i;
+ }
+ }
+ return iN; //Otherwise return the oldest
+}
+void Ar6MakeRequestForMacFromIp(char* ip)
+{
+ //Don't treat non ips
+ if (!ip[0]) return;
+ int i;
+
+ //If a record already exists then request an update
+ i = getExistingIp(ip);
+ if (i > -1)
+ {
+ if (elapsed < records[i].elapsed + FREEZE_TIMEOUT) return;
+ if (Ar6Trace)
+ {
+ LogTime("AR6 Updated request for MAC of ");
+ Ip6AddressLog(ip);
+ Log("\r\n");
+ }
+ records[i].state = STATE_WANT_MAC_FROM_IP;
+ records[i].tries = 0;
+ records[i].elapsed = elapsed;
+ return;
+ }
+
+ //If a record does not exist then find the first empty slot and add the IP and date
+ if (Ar6Trace)
+ {
+ LogTime("AR6 Made request for MAC of ");
+ Ip6AddressLog(ip);
+ Log("\r\n");
+ }
+ i = getOldest();
+ Ip6Copy(records[i].ip, ip);
+ records[i].state = STATE_WANT_MAC_FROM_IP;
+ records[i].tries = 0;
+ records[i].elapsed = elapsed;
+ MacClear(records[i].mac);
+}
+void Ar6AddIpRecord(void (*traceback)(void), char* mac, char* ip)
+{
+ //Don't treat non ips
+ if (!ip[0])
+ {
+ if (Ar6Trace)
+ {
+ LogTime("Ar6AddIpRecord had blank ip\r\n");
+ if (NetTraceStack) traceback();
+ }
+ return;
+ }
+ if (MacIsEmpty(mac))
+ {
+ if (Ar6Trace)
+ {
+ LogTime("Ar6AddIpRecord had blank mac\r\n");
+ if (NetTraceStack) traceback();
+ }
+ return;
+ }
+ int i;
+
+ //See if any record corresponds to the IP and, if so, update the MAC and time
+ i = getExistingIp(ip);
+ if (i > -1)
+ {
+ records[i].elapsed = elapsed;
+ records[i].state = STATE_VALID;
+ MacCopy(records[i].mac, mac);
+ return;
+ }
+
+ //Otherwise find the first empty slot and add the MAC, IP and date
+ i = getOldest();
+ MacCopy(records[i].mac, mac);
+ Ip6Copy(records[i].ip, ip);
+ records[i].elapsed = elapsed;
+ records[i].state = STATE_VALID;
+ return;
+}
+void Ar6IpToMac(char* ip, char* mac)
+{
+ for (int i = 0; i < RECORDS_COUNT; i++)
+ {
+ if (records[i].state == STATE_VALID && Ip6IsSame(records[i].ip, ip))
+ {
+ MacCopy(mac, records[i].mac);
+ return;
+ }
+ }
+ MacClear(mac);
+}
+void Ar6SendHttp()
+{
+ for (int i = 0; i < RECORDS_COUNT; i++)
+ {
+ if (records[i].ip[0])
+ {
+ HttpReplyAddF("%4u ", (elapsed - records[i].elapsed) / 60);
+
+ int ipLen = Ip6AddressHttp(records[i].ip);
+ HttpReplyFillChar(' ', 40 - ipLen);
+
+ MacHttp(records[i].mac);
+
+ HttpReplyAddChar('\r');
+ HttpReplyAddChar('\n');
+ }
+ }
+}
+static void clear(struct record* pr)
+{
+ pr->state = STATE_NONE;
+ pr->tries = 0;
+ pr->ip[0] = 0;
+ MacClear(pr->mac);
+}
+static void clearCache(struct record* pr)
+{
+ if (elapsed > pr->elapsed + CACHE_TIMEOUT) clear(pr);
+}
+static void retry(struct record* pr)
+{
+ if (pr->state == STATE_SENT_MAC_FROM_IP && elapsed > pr->elapsed + REPLY_TIMEOUT)
+ {
+ if (pr->tries < SEND_ATTEMPTS)
+ {
+ pr->state = STATE_WANT_MAC_FROM_IP;
+ pr->elapsed = elapsed;
+ pr->tries++;
+ }
+ else
+ {
+ clear(pr);
+ }
+ }
+}
+static void sendRequest(struct record* pr)
+{
+ if (!NsResolveRequestFlag)
+ {
+ if (pr->state == STATE_WANT_MAC_FROM_IP)
+ {
+ if (Ar6Trace)
+ {
+ LogTime("AR6 Send request for MAC from IP6 ");
+ Ip6AddressLog(pr->ip);
+ Log("\r\n");
+ }
+ Ip6Copy(NsAddressToResolve, pr->ip);
+ NsResolveRequestFlag = true;
+ pr->state = STATE_SENT_MAC_FROM_IP;
+ pr->elapsed = elapsed;
+ return;
+ }
+ }
+}
+void Ar6Main()
+{
+ static int i = -1;
+ i++;
+ if (i >= RECORDS_COUNT) i = 0;
+
+ struct record* pr = &records[i];
+
+ clearCache (pr);
+ retry (pr);
+ sendRequest(pr);
+
+ if (ClockTicked) elapsed++;
+}
+void Ar6Init()
+{
+ for (int i = 0; i < RECORDS_COUNT; i++)
+ {
+
+ struct record* pr = &records[i];
+ clear(pr);
+ }
+}