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
eth/ar6.cpp
- Committer:
- andrewboyson
- Date:
- 2017-10-31
- Revision:
- 48:952dddb74b8b
- Child:
- 49:1a6336f2b3f9
File content as of revision 48:952dddb74b8b:
#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);
}
}