Free (GPLv2) TCP/IP stack developed by TASS Belgium

Dependents:   lpc1768-picotcp-demo ZeroMQ_PicoTCP_Publisher_demo TCPSocket_HelloWorld_PicoTCP Pico_TCP_UDP_Test ... more

PicoTCP. Copyright (c) 2013 TASS Belgium NV.

Released under the GNU General Public License, version 2.

Different licensing models may exist, at the sole discretion of the Copyright holders.

Official homepage: http://www.picotcp.com

Bug tracker: https://github.com/tass-belgium/picotcp/issues

Development steps:

  • initial integration with mbed RTOS
  • generic mbed Ethernet driver
  • high performance NXP LPC1768 specific Ethernet driver
  • Multi-threading support for mbed RTOS
  • Berkeley sockets and integration with the New Socket API
  • Fork of the apps running on top of the New Socket API
  • Scheduling optimizations
  • Debugging/benchmarking/testing

Demo application (measuring TCP sender performance):

Import programlpc1768-picotcp-demo

A PicoTCP demo app testing the ethernet throughput on the lpc1768 mbed board.

Committer:
tass picotcp@tass.be
Date:
Fri Feb 07 11:24:45 2014 +0100
Revision:
138:0a7a449980e6
Parent:
137:a1c8bfa9d691
Update from masterbranch

Who changed what in which revision?

