Free (GPLv2) TCP/IP stack developed by TASS Belgium

Dependents:   lpc1768-picotcp-demo ZeroMQ_PicoTCP_Publisher_demo TCPSocket_HelloWorld_PicoTCP Pico_TCP_UDP_Test ... more

PicoTCP. Copyright (c) 2013 TASS Belgium NV.

Released under the GNU General Public License, version 2.

Different licensing models may exist, at the sole discretion of the Copyright holders.

Official homepage: http://www.picotcp.com

Bug tracker: https://github.com/tass-belgium/picotcp/issues

Development steps:

  • initial integration with mbed RTOS
  • generic mbed Ethernet driver
  • high performance NXP LPC1768 specific Ethernet driver
  • Multi-threading support for mbed RTOS
  • Berkeley sockets and integration with the New Socket API
  • Fork of the apps running on top of the New Socket API
  • Scheduling optimizations
  • Debugging/benchmarking/testing

Demo application (measuring TCP sender performance):

Import programlpc1768-picotcp-demo

A PicoTCP demo app testing the ethernet throughput on the lpc1768 mbed board.

Committer:
tass
Date:
Mon Sep 02 08:02:21 2013 +0000
Revision:
51:ab4529a384a6
Parent:
40:c8ab0d2bba0b
Updated from masterbranch

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 51:ab4529a384a6 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