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 picotcp@tass.be
Date:
Fri Feb 07 11:24:45 2014 +0100
Revision:
138:0a7a449980e6
Parent:
137:a1c8bfa9d691
Child:
149:5f4cb161cec3
Update from masterbranch

Who changed what in which revision?

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