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:
daniele
Date:
Fri May 24 15:25:25 2013 +0000
Revision:
3:b4047e8a0123
Updated from main repo + fixed Mutexes;

Who changed what in which revision?

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