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