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 RTOSgeneric mbed Ethernet driverhigh performance NXP LPC1768 specific Ethernet driverMulti-threading support for mbed RTOSBerkeley sockets and integration with the New Socket APIFork of the apps running on top of the New Socket APIScheduling 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.
stack/pico_arp.c@131:4758606c9316, 2013-12-16 (annotated)
- 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?
User | Revision | Line number | New 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 | } |