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