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 Belgium NV
Date:
Mon Dec 16 11:25:54 2013 +0100
Revision:
131:4758606c9316
Parent:
128:ae39e6e81531
Child:
132:40ba3014da35
Syncronized with master branch

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