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.
modules/pico_arp.c@155:a70f34550c34, 2016-01-28 (annotated)
- Committer:
- tass
- Date:
- Thu Jan 28 15:12:00 2016 +0100
- Revision:
- 155:a70f34550c34
- Parent:
- 154:6c0e92a80c4a
Adding TCP flag for FIN.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
tass picotcp@tass.be | 149:5f4cb161cec3 | 1 | /********************************************************************* |
tass | 152:a3d286bf94e5 | 2 | PicoTCP. Copyright (c) 2012-2015 Altran Intelligent Systems. Some rights reserved. |
tass picotcp@tass.be | 149:5f4cb161cec3 | 3 | See LICENSE and COPYING for usage. |
tass picotcp@tass.be | 149:5f4cb161cec3 | 4 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 5 | . |
tass picotcp@tass.be | 149:5f4cb161cec3 | 6 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 7 | Authors: Daniele Lacamera |
tass picotcp@tass.be | 149:5f4cb161cec3 | 8 | *********************************************************************/ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 9 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 10 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 11 | #include "pico_config.h" |
tass picotcp@tass.be | 149:5f4cb161cec3 | 12 | #include "pico_arp.h" |
tass picotcp@tass.be | 149:5f4cb161cec3 | 13 | #include "pico_tree.h" |
tass picotcp@tass.be | 149:5f4cb161cec3 | 14 | #include "pico_ipv4.h" |
tass picotcp@tass.be | 149:5f4cb161cec3 | 15 | #include "pico_device.h" |
tass picotcp@tass.be | 149:5f4cb161cec3 | 16 | #include "pico_stack.h" |
tass picotcp@tass.be | 149:5f4cb161cec3 | 17 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 18 | extern const uint8_t PICO_ETHADDR_ALL[6]; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 19 | #define PICO_ARP_TIMEOUT 600000llu |
tass picotcp@tass.be | 149:5f4cb161cec3 | 20 | #define PICO_ARP_RETRY 300lu |
tass | 152:a3d286bf94e5 | 21 | #define PICO_ARP_MAX_PENDING 5 |
tass picotcp@tass.be | 149:5f4cb161cec3 | 22 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 23 | #ifdef DEBUG_ARP |
tass picotcp@tass.be | 149:5f4cb161cec3 | 24 | #define arp_dbg dbg |
tass picotcp@tass.be | 149:5f4cb161cec3 | 25 | #else |
tass picotcp@tass.be | 149:5f4cb161cec3 | 26 | #define arp_dbg(...) do {} while(0) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 27 | #endif |
tass picotcp@tass.be | 149:5f4cb161cec3 | 28 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 29 | static int max_arp_reqs = PICO_ARP_MAX_RATE; |
tass | 154:6c0e92a80c4a | 30 | static struct pico_frame *frames_queued[PICO_ARP_MAX_PENDING] = { 0 }; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 31 | |
tass | 152:a3d286bf94e5 | 32 | static void pico_arp_queued_trigger(void) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 33 | { |
tass | 152:a3d286bf94e5 | 34 | int i; |
tass | 152:a3d286bf94e5 | 35 | struct pico_frame *f; |
tass | 152:a3d286bf94e5 | 36 | for (i = 0; i < PICO_ARP_MAX_PENDING; i++) |
tass | 152:a3d286bf94e5 | 37 | { |
tass | 152:a3d286bf94e5 | 38 | f = frames_queued[i]; |
tass | 152:a3d286bf94e5 | 39 | if (f) { |
tass | 152:a3d286bf94e5 | 40 | if (!pico_ethernet_send(f)) |
tass | 152:a3d286bf94e5 | 41 | { |
tass | 152:a3d286bf94e5 | 42 | pico_frame_discard(f); |
tass | 152:a3d286bf94e5 | 43 | frames_queued[i] = NULL; |
tass | 152:a3d286bf94e5 | 44 | } |
tass | 152:a3d286bf94e5 | 45 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 46 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 47 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 48 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 49 | static void update_max_arp_reqs(pico_time now, void *unused) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 50 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 51 | IGNORE_PARAMETER(now); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 52 | IGNORE_PARAMETER(unused); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 53 | if (max_arp_reqs < PICO_ARP_MAX_RATE) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 54 | max_arp_reqs++; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 55 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 56 | pico_timer_add(PICO_ARP_INTERVAL / PICO_ARP_MAX_RATE, &update_max_arp_reqs, NULL); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 57 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 58 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 59 | void pico_arp_init(void) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 60 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 61 | pico_timer_add(PICO_ARP_INTERVAL / PICO_ARP_MAX_RATE, &update_max_arp_reqs, NULL); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 62 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 63 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 64 | PACKED_STRUCT_DEF pico_arp_hdr |
tass picotcp@tass.be | 149:5f4cb161cec3 | 65 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 66 | uint16_t htype; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 67 | uint16_t ptype; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 68 | uint8_t hsize; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 69 | uint8_t psize; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 70 | uint16_t opcode; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 71 | uint8_t s_mac[PICO_SIZE_ETH]; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 72 | struct pico_ip4 src; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 73 | uint8_t d_mac[PICO_SIZE_ETH]; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 74 | struct pico_ip4 dst; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 75 | }; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 76 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 77 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 78 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 79 | /* Callback handler for ip conflict service (e.g. IPv4 SLAAC) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 80 | * Whenever the IP address registered here is seen in the network, |
tass picotcp@tass.be | 149:5f4cb161cec3 | 81 | * the callback is awaken to take countermeasures against IP collisions. |
tass picotcp@tass.be | 149:5f4cb161cec3 | 82 | * |
tass picotcp@tass.be | 149:5f4cb161cec3 | 83 | */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 84 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 85 | struct arp_service_ipconflict { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 86 | struct pico_eth mac; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 87 | struct pico_ip4 ip; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 88 | void (*conflict)(void); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 89 | }; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 90 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 91 | static struct arp_service_ipconflict conflict_ipv4; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 92 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 93 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 94 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 95 | #define PICO_SIZE_ARPHDR ((sizeof(struct pico_arp_hdr))) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 96 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 97 | /* Arp Entries for the tables. */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 98 | struct pico_arp { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 99 | /* CAREFUL MAN! ARP entry MUST begin with a pico_eth structure, |
tass picotcp@tass.be | 149:5f4cb161cec3 | 100 | * due to in-place casting!!! */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 101 | struct pico_eth eth; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 102 | struct pico_ip4 ipv4; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 103 | int arp_status; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 104 | pico_time timestamp; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 105 | struct pico_device *dev; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 106 | struct pico_timer *timer; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 107 | }; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 108 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 109 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 110 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 111 | /*****************/ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 112 | /** ARP TREE **/ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 113 | /*****************/ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 114 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 115 | /* Routing destination */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 116 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 117 | static int arp_compare(void *ka, void *kb) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 118 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 119 | struct pico_arp *a = ka, *b = kb; |
tass | 152:a3d286bf94e5 | 120 | return pico_ipv4_compare(&a->ipv4, &b->ipv4); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 121 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 122 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 123 | PICO_TREE_DECLARE(arp_tree, arp_compare); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 124 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 125 | /*********************/ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 126 | /** END ARP TREE **/ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 127 | /*********************/ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 128 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 129 | struct pico_eth *pico_arp_lookup(struct pico_ip4 *dst) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 130 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 131 | struct pico_arp search, *found; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 132 | search.ipv4.addr = dst->addr; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 133 | found = pico_tree_findKey(&arp_tree, &search); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 134 | if (found && (found->arp_status != PICO_ARP_STATUS_STALE)) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 135 | return &found->eth; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 136 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 137 | return NULL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 138 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 139 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 140 | struct pico_ip4 *pico_arp_reverse_lookup(struct pico_eth *dst) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 141 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 142 | struct pico_arp*search; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 143 | struct pico_tree_node *index; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 144 | pico_tree_foreach(index, &arp_tree){ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 145 | search = index->keyValue; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 146 | if(memcmp(&(search->eth.addr), &dst->addr, 6) == 0) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 147 | return &search->ipv4; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 148 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 149 | return NULL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 150 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 151 | |
tass | 152:a3d286bf94e5 | 152 | static void pico_arp_unreachable(struct pico_ip4 *a) |
tass | 152:a3d286bf94e5 | 153 | { |
tass | 152:a3d286bf94e5 | 154 | int i; |
tass | 152:a3d286bf94e5 | 155 | struct pico_frame *f; |
tass | 152:a3d286bf94e5 | 156 | struct pico_ipv4_hdr *hdr; |
tass | 152:a3d286bf94e5 | 157 | struct pico_ip4 dst; |
tass | 152:a3d286bf94e5 | 158 | for (i = 0; i < PICO_ARP_MAX_PENDING; i++) |
tass | 152:a3d286bf94e5 | 159 | { |
tass | 152:a3d286bf94e5 | 160 | f = frames_queued[i]; |
tass | 152:a3d286bf94e5 | 161 | if (f) { |
tass | 152:a3d286bf94e5 | 162 | hdr = (struct pico_ipv4_hdr *) f->net_hdr; |
tass | 152:a3d286bf94e5 | 163 | dst = pico_ipv4_route_get_gateway(&hdr->dst); |
tass | 152:a3d286bf94e5 | 164 | if (!dst.addr) |
tass | 152:a3d286bf94e5 | 165 | dst.addr = hdr->dst.addr; |
tass | 152:a3d286bf94e5 | 166 | |
tass | 152:a3d286bf94e5 | 167 | if (dst.addr == a->addr) { |
tass | 152:a3d286bf94e5 | 168 | if (!pico_source_is_local(f)) { |
tass | 152:a3d286bf94e5 | 169 | pico_notify_dest_unreachable(f); |
tass | 152:a3d286bf94e5 | 170 | } |
tass | 152:a3d286bf94e5 | 171 | |
tass | 152:a3d286bf94e5 | 172 | pico_frame_discard(f); |
tass | 152:a3d286bf94e5 | 173 | frames_queued[i] = NULL; |
tass | 152:a3d286bf94e5 | 174 | } |
tass | 152:a3d286bf94e5 | 175 | } |
tass | 152:a3d286bf94e5 | 176 | } |
tass | 152:a3d286bf94e5 | 177 | } |
tass | 152:a3d286bf94e5 | 178 | |
tass | 152:a3d286bf94e5 | 179 | static void pico_arp_retry(struct pico_frame *f, struct pico_ip4 *where) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 180 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 181 | if (++f->failure_count < 4) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 182 | arp_dbg ("================= ARP REQUIRED: %d =============\n\n", f->failure_count); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 183 | /* check if dst is local (gateway = 0), or if to use gateway */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 184 | pico_arp_request(f->dev, where, PICO_ARP_QUERY); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 185 | } else { |
tass | 152:a3d286bf94e5 | 186 | pico_arp_unreachable(where); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 187 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 188 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 189 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 190 | struct pico_eth *pico_arp_get(struct pico_frame *f) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 191 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 192 | struct pico_eth *a4; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 193 | struct pico_ip4 gateway; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 194 | struct pico_ip4 *where; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 195 | struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 196 | struct pico_ipv4_link *l; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 197 | if (!hdr) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 198 | return NULL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 199 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 200 | l = pico_ipv4_link_get(&hdr->dst); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 201 | if(l) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 202 | /* address belongs to ourself */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 203 | return &l->dev->eth->mac; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 204 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 205 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 206 | gateway = pico_ipv4_route_get_gateway(&hdr->dst); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 207 | /* check if dst is local (gateway = 0), or if to use gateway */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 208 | if (gateway.addr != 0) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 209 | where = &gateway; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 210 | else |
tass picotcp@tass.be | 149:5f4cb161cec3 | 211 | where = &hdr->dst; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 212 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 213 | a4 = pico_arp_lookup(where); /* check if dst ip mac in cache */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 214 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 215 | if (!a4) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 216 | pico_arp_retry(f, where); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 217 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 218 | return a4; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 219 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 220 | |
tass | 152:a3d286bf94e5 | 221 | |
tass | 152:a3d286bf94e5 | 222 | void pico_arp_postpone(struct pico_frame *f) |
tass | 152:a3d286bf94e5 | 223 | { |
tass | 152:a3d286bf94e5 | 224 | int i; |
tass | 152:a3d286bf94e5 | 225 | for (i = 0; i < PICO_ARP_MAX_PENDING; i++) |
tass | 152:a3d286bf94e5 | 226 | { |
tass | 152:a3d286bf94e5 | 227 | if (!frames_queued[i]) { |
tass | 152:a3d286bf94e5 | 228 | frames_queued[i] = pico_frame_copy(f); |
tass | 152:a3d286bf94e5 | 229 | return; |
tass | 152:a3d286bf94e5 | 230 | } |
tass | 152:a3d286bf94e5 | 231 | } |
tass | 152:a3d286bf94e5 | 232 | /* Not possible to enqueue: caller will discard packet */ |
tass | 152:a3d286bf94e5 | 233 | } |
tass | 152:a3d286bf94e5 | 234 | |
tass | 152:a3d286bf94e5 | 235 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 236 | #ifdef DEBUG_ARP |
tass picotcp@tass.be | 149:5f4cb161cec3 | 237 | void dbg_arp(void) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 238 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 239 | struct pico_arp *a; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 240 | struct pico_tree_node *index; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 241 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 242 | pico_tree_foreach(index, &arp_tree) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 243 | a = index->keyValue; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 244 | 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 picotcp@tass.be | 149:5f4cb161cec3 | 245 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 246 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 247 | #endif |
tass picotcp@tass.be | 149:5f4cb161cec3 | 248 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 249 | static void arp_expire(pico_time now, void *_stale) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 250 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 251 | struct pico_arp *stale = (struct pico_arp *) _stale; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 252 | if (now >= (stale->timestamp + PICO_ARP_TIMEOUT)) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 253 | stale->arp_status = PICO_ARP_STATUS_STALE; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 254 | arp_dbg("ARP: Setting arp_status to STALE\n"); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 255 | pico_arp_request(stale->dev, &stale->ipv4, PICO_ARP_QUERY); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 256 | } else { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 257 | /* Timer must be rescheduled, ARP entry has been renewed lately. |
tass picotcp@tass.be | 149:5f4cb161cec3 | 258 | * No action required to refresh the entry, will check on the next timeout */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 259 | pico_timer_add(PICO_ARP_TIMEOUT + stale->timestamp - now, arp_expire, stale); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 260 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 261 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 262 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 263 | static void pico_arp_add_entry(struct pico_arp *entry) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 264 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 265 | entry->arp_status = PICO_ARP_STATUS_REACHABLE; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 266 | entry->timestamp = PICO_TIME(); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 267 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 268 | pico_tree_insert(&arp_tree, entry); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 269 | arp_dbg("ARP ## reachable.\n"); |
tass | 152:a3d286bf94e5 | 270 | pico_arp_queued_trigger(); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 271 | pico_timer_add(PICO_ARP_TIMEOUT, arp_expire, entry); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 272 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 273 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 274 | int pico_arp_create_entry(uint8_t *hwaddr, struct pico_ip4 ipv4, struct pico_device *dev) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 275 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 276 | struct pico_arp*arp = PICO_ZALLOC(sizeof(struct pico_arp)); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 277 | if(!arp) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 278 | pico_err = PICO_ERR_ENOMEM; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 279 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 280 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 281 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 282 | memcpy(arp->eth.addr, hwaddr, 6); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 283 | arp->ipv4.addr = ipv4.addr; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 284 | arp->dev = dev; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 285 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 286 | pico_arp_add_entry(arp); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 287 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 288 | return 0; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 289 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 290 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 291 | static void pico_arp_check_conflict(struct pico_arp_hdr *hdr) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 292 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 293 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 294 | if ((conflict_ipv4.conflict) && |
tass picotcp@tass.be | 149:5f4cb161cec3 | 295 | ((conflict_ipv4.ip.addr == hdr->src.addr) && |
tass picotcp@tass.be | 149:5f4cb161cec3 | 296 | (memcmp(hdr->s_mac, conflict_ipv4.mac.addr, PICO_SIZE_ETH) != 0))) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 297 | conflict_ipv4.conflict(); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 298 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 299 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 300 | static struct pico_arp *pico_arp_lookup_entry(struct pico_frame *f) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 301 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 302 | struct pico_arp search; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 303 | struct pico_arp *found = NULL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 304 | struct pico_arp_hdr *hdr = (struct pico_arp_hdr *) f->net_hdr; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 305 | /* Populate a new arp entry */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 306 | search.ipv4.addr = hdr->src.addr; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 307 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 308 | /* Search for already existing entry */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 309 | found = pico_tree_findKey(&arp_tree, &search); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 310 | if (found) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 311 | if (found->arp_status == PICO_ARP_STATUS_STALE) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 312 | /* Replace if stale */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 313 | pico_tree_delete(&arp_tree, found); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 314 | pico_arp_add_entry(found); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 315 | } else { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 316 | /* Update mac address */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 317 | memcpy(found->eth.addr, hdr->s_mac, PICO_SIZE_ETH); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 318 | arp_dbg("ARP entry updated!\n"); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 319 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 320 | /* Refresh timestamp, this will force a reschedule on the next timeout*/ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 321 | found->timestamp = PICO_TIME(); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 322 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 323 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 324 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 325 | return found; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 326 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 327 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 328 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 329 | static int pico_arp_check_incoming_hdr_type(struct pico_arp_hdr *h) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 330 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 331 | /* Check the hardware type and protocol */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 332 | if ((h->htype != PICO_ARP_HTYPE_ETH) || (h->ptype != PICO_IDETH_IPV4)) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 333 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 334 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 335 | return 0; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 336 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 337 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 338 | static int pico_arp_check_incoming_hdr(struct pico_frame *f, struct pico_ip4 *dst_addr) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 339 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 340 | struct pico_arp_hdr *hdr = (struct pico_arp_hdr *) f->net_hdr; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 341 | if (!hdr) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 342 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 343 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 344 | dst_addr->addr = hdr->dst.addr; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 345 | if (pico_arp_check_incoming_hdr_type(hdr) < 0) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 346 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 347 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 348 | /* The source mac address must not be a multicast or broadcast address */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 349 | if (hdr->s_mac[0] & 0x01) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 350 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 351 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 352 | return 0; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 353 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 354 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 355 | static void pico_arp_reply_on_request(struct pico_frame *f, struct pico_ip4 me) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 356 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 357 | struct pico_arp_hdr *hdr; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 358 | struct pico_eth_hdr *eh; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 359 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 360 | hdr = (struct pico_arp_hdr *) f->net_hdr; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 361 | eh = (struct pico_eth_hdr *)f->datalink_hdr; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 362 | if (hdr->opcode != PICO_ARP_REQUEST) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 363 | return; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 364 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 365 | hdr->opcode = PICO_ARP_REPLY; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 366 | memcpy(hdr->d_mac, hdr->s_mac, PICO_SIZE_ETH); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 367 | memcpy(hdr->s_mac, f->dev->eth->mac.addr, PICO_SIZE_ETH); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 368 | hdr->dst.addr = hdr->src.addr; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 369 | hdr->src.addr = me.addr; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 370 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 371 | /* Prepare eth header for arp reply */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 372 | memcpy(eh->daddr, eh->saddr, PICO_SIZE_ETH); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 373 | memcpy(eh->saddr, f->dev->eth->mac.addr, PICO_SIZE_ETH); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 374 | f->start = f->datalink_hdr; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 375 | f->len = PICO_SIZE_ETHHDR + PICO_SIZE_ARPHDR; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 376 | f->dev->send(f->dev, f->start, (int)f->len); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 377 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 378 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 379 | static int pico_arp_check_flooding(struct pico_frame *f, struct pico_ip4 me) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 380 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 381 | struct pico_device *link_dev; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 382 | struct pico_arp_hdr *hdr; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 383 | hdr = (struct pico_arp_hdr *) f->net_hdr; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 384 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 385 | /* Prevent ARP flooding */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 386 | link_dev = pico_ipv4_link_find(&me); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 387 | if ((link_dev == f->dev) && (hdr->opcode == PICO_ARP_REQUEST)) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 388 | if (max_arp_reqs == 0) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 389 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 390 | else |
tass picotcp@tass.be | 149:5f4cb161cec3 | 391 | max_arp_reqs--; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 392 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 393 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 394 | /* Check if we are the target IP address */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 395 | if (link_dev != f->dev) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 396 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 397 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 398 | return 0; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 399 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 400 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 401 | static int pico_arp_process_in(struct pico_frame *f, struct pico_arp_hdr *hdr, struct pico_arp *found) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 402 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 403 | struct pico_ip4 me; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 404 | if (pico_arp_check_incoming_hdr(f, &me) < 0) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 405 | pico_frame_discard(f); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 406 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 407 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 408 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 409 | if (pico_arp_check_flooding(f, me) < 0) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 410 | pico_frame_discard(f); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 411 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 412 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 413 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 414 | /* If no existing entry was found, create a new entry, or fail trying. */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 415 | if ((!found) && (pico_arp_create_entry(hdr->s_mac, hdr->src, f->dev) < 0)) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 416 | pico_frame_discard(f); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 417 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 418 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 419 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 420 | /* If the packet is a request, send a reply */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 421 | pico_arp_reply_on_request(f, me); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 422 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 423 | #ifdef DEBUG_ARP |
tass picotcp@tass.be | 149:5f4cb161cec3 | 424 | dbg_arp(); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 425 | #endif |
tass picotcp@tass.be | 149:5f4cb161cec3 | 426 | pico_frame_discard(f); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 427 | return 0; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 428 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 429 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 430 | int pico_arp_receive(struct pico_frame *f) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 431 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 432 | struct pico_arp_hdr *hdr; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 433 | struct pico_arp *found = NULL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 434 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 435 | hdr = (struct pico_arp_hdr *) f->net_hdr; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 436 | if (!hdr) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 437 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 438 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 439 | pico_arp_check_conflict(hdr); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 440 | found = pico_arp_lookup_entry(f); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 441 | return pico_arp_process_in(f, hdr, found); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 442 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 443 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 444 | |
tass | 152:a3d286bf94e5 | 445 | static int32_t pico_arp_request_xmit(struct pico_device *dev, struct pico_frame *f, struct pico_ip4 *src, struct pico_ip4 *dst, uint8_t type) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 446 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 447 | struct pico_arp_hdr *ah = (struct pico_arp_hdr *) (f->start + PICO_SIZE_ETHHDR); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 448 | int ret; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 449 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 450 | /* Fill arp header */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 451 | ah->htype = PICO_ARP_HTYPE_ETH; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 452 | ah->ptype = PICO_IDETH_IPV4; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 453 | ah->hsize = PICO_SIZE_ETH; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 454 | ah->psize = PICO_SIZE_IP4; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 455 | ah->opcode = PICO_ARP_REQUEST; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 456 | memcpy(ah->s_mac, dev->eth->mac.addr, PICO_SIZE_ETH); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 457 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 458 | switch (type) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 459 | case PICO_ARP_ANNOUNCE: |
tass picotcp@tass.be | 149:5f4cb161cec3 | 460 | ah->src.addr = dst->addr; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 461 | ah->dst.addr = dst->addr; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 462 | break; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 463 | case PICO_ARP_PROBE: |
tass picotcp@tass.be | 149:5f4cb161cec3 | 464 | ah->src.addr = 0; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 465 | ah->dst.addr = dst->addr; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 466 | break; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 467 | case PICO_ARP_QUERY: |
tass picotcp@tass.be | 149:5f4cb161cec3 | 468 | ah->src.addr = src->addr; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 469 | ah->dst.addr = dst->addr; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 470 | break; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 471 | default: |
tass picotcp@tass.be | 149:5f4cb161cec3 | 472 | pico_frame_discard(f); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 473 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 474 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 475 | arp_dbg("Sending arp request.\n"); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 476 | ret = dev->send(dev, f->start, (int) f->len); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 477 | pico_frame_discard(f); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 478 | return ret; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 479 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 480 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 481 | int32_t pico_arp_request(struct pico_device *dev, struct pico_ip4 *dst, uint8_t type) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 482 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 483 | struct pico_frame *q = pico_frame_alloc(PICO_SIZE_ETHHDR + PICO_SIZE_ARPHDR); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 484 | struct pico_eth_hdr *eh; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 485 | struct pico_ip4 *src = NULL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 486 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 487 | if (!q) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 488 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 489 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 490 | if (type == PICO_ARP_QUERY) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 491 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 492 | src = pico_ipv4_source_find(dst); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 493 | if (!src) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 494 | pico_frame_discard(q); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 495 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 496 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 497 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 498 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 499 | arp_dbg("QUERY: %08x\n", dst->addr); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 500 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 501 | eh = (struct pico_eth_hdr *)q->start; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 502 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 503 | /* Fill eth header */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 504 | memcpy(eh->saddr, dev->eth->mac.addr, PICO_SIZE_ETH); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 505 | memcpy(eh->daddr, PICO_ETHADDR_ALL, PICO_SIZE_ETH); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 506 | eh->proto = PICO_IDETH_ARP; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 507 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 508 | return pico_arp_request_xmit(dev, q, src, dst, type); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 509 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 510 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 511 | int pico_arp_get_neighbors(struct pico_device *dev, struct pico_ip4 *neighbors, int maxlen) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 512 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 513 | struct pico_arp*search; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 514 | struct pico_tree_node *index; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 515 | int i = 0; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 516 | pico_tree_foreach(index, &arp_tree){ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 517 | search = index->keyValue; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 518 | if (search->dev == dev) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 519 | neighbors[i++].addr = search->ipv4.addr; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 520 | if (i >= maxlen) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 521 | return i; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 522 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 523 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 524 | return i; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 525 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 526 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 527 | void pico_arp_register_ipconflict(struct pico_ip4 *ip, struct pico_eth *mac, void (*cb)(void)) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 528 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 529 | conflict_ipv4.conflict = cb; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 530 | conflict_ipv4.ip.addr = ip->addr; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 531 | if (mac != NULL) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 532 | memcpy(conflict_ipv4.mac.addr, mac, 6); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 533 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 534 |