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
eth/ar4.cpp@50:492f2d2954e4, 2017-11-03 (annotated)
- Committer:
- andrewboyson
- Date:
- Fri Nov 03 16:19:15 2017 +0000
- Revision:
- 50:492f2d2954e4
- Parent:
- 49:1a6336f2b3f9
- Child:
- 51:007bd938f2c3
Split name resolution into NR4 and NR6
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
andrewboyson | 49:1a6336f2b3f9 | 1 | #include "mbed.h" |
andrewboyson | 49:1a6336f2b3f9 | 2 | #include "log.h" |
andrewboyson | 49:1a6336f2b3f9 | 3 | #include "clock.h" |
andrewboyson | 49:1a6336f2b3f9 | 4 | #include "net.h" |
andrewboyson | 49:1a6336f2b3f9 | 5 | #include "mac.h" |
andrewboyson | 49:1a6336f2b3f9 | 6 | #include "ip4addr.h" |
andrewboyson | 49:1a6336f2b3f9 | 7 | #include "arp.h" |
andrewboyson | 49:1a6336f2b3f9 | 8 | #include "http.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 | 50:492f2d2954e4 | 18 | #define STATE_EMPTY 0 |
andrewboyson | 50:492f2d2954e4 | 19 | #define STATE_WANT 1 |
andrewboyson | 50:492f2d2954e4 | 20 | #define STATE_SENT 2 |
andrewboyson | 50:492f2d2954e4 | 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 | 50:492f2d2954e4 | 73 | records[i].state = STATE_WANT; |
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 | 50:492f2d2954e4 | 88 | records[i].state = STATE_WANT; |
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 | 50:492f2d2954e4 | 166 | pr->state = STATE_EMPTY; |
andrewboyson | 48:952dddb74b8b | 167 | } |
andrewboyson | 48:952dddb74b8b | 168 | static void clearCache(struct record* pr) |
andrewboyson | 48:952dddb74b8b | 169 | { |
andrewboyson | 48:952dddb74b8b | 170 | if (elapsed > pr->elapsed + CACHE_TIMEOUT) clear(pr); |
andrewboyson | 48:952dddb74b8b | 171 | } |
andrewboyson | 48:952dddb74b8b | 172 | static void retry(struct record* pr) |
andrewboyson | 48:952dddb74b8b | 173 | { |
andrewboyson | 50:492f2d2954e4 | 174 | if (pr->state == STATE_SENT && elapsed > pr->elapsed + REPLY_TIMEOUT) |
andrewboyson | 48:952dddb74b8b | 175 | { |
andrewboyson | 48:952dddb74b8b | 176 | if (pr->tries < SEND_ATTEMPTS) |
andrewboyson | 48:952dddb74b8b | 177 | { |
andrewboyson | 50:492f2d2954e4 | 178 | pr->state = STATE_WANT; |
andrewboyson | 48:952dddb74b8b | 179 | pr->elapsed = elapsed; |
andrewboyson | 48:952dddb74b8b | 180 | pr->tries++; |
andrewboyson | 48:952dddb74b8b | 181 | } |
andrewboyson | 48:952dddb74b8b | 182 | else |
andrewboyson | 48:952dddb74b8b | 183 | { |
andrewboyson | 48:952dddb74b8b | 184 | clear(pr); |
andrewboyson | 48:952dddb74b8b | 185 | } |
andrewboyson | 48:952dddb74b8b | 186 | } |
andrewboyson | 48:952dddb74b8b | 187 | } |
andrewboyson | 48:952dddb74b8b | 188 | static void sendRequest(struct record* pr) |
andrewboyson | 48:952dddb74b8b | 189 | { |
andrewboyson | 48:952dddb74b8b | 190 | if (!ArpResolveRequestFlag) |
andrewboyson | 48:952dddb74b8b | 191 | { |
andrewboyson | 50:492f2d2954e4 | 192 | if (pr->state == STATE_WANT) |
andrewboyson | 48:952dddb74b8b | 193 | { |
andrewboyson | 48:952dddb74b8b | 194 | if (Ar4Trace) |
andrewboyson | 48:952dddb74b8b | 195 | { |
andrewboyson | 48:952dddb74b8b | 196 | LogTimeF("AR4 Send request for MAC from IP4 "); |
andrewboyson | 48:952dddb74b8b | 197 | Ip4AddressLog(pr->ip); |
andrewboyson | 48:952dddb74b8b | 198 | Log("\r\n"); |
andrewboyson | 48:952dddb74b8b | 199 | } |
andrewboyson | 48:952dddb74b8b | 200 | ArpAddressToResolve = pr->ip; |
andrewboyson | 48:952dddb74b8b | 201 | ArpResolveRequestFlag = true; |
andrewboyson | 50:492f2d2954e4 | 202 | pr->state = STATE_SENT; |
andrewboyson | 48:952dddb74b8b | 203 | pr->elapsed = elapsed; |
andrewboyson | 48:952dddb74b8b | 204 | return; |
andrewboyson | 48:952dddb74b8b | 205 | } |
andrewboyson | 48:952dddb74b8b | 206 | } |
andrewboyson | 48:952dddb74b8b | 207 | } |
andrewboyson | 48:952dddb74b8b | 208 | void Ar4Main() |
andrewboyson | 48:952dddb74b8b | 209 | { |
andrewboyson | 48:952dddb74b8b | 210 | static int i = -1; |
andrewboyson | 48:952dddb74b8b | 211 | i++; |
andrewboyson | 48:952dddb74b8b | 212 | if (i >= RECORDS_COUNT) i = 0; |
andrewboyson | 48:952dddb74b8b | 213 | |
andrewboyson | 48:952dddb74b8b | 214 | struct record* pr = &records[i]; |
andrewboyson | 48:952dddb74b8b | 215 | |
andrewboyson | 48:952dddb74b8b | 216 | clearCache (pr); |
andrewboyson | 48:952dddb74b8b | 217 | retry (pr); |
andrewboyson | 48:952dddb74b8b | 218 | sendRequest(pr); |
andrewboyson | 48:952dddb74b8b | 219 | |
andrewboyson | 48:952dddb74b8b | 220 | if (ClockTicked) elapsed++; |
andrewboyson | 48:952dddb74b8b | 221 | } |
andrewboyson | 48:952dddb74b8b | 222 | void Ar4Init() |
andrewboyson | 48:952dddb74b8b | 223 | { |
andrewboyson | 48:952dddb74b8b | 224 | for (int i = 0; i < RECORDS_COUNT; i++) |
andrewboyson | 48:952dddb74b8b | 225 | { |
andrewboyson | 48:952dddb74b8b | 226 | struct record* pr = &records[i]; |
andrewboyson | 48:952dddb74b8b | 227 | clear(pr); |
andrewboyson | 48:952dddb74b8b | 228 | } |
andrewboyson | 48:952dddb74b8b | 229 | } |