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:
Tue Oct 31 21:25:09 2017 +0000
Revision:
48:952dddb74b8b
Child:
49:1a6336f2b3f9
Split address resolution into AR4 and AR6. Corrected issue clearing a AR6 record.

Who changed what in which revision?

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