UserRevisionLine numberNew contents of line
tass 68:0847e35d08a6 1 /*********************************************************************
TASS Belgium NV 131:4758606c9316 2 PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved.
TASS Belgium NV 131:4758606c9316 3 See LICENSE and COPYING for usage.
tass 68:0847e35d08a6 4
TASS Belgium NV 131:4758606c9316 5 .
tass 68:0847e35d08a6 6
TASS Belgium NV 131:4758606c9316 7 Authors: Daniele Lacamera
TASS Belgium NV 131:4758606c9316 8 *********************************************************************/
tass 68:0847e35d08a6 9
tass 68:0847e35d08a6 10
tass 68:0847e35d08a6 11 #include "pico_config.h"
tass 68:0847e35d08a6 12 #include "pico_arp.h"
tass 68:0847e35d08a6 13 #include "pico_tree.h"
tass 68:0847e35d08a6 14 #include "pico_ipv4.h"
tass 68:0847e35d08a6 15 #include "pico_device.h"
tass 68:0847e35d08a6 16 #include "pico_stack.h"
tass 68:0847e35d08a6 17
TASS Belgium NV 131:4758606c9316 18 const uint8_t PICO_ETHADDR_ALL[6] = {
TASS Belgium NV 131:4758606c9316 19 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
TASS Belgium NV 131:4758606c9316 20 };
tass 68:0847e35d08a6 21 #define PICO_ARP_TIMEOUT 600000
tass 68:0847e35d08a6 22 #define PICO_ARP_RETRY 300
tass 68:0847e35d08a6 23
tass 68:0847e35d08a6 24 #ifdef DEBUG_ARP
TASS Belgium NV 131:4758606c9316 25 #define arp_dbg dbg
tass 68:0847e35d08a6 26 #else
TASS Belgium NV 131:4758606c9316 27 #define arp_dbg(...) do {} while(0)
tass 68:0847e35d08a6 28 #endif
tass 68:0847e35d08a6 29
tass 68:0847e35d08a6 30 static struct pico_queue pending;
tass 68:0847e35d08a6 31 static int pending_timer_on = 0;
tass picotcp@tass.be 133:5b075f5e141a 32 static int max_arp_reqs = PICO_ARP_MAX_RATE;
tass 68:0847e35d08a6 33
tass picotcp@tass.be 137:a1c8bfa9d691 34 static void check_pending(pico_time now, void *_unused)
tass 68:0847e35d08a6 35 {
TASS Belgium NV 131:4758606c9316 36 struct pico_frame *f = pico_dequeue(&pending);
TASS Belgium NV 131:4758606c9316 37 IGNORE_PARAMETER(now);
TASS Belgium NV 131:4758606c9316 38 IGNORE_PARAMETER(_unused);
TASS Belgium NV 131:4758606c9316 39 if (!f) {
TASS Belgium NV 131:4758606c9316 40 pending_timer_on = 0;
TASS Belgium NV 131:4758606c9316 41 return;
TASS Belgium NV 131:4758606c9316 42 }
TASS Belgium NV 131:4758606c9316 43
tass picotcp@tass.be 137:a1c8bfa9d691 44 pico_ethernet_send(f);
TASS Belgium NV 131:4758606c9316 45
TASS Belgium NV 131:4758606c9316 46 pico_timer_add(PICO_ARP_RETRY, &check_pending, NULL);
tass 68:0847e35d08a6 47 }
tass 68:0847e35d08a6 48
tass picotcp@tass.be 133:5b075f5e141a 49 static void update_max_arp_reqs(pico_time now, void *unused)
tass picotcp@tass.be 133:5b075f5e141a 50 {
tass picotcp@tass.be 133:5b075f5e141a 51 IGNORE_PARAMETER(now);
tass picotcp@tass.be 133:5b075f5e141a 52 IGNORE_PARAMETER(unused);
tass picotcp@tass.be 133:5b075f5e141a 53 if (max_arp_reqs < PICO_ARP_MAX_RATE)
tass picotcp@tass.be 133:5b075f5e141a 54 max_arp_reqs++;
tass picotcp@tass.be 133:5b075f5e141a 55
tass picotcp@tass.be 133:5b075f5e141a 56 pico_timer_add(PICO_ARP_INTERVAL / PICO_ARP_MAX_RATE, &update_max_arp_reqs, NULL);
tass picotcp@tass.be 133:5b075f5e141a 57 }
tass picotcp@tass.be 133:5b075f5e141a 58
tass picotcp@tass.be 133:5b075f5e141a 59 void pico_arp_init()
tass picotcp@tass.be 133:5b075f5e141a 60 {
tass picotcp@tass.be 133:5b075f5e141a 61 pico_timer_add(PICO_ARP_INTERVAL / PICO_ARP_MAX_RATE, &update_max_arp_reqs, NULL);
tass picotcp@tass.be 133:5b075f5e141a 62 }
tass 68:0847e35d08a6 63
tass 68:0847e35d08a6 64 struct
TASS Belgium NV 131:4758606c9316 65 __attribute__ ((__packed__))
tass 68:0847e35d08a6 66 pico_arp_hdr
tass 68:0847e35d08a6 67 {
TASS Belgium NV 131:4758606c9316 68 uint16_t htype;
TASS Belgium NV 131:4758606c9316 69 uint16_t ptype;
TASS Belgium NV 131:4758606c9316 70 uint8_t hsize;
TASS Belgium NV 131:4758606c9316 71 uint8_t psize;
TASS Belgium NV 131:4758606c9316 72 uint16_t opcode;
TASS Belgium NV 131:4758606c9316 73 uint8_t s_mac[PICO_SIZE_ETH];
TASS Belgium NV 131:4758606c9316 74 struct pico_ip4 src;
TASS Belgium NV 131:4758606c9316 75 uint8_t d_mac[PICO_SIZE_ETH];
TASS Belgium NV 131:4758606c9316 76 struct pico_ip4 dst;
tass 68:0847e35d08a6 77 };
tass 68:0847e35d08a6 78
TASS Belgium NV 131:4758606c9316 79 struct arp_service_ipconflict {
TASS Belgium NV 131:4758606c9316 80 struct pico_eth mac;
TASS Belgium NV 131:4758606c9316 81 struct pico_ip4 ip;
TASS Belgium NV 131:4758606c9316 82 void (*conflict)(void);
tass 123:dd26752a4538 83 };
tass 123:dd26752a4538 84
tass 123:dd26752a4538 85 static struct arp_service_ipconflict conflict_ipv4;
tass 68:0847e35d08a6 86
tass 68:0847e35d08a6 87 #define PICO_SIZE_ARPHDR ((sizeof(struct pico_arp_hdr)))
tass 68:0847e35d08a6 88
tass 68:0847e35d08a6 89 /* Arp Entries for the tables. */
tass 68:0847e35d08a6 90 struct pico_arp {
TASS Belgium NV 131:4758606c9316 91 /* CAREFUL MAN! ARP entry MUST begin with a pico_eth structure,
tass 68:0847e35d08a6 92 * due to in-place casting!!! */
TASS Belgium NV 131:4758606c9316 93 struct pico_eth eth;
TASS Belgium NV 131:4758606c9316 94 struct pico_ip4 ipv4;
TASS Belgium NV 131:4758606c9316 95 int arp_status;
TASS Belgium NV 131:4758606c9316 96 pico_time timestamp;
TASS Belgium NV 131:4758606c9316 97 struct pico_device *dev;
tass picotcp@tass.be 133:5b075f5e141a 98 struct pico_timer *timer;
tass 68:0847e35d08a6 99 };
tass 68:0847e35d08a6 100
tass 68:0847e35d08a6 101
tass 68:0847e35d08a6 102
tass 68:0847e35d08a6 103 /*****************/
tass 68:0847e35d08a6 104 /** ARP TREE **/
tass 68:0847e35d08a6 105 /*****************/
tass 68:0847e35d08a6 106
tass 68:0847e35d08a6 107 /* Routing destination */
tass 68:0847e35d08a6 108
TASS Belgium NV 131:4758606c9316 109 static int arp_compare(void *ka, void *kb)
tass 68:0847e35d08a6 110 {
TASS Belgium NV 131:4758606c9316 111 struct pico_arp *a = ka, *b = kb;
TASS Belgium NV 131:4758606c9316 112 if (a->ipv4.addr < b->ipv4.addr)
TASS Belgium NV 131:4758606c9316 113 return -1;
TASS Belgium NV 131:4758606c9316 114 else if (a->ipv4.addr > b->ipv4.addr)
TASS Belgium NV 131:4758606c9316 115 return 1;
TASS Belgium NV 131:4758606c9316 116
TASS Belgium NV 131:4758606c9316 117 return 0;
tass 68:0847e35d08a6 118 }
tass 68:0847e35d08a6 119
tass 68:0847e35d08a6 120 PICO_TREE_DECLARE(arp_tree, arp_compare);
tass 68:0847e35d08a6 121
tass 68:0847e35d08a6 122 /*********************/
tass 68:0847e35d08a6 123 /** END ARP TREE **/
tass 68:0847e35d08a6 124 /*********************/
tass 68:0847e35d08a6 125
tass 68:0847e35d08a6 126 struct pico_eth *pico_arp_lookup(struct pico_ip4 *dst)
tass 68:0847e35d08a6 127 {
TASS Belgium NV 131:4758606c9316 128 struct pico_arp search, *found;
TASS Belgium NV 131:4758606c9316 129 search.ipv4.addr = dst->addr;
TASS Belgium NV 131:4758606c9316 130 found = pico_tree_findKey(&arp_tree, &search);
TASS Belgium NV 131:4758606c9316 131 if (found && (found->arp_status != PICO_ARP_STATUS_STALE))
TASS Belgium NV 131:4758606c9316 132 return &found->eth;
TASS Belgium NV 131:4758606c9316 133
TASS Belgium NV 131:4758606c9316 134 return NULL;
tass 68:0847e35d08a6 135 }
tass 68:0847e35d08a6 136
tass 68:0847e35d08a6 137 struct pico_ip4 *pico_arp_reverse_lookup(struct pico_eth *dst)
tass 68:0847e35d08a6 138 {
TASS Belgium NV 131:4758606c9316 139 struct pico_arp*search;
TASS Belgium NV 131:4758606c9316 140 struct pico_tree_node *index;
TASS Belgium NV 131:4758606c9316 141 pico_tree_foreach(index, &arp_tree){
TASS Belgium NV 131:4758606c9316 142 search = index->keyValue;
TASS Belgium NV 131:4758606c9316 143 if(memcmp(&(search->eth.addr), &dst->addr, 6) == 0)
TASS Belgium NV 131:4758606c9316 144 return &search->ipv4;
TASS Belgium NV 131:4758606c9316 145 }
TASS Belgium NV 131:4758606c9316 146 return NULL;
tass 68:0847e35d08a6 147 }
tass 68:0847e35d08a6 148
TASS Belgium NV 131:4758606c9316 149 struct pico_eth *pico_arp_get(struct pico_frame *f)
TASS Belgium NV 131:4758606c9316 150 {
TASS Belgium NV 131:4758606c9316 151 struct pico_eth *a4;
TASS Belgium NV 131:4758606c9316 152 struct pico_ip4 gateway;
TASS Belgium NV 131:4758606c9316 153 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr;
TASS Belgium NV 131:4758606c9316 154 struct pico_ipv4_link *l;
tass 68:0847e35d08a6 155
tass picotcp@tass.be 137:a1c8bfa9d691 156 #ifndef PICO_SUPPORT_IPV4
tass picotcp@tass.be 137:a1c8bfa9d691 157 return NULL;
tass picotcp@tass.be 137:a1c8bfa9d691 158 #endif
tass picotcp@tass.be 137:a1c8bfa9d691 159
TASS Belgium NV 131:4758606c9316 160 l = pico_ipv4_link_get(&hdr->dst);
TASS Belgium NV 131:4758606c9316 161 if(l) {
TASS Belgium NV 131:4758606c9316 162 /* address belongs to ourself */
TASS Belgium NV 131:4758606c9316 163 return &l->dev->eth->mac;
TASS Belgium NV 131:4758606c9316 164 }
TASS Belgium NV 131:4758606c9316 165
TASS Belgium NV 131:4758606c9316 166 gateway = pico_ipv4_route_get_gateway(&hdr->dst);
TASS Belgium NV 131:4758606c9316 167 /* check if dst is local (gateway = 0), or if to use gateway */
TASS Belgium NV 131:4758606c9316 168 if (gateway.addr != 0)
TASS Belgium NV 131:4758606c9316 169 a4 = pico_arp_lookup(&gateway); /* check if gateway ip mac in cache */
TASS Belgium NV 131:4758606c9316 170 else
TASS Belgium NV 131:4758606c9316 171 a4 = pico_arp_lookup(&hdr->dst); /* check if local ip mac in cache */
tass 68:0847e35d08a6 172
TASS Belgium NV 131:4758606c9316 173 if (!a4) {
TASS Belgium NV 131:4758606c9316 174 if (++f->failure_count < 4) {
tass picotcp@tass.be 138:0a7a449980e6 175 arp_dbg ("================= ARP REQUIRED: %d =============\n\n", f->failure_count);
TASS Belgium NV 131:4758606c9316 176 /* check if dst is local (gateway = 0), or if to use gateway */
TASS Belgium NV 131:4758606c9316 177 if (gateway.addr != 0)
TASS Belgium NV 131:4758606c9316 178 pico_arp_request(f->dev, &gateway, PICO_ARP_QUERY); /* arp to gateway */
TASS Belgium NV 131:4758606c9316 179 else
TASS Belgium NV 131:4758606c9316 180 pico_arp_request(f->dev, &hdr->dst, PICO_ARP_QUERY); /* arp to dst */
tass 68:0847e35d08a6 181
TASS Belgium NV 131:4758606c9316 182 pico_enqueue(&pending, f);
TASS Belgium NV 131:4758606c9316 183 if (!pending_timer_on) {
TASS Belgium NV 131:4758606c9316 184 pending_timer_on++;
TASS Belgium NV 131:4758606c9316 185 pico_timer_add(PICO_ARP_RETRY, &check_pending, NULL);
TASS Belgium NV 131:4758606c9316 186 }
TASS Belgium NV 131:4758606c9316 187 } else {
TASS Belgium NV 131:4758606c9316 188 dbg("ARP: Destination Unreachable\n");
TASS Belgium NV 131:4758606c9316 189 pico_notify_dest_unreachable(f);
TASS Belgium NV 131:4758606c9316 190 pico_frame_discard(f);
TASS Belgium NV 131:4758606c9316 191 }
tass 68:0847e35d08a6 192 }
TASS Belgium NV 131:4758606c9316 193
TASS Belgium NV 131:4758606c9316 194 return a4;
tass 68:0847e35d08a6 195 }
tass 68:0847e35d08a6 196
tass 68:0847e35d08a6 197 #ifdef DEBUG_ARP
tass 68:0847e35d08a6 198 void dbg_arp(void)
tass 68:0847e35d08a6 199 {
TASS Belgium NV 131:4758606c9316 200 struct pico_arp *a;
TASS Belgium NV 131:4758606c9316 201 struct pico_tree_node *index;
tass 68:0847e35d08a6 202
TASS Belgium NV 131:4758606c9316 203 pico_tree_foreach(index, &arp_tree) {
TASS Belgium NV 131:4758606c9316 204 a = index->keyValue;
TASS Belgium NV 131:4758606c9316 205 arp_dbg("ARP to %08x, mac: %02x:%02x:%02x:%02x:%02x:%02x\n", a->ipv4.addr, a->eth.addr[0], a->eth.addr[1], a->eth.addr[2], a->eth.addr[3], a->eth.addr[4], a->eth.addr[5] );
TASS Belgium NV 131:4758606c9316 206 }
tass 68:0847e35d08a6 207 }
tass 68:0847e35d08a6 208 #endif
tass 68:0847e35d08a6 209
tass picotcp@tass.be 137:a1c8bfa9d691 210 static void arp_expire(pico_time now, void *_stale)
tass 68:0847e35d08a6 211 {
TASS Belgium NV 131:4758606c9316 212 struct pico_arp *stale = (struct pico_arp *) _stale;
tass picotcp@tass.be 138:0a7a449980e6 213 if (now >= (stale->timestamp + PICO_ARP_TIMEOUT)) {
tass picotcp@tass.be 138:0a7a449980e6 214 stale->arp_status = PICO_ARP_STATUS_STALE;
tass picotcp@tass.be 138:0a7a449980e6 215 arp_dbg("ARP: Setting arp_status to STALE\n");
tass picotcp@tass.be 138:0a7a449980e6 216 pico_arp_request(stale->dev, &stale->ipv4, PICO_ARP_QUERY);
tass picotcp@tass.be 138:0a7a449980e6 217 } else {
tass picotcp@tass.be 138:0a7a449980e6 218 /* Timer must be rescheduled, ARP entry has been renewed lately.
tass picotcp@tass.be 138:0a7a449980e6 219 * No action required to refresh the entry, will check on the next timeout */
tass picotcp@tass.be 138:0a7a449980e6 220 pico_timer_add(PICO_ARP_TIMEOUT + stale->timestamp - now, arp_expire, stale);
tass picotcp@tass.be 138:0a7a449980e6 221 }
tass 68:0847e35d08a6 222 }
tass 68:0847e35d08a6 223
tass picotcp@tass.be 137:a1c8bfa9d691 224 static void pico_arp_add_entry(struct pico_arp *entry)
tass 68:0847e35d08a6 225 {
tass 68:0847e35d08a6 226 entry->arp_status = PICO_ARP_STATUS_REACHABLE;
tass 68:0847e35d08a6 227 entry->timestamp = PICO_TIME();
tass 68:0847e35d08a6 228
TASS Belgium NV 131:4758606c9316 229 pico_tree_insert(&arp_tree, entry);
tass 68:0847e35d08a6 230 arp_dbg("ARP ## reachable.\n");
tass 68:0847e35d08a6 231 pico_timer_add(PICO_ARP_TIMEOUT, arp_expire, entry);
tass 68:0847e35d08a6 232 }
tass 68:0847e35d08a6 233
TASS Belgium NV 131:4758606c9316 234 int pico_arp_create_entry(uint8_t*hwaddr, struct pico_ip4 ipv4, struct pico_device*dev)
tass 68:0847e35d08a6 235 {
TASS Belgium NV 131:4758606c9316 236 struct pico_arp*arp = pico_zalloc(sizeof(struct pico_arp));
TASS Belgium NV 131:4758606c9316 237 if(!arp) {
TASS Belgium NV 131:4758606c9316 238 pico_err = PICO_ERR_ENOMEM;
TASS Belgium NV 131:4758606c9316 239 return -1;
TASS Belgium NV 131:4758606c9316 240 }
tass 68:0847e35d08a6 241
TASS Belgium NV 131:4758606c9316 242 memcpy(arp->eth.addr, hwaddr, 6);
TASS Belgium NV 131:4758606c9316 243 arp->ipv4.addr = ipv4.addr;
TASS Belgium NV 131:4758606c9316 244 arp->dev = dev;
tass 68:0847e35d08a6 245
TASS Belgium NV 131:4758606c9316 246 pico_arp_add_entry(arp);
TASS Belgium NV 131:4758606c9316 247
TASS Belgium NV 131:4758606c9316 248 return 0;
tass 68:0847e35d08a6 249 }
tass 68:0847e35d08a6 250
tass 68:0847e35d08a6 251 int pico_arp_receive(struct pico_frame *f)
tass 68:0847e35d08a6 252 {
TASS Belgium NV 131:4758606c9316 253 struct pico_arp_hdr *hdr;
TASS Belgium NV 131:4758606c9316 254 struct pico_arp search, *found, *new = NULL;
tass picotcp@tass.be 133:5b075f5e141a 255 struct pico_ip4 me;
tass picotcp@tass.be 133:5b075f5e141a 256 struct pico_device *link_dev;
tass picotcp@tass.be 133:5b075f5e141a 257 struct pico_eth_hdr *eh;
TASS Belgium NV 131:4758606c9316 258 int ret = -1;
TASS Belgium NV 131:4758606c9316 259 hdr = (struct pico_arp_hdr *) f->net_hdr;
tass picotcp@tass.be 133:5b075f5e141a 260 eh = (struct pico_eth_hdr *)f->datalink_hdr;
tass 68:0847e35d08a6 261
TASS Belgium NV 131:4758606c9316 262 if (!hdr)
TASS Belgium NV 131:4758606c9316 263 goto end;
tass 68:0847e35d08a6 264
tass picotcp@tass.be 137:a1c8bfa9d691 265 #ifndef PICO_SUPPORT_IPV4
tass picotcp@tass.be 137:a1c8bfa9d691 266 goto end;
tass picotcp@tass.be 137:a1c8bfa9d691 267 #endif
tass picotcp@tass.be 137:a1c8bfa9d691 268
tass picotcp@tass.be 137:a1c8bfa9d691 269 me.addr = hdr->dst.addr;
tass picotcp@tass.be 137:a1c8bfa9d691 270
TASS Belgium NV 132:40ba3014da35 271 /* Validate the incoming arp packet */
tass picotcp@tass.be 133:5b075f5e141a 272
tass picotcp@tass.be 133:5b075f5e141a 273 /* Check the hardware type and protocol */
TASS Belgium NV 132:40ba3014da35 274 if ((hdr->htype != PICO_ARP_HTYPE_ETH) || (hdr->ptype != PICO_IDETH_IPV4))
TASS Belgium NV 132:40ba3014da35 275 goto end;
TASS Belgium NV 132:40ba3014da35 276
tass picotcp@tass.be 133:5b075f5e141a 277 /* The source mac address must not be a multicast or broadcast address */
tass picotcp@tass.be 133:5b075f5e141a 278 if (hdr->s_mac[0] & 0x01)
tass picotcp@tass.be 133:5b075f5e141a 279 goto end;
tass picotcp@tass.be 133:5b075f5e141a 280
tass picotcp@tass.be 133:5b075f5e141a 281 /* Prevent ARP flooding */
tass picotcp@tass.be 133:5b075f5e141a 282 link_dev = pico_ipv4_link_find(&me);
tass picotcp@tass.be 133:5b075f5e141a 283 if ((link_dev == f->dev) && (hdr->opcode == PICO_ARP_REQUEST)) {
tass picotcp@tass.be 133:5b075f5e141a 284 if (max_arp_reqs == 0)
tass picotcp@tass.be 133:5b075f5e141a 285 goto end;
tass picotcp@tass.be 133:5b075f5e141a 286 else
tass picotcp@tass.be 133:5b075f5e141a 287 max_arp_reqs--;
tass picotcp@tass.be 133:5b075f5e141a 288 }
tass picotcp@tass.be 133:5b075f5e141a 289
TASS Belgium NV 131:4758606c9316 290 if (conflict_ipv4.conflict != NULL)
TASS Belgium NV 131:4758606c9316 291 {
TASS Belgium NV 131:4758606c9316 292 if ((conflict_ipv4.ip.addr == hdr->src.addr) && (memcmp(hdr->s_mac, conflict_ipv4.mac.addr, 6) != 0))
TASS Belgium NV 131:4758606c9316 293 conflict_ipv4.conflict();
TASS Belgium NV 131:4758606c9316 294 }
tass 68:0847e35d08a6 295
TASS Belgium NV 131:4758606c9316 296 /* Populate a new arp entry */
TASS Belgium NV 131:4758606c9316 297 search.ipv4.addr = hdr->src.addr;
TASS Belgium NV 131:4758606c9316 298 memcpy(search.eth.addr, hdr->s_mac, PICO_SIZE_ETH);
tass 68:0847e35d08a6 299
TASS Belgium NV 131:4758606c9316 300 /* Search for already existing entry */
tass picotcp@tass.be 133:5b075f5e141a 301 found = pico_tree_findKey(&arp_tree, &search);
tass picotcp@tass.be 133:5b075f5e141a 302 if (found) {
tass picotcp@tass.be 133:5b075f5e141a 303 if (found->arp_status == PICO_ARP_STATUS_STALE) {
tass picotcp@tass.be 133:5b075f5e141a 304 /* Replace if stale */
tass picotcp@tass.be 133:5b075f5e141a 305 new = found;
tass 68:0847e35d08a6 306
tass picotcp@tass.be 133:5b075f5e141a 307 pico_tree_delete(&arp_tree, new);
tass picotcp@tass.be 138:0a7a449980e6 308 } else {
tass picotcp@tass.be 133:5b075f5e141a 309 /* Update mac address */
tass picotcp@tass.be 133:5b075f5e141a 310 memcpy(found->eth.addr, hdr->s_mac, PICO_SIZE_ETH);
tass picotcp@tass.be 133:5b075f5e141a 311
tass picotcp@tass.be 138:0a7a449980e6 312 /* Refresh timestamp, this will force a reschedule on the next timeout*/
tass picotcp@tass.be 133:5b075f5e141a 313 found->timestamp = PICO_TIME();
tass picotcp@tass.be 138:0a7a449980e6 314 new = NULL; /* Avoid re-inserting the entry in the table */
tass picotcp@tass.be 133:5b075f5e141a 315 }
tass picotcp@tass.be 133:5b075f5e141a 316 }
tass picotcp@tass.be 133:5b075f5e141a 317
tass picotcp@tass.be 133:5b075f5e141a 318 /* Check if we are the target IP address */
tass picotcp@tass.be 133:5b075f5e141a 319 if (link_dev != f->dev)
tass picotcp@tass.be 133:5b075f5e141a 320 goto end;
tass picotcp@tass.be 133:5b075f5e141a 321
tass picotcp@tass.be 133:5b075f5e141a 322 /* If no existing entry was found, create a new entry */
TASS Belgium NV 131:4758606c9316 323 if (!found) {
TASS Belgium NV 131:4758606c9316 324 new = pico_zalloc(sizeof(struct pico_arp));
TASS Belgium NV 131:4758606c9316 325 if (!new)
TASS Belgium NV 131:4758606c9316 326 goto end;
TASS Belgium NV 131:4758606c9316 327
TASS Belgium NV 131:4758606c9316 328 new->ipv4.addr = hdr->src.addr;
tass picotcp@tass.be 133:5b075f5e141a 329 memcpy(new->eth.addr, hdr->s_mac, PICO_SIZE_ETH);
tass picotcp@tass.be 133:5b075f5e141a 330 new->dev = f->dev;
TASS Belgium NV 131:4758606c9316 331 }
tass 68:0847e35d08a6 332
tass picotcp@tass.be 133:5b075f5e141a 333 if (new)
tass picotcp@tass.be 133:5b075f5e141a 334 pico_arp_add_entry(new);
tass 68:0847e35d08a6 335
TASS Belgium NV 131:4758606c9316 336 ret = 0;
tass 68:0847e35d08a6 337
tass picotcp@tass.be 133:5b075f5e141a 338 /* If the packet is a request, send a reply */
TASS Belgium NV 131:4758606c9316 339 if (hdr->opcode == PICO_ARP_REQUEST) {
TASS Belgium NV 131:4758606c9316 340 hdr->opcode = PICO_ARP_REPLY;
TASS Belgium NV 131:4758606c9316 341 memcpy(hdr->d_mac, hdr->s_mac, PICO_SIZE_ETH);
TASS Belgium NV 131:4758606c9316 342 memcpy(hdr->s_mac, f->dev->eth->mac.addr, PICO_SIZE_ETH);
TASS Belgium NV 131:4758606c9316 343 hdr->dst.addr = hdr->src.addr;
TASS Belgium NV 131:4758606c9316 344 hdr->src.addr = me.addr;
tass 68:0847e35d08a6 345
TASS Belgium NV 131:4758606c9316 346 /* Prepare eth header for arp reply */
TASS Belgium NV 131:4758606c9316 347 memcpy(eh->daddr, eh->saddr, PICO_SIZE_ETH);
TASS Belgium NV 131:4758606c9316 348 memcpy(eh->saddr, f->dev->eth->mac.addr, PICO_SIZE_ETH);
TASS Belgium NV 131:4758606c9316 349 f->start = f->datalink_hdr;
TASS Belgium NV 131:4758606c9316 350 f->len = PICO_SIZE_ETHHDR + PICO_SIZE_ARPHDR;
TASS Belgium NV 131:4758606c9316 351 f->dev->send(f->dev, f->start, (int)f->len);
TASS Belgium NV 131:4758606c9316 352 }
tass 68:0847e35d08a6 353
tass 68:0847e35d08a6 354 #ifdef DEBUG_ARG
TASS Belgium NV 131:4758606c9316 355 dbg_arp();
tass 68:0847e35d08a6 356 #endif
tass 68:0847e35d08a6 357
tass 68:0847e35d08a6 358 end:
TASS Belgium NV 131:4758606c9316 359 pico_frame_discard(f);
TASS Belgium NV 131:4758606c9316 360 return ret;
tass 68:0847e35d08a6 361 }
tass 68:0847e35d08a6 362
tass 123:dd26752a4538 363 int32_t pico_arp_request(struct pico_device *dev, struct pico_ip4 *dst, uint8_t type)
tass 68:0847e35d08a6 364 {
TASS Belgium NV 131:4758606c9316 365 struct pico_frame *q = pico_frame_alloc(PICO_SIZE_ETHHDR + PICO_SIZE_ARPHDR);
TASS Belgium NV 131:4758606c9316 366 struct pico_eth_hdr *eh;
TASS Belgium NV 131:4758606c9316 367 struct pico_arp_hdr *ah;
tass picotcp@tass.be 137:a1c8bfa9d691 368 struct pico_ip4 *src = NULL;
TASS Belgium NV 131:4758606c9316 369 int ret;
TASS Belgium NV 131:4758606c9316 370
tass picotcp@tass.be 137:a1c8bfa9d691 371 if (!q)
tass picotcp@tass.be 137:a1c8bfa9d691 372 return -1;
tass picotcp@tass.be 137:a1c8bfa9d691 373
tass picotcp@tass.be 137:a1c8bfa9d691 374 #ifndef PICO_SUPPORT_IPV4
tass picotcp@tass.be 137:a1c8bfa9d691 375 return -1;
tass picotcp@tass.be 137:a1c8bfa9d691 376 #endif
tass picotcp@tass.be 137:a1c8bfa9d691 377
TASS Belgium NV 131:4758606c9316 378 if (type == PICO_ARP_QUERY)
TASS Belgium NV 131:4758606c9316 379 {
TASS Belgium NV 131:4758606c9316 380 src = pico_ipv4_source_find(dst);
tass picotcp@tass.be 137:a1c8bfa9d691 381 if (!src) {
tass picotcp@tass.be 137:a1c8bfa9d691 382 pico_frame_discard(q);
TASS Belgium NV 131:4758606c9316 383 return -1;
tass picotcp@tass.be 137:a1c8bfa9d691 384 }
TASS Belgium NV 131:4758606c9316 385 }
tass 68:0847e35d08a6 386
TASS Belgium NV 131:4758606c9316 387 arp_dbg("QUERY: %08x\n", dst->addr);
tass 68:0847e35d08a6 388
TASS Belgium NV 131:4758606c9316 389 eh = (struct pico_eth_hdr *)q->start;
TASS Belgium NV 131:4758606c9316 390 ah = (struct pico_arp_hdr *) (q->start + PICO_SIZE_ETHHDR);
tass 68:0847e35d08a6 391
TASS Belgium NV 131:4758606c9316 392 /* Fill eth header */
TASS Belgium NV 131:4758606c9316 393 memcpy(eh->saddr, dev->eth->mac.addr, PICO_SIZE_ETH);
TASS Belgium NV 131:4758606c9316 394 memcpy(eh->daddr, PICO_ETHADDR_ALL, PICO_SIZE_ETH);
TASS Belgium NV 131:4758606c9316 395 eh->proto = PICO_IDETH_ARP;
tass 68:0847e35d08a6 396
TASS Belgium NV 131:4758606c9316 397 /* Fill arp header */
TASS Belgium NV 131:4758606c9316 398 ah->htype = PICO_ARP_HTYPE_ETH;
TASS Belgium NV 131:4758606c9316 399 ah->ptype = PICO_IDETH_IPV4;
TASS Belgium NV 131:4758606c9316 400 ah->hsize = PICO_SIZE_ETH;
TASS Belgium NV 131:4758606c9316 401 ah->psize = PICO_SIZE_IP4;
TASS Belgium NV 131:4758606c9316 402 ah->opcode = PICO_ARP_REQUEST;
TASS Belgium NV 131:4758606c9316 403 memcpy(ah->s_mac, dev->eth->mac.addr, PICO_SIZE_ETH);
tass 123:dd26752a4538 404
TASS Belgium NV 131:4758606c9316 405 switch (type) {
TASS Belgium NV 131:4758606c9316 406 case PICO_ARP_ANNOUNCE:
TASS Belgium NV 131:4758606c9316 407 ah->src.addr = dst->addr;
TASS Belgium NV 131:4758606c9316 408 ah->dst.addr = dst->addr;
TASS Belgium NV 131:4758606c9316 409 break;
TASS Belgium NV 131:4758606c9316 410 case PICO_ARP_PROBE:
TASS Belgium NV 131:4758606c9316 411 ah->src.addr = 0;
TASS Belgium NV 131:4758606c9316 412 ah->dst.addr = dst->addr;
TASS Belgium NV 131:4758606c9316 413 break;
tass picotcp@tass.be 134:cc4e6d2654d9 414 case PICO_ARP_QUERY:
TASS Belgium NV 131:4758606c9316 415 ah->src.addr = src->addr;
TASS Belgium NV 131:4758606c9316 416 ah->dst.addr = dst->addr;
TASS Belgium NV 131:4758606c9316 417 }
tass 123:dd26752a4538 418
TASS Belgium NV 131:4758606c9316 419 arp_dbg("Sending arp request.\n");
TASS Belgium NV 131:4758606c9316 420 ret = dev->send(dev, q->start, (int) q->len);
TASS Belgium NV 131:4758606c9316 421 pico_frame_discard(q);
TASS Belgium NV 131:4758606c9316 422 return ret;
tass 68:0847e35d08a6 423 }
tass 74:c146c4e346c4 424
tass 74:c146c4e346c4 425 int pico_arp_get_neighbors(struct pico_device *dev, struct pico_ip4 *neighbors, int maxlen)
tass 74:c146c4e346c4 426 {
TASS Belgium NV 131:4758606c9316 427 struct pico_arp*search;
TASS Belgium NV 131:4758606c9316 428 struct pico_tree_node *index;
TASS Belgium NV 131:4758606c9316 429 int i = 0;
TASS Belgium NV 131:4758606c9316 430 pico_tree_foreach(index, &arp_tree){
TASS Belgium NV 131:4758606c9316 431 search = index->keyValue;
TASS Belgium NV 131:4758606c9316 432 if (search->dev == dev) {
TASS Belgium NV 131:4758606c9316 433 neighbors[i++].addr = search->ipv4.addr;
TASS Belgium NV 131:4758606c9316 434 if (i >= maxlen)
TASS Belgium NV 131:4758606c9316 435 return i;
TASS Belgium NV 131:4758606c9316 436 }
tass 74:c146c4e346c4 437 }
TASS Belgium NV 131:4758606c9316 438 return i;
tass 74:c146c4e346c4 439 }
tass 123:dd26752a4538 440
TASS Belgium NV 131:4758606c9316 441 void pico_arp_register_ipconflict(struct pico_ip4 *ip, struct pico_eth *mac, void (*cb)(void))
tass 123:dd26752a4538 442 {
TASS Belgium NV 131:4758606c9316 443 conflict_ipv4.conflict = cb;
TASS Belgium NV 131:4758606c9316 444 conflict_ipv4.ip.addr = ip->addr;
TASS Belgium NV 131:4758606c9316 445 if (mac != NULL)
TASS Belgium NV 131:4758606c9316 446 memcpy(conflict_ipv4.mac.addr, mac, 6);
tass 123:dd26752a4538 447 }