Daniele Lacamera / PicoTCP-Experimental_CDC_ECM_Branch

Fork of PicoTCP by Daniele Lacamera

Committer:
tass
Date:
Tue Jul 16 06:40:35 2013 +0000
Revision:
40:c8ab0d2bba0b
Parent:
10:dd7111d4279f
Added tcp patch, fixed memory leak, disabled nagle by default.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
daniele 10:dd7111d4279f 1 /*********************************************************************
daniele 10:dd7111d4279f 2 PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved.
daniele 10:dd7111d4279f 3 See LICENSE and COPYING for usage.
daniele 10:dd7111d4279f 4
daniele 10:dd7111d4279f 5 .
daniele 10:dd7111d4279f 6
daniele 10:dd7111d4279f 7 Authors: Daniele Lacamera
daniele 10:dd7111d4279f 8 *********************************************************************/
daniele 10:dd7111d4279f 9
daniele 10:dd7111d4279f 10
daniele 10:dd7111d4279f 11 #include "pico_config.h"
daniele 10:dd7111d4279f 12 #include "pico_frame.h"
daniele 10:dd7111d4279f 13 #include "pico_device.h"
daniele 10:dd7111d4279f 14 #include "pico_protocol.h"
daniele 10:dd7111d4279f 15 #include "pico_stack.h"
daniele 10:dd7111d4279f 16 #include "pico_addressing.h"
daniele 10:dd7111d4279f 17 #include "pico_dns_client.h"
daniele 10:dd7111d4279f 18
daniele 10:dd7111d4279f 19 #include "pico_eth.h"
daniele 10:dd7111d4279f 20 #include "pico_arp.h"
daniele 10:dd7111d4279f 21 #include "pico_ipv4.h"
daniele 10:dd7111d4279f 22 #include "pico_ipv6.h"
daniele 10:dd7111d4279f 23 #include "pico_icmp4.h"
daniele 10:dd7111d4279f 24 #include "pico_igmp.h"
daniele 10:dd7111d4279f 25 #include "pico_udp.h"
daniele 10:dd7111d4279f 26 #include "pico_tcp.h"
daniele 10:dd7111d4279f 27 #include "pico_socket.h"
daniele 10:dd7111d4279f 28 #include "heap.h"
daniele 10:dd7111d4279f 29
daniele 10:dd7111d4279f 30 #define IS_LIMITED_BCAST(f) ( ((struct pico_ipv4_hdr *) f->net_hdr)->dst.addr == PICO_IP4_BCAST )
daniele 10:dd7111d4279f 31
daniele 10:dd7111d4279f 32 #ifdef PICO_SUPPORT_MCAST
daniele 10:dd7111d4279f 33 # define PICO_SIZE_MCAST 3
daniele 10:dd7111d4279f 34 const uint8_t PICO_ETHADDR_MCAST[6] = {0x01, 0x00, 0x5e, 0x00, 0x00, 0x00};
daniele 10:dd7111d4279f 35 #endif
daniele 10:dd7111d4279f 36
daniele 10:dd7111d4279f 37 volatile unsigned long pico_tick;
daniele 10:dd7111d4279f 38 volatile pico_err_t pico_err;
daniele 10:dd7111d4279f 39
daniele 10:dd7111d4279f 40 static uint32_t _rand_seed;
daniele 10:dd7111d4279f 41
daniele 10:dd7111d4279f 42 void pico_rand_feed(uint32_t feed)
daniele 10:dd7111d4279f 43 {
daniele 10:dd7111d4279f 44 if (!feed)
daniele 10:dd7111d4279f 45 return;
daniele 10:dd7111d4279f 46 _rand_seed *= 1664525;
daniele 10:dd7111d4279f 47 _rand_seed += 1013904223;
daniele 10:dd7111d4279f 48 _rand_seed ^= ~(feed);
daniele 10:dd7111d4279f 49 }
daniele 10:dd7111d4279f 50
daniele 10:dd7111d4279f 51 uint32_t pico_rand(void)
daniele 10:dd7111d4279f 52 {
daniele 10:dd7111d4279f 53 pico_rand_feed(pico_tick);
daniele 10:dd7111d4279f 54 return _rand_seed;
daniele 10:dd7111d4279f 55 }
daniele 10:dd7111d4279f 56
daniele 10:dd7111d4279f 57 /* NOTIFICATIONS: distributed notifications for stack internal errors.
daniele 10:dd7111d4279f 58 */
daniele 10:dd7111d4279f 59
daniele 10:dd7111d4279f 60 int pico_notify_socket_unreachable(struct pico_frame *f)
daniele 10:dd7111d4279f 61 {
daniele 10:dd7111d4279f 62 if (0) {}
daniele 10:dd7111d4279f 63 #ifdef PICO_SUPPORT_ICMP4
daniele 10:dd7111d4279f 64 else if (IS_IPV4(f)) {
daniele 10:dd7111d4279f 65 pico_icmp4_port_unreachable(f);
daniele 10:dd7111d4279f 66 }
daniele 10:dd7111d4279f 67 #endif
daniele 10:dd7111d4279f 68 #ifdef PICO_SUPPORT_ICMP6
daniele 10:dd7111d4279f 69 else if (IS_IPV6(f)) {
daniele 10:dd7111d4279f 70 pico_icmp6_port_unreachable(f);
daniele 10:dd7111d4279f 71 }
daniele 10:dd7111d4279f 72 #endif
daniele 10:dd7111d4279f 73
daniele 10:dd7111d4279f 74 return 0;
daniele 10:dd7111d4279f 75 }
daniele 10:dd7111d4279f 76
daniele 10:dd7111d4279f 77 int pico_notify_proto_unreachable(struct pico_frame *f)
daniele 10:dd7111d4279f 78 {
daniele 10:dd7111d4279f 79 if (0) {}
daniele 10:dd7111d4279f 80 #ifdef PICO_SUPPORT_ICMP4
daniele 10:dd7111d4279f 81 else if (IS_IPV4(f)) {
daniele 10:dd7111d4279f 82 pico_icmp4_proto_unreachable(f);
daniele 10:dd7111d4279f 83 }
daniele 10:dd7111d4279f 84 #endif
daniele 10:dd7111d4279f 85 #ifdef PICO_SUPPORT_ICMP6
daniele 10:dd7111d4279f 86 else if (IS_IPV6(f)) {
daniele 10:dd7111d4279f 87 pico_icmp6_proto_unreachable(f);
daniele 10:dd7111d4279f 88 }
daniele 10:dd7111d4279f 89 #endif
daniele 10:dd7111d4279f 90 return 0;
daniele 10:dd7111d4279f 91 }
daniele 10:dd7111d4279f 92
daniele 10:dd7111d4279f 93 int pico_notify_dest_unreachable(struct pico_frame *f)
daniele 10:dd7111d4279f 94 {
daniele 10:dd7111d4279f 95 if (0) {}
daniele 10:dd7111d4279f 96 #ifdef PICO_SUPPORT_ICMP4
daniele 10:dd7111d4279f 97 else if (IS_IPV4(f)) {
daniele 10:dd7111d4279f 98 pico_icmp4_dest_unreachable(f);
daniele 10:dd7111d4279f 99 }
daniele 10:dd7111d4279f 100 #endif
daniele 10:dd7111d4279f 101 #ifdef PICO_SUPPORT_ICMP6
daniele 10:dd7111d4279f 102 else if (IS_IPV6(f)) {
daniele 10:dd7111d4279f 103 pico_icmp6_dest_unreachable(f);
daniele 10:dd7111d4279f 104 }
daniele 10:dd7111d4279f 105 #endif
daniele 10:dd7111d4279f 106 return 0;
daniele 10:dd7111d4279f 107 }
daniele 10:dd7111d4279f 108
daniele 10:dd7111d4279f 109 int pico_notify_ttl_expired(struct pico_frame *f)
daniele 10:dd7111d4279f 110 {
daniele 10:dd7111d4279f 111 if (0) {}
daniele 10:dd7111d4279f 112 #ifdef PICO_SUPPORT_ICMP4
daniele 10:dd7111d4279f 113 else if (IS_IPV4(f)) {
daniele 10:dd7111d4279f 114 pico_icmp4_ttl_expired(f);
daniele 10:dd7111d4279f 115 }
daniele 10:dd7111d4279f 116 #endif
daniele 10:dd7111d4279f 117 #ifdef PICO_SUPPORT_ICMP6
daniele 10:dd7111d4279f 118 else if (IS_IPV6(f)) {
daniele 10:dd7111d4279f 119 pico_icmp6_ttl_expired(f);
daniele 10:dd7111d4279f 120 }
daniele 10:dd7111d4279f 121 #endif
daniele 10:dd7111d4279f 122 return 0;
daniele 10:dd7111d4279f 123 }
daniele 10:dd7111d4279f 124
daniele 10:dd7111d4279f 125
daniele 10:dd7111d4279f 126 /* Transport layer */
daniele 10:dd7111d4279f 127 int pico_transport_receive(struct pico_frame *f, uint8_t proto)
daniele 10:dd7111d4279f 128 {
daniele 10:dd7111d4279f 129 int ret = -1;
daniele 10:dd7111d4279f 130 switch (proto) {
daniele 10:dd7111d4279f 131
daniele 10:dd7111d4279f 132 #ifdef PICO_SUPPORT_ICMP4
daniele 10:dd7111d4279f 133 case PICO_PROTO_ICMP4:
daniele 10:dd7111d4279f 134 ret = pico_enqueue(pico_proto_icmp4.q_in, f);
daniele 10:dd7111d4279f 135 break;
daniele 10:dd7111d4279f 136 #endif
daniele 10:dd7111d4279f 137
daniele 10:dd7111d4279f 138 #ifdef PICO_SUPPORT_IGMP
daniele 10:dd7111d4279f 139 case PICO_PROTO_IGMP:
daniele 10:dd7111d4279f 140 ret = pico_enqueue(pico_proto_igmp.q_in, f);
daniele 10:dd7111d4279f 141 break;
daniele 10:dd7111d4279f 142 #endif
daniele 10:dd7111d4279f 143
daniele 10:dd7111d4279f 144 #ifdef PICO_SUPPORT_UDP
daniele 10:dd7111d4279f 145 case PICO_PROTO_UDP:
daniele 10:dd7111d4279f 146 ret = pico_enqueue(pico_proto_udp.q_in, f);
daniele 10:dd7111d4279f 147 break;
daniele 10:dd7111d4279f 148 #endif
daniele 10:dd7111d4279f 149
daniele 10:dd7111d4279f 150 #ifdef PICO_SUPPORT_TCP
daniele 10:dd7111d4279f 151 case PICO_PROTO_TCP:
daniele 10:dd7111d4279f 152 ret = pico_enqueue(pico_proto_tcp.q_in, f);
daniele 10:dd7111d4279f 153 break;
daniele 10:dd7111d4279f 154 #endif
daniele 10:dd7111d4279f 155
daniele 10:dd7111d4279f 156 default:
daniele 10:dd7111d4279f 157 /* Protocol not available */
daniele 10:dd7111d4279f 158 dbg("pkt: no such protocol (%d)\n", proto);
daniele 10:dd7111d4279f 159 pico_notify_proto_unreachable(f);
daniele 10:dd7111d4279f 160 pico_frame_discard(f);
daniele 10:dd7111d4279f 161 ret = -1;
daniele 10:dd7111d4279f 162 }
daniele 10:dd7111d4279f 163 return ret;
daniele 10:dd7111d4279f 164 }
daniele 10:dd7111d4279f 165
daniele 10:dd7111d4279f 166 int pico_transport_send(struct pico_frame *f)
daniele 10:dd7111d4279f 167 {
daniele 10:dd7111d4279f 168 if (!f || !f->sock || !f->sock->proto) {
daniele 10:dd7111d4279f 169 pico_frame_discard(f);
daniele 10:dd7111d4279f 170 return -1;
daniele 10:dd7111d4279f 171 }
daniele 10:dd7111d4279f 172 return f->sock->proto->push(f->sock->net, f);
daniele 10:dd7111d4279f 173 }
daniele 10:dd7111d4279f 174
daniele 10:dd7111d4279f 175 int pico_network_receive(struct pico_frame *f)
daniele 10:dd7111d4279f 176 {
daniele 10:dd7111d4279f 177 if (0) {}
daniele 10:dd7111d4279f 178 #ifdef PICO_SUPPORT_IPV4
daniele 10:dd7111d4279f 179 else if (IS_IPV4(f)) {
daniele 10:dd7111d4279f 180 pico_enqueue(pico_proto_ipv4.q_in, f);
daniele 10:dd7111d4279f 181 }
daniele 10:dd7111d4279f 182 #endif
daniele 10:dd7111d4279f 183 #ifdef PICO_SUPPORT_IPV6
daniele 10:dd7111d4279f 184 else if (IS_IPV6(f)) {
daniele 10:dd7111d4279f 185 pico_enqueue(pico_proto_ipv6.q_in, f);
daniele 10:dd7111d4279f 186 }
daniele 10:dd7111d4279f 187 #endif
daniele 10:dd7111d4279f 188 else {
daniele 10:dd7111d4279f 189 dbg("Network not found.\n");
daniele 10:dd7111d4279f 190 pico_frame_discard(f);
daniele 10:dd7111d4279f 191 return -1;
daniele 10:dd7111d4279f 192 }
daniele 10:dd7111d4279f 193 return f->buffer_len;
daniele 10:dd7111d4279f 194 }
daniele 10:dd7111d4279f 195
daniele 10:dd7111d4279f 196
daniele 10:dd7111d4279f 197 /* Network layer: interface towards socket for frame sending */
daniele 10:dd7111d4279f 198 int pico_network_send(struct pico_frame *f)
daniele 10:dd7111d4279f 199 {
daniele 10:dd7111d4279f 200 if (!f || !f->sock || !f->sock->net) {
daniele 10:dd7111d4279f 201 pico_frame_discard(f);
daniele 10:dd7111d4279f 202 return -1;
daniele 10:dd7111d4279f 203 }
daniele 10:dd7111d4279f 204 return f->sock->net->push(f->sock->net, f);
daniele 10:dd7111d4279f 205 }
daniele 10:dd7111d4279f 206
daniele 10:dd7111d4279f 207 int pico_destination_is_local(struct pico_frame *f)
daniele 10:dd7111d4279f 208 {
daniele 10:dd7111d4279f 209 if (0) { }
daniele 10:dd7111d4279f 210 #ifdef PICO_SUPPORT_IPV4
daniele 10:dd7111d4279f 211 else if (IS_IPV4(f)) {
daniele 10:dd7111d4279f 212 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *)f->net_hdr;
daniele 10:dd7111d4279f 213 if (pico_ipv4_link_find(&hdr->dst))
daniele 10:dd7111d4279f 214 return 1;
daniele 10:dd7111d4279f 215 }
daniele 10:dd7111d4279f 216 #endif
daniele 10:dd7111d4279f 217 #ifdef PICO_SUPPORT_IPV6
daniele 10:dd7111d4279f 218 else if (IS_IPV6(f)) {
daniele 10:dd7111d4279f 219 }
daniele 10:dd7111d4279f 220 #endif
daniele 10:dd7111d4279f 221 return 0;
daniele 10:dd7111d4279f 222 }
daniele 10:dd7111d4279f 223
daniele 10:dd7111d4279f 224 int pico_source_is_local(struct pico_frame *f)
daniele 10:dd7111d4279f 225 {
daniele 10:dd7111d4279f 226 if (0) { }
daniele 10:dd7111d4279f 227 #ifdef PICO_SUPPORT_IPV4
daniele 10:dd7111d4279f 228 else if (IS_IPV4(f)) {
daniele 10:dd7111d4279f 229 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *)f->net_hdr;
daniele 10:dd7111d4279f 230 if (hdr->src.addr == PICO_IPV4_INADDR_ANY)
daniele 10:dd7111d4279f 231 return 1;
daniele 10:dd7111d4279f 232 if (pico_ipv4_link_find(&hdr->src))
daniele 10:dd7111d4279f 233 return 1;
daniele 10:dd7111d4279f 234 }
daniele 10:dd7111d4279f 235 #endif
daniele 10:dd7111d4279f 236 #ifdef PICO_SUPPORT_IPV6
daniele 10:dd7111d4279f 237 else if (IS_IPV6(f)) {
daniele 10:dd7111d4279f 238 /* XXX */
daniele 10:dd7111d4279f 239 }
daniele 10:dd7111d4279f 240 #endif
daniele 10:dd7111d4279f 241 return 0;
daniele 10:dd7111d4279f 242
daniele 10:dd7111d4279f 243
daniele 10:dd7111d4279f 244 }
daniele 10:dd7111d4279f 245
daniele 10:dd7111d4279f 246
daniele 10:dd7111d4279f 247 /* DATALINK LEVEL: interface from network to the device
daniele 10:dd7111d4279f 248 * and vice versa.
daniele 10:dd7111d4279f 249 */
daniele 10:dd7111d4279f 250
daniele 10:dd7111d4279f 251 /* The pico_ethernet_receive() function is used by
daniele 10:dd7111d4279f 252 * those devices supporting ETH in order to push packets up
daniele 10:dd7111d4279f 253 * into the stack.
daniele 10:dd7111d4279f 254 */
daniele 10:dd7111d4279f 255 int pico_ethernet_receive(struct pico_frame *f)
daniele 10:dd7111d4279f 256 {
daniele 10:dd7111d4279f 257 struct pico_eth_hdr *hdr;
daniele 10:dd7111d4279f 258 if (!f || !f->dev || !f->datalink_hdr)
daniele 10:dd7111d4279f 259 goto discard;
daniele 10:dd7111d4279f 260 hdr = (struct pico_eth_hdr *) f->datalink_hdr;
daniele 10:dd7111d4279f 261 if ( (memcmp(hdr->daddr, f->dev->eth->mac.addr, PICO_SIZE_ETH) != 0) &&
daniele 10:dd7111d4279f 262 #ifdef PICO_SUPPORT_MCAST
daniele 10:dd7111d4279f 263 (memcmp(hdr->daddr, PICO_ETHADDR_MCAST, PICO_SIZE_MCAST) != 0) &&
daniele 10:dd7111d4279f 264 #endif
daniele 10:dd7111d4279f 265 (memcmp(hdr->daddr, PICO_ETHADDR_ALL, PICO_SIZE_ETH) != 0) )
daniele 10:dd7111d4279f 266 goto discard;
daniele 10:dd7111d4279f 267
daniele 10:dd7111d4279f 268 f->net_hdr = f->datalink_hdr + sizeof(struct pico_eth_hdr);
daniele 10:dd7111d4279f 269 if (hdr->proto == PICO_IDETH_ARP)
daniele 10:dd7111d4279f 270 return pico_arp_receive(f);
daniele 10:dd7111d4279f 271 if ((hdr->proto == PICO_IDETH_IPV4) || (hdr->proto == PICO_IDETH_IPV6))
daniele 10:dd7111d4279f 272 return pico_network_receive(f);
daniele 10:dd7111d4279f 273 discard:
daniele 10:dd7111d4279f 274 pico_frame_discard(f);
daniele 10:dd7111d4279f 275 return -1;
daniele 10:dd7111d4279f 276 }
daniele 10:dd7111d4279f 277
daniele 10:dd7111d4279f 278 static int destination_is_bcast(struct pico_frame *f)
daniele 10:dd7111d4279f 279 {
daniele 10:dd7111d4279f 280 if (!f)
daniele 10:dd7111d4279f 281 return 0;
daniele 10:dd7111d4279f 282
daniele 10:dd7111d4279f 283 if (IS_IPV6(f))
daniele 10:dd7111d4279f 284 return 0;
daniele 10:dd7111d4279f 285 #ifdef PICO_SUPPORT_IPV4
daniele 10:dd7111d4279f 286 else {
daniele 10:dd7111d4279f 287 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr;
daniele 10:dd7111d4279f 288 return pico_ipv4_is_broadcast(hdr->dst.addr);
daniele 10:dd7111d4279f 289 }
daniele 10:dd7111d4279f 290 #endif
daniele 10:dd7111d4279f 291 return 0;
daniele 10:dd7111d4279f 292 }
daniele 10:dd7111d4279f 293
daniele 10:dd7111d4279f 294 #ifdef PICO_SUPPORT_MCAST
daniele 10:dd7111d4279f 295 static int destination_is_mcast(struct pico_frame *f)
daniele 10:dd7111d4279f 296 {
daniele 10:dd7111d4279f 297 if (!f)
daniele 10:dd7111d4279f 298 return 0;
daniele 10:dd7111d4279f 299
daniele 10:dd7111d4279f 300 if (IS_IPV6(f))
daniele 10:dd7111d4279f 301 return 0;
daniele 10:dd7111d4279f 302 #ifdef PICO_SUPPORT_IPV4
daniele 10:dd7111d4279f 303 else {
daniele 10:dd7111d4279f 304 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr;
daniele 10:dd7111d4279f 305 return pico_ipv4_is_multicast(hdr->dst.addr);
daniele 10:dd7111d4279f 306 }
daniele 10:dd7111d4279f 307 #endif
daniele 10:dd7111d4279f 308 return 0;
daniele 10:dd7111d4279f 309 }
daniele 10:dd7111d4279f 310
daniele 10:dd7111d4279f 311 static struct pico_eth *pico_ethernet_mcast_translate(struct pico_frame *f, uint8_t *pico_mcast_mac)
daniele 10:dd7111d4279f 312 {
daniele 10:dd7111d4279f 313 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr;
daniele 10:dd7111d4279f 314
daniele 10:dd7111d4279f 315 /* place 23 lower bits of IP in lower 23 bits of MAC */
daniele 10:dd7111d4279f 316 pico_mcast_mac[5] = (long_be(hdr->dst.addr) & 0x000000FF);
daniele 10:dd7111d4279f 317 pico_mcast_mac[4] = (long_be(hdr->dst.addr) & 0x0000FF00) >> 8;
daniele 10:dd7111d4279f 318 pico_mcast_mac[3] = (long_be(hdr->dst.addr) & 0x007F0000) >> 16;
daniele 10:dd7111d4279f 319
daniele 10:dd7111d4279f 320 return (struct pico_eth *)pico_mcast_mac;
daniele 10:dd7111d4279f 321 }
daniele 10:dd7111d4279f 322
daniele 10:dd7111d4279f 323
daniele 10:dd7111d4279f 324 #endif /* PICO_SUPPORT_MCAST */
daniele 10:dd7111d4279f 325
daniele 10:dd7111d4279f 326 /* This is called by dev loop in order to ensure correct ethernet addressing.
daniele 10:dd7111d4279f 327 * Returns 0 if the destination is unknown, and -1 if the packet is not deliverable
daniele 10:dd7111d4279f 328 * due to ethernet addressing (i.e., no arp association was possible.
daniele 10:dd7111d4279f 329 *
daniele 10:dd7111d4279f 330 * Only IP packets must pass by this. ARP will always use direct dev->send() function, so
daniele 10:dd7111d4279f 331 * we assume IP is used.
daniele 10:dd7111d4279f 332 */
daniele 10:dd7111d4279f 333 int pico_ethernet_send(struct pico_frame *f)
daniele 10:dd7111d4279f 334 {
daniele 10:dd7111d4279f 335 struct pico_eth *dstmac = NULL;
tass 40:c8ab0d2bba0b 336 int ret = -1;
daniele 10:dd7111d4279f 337
daniele 10:dd7111d4279f 338 if (IS_IPV6(f)) {
daniele 10:dd7111d4279f 339 /*TODO: Neighbor solicitation */
daniele 10:dd7111d4279f 340 dstmac = NULL;
daniele 10:dd7111d4279f 341 }
daniele 10:dd7111d4279f 342
daniele 10:dd7111d4279f 343 else if (IS_IPV4(f)) {
daniele 10:dd7111d4279f 344 if (IS_BCAST(f) || destination_is_bcast(f)) {
daniele 10:dd7111d4279f 345 dstmac = (struct pico_eth *) PICO_ETHADDR_ALL;
daniele 10:dd7111d4279f 346 }
daniele 10:dd7111d4279f 347 #ifdef PICO_SUPPORT_MCAST
daniele 10:dd7111d4279f 348 else if (destination_is_mcast(f)) {
daniele 10:dd7111d4279f 349 uint8_t pico_mcast_mac[6] = {0x01, 0x00, 0x5e, 0x00, 0x00, 0x00};
daniele 10:dd7111d4279f 350 dstmac = pico_ethernet_mcast_translate(f, pico_mcast_mac);
daniele 10:dd7111d4279f 351 }
daniele 10:dd7111d4279f 352 #endif
daniele 10:dd7111d4279f 353 else {
daniele 10:dd7111d4279f 354 dstmac = pico_arp_get(f);
daniele 10:dd7111d4279f 355 if (!dstmac)
daniele 10:dd7111d4279f 356 return 0;
daniele 10:dd7111d4279f 357 }
daniele 10:dd7111d4279f 358 /* This sets destination and source address, then pushes the packet to the device. */
daniele 10:dd7111d4279f 359 if (dstmac && (f->start > f->buffer) && ((f->start - f->buffer) >= PICO_SIZE_ETHHDR)) {
daniele 10:dd7111d4279f 360 struct pico_eth_hdr *hdr;
daniele 10:dd7111d4279f 361 f->start -= PICO_SIZE_ETHHDR;
daniele 10:dd7111d4279f 362 f->len += PICO_SIZE_ETHHDR;
daniele 10:dd7111d4279f 363 f->datalink_hdr = f->start;
daniele 10:dd7111d4279f 364 hdr = (struct pico_eth_hdr *) f->datalink_hdr;
daniele 10:dd7111d4279f 365 memcpy(hdr->saddr, f->dev->eth->mac.addr, PICO_SIZE_ETH);
daniele 10:dd7111d4279f 366 memcpy(hdr->daddr, dstmac, PICO_SIZE_ETH);
daniele 10:dd7111d4279f 367 hdr->proto = PICO_IDETH_IPV4;
daniele 10:dd7111d4279f 368 if(!memcmp(hdr->daddr, hdr->saddr, PICO_SIZE_ETH)){
daniele 10:dd7111d4279f 369 dbg("sending out packet destined for our own mac\n");
tass 40:c8ab0d2bba0b 370 return pico_ethernet_receive(f);
daniele 10:dd7111d4279f 371 }else if(IS_LIMITED_BCAST(f)){
tass 40:c8ab0d2bba0b 372 ret = pico_device_broadcast(f);
daniele 10:dd7111d4279f 373 }else {
tass 40:c8ab0d2bba0b 374 ret = f->dev->send(f->dev, f->start, f->len);
daniele 10:dd7111d4279f 375 /* Frame is discarded after this return by the caller */
daniele 10:dd7111d4279f 376 }
tass 40:c8ab0d2bba0b 377
tass 40:c8ab0d2bba0b 378 if(!ret) pico_frame_discard(f);
tass 40:c8ab0d2bba0b 379 return ret;
daniele 10:dd7111d4279f 380 } else {
daniele 10:dd7111d4279f 381 return -1;
daniele 10:dd7111d4279f 382 }
daniele 10:dd7111d4279f 383 } /* End IPV4 ethernet addressing */
daniele 10:dd7111d4279f 384 return -1;
tass 40:c8ab0d2bba0b 385
daniele 10:dd7111d4279f 386 }
daniele 10:dd7111d4279f 387
daniele 10:dd7111d4279f 388 void pico_store_network_origin(void *src, struct pico_frame *f)
daniele 10:dd7111d4279f 389 {
daniele 10:dd7111d4279f 390 #ifdef PICO_SUPPORT_IPV4
daniele 10:dd7111d4279f 391 struct pico_ip4 *ip4;
daniele 10:dd7111d4279f 392 #endif
daniele 10:dd7111d4279f 393
daniele 10:dd7111d4279f 394 #ifdef PICO_SUPPORT_IPV6
daniele 10:dd7111d4279f 395 struct pico_ip6 *ip6;
daniele 10:dd7111d4279f 396 #endif
daniele 10:dd7111d4279f 397
daniele 10:dd7111d4279f 398 #ifdef PICO_SUPPORT_IPV4
daniele 10:dd7111d4279f 399 if (IS_IPV4(f)) {
daniele 10:dd7111d4279f 400 struct pico_ipv4_hdr *hdr;
daniele 10:dd7111d4279f 401 hdr = (struct pico_ipv4_hdr *) f->net_hdr;
daniele 10:dd7111d4279f 402 ip4 = (struct pico_ip4 *) src;
daniele 10:dd7111d4279f 403 ip4->addr = hdr->src.addr;
daniele 10:dd7111d4279f 404 }
daniele 10:dd7111d4279f 405 #endif
daniele 10:dd7111d4279f 406 #ifdef PICO_SUPPORT_IPV6
daniele 10:dd7111d4279f 407 if (IS_IPV6(f)) {
daniele 10:dd7111d4279f 408 struct pico_ipv6_hdr *hdr;
daniele 10:dd7111d4279f 409 hdr = (struct pico_ipv6_hdr *) f->net_hdr;
daniele 10:dd7111d4279f 410 ip6 = (struct pico_ip6 *) src;
daniele 10:dd7111d4279f 411 memcpy(ip6->addr, hdr->src.addr, PICO_SIZE_IP6);
daniele 10:dd7111d4279f 412 }
daniele 10:dd7111d4279f 413 #endif
daniele 10:dd7111d4279f 414 }
daniele 10:dd7111d4279f 415
daniele 10:dd7111d4279f 416
daniele 10:dd7111d4279f 417 /* LOWEST LEVEL: interface towards devices. */
daniele 10:dd7111d4279f 418 /* Device driver will call this function which returns immediately.
daniele 10:dd7111d4279f 419 * Incoming packet will be processed later on in the dev loop.
daniele 10:dd7111d4279f 420 */
daniele 10:dd7111d4279f 421 int pico_stack_recv(struct pico_device *dev, uint8_t *buffer, int len)
daniele 10:dd7111d4279f 422 {
daniele 10:dd7111d4279f 423 struct pico_frame *f;
daniele 10:dd7111d4279f 424 int ret;
daniele 10:dd7111d4279f 425 if (len <= 0)
daniele 10:dd7111d4279f 426 return -1;
daniele 10:dd7111d4279f 427 f = pico_frame_alloc(len);
daniele 10:dd7111d4279f 428 if (!f)
daniele 10:dd7111d4279f 429 return -1;
daniele 10:dd7111d4279f 430
daniele 10:dd7111d4279f 431 /* Association to the device that just received the frame. */
daniele 10:dd7111d4279f 432 f->dev = dev;
daniele 10:dd7111d4279f 433
daniele 10:dd7111d4279f 434 /* Setup the start pointer, lenght. */
daniele 10:dd7111d4279f 435 f->start = f->buffer;
daniele 10:dd7111d4279f 436 f->len = f->buffer_len;
daniele 10:dd7111d4279f 437 if (f->len > 8) {
daniele 10:dd7111d4279f 438 int mid_frame = (f->buffer_len >> 2)<<1;
daniele 10:dd7111d4279f 439 mid_frame -= (mid_frame % 4);
daniele 10:dd7111d4279f 440 pico_rand_feed(*(uint32_t*)(f->buffer + mid_frame));
daniele 10:dd7111d4279f 441 }
daniele 10:dd7111d4279f 442 memcpy(f->buffer, buffer, len);
daniele 10:dd7111d4279f 443 ret = pico_enqueue(dev->q_in, f);
daniele 10:dd7111d4279f 444 if (ret <= 0) {
daniele 10:dd7111d4279f 445 pico_frame_discard(f);
daniele 10:dd7111d4279f 446 }
daniele 10:dd7111d4279f 447 return ret;
daniele 10:dd7111d4279f 448 }
daniele 10:dd7111d4279f 449
daniele 10:dd7111d4279f 450 int pico_sendto_dev(struct pico_frame *f)
daniele 10:dd7111d4279f 451 {
daniele 10:dd7111d4279f 452 if (!f->dev) {
daniele 10:dd7111d4279f 453 pico_frame_discard(f);
daniele 10:dd7111d4279f 454 return -1;
daniele 10:dd7111d4279f 455 } else {
daniele 10:dd7111d4279f 456 if (f->len > 8) {
daniele 10:dd7111d4279f 457 int mid_frame = (f->buffer_len >> 2)<<1;
daniele 10:dd7111d4279f 458 mid_frame -= (mid_frame % 4);
daniele 10:dd7111d4279f 459 pico_rand_feed(*(uint32_t*)(f->buffer + mid_frame));
daniele 10:dd7111d4279f 460 }
daniele 10:dd7111d4279f 461 return pico_enqueue(f->dev->q_out, f);
daniele 10:dd7111d4279f 462 }
daniele 10:dd7111d4279f 463 }
daniele 10:dd7111d4279f 464
daniele 10:dd7111d4279f 465 struct pico_timer
daniele 10:dd7111d4279f 466 {
daniele 10:dd7111d4279f 467 unsigned long expire;
daniele 10:dd7111d4279f 468 void *arg;
daniele 10:dd7111d4279f 469 void (*timer)(unsigned long timestamp, void *arg);
daniele 10:dd7111d4279f 470 };
daniele 10:dd7111d4279f 471
daniele 10:dd7111d4279f 472 typedef struct pico_timer pico_timer;
daniele 10:dd7111d4279f 473
daniele 10:dd7111d4279f 474 DECLARE_HEAP(pico_timer, expire);
daniele 10:dd7111d4279f 475
daniele 10:dd7111d4279f 476 static heap_pico_timer *Timers;
daniele 10:dd7111d4279f 477
daniele 10:dd7111d4279f 478 void pico_check_timers(void)
daniele 10:dd7111d4279f 479 {
daniele 10:dd7111d4279f 480 struct pico_timer timer;
daniele 10:dd7111d4279f 481 struct pico_timer *t = heap_first(Timers);
daniele 10:dd7111d4279f 482 pico_tick = PICO_TIME_MS();
daniele 10:dd7111d4279f 483 while((t) && (t->expire < pico_tick)) {
daniele 10:dd7111d4279f 484 t->timer(pico_tick, t->arg);
daniele 10:dd7111d4279f 485 heap_peek(Timers, &timer);
daniele 10:dd7111d4279f 486 t = heap_first(Timers);
daniele 10:dd7111d4279f 487 }
daniele 10:dd7111d4279f 488 }
daniele 10:dd7111d4279f 489
daniele 10:dd7111d4279f 490
daniele 10:dd7111d4279f 491 #define PROTO_DEF_NR 11
daniele 10:dd7111d4279f 492 #define PROTO_DEF_AVG_NR 4
daniele 10:dd7111d4279f 493 #define PROTO_DEF_SCORE 32
daniele 10:dd7111d4279f 494 #define PROTO_MIN_SCORE 32
daniele 10:dd7111d4279f 495 #define PROTO_MAX_SCORE 128
daniele 10:dd7111d4279f 496 #define PROTO_LAT_IND 3 /* latecy indication 0-3 (lower is better latency performance), x1, x2, x4, x8 */
daniele 10:dd7111d4279f 497 #define PROTO_MAX_LOOP (PROTO_MAX_SCORE<<PROTO_LAT_IND) /* max global loop score, so per tick */
daniele 10:dd7111d4279f 498
daniele 10:dd7111d4279f 499 static int calc_score(int *score, int *index, int avg[][PROTO_DEF_AVG_NR], int *ret)
daniele 10:dd7111d4279f 500 {
daniele 10:dd7111d4279f 501 int temp, i, j, sum;
daniele 10:dd7111d4279f 502 int max_total = PROTO_MAX_LOOP, total = 0;
daniele 10:dd7111d4279f 503
daniele 10:dd7111d4279f 504 //dbg("USED SCORES> ");
daniele 10:dd7111d4279f 505
daniele 10:dd7111d4279f 506 for (i = 0; i < PROTO_DEF_NR; i++) {
daniele 10:dd7111d4279f 507
daniele 10:dd7111d4279f 508 /* if used looped score */
daniele 10:dd7111d4279f 509 if (ret[i] < score[i]) {
daniele 10:dd7111d4279f 510 temp = score[i] - ret[i]; /* remaining loop score */
daniele 10:dd7111d4279f 511
daniele 10:dd7111d4279f 512 //dbg("%3d - ",temp);
daniele 10:dd7111d4279f 513
daniele 10:dd7111d4279f 514 if (index[i] >= PROTO_DEF_AVG_NR)
daniele 10:dd7111d4279f 515 index[i] = 0; /* reset index */
daniele 10:dd7111d4279f 516 j = index[i];
daniele 10:dd7111d4279f 517 avg[i][j] = temp;
daniele 10:dd7111d4279f 518
daniele 10:dd7111d4279f 519 index[i]++;
daniele 10:dd7111d4279f 520
daniele 10:dd7111d4279f 521 if (ret[i] == 0 && (score[i]<<1 <= PROTO_MAX_SCORE) && ((total+(score[i]<<1)) < max_total) ) { /* used all loop score -> increase next score directly */
daniele 10:dd7111d4279f 522 score[i] <<= 1;
daniele 10:dd7111d4279f 523 total += score[i];
daniele 10:dd7111d4279f 524 continue;
daniele 10:dd7111d4279f 525 }
daniele 10:dd7111d4279f 526
daniele 10:dd7111d4279f 527 sum = 0;
daniele 10:dd7111d4279f 528 for (j = 0; j < PROTO_DEF_AVG_NR; j++)
daniele 10:dd7111d4279f 529 sum += avg[i][j]; /* calculate sum */
daniele 10:dd7111d4279f 530
daniele 10:dd7111d4279f 531 sum >>= 2; /* divide by 4 to get average used score */
daniele 10:dd7111d4279f 532
daniele 10:dd7111d4279f 533 /* criterion to increase next loop score */
daniele 10:dd7111d4279f 534 if (sum > (score[i] - (score[i]>>2)) && (score[i]<<1 <= PROTO_MAX_SCORE) && ((total+(score[i]<<1)) < max_total)) { /* > 3/4 */
daniele 10:dd7111d4279f 535 score[i] <<= 1; /* double loop score */
daniele 10:dd7111d4279f 536 total += score[i];
daniele 10:dd7111d4279f 537 continue;
daniele 10:dd7111d4279f 538 }
daniele 10:dd7111d4279f 539
daniele 10:dd7111d4279f 540 /* criterion to decrease next loop score */
daniele 10:dd7111d4279f 541 if (sum < (score[i]>>2) && (score[i]>>1 >= PROTO_MIN_SCORE)) { /* < 1/4 */
daniele 10:dd7111d4279f 542 score[i] >>= 1; /* half loop score */
daniele 10:dd7111d4279f 543 total += score[i];
daniele 10:dd7111d4279f 544 continue;
daniele 10:dd7111d4279f 545 }
daniele 10:dd7111d4279f 546
daniele 10:dd7111d4279f 547 /* also add non-changed scores */
daniele 10:dd7111d4279f 548 total += score[i];
daniele 10:dd7111d4279f 549 }
daniele 10:dd7111d4279f 550 else if (ret[i] == score[i]) {
daniele 10:dd7111d4279f 551 /* no used loop score - gradually decrease */
daniele 10:dd7111d4279f 552
daniele 10:dd7111d4279f 553 // dbg("%3d - ",0);
daniele 10:dd7111d4279f 554
daniele 10:dd7111d4279f 555 if (index[i] >= PROTO_DEF_AVG_NR)
daniele 10:dd7111d4279f 556 index[i] = 0; /* reset index */
daniele 10:dd7111d4279f 557 j = index[i];
daniele 10:dd7111d4279f 558 avg[i][j] = 0;
daniele 10:dd7111d4279f 559
daniele 10:dd7111d4279f 560 index[i]++;
daniele 10:dd7111d4279f 561
daniele 10:dd7111d4279f 562 sum = 0;
daniele 10:dd7111d4279f 563 for (j = 0; j < PROTO_DEF_AVG_NR; j++)
daniele 10:dd7111d4279f 564 sum += avg[i][j]; /* calculate sum */
daniele 10:dd7111d4279f 565
daniele 10:dd7111d4279f 566 sum >>= 2; /* divide by 4 to get average used score */
daniele 10:dd7111d4279f 567
daniele 10:dd7111d4279f 568 if ((sum == 0) && (score[i]>>1 >= PROTO_MIN_SCORE)) {
daniele 10:dd7111d4279f 569 score[i] >>= 1; /* half loop score */
daniele 10:dd7111d4279f 570 total += score[i];
daniele 10:dd7111d4279f 571 for (j = 0; j < PROTO_DEF_AVG_NR; j++)
daniele 10:dd7111d4279f 572 avg[i][j] = score[i];
daniele 10:dd7111d4279f 573 }
daniele 10:dd7111d4279f 574
daniele 10:dd7111d4279f 575 }
daniele 10:dd7111d4279f 576 }
daniele 10:dd7111d4279f 577
daniele 10:dd7111d4279f 578 //dbg("\n");
daniele 10:dd7111d4279f 579
daniele 10:dd7111d4279f 580 return 0;
daniele 10:dd7111d4279f 581 }
daniele 10:dd7111d4279f 582
daniele 10:dd7111d4279f 583
daniele 10:dd7111d4279f 584
daniele 10:dd7111d4279f 585 /*
daniele 10:dd7111d4279f 586
daniele 10:dd7111d4279f 587 .
daniele 10:dd7111d4279f 588 .vS.
daniele 10:dd7111d4279f 589 <aoSo.
daniele 10:dd7111d4279f 590 .XoS22.
daniele 10:dd7111d4279f 591 .S2S22. ._... ...... ..._.
daniele 10:dd7111d4279f 592 :=|2S2X2|=++; <vSX2XX2z+ |vSSSXSSs>. :iXXZUZXXe=
daniele 10:dd7111d4279f 593 )2SS2SS2S2S2I =oS2S2S2S2X22;. _vuXS22S2S2S22i ._wZZXZZZXZZXZX=
daniele 10:dd7111d4279f 594 )22S2S2S2S2Sl |S2S2S22S2SSSXc: .S2SS2S2S22S2SS= .]#XZZZXZXZZZZZZ:
daniele 10:dd7111d4279f 595 )oSS2SS2S2Sol |2}!"""!32S22S(. uS2S2Se**12oS2e ]dXZZXX2?YYXXXZ*
daniele 10:dd7111d4279f 596 .:2S2So:..-. . :]S2S2e;=X2SS2o .)oc ]XZZXZ( =nX:
daniele 10:dd7111d4279f 597 .S2S22. ___s_i,.)oS2So(;2SS2So, ` 3XZZZZc, -
daniele 10:dd7111d4279f 598 .S2SSo. =oXXXSSS2XoS2S2o( XS2S2XSos;. ]ZZZZXXXX|=
daniele 10:dd7111d4279f 599 .S2S22. .)S2S2S22S2S2S2S2o( "X2SS2S2S2Sus,, +3XZZZZZXZZoos_
daniele 10:dd7111d4279f 600 .S2S22. .]2S2SS22S222S2SS2o( ]S22S2S2S222So :3XXZZZZZZZZXXv
daniele 10:dd7111d4279f 601 .S2S22. =u2SS2e"~---"{2S2So( -"12S2S2SSS2Su. "?SXXXZXZZZZXo
daniele 10:dd7111d4279f 602 .S2SSo. )SS22z; :S2S2o( ={vS2S2S22v .<vXZZZZZZZ;
daniele 10:dd7111d4279f 603 .S2S2S: ]oSS2c; =22S2o( -"S2SS2n ~4XXZXZ(
daniele 10:dd7111d4279f 604 .2S2S2i )2S2S2[. .)XS2So( <;. .2S2S2o :<. ]XZZZX(
daniele 10:dd7111d4279f 605 nX2S2S,,_s_=3oSS2SoaasuXXS2S2o( .oXoasi_aioSSS22l.]dZoaas_aadXZZXZ'
daniele 10:dd7111d4279f 606 vS2SSSXXX2; )S2S2S2SoS2S2S2S2o( iS2S222XSoSS22So.)nXZZXXXZZXXZZXZo
daniele 10:dd7111d4279f 607 +32S22S2Sn -+S2S2S2S2So22S2So( 12S2SS2S2SS22S}- )SXXZZZZZZZZZXX!-
daniele 10:dd7111d4279f 608 .)S22222i .i2S2S2o>;:S2S2o( .<vSoSoSo2S(; :nXXXXXZXXX(
daniele 10:dd7111d4279f 609 .-~~~~- --- . - - --~~~-- --^^~~-
daniele 10:dd7111d4279f 610 .
daniele 10:dd7111d4279f 611
daniele 10:dd7111d4279f 612
daniele 10:dd7111d4279f 613 ... curious about our source code? We are hiring! mailto:<recruiting@tass.be>
daniele 10:dd7111d4279f 614
daniele 10:dd7111d4279f 615
daniele 10:dd7111d4279f 616 */
daniele 10:dd7111d4279f 617
daniele 10:dd7111d4279f 618 void pico_stack_tick(void)
daniele 10:dd7111d4279f 619 {
daniele 10:dd7111d4279f 620 static int score[PROTO_DEF_NR] = {PROTO_DEF_SCORE, PROTO_DEF_SCORE, PROTO_DEF_SCORE, PROTO_DEF_SCORE, PROTO_DEF_SCORE, PROTO_DEF_SCORE, PROTO_DEF_SCORE, PROTO_DEF_SCORE, PROTO_DEF_SCORE, PROTO_DEF_SCORE, PROTO_DEF_SCORE};
daniele 10:dd7111d4279f 621 static int index[PROTO_DEF_NR] = {0,0,0,0,0,0};
daniele 10:dd7111d4279f 622 static int avg[PROTO_DEF_NR][PROTO_DEF_AVG_NR];
daniele 10:dd7111d4279f 623 static int ret[PROTO_DEF_NR] = {0};
daniele 10:dd7111d4279f 624
daniele 10:dd7111d4279f 625 pico_check_timers();
daniele 10:dd7111d4279f 626
daniele 10:dd7111d4279f 627 //dbg("LOOP_SCORES> %3d - %3d - %3d - %3d - %3d - %3d - %3d - %3d - %3d - %3d - %3d\n",score[0],score[1],score[2],score[3],score[4],score[5],score[6],score[7],score[8],score[9],score[10]);
daniele 10:dd7111d4279f 628
daniele 10:dd7111d4279f 629 //score = pico_protocols_loop(100);
daniele 10:dd7111d4279f 630
daniele 10:dd7111d4279f 631 ret[0] = pico_devices_loop(score[0],PICO_LOOP_DIR_IN);
daniele 10:dd7111d4279f 632 pico_rand_feed(ret[0]);
daniele 10:dd7111d4279f 633
daniele 10:dd7111d4279f 634 ret[1] = pico_protocol_datalink_loop(score[1], PICO_LOOP_DIR_IN);
daniele 10:dd7111d4279f 635 pico_rand_feed(ret[1]);
daniele 10:dd7111d4279f 636
daniele 10:dd7111d4279f 637 ret[2] = pico_protocol_network_loop(score[2], PICO_LOOP_DIR_IN);
daniele 10:dd7111d4279f 638 pico_rand_feed(ret[2]);
daniele 10:dd7111d4279f 639
daniele 10:dd7111d4279f 640 ret[3] = pico_protocol_transport_loop(score[3], PICO_LOOP_DIR_IN);
daniele 10:dd7111d4279f 641 pico_rand_feed(ret[3]);
daniele 10:dd7111d4279f 642
daniele 10:dd7111d4279f 643
daniele 10:dd7111d4279f 644 ret[5] = score[5];
daniele 10:dd7111d4279f 645 #if defined (PICO_SUPPORT_IPV4) || defined (PICO_SUPPORT_IPV6)
daniele 10:dd7111d4279f 646 #if defined (PICO_SUPPORT_TCP) || defined (PICO_SUPPORT_UDP)
daniele 10:dd7111d4279f 647 ret[5] = pico_sockets_loop(score[5]); // swapped
daniele 10:dd7111d4279f 648 pico_rand_feed(ret[5]);
daniele 10:dd7111d4279f 649 #endif
daniele 10:dd7111d4279f 650 #endif
daniele 10:dd7111d4279f 651
daniele 10:dd7111d4279f 652 ret[4] = pico_protocol_socket_loop(score[4], PICO_LOOP_DIR_IN);
daniele 10:dd7111d4279f 653 pico_rand_feed(ret[4]);
daniele 10:dd7111d4279f 654
daniele 10:dd7111d4279f 655
daniele 10:dd7111d4279f 656 ret[6] = pico_protocol_socket_loop(score[6], PICO_LOOP_DIR_OUT);
daniele 10:dd7111d4279f 657 pico_rand_feed(ret[6]);
daniele 10:dd7111d4279f 658
daniele 10:dd7111d4279f 659 ret[7] = pico_protocol_transport_loop(score[7], PICO_LOOP_DIR_OUT);
daniele 10:dd7111d4279f 660 pico_rand_feed(ret[7]);
daniele 10:dd7111d4279f 661
daniele 10:dd7111d4279f 662 ret[8] = pico_protocol_network_loop(score[8], PICO_LOOP_DIR_OUT);
daniele 10:dd7111d4279f 663 pico_rand_feed(ret[8]);
daniele 10:dd7111d4279f 664
daniele 10:dd7111d4279f 665 ret[9] = pico_protocol_datalink_loop(score[9], PICO_LOOP_DIR_OUT);
daniele 10:dd7111d4279f 666 pico_rand_feed(ret[9]);
daniele 10:dd7111d4279f 667
daniele 10:dd7111d4279f 668 ret[10] = pico_devices_loop(score[10],PICO_LOOP_DIR_OUT);
daniele 10:dd7111d4279f 669 pico_rand_feed(ret[10]);
daniele 10:dd7111d4279f 670
daniele 10:dd7111d4279f 671 /* calculate new loop scores for next iteration */
daniele 10:dd7111d4279f 672 calc_score(score, index,(int (*)[]) avg, ret);
daniele 10:dd7111d4279f 673 }
daniele 10:dd7111d4279f 674
daniele 10:dd7111d4279f 675 void pico_stack_loop(void)
daniele 10:dd7111d4279f 676 {
daniele 10:dd7111d4279f 677 while(1) {
daniele 10:dd7111d4279f 678 pico_stack_tick();
daniele 10:dd7111d4279f 679 PICO_IDLE();
daniele 10:dd7111d4279f 680 }
daniele 10:dd7111d4279f 681 }
daniele 10:dd7111d4279f 682
daniele 10:dd7111d4279f 683 void pico_timer_add(unsigned long expire, void (*timer)(unsigned long, void *), void *arg)
daniele 10:dd7111d4279f 684 {
daniele 10:dd7111d4279f 685 pico_timer t;
daniele 10:dd7111d4279f 686 t.expire = PICO_TIME_MS() + expire;
daniele 10:dd7111d4279f 687 t.arg = arg;
daniele 10:dd7111d4279f 688 t.timer = timer;
daniele 10:dd7111d4279f 689 heap_insert(Timers, &t);
daniele 10:dd7111d4279f 690 if (Timers->n > PICO_MAX_TIMERS) {
daniele 10:dd7111d4279f 691 dbg("Warning: I have %d timers\n", Timers->n);
daniele 10:dd7111d4279f 692 }
daniele 10:dd7111d4279f 693 }
daniele 10:dd7111d4279f 694
daniele 10:dd7111d4279f 695 void pico_stack_init(void)
daniele 10:dd7111d4279f 696 {
daniele 10:dd7111d4279f 697
daniele 10:dd7111d4279f 698 #ifdef PICO_SUPPORT_IPV4
daniele 10:dd7111d4279f 699 pico_protocol_init(&pico_proto_ipv4);
daniele 10:dd7111d4279f 700 #endif
daniele 10:dd7111d4279f 701
daniele 10:dd7111d4279f 702 #ifdef PICO_SUPPORT_IPV6
daniele 10:dd7111d4279f 703 pico_protocol_init(&pico_proto_ipv6);
daniele 10:dd7111d4279f 704 #endif
daniele 10:dd7111d4279f 705
daniele 10:dd7111d4279f 706 #ifdef PICO_SUPPORT_ICMP4
daniele 10:dd7111d4279f 707 pico_protocol_init(&pico_proto_icmp4);
daniele 10:dd7111d4279f 708 #endif
daniele 10:dd7111d4279f 709
daniele 10:dd7111d4279f 710 #ifdef PICO_SUPPORT_IGMP
daniele 10:dd7111d4279f 711 pico_protocol_init(&pico_proto_igmp);
daniele 10:dd7111d4279f 712 #endif
daniele 10:dd7111d4279f 713
daniele 10:dd7111d4279f 714 #ifdef PICO_SUPPORT_UDP
daniele 10:dd7111d4279f 715 pico_protocol_init(&pico_proto_udp);
daniele 10:dd7111d4279f 716 #endif
daniele 10:dd7111d4279f 717
daniele 10:dd7111d4279f 718 #ifdef PICO_SUPPORT_TCP
daniele 10:dd7111d4279f 719 pico_protocol_init(&pico_proto_tcp);
daniele 10:dd7111d4279f 720 #endif
daniele 10:dd7111d4279f 721
daniele 10:dd7111d4279f 722 #ifdef PICO_SUPPORT_DNS_CLIENT
daniele 10:dd7111d4279f 723 pico_dns_client_init();
daniele 10:dd7111d4279f 724 #endif
daniele 10:dd7111d4279f 725
daniele 10:dd7111d4279f 726 pico_rand_feed(123456);
daniele 10:dd7111d4279f 727
daniele 10:dd7111d4279f 728 /* Initialize timer heap */
daniele 10:dd7111d4279f 729 Timers = heap_init();
daniele 10:dd7111d4279f 730 pico_stack_tick();
daniele 10:dd7111d4279f 731 pico_stack_tick();
daniele 10:dd7111d4279f 732 pico_stack_tick();
daniele 10:dd7111d4279f 733 }
daniele 10:dd7111d4279f 734