A stack which works with or without an Mbed os library. Provides IPv4 or IPv6 with a full 1500 byte buffer.

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Sat Dec 16 14:39:50 2017 +0000
Revision:
60:1d8c7a1e7483
Obtained MAC directly from __semihost call

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 60:1d8c7a1e7483 1 #include "mbed.h"
andrewboyson 60:1d8c7a1e7483 2 #include "log.h"
andrewboyson 60:1d8c7a1e7483 3 #include "clock.h"
andrewboyson 60:1d8c7a1e7483 4 #include "net.h"
andrewboyson 60:1d8c7a1e7483 5 #include "mac.h"
andrewboyson 60:1d8c7a1e7483 6 #include "ip4addr.h"
andrewboyson 60:1d8c7a1e7483 7 #include "arp.h"
andrewboyson 60:1d8c7a1e7483 8 #include "http.h"
andrewboyson 60:1d8c7a1e7483 9
andrewboyson 60:1d8c7a1e7483 10 bool Ar4Trace = false;
andrewboyson 60:1d8c7a1e7483 11
andrewboyson 60:1d8c7a1e7483 12 #define CACHE_TIMEOUT 3600
andrewboyson 60:1d8c7a1e7483 13 #define FREEZE_TIMEOUT 1800
andrewboyson 60:1d8c7a1e7483 14 #define REPLY_TIMEOUT 2
andrewboyson 60:1d8c7a1e7483 15 #define SEND_ATTEMPTS 3
andrewboyson 60:1d8c7a1e7483 16 #define RECORDS_COUNT 20
andrewboyson 60:1d8c7a1e7483 17
andrewboyson 60:1d8c7a1e7483 18 #define STATE_EMPTY 0
andrewboyson 60:1d8c7a1e7483 19 #define STATE_WANT 1
andrewboyson 60:1d8c7a1e7483 20 #define STATE_SENT 2
andrewboyson 60:1d8c7a1e7483 21 #define STATE_VALID 3
andrewboyson 60:1d8c7a1e7483 22
andrewboyson 60:1d8c7a1e7483 23 static uint32_t elapsed = 0;
andrewboyson 60:1d8c7a1e7483 24 struct record
andrewboyson 60:1d8c7a1e7483 25 {
andrewboyson 60:1d8c7a1e7483 26 uint32_t elapsed;
andrewboyson 60:1d8c7a1e7483 27 uint32_t ip;
andrewboyson 60:1d8c7a1e7483 28 uint8_t state;
andrewboyson 60:1d8c7a1e7483 29 uint8_t tries;
andrewboyson 60:1d8c7a1e7483 30 char mac[6];
andrewboyson 60:1d8c7a1e7483 31 };
andrewboyson 60:1d8c7a1e7483 32 static struct record records[RECORDS_COUNT];
andrewboyson 60:1d8c7a1e7483 33 static int getExistingIp(uint32_t ip)
andrewboyson 60:1d8c7a1e7483 34 {
andrewboyson 60:1d8c7a1e7483 35 for (int i = 0; i < RECORDS_COUNT; i++)
andrewboyson 60:1d8c7a1e7483 36 {
andrewboyson 60:1d8c7a1e7483 37 if (records[i].state && records[i].ip == ip) return i;
andrewboyson 60:1d8c7a1e7483 38 }
andrewboyson 60:1d8c7a1e7483 39 return -1;
andrewboyson 60:1d8c7a1e7483 40 }
andrewboyson 60:1d8c7a1e7483 41 static int getOldest()
andrewboyson 60:1d8c7a1e7483 42 {
andrewboyson 60:1d8c7a1e7483 43 int iN = 0;
andrewboyson 60:1d8c7a1e7483 44 uint32_t tN = 0xFFFFFFFF;
andrewboyson 60:1d8c7a1e7483 45 for (int i = 0; i < RECORDS_COUNT; i++)
andrewboyson 60:1d8c7a1e7483 46 {
andrewboyson 60:1d8c7a1e7483 47 if (!records[i].state) return i; //Found an empty slot so just return it
andrewboyson 60:1d8c7a1e7483 48 if (records[i].elapsed < tN)
andrewboyson 60:1d8c7a1e7483 49 {
andrewboyson 60:1d8c7a1e7483 50 tN = records[i].elapsed;
andrewboyson 60:1d8c7a1e7483 51 iN = i;
andrewboyson 60:1d8c7a1e7483 52 }
andrewboyson 60:1d8c7a1e7483 53 }
andrewboyson 60:1d8c7a1e7483 54 return iN; //Otherwise return the oldest
andrewboyson 60:1d8c7a1e7483 55 }
andrewboyson 60:1d8c7a1e7483 56 void Ar4MakeRequestForMacFromIp(uint32_t ip)
andrewboyson 60:1d8c7a1e7483 57 {
andrewboyson 60:1d8c7a1e7483 58 //Don't treat non ips
andrewboyson 60:1d8c7a1e7483 59 if (!ip) return;
andrewboyson 60:1d8c7a1e7483 60 int i;
andrewboyson 60:1d8c7a1e7483 61
andrewboyson 60:1d8c7a1e7483 62 //If a record already exists then request an update
andrewboyson 60:1d8c7a1e7483 63 i = getExistingIp(ip);
andrewboyson 60:1d8c7a1e7483 64 if (i > -1)
andrewboyson 60:1d8c7a1e7483 65 {
andrewboyson 60:1d8c7a1e7483 66 if (elapsed < records[i].elapsed + FREEZE_TIMEOUT) return;
andrewboyson 60:1d8c7a1e7483 67 if (Ar4Trace)
andrewboyson 60:1d8c7a1e7483 68 {
andrewboyson 60:1d8c7a1e7483 69 LogTimeF("AR4 Updated request for MAC of ");
andrewboyson 60:1d8c7a1e7483 70 Ip4AddressLog(ip);
andrewboyson 60:1d8c7a1e7483 71 Log("\r\n");
andrewboyson 60:1d8c7a1e7483 72 }
andrewboyson 60:1d8c7a1e7483 73 records[i].state = STATE_WANT;
andrewboyson 60:1d8c7a1e7483 74 records[i].tries = 0;
andrewboyson 60:1d8c7a1e7483 75 records[i].elapsed = elapsed;
andrewboyson 60:1d8c7a1e7483 76 return;
andrewboyson 60:1d8c7a1e7483 77 }
andrewboyson 60:1d8c7a1e7483 78
andrewboyson 60:1d8c7a1e7483 79 //If a record does not exist then find the first empty slot and add the IP and date
andrewboyson 60:1d8c7a1e7483 80 if (Ar4Trace)
andrewboyson 60:1d8c7a1e7483 81 {
andrewboyson 60:1d8c7a1e7483 82 LogTimeF("AR4 Made request for MAC of ");
andrewboyson 60:1d8c7a1e7483 83 Ip4AddressLog(ip);
andrewboyson 60:1d8c7a1e7483 84 Log("\r\n");
andrewboyson 60:1d8c7a1e7483 85 }
andrewboyson 60:1d8c7a1e7483 86 i = getOldest();
andrewboyson 60:1d8c7a1e7483 87 records[i].ip = ip;
andrewboyson 60:1d8c7a1e7483 88 records[i].state = STATE_WANT;
andrewboyson 60:1d8c7a1e7483 89 records[i].tries = 0;
andrewboyson 60:1d8c7a1e7483 90 records[i].elapsed = elapsed;
andrewboyson 60:1d8c7a1e7483 91 MacClear(records[i].mac);
andrewboyson 60:1d8c7a1e7483 92 }
andrewboyson 60:1d8c7a1e7483 93 void Ar4AddIpRecord(void (*traceback)(void), char* mac, uint32_t ip)
andrewboyson 60:1d8c7a1e7483 94 {
andrewboyson 60:1d8c7a1e7483 95 //Don't treat non ips
andrewboyson 60:1d8c7a1e7483 96 if (!ip)
andrewboyson 60:1d8c7a1e7483 97 {
andrewboyson 60:1d8c7a1e7483 98 if (Ar4Trace)
andrewboyson 60:1d8c7a1e7483 99 {
andrewboyson 60:1d8c7a1e7483 100 LogTime("Ar4AddIpRecord had blank ip\r\n");
andrewboyson 60:1d8c7a1e7483 101 if (NetTraceStack) traceback();
andrewboyson 60:1d8c7a1e7483 102 }
andrewboyson 60:1d8c7a1e7483 103 return;
andrewboyson 60:1d8c7a1e7483 104 }
andrewboyson 60:1d8c7a1e7483 105 if (MacIsEmpty(mac))
andrewboyson 60:1d8c7a1e7483 106 {
andrewboyson 60:1d8c7a1e7483 107 if (Ar4Trace)
andrewboyson 60:1d8c7a1e7483 108 {
andrewboyson 60:1d8c7a1e7483 109 LogTime("Ar4AddIpRecord had blank mac\r\n");
andrewboyson 60:1d8c7a1e7483 110 if (NetTraceStack) traceback();
andrewboyson 60:1d8c7a1e7483 111 }
andrewboyson 60:1d8c7a1e7483 112 return;
andrewboyson 60:1d8c7a1e7483 113 }
andrewboyson 60:1d8c7a1e7483 114 int i;
andrewboyson 60:1d8c7a1e7483 115
andrewboyson 60:1d8c7a1e7483 116 //See if any record corresponds to the IP and, if so, update the MAC and time
andrewboyson 60:1d8c7a1e7483 117 i = getExistingIp(ip);
andrewboyson 60:1d8c7a1e7483 118 if (i > -1)
andrewboyson 60:1d8c7a1e7483 119 {
andrewboyson 60:1d8c7a1e7483 120 records[i].elapsed = elapsed;
andrewboyson 60:1d8c7a1e7483 121 records[i].state = STATE_VALID;
andrewboyson 60:1d8c7a1e7483 122 MacCopy(records[i].mac, mac);
andrewboyson 60:1d8c7a1e7483 123 return;
andrewboyson 60:1d8c7a1e7483 124 }
andrewboyson 60:1d8c7a1e7483 125
andrewboyson 60:1d8c7a1e7483 126 //Otherwise find the first empty slot and add the IP, MAC, and date
andrewboyson 60:1d8c7a1e7483 127 i = getOldest();
andrewboyson 60:1d8c7a1e7483 128 records[i].ip = ip;
andrewboyson 60:1d8c7a1e7483 129 records[i].elapsed = elapsed;
andrewboyson 60:1d8c7a1e7483 130 records[i].state = STATE_VALID;
andrewboyson 60:1d8c7a1e7483 131 MacCopy(records[i].mac, mac);
andrewboyson 60:1d8c7a1e7483 132 return;
andrewboyson 60:1d8c7a1e7483 133 }
andrewboyson 60:1d8c7a1e7483 134 void Ar4IpToMac(uint32_t ip, char* mac)
andrewboyson 60:1d8c7a1e7483 135 {
andrewboyson 60:1d8c7a1e7483 136 for (int i = 0; i < RECORDS_COUNT; i++)
andrewboyson 60:1d8c7a1e7483 137 {
andrewboyson 60:1d8c7a1e7483 138 if (records[i].state == STATE_VALID && records[i].ip == ip)
andrewboyson 60:1d8c7a1e7483 139 {
andrewboyson 60:1d8c7a1e7483 140 MacCopy(mac, records[i].mac);
andrewboyson 60:1d8c7a1e7483 141 return;
andrewboyson 60:1d8c7a1e7483 142 }
andrewboyson 60:1d8c7a1e7483 143 }
andrewboyson 60:1d8c7a1e7483 144 MacClear(mac);
andrewboyson 60:1d8c7a1e7483 145 }
andrewboyson 60:1d8c7a1e7483 146 void Ar4SendHttp()
andrewboyson 60:1d8c7a1e7483 147 {
andrewboyson 60:1d8c7a1e7483 148 for (int i = 0; i < RECORDS_COUNT; i++)
andrewboyson 60:1d8c7a1e7483 149 {
andrewboyson 60:1d8c7a1e7483 150 if (records[i].state)
andrewboyson 60:1d8c7a1e7483 151 {
andrewboyson 60:1d8c7a1e7483 152 HttpAddF("%4u ", (elapsed - records[i].elapsed) / 60);
andrewboyson 60:1d8c7a1e7483 153
andrewboyson 60:1d8c7a1e7483 154 int ipLen = Ip4AddressHttp(records[i].ip);
andrewboyson 60:1d8c7a1e7483 155 HttpFillChar(' ', 40 - ipLen);
andrewboyson 60:1d8c7a1e7483 156
andrewboyson 60:1d8c7a1e7483 157 MacHttp(records[i].mac);
andrewboyson 60:1d8c7a1e7483 158
andrewboyson 60:1d8c7a1e7483 159 HttpAddChar('\r');
andrewboyson 60:1d8c7a1e7483 160 HttpAddChar('\n');
andrewboyson 60:1d8c7a1e7483 161 }
andrewboyson 60:1d8c7a1e7483 162 }
andrewboyson 60:1d8c7a1e7483 163 }
andrewboyson 60:1d8c7a1e7483 164 static void clear(struct record* pr)
andrewboyson 60:1d8c7a1e7483 165 {
andrewboyson 60:1d8c7a1e7483 166 pr->state = STATE_EMPTY;
andrewboyson 60:1d8c7a1e7483 167 }
andrewboyson 60:1d8c7a1e7483 168 static void clearCache(struct record* pr)
andrewboyson 60:1d8c7a1e7483 169 {
andrewboyson 60:1d8c7a1e7483 170 if (elapsed > pr->elapsed + CACHE_TIMEOUT) clear(pr);
andrewboyson 60:1d8c7a1e7483 171 }
andrewboyson 60:1d8c7a1e7483 172 static void retry(struct record* pr)
andrewboyson 60:1d8c7a1e7483 173 {
andrewboyson 60:1d8c7a1e7483 174 if (pr->state == STATE_SENT && elapsed > pr->elapsed + REPLY_TIMEOUT)
andrewboyson 60:1d8c7a1e7483 175 {
andrewboyson 60:1d8c7a1e7483 176 if (pr->tries < SEND_ATTEMPTS)
andrewboyson 60:1d8c7a1e7483 177 {
andrewboyson 60:1d8c7a1e7483 178 pr->state = STATE_WANT;
andrewboyson 60:1d8c7a1e7483 179 pr->elapsed = elapsed;
andrewboyson 60:1d8c7a1e7483 180 pr->tries++;
andrewboyson 60:1d8c7a1e7483 181 }
andrewboyson 60:1d8c7a1e7483 182 else
andrewboyson 60:1d8c7a1e7483 183 {
andrewboyson 60:1d8c7a1e7483 184 clear(pr);
andrewboyson 60:1d8c7a1e7483 185 }
andrewboyson 60:1d8c7a1e7483 186 }
andrewboyson 60:1d8c7a1e7483 187 }
andrewboyson 60:1d8c7a1e7483 188 static void sendRequest(struct record* pr)
andrewboyson 60:1d8c7a1e7483 189 {
andrewboyson 60:1d8c7a1e7483 190 if (!ArpResolveRequestFlag)
andrewboyson 60:1d8c7a1e7483 191 {
andrewboyson 60:1d8c7a1e7483 192 if (pr->state == STATE_WANT)
andrewboyson 60:1d8c7a1e7483 193 {
andrewboyson 60:1d8c7a1e7483 194 if (Ar4Trace)
andrewboyson 60:1d8c7a1e7483 195 {
andrewboyson 60:1d8c7a1e7483 196 LogTimeF("AR4 Send request for MAC from IP4 ");
andrewboyson 60:1d8c7a1e7483 197 Ip4AddressLog(pr->ip);
andrewboyson 60:1d8c7a1e7483 198 Log("\r\n");
andrewboyson 60:1d8c7a1e7483 199 }
andrewboyson 60:1d8c7a1e7483 200 ArpAddressToResolve = pr->ip;
andrewboyson 60:1d8c7a1e7483 201 ArpResolveRequestFlag = true;
andrewboyson 60:1d8c7a1e7483 202 pr->state = STATE_SENT;
andrewboyson 60:1d8c7a1e7483 203 pr->elapsed = elapsed;
andrewboyson 60:1d8c7a1e7483 204 return;
andrewboyson 60:1d8c7a1e7483 205 }
andrewboyson 60:1d8c7a1e7483 206 }
andrewboyson 60:1d8c7a1e7483 207 }
andrewboyson 60:1d8c7a1e7483 208 void Ar4Main()
andrewboyson 60:1d8c7a1e7483 209 {
andrewboyson 60:1d8c7a1e7483 210 static int i = -1;
andrewboyson 60:1d8c7a1e7483 211 i++;
andrewboyson 60:1d8c7a1e7483 212 if (i >= RECORDS_COUNT) i = 0;
andrewboyson 60:1d8c7a1e7483 213
andrewboyson 60:1d8c7a1e7483 214 struct record* pr = &records[i];
andrewboyson 60:1d8c7a1e7483 215
andrewboyson 60:1d8c7a1e7483 216 clearCache (pr);
andrewboyson 60:1d8c7a1e7483 217 retry (pr);
andrewboyson 60:1d8c7a1e7483 218 sendRequest(pr);
andrewboyson 60:1d8c7a1e7483 219
andrewboyson 60:1d8c7a1e7483 220 if (ClockTicked) elapsed++;
andrewboyson 60:1d8c7a1e7483 221 }
andrewboyson 60:1d8c7a1e7483 222 void Ar4Init()
andrewboyson 60:1d8c7a1e7483 223 {
andrewboyson 60:1d8c7a1e7483 224 for (int i = 0; i < RECORDS_COUNT; i++)
andrewboyson 60:1d8c7a1e7483 225 {
andrewboyson 60:1d8c7a1e7483 226 struct record* pr = &records[i];
andrewboyson 60:1d8c7a1e7483 227 clear(pr);
andrewboyson 60:1d8c7a1e7483 228 }
andrewboyson 60:1d8c7a1e7483 229 }