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:
Thu Jan 28 15:12:00 2016 +0100
Revision:
155:a70f34550c34
Parent:
154:6c0e92a80c4a
Adding TCP flag for FIN.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
tass 68:0847e35d08a6 1 /*********************************************************************
tass 152:a3d286bf94e5 2 PicoTCP. Copyright (c) 2012-2015 Altran Intelligent Systems. 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 152:a3d286bf94e5 19 #include "pico_olsr.h"
tass 152:a3d286bf94e5 20 #include "pico_aodv.h"
tass 68:0847e35d08a6 21 #include "pico_eth.h"
tass 68:0847e35d08a6 22 #include "pico_arp.h"
tass 68:0847e35d08a6 23 #include "pico_ipv4.h"
tass 68:0847e35d08a6 24 #include "pico_ipv6.h"
tass 68:0847e35d08a6 25 #include "pico_icmp4.h"
tass picotcp@tass.be 149:5f4cb161cec3 26 #include "pico_icmp6.h"
tass 68:0847e35d08a6 27 #include "pico_igmp.h"
tass 68:0847e35d08a6 28 #include "pico_udp.h"
tass 68:0847e35d08a6 29 #include "pico_tcp.h"
tass 68:0847e35d08a6 30 #include "pico_socket.h"
tass 68:0847e35d08a6 31 #include "heap.h"
tass 68:0847e35d08a6 32
TASS Belgium NV 131:4758606c9316 33 #define IS_LIMITED_BCAST(f) (((struct pico_ipv4_hdr *) f->net_hdr)->dst.addr == PICO_IP4_BCAST)
tass 68:0847e35d08a6 34
tass picotcp@tass.be 149:5f4cb161cec3 35 const uint8_t PICO_ETHADDR_ALL[6] = {
tass picotcp@tass.be 149:5f4cb161cec3 36 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
tass picotcp@tass.be 149:5f4cb161cec3 37 };
tass picotcp@tass.be 149:5f4cb161cec3 38
tass 68:0847e35d08a6 39 # define PICO_SIZE_MCAST 3
TASS Belgium NV 131:4758606c9316 40 const uint8_t PICO_ETHADDR_MCAST[6] = {
TASS Belgium NV 131:4758606c9316 41 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00
TASS Belgium NV 131:4758606c9316 42 };
tass 68:0847e35d08a6 43
tass picotcp@tass.be 149:5f4cb161cec3 44 #ifdef PICO_SUPPORT_IPV6
tass picotcp@tass.be 149:5f4cb161cec3 45 # define PICO_SIZE_MCAST6 2
tass picotcp@tass.be 149:5f4cb161cec3 46 const uint8_t PICO_ETHADDR_MCAST6[6] = {
tass picotcp@tass.be 149:5f4cb161cec3 47 0x33, 0x33, 0x00, 0x00, 0x00, 0x00
tass picotcp@tass.be 149:5f4cb161cec3 48 };
tass picotcp@tass.be 149:5f4cb161cec3 49 #endif
tass picotcp@tass.be 149:5f4cb161cec3 50
tass picotcp@tass.be 149:5f4cb161cec3 51
tass 128:ae39e6e81531 52 volatile pico_time pico_tick;
tass 68:0847e35d08a6 53 volatile pico_err_t pico_err;
tass 68:0847e35d08a6 54
tass 68:0847e35d08a6 55 static uint32_t _rand_seed;
tass 68:0847e35d08a6 56
tass 152:a3d286bf94e5 57 void WEAK pico_rand_feed(uint32_t feed)
tass 68:0847e35d08a6 58 {
TASS Belgium NV 131:4758606c9316 59 if (!feed)
TASS Belgium NV 131:4758606c9316 60 return;
TASS Belgium NV 131:4758606c9316 61
TASS Belgium NV 131:4758606c9316 62 _rand_seed *= 1664525;
TASS Belgium NV 131:4758606c9316 63 _rand_seed += 1013904223;
TASS Belgium NV 131:4758606c9316 64 _rand_seed ^= ~(feed);
tass 68:0847e35d08a6 65 }
tass 68:0847e35d08a6 66
tass 152:a3d286bf94e5 67 uint32_t WEAK pico_rand(void)
tass 68:0847e35d08a6 68 {
TASS Belgium NV 131:4758606c9316 69 pico_rand_feed((uint32_t)pico_tick);
TASS Belgium NV 131:4758606c9316 70 return _rand_seed;
tass 68:0847e35d08a6 71 }
tass 68:0847e35d08a6 72
tass 152:a3d286bf94e5 73 void pico_to_lowercase(char *str)
tass 152:a3d286bf94e5 74 {
tass 152:a3d286bf94e5 75 int i = 0;
tass 152:a3d286bf94e5 76 if (!str)
tass 152:a3d286bf94e5 77 return;
tass 152:a3d286bf94e5 78
tass 152:a3d286bf94e5 79 while(str[i]) {
tass 152:a3d286bf94e5 80 if ((str[i] <= 'Z') && (str[i] >= 'A'))
tass 152:a3d286bf94e5 81 str[i] = (char) (str[i] - (char)('A' - 'a'));
tass 152:a3d286bf94e5 82
tass 152:a3d286bf94e5 83 i++;
tass 152:a3d286bf94e5 84 }
tass 152:a3d286bf94e5 85 }
tass 152:a3d286bf94e5 86
tass 68:0847e35d08a6 87 /* NOTIFICATIONS: distributed notifications for stack internal errors.
tass 68:0847e35d08a6 88 */
tass 68:0847e35d08a6 89
tass 68:0847e35d08a6 90 int pico_notify_socket_unreachable(struct pico_frame *f)
tass 68:0847e35d08a6 91 {
TASS Belgium NV 131:4758606c9316 92 if (0) {}
TASS Belgium NV 131:4758606c9316 93
TASS Belgium NV 131:4758606c9316 94 #ifdef PICO_SUPPORT_ICMP4
TASS Belgium NV 131:4758606c9316 95 else if (IS_IPV4(f)) {
TASS Belgium NV 131:4758606c9316 96 pico_icmp4_port_unreachable(f);
TASS Belgium NV 131:4758606c9316 97 }
tass 68:0847e35d08a6 98 #endif
TASS Belgium NV 131:4758606c9316 99 #ifdef PICO_SUPPORT_ICMP6
TASS Belgium NV 131:4758606c9316 100 else if (IS_IPV6(f)) {
TASS Belgium NV 131:4758606c9316 101 pico_icmp6_port_unreachable(f);
TASS Belgium NV 131:4758606c9316 102 }
tass 68:0847e35d08a6 103 #endif
tass 68:0847e35d08a6 104
TASS Belgium NV 131:4758606c9316 105 return 0;
tass 68:0847e35d08a6 106 }
tass 68:0847e35d08a6 107
tass 68:0847e35d08a6 108 int pico_notify_proto_unreachable(struct pico_frame *f)
tass 68:0847e35d08a6 109 {
TASS Belgium NV 131:4758606c9316 110 if (0) {}
TASS Belgium NV 131:4758606c9316 111
TASS Belgium NV 131:4758606c9316 112 #ifdef PICO_SUPPORT_ICMP4
TASS Belgium NV 131:4758606c9316 113 else if (IS_IPV4(f)) {
TASS Belgium NV 131:4758606c9316 114 pico_icmp4_proto_unreachable(f);
TASS Belgium NV 131:4758606c9316 115 }
tass 68:0847e35d08a6 116 #endif
TASS Belgium NV 131:4758606c9316 117 #ifdef PICO_SUPPORT_ICMP6
TASS Belgium NV 131:4758606c9316 118 else if (IS_IPV6(f)) {
TASS Belgium NV 131:4758606c9316 119 pico_icmp6_proto_unreachable(f);
TASS Belgium NV 131:4758606c9316 120 }
tass 68:0847e35d08a6 121 #endif
TASS Belgium NV 131:4758606c9316 122 return 0;
tass 68:0847e35d08a6 123 }
tass 68:0847e35d08a6 124
tass 68:0847e35d08a6 125 int pico_notify_dest_unreachable(struct pico_frame *f)
tass 68:0847e35d08a6 126 {
TASS Belgium NV 131:4758606c9316 127 if (0) {}
TASS Belgium NV 131:4758606c9316 128
TASS Belgium NV 131:4758606c9316 129 #ifdef PICO_SUPPORT_ICMP4
TASS Belgium NV 131:4758606c9316 130 else if (IS_IPV4(f)) {
TASS Belgium NV 131:4758606c9316 131 pico_icmp4_dest_unreachable(f);
TASS Belgium NV 131:4758606c9316 132 }
tass 68:0847e35d08a6 133 #endif
TASS Belgium NV 131:4758606c9316 134 #ifdef PICO_SUPPORT_ICMP6
TASS Belgium NV 131:4758606c9316 135 else if (IS_IPV6(f)) {
TASS Belgium NV 131:4758606c9316 136 pico_icmp6_dest_unreachable(f);
TASS Belgium NV 131:4758606c9316 137 }
tass 68:0847e35d08a6 138 #endif
TASS Belgium NV 131:4758606c9316 139 return 0;
tass 68:0847e35d08a6 140 }
tass 68:0847e35d08a6 141
tass 68:0847e35d08a6 142 int pico_notify_ttl_expired(struct pico_frame *f)
tass 68:0847e35d08a6 143 {
TASS Belgium NV 131:4758606c9316 144 if (0) {}
TASS Belgium NV 131:4758606c9316 145
TASS Belgium NV 131:4758606c9316 146 #ifdef PICO_SUPPORT_ICMP4
TASS Belgium NV 131:4758606c9316 147 else if (IS_IPV4(f)) {
TASS Belgium NV 131:4758606c9316 148 pico_icmp4_ttl_expired(f);
TASS Belgium NV 131:4758606c9316 149 }
tass 68:0847e35d08a6 150 #endif
TASS Belgium NV 131:4758606c9316 151 #ifdef PICO_SUPPORT_ICMP6
TASS Belgium NV 131:4758606c9316 152 else if (IS_IPV6(f)) {
TASS Belgium NV 131:4758606c9316 153 pico_icmp6_ttl_expired(f);
TASS Belgium NV 131:4758606c9316 154 }
tass 68:0847e35d08a6 155 #endif
TASS Belgium NV 131:4758606c9316 156 return 0;
tass 68:0847e35d08a6 157 }
tass 68:0847e35d08a6 158
tass 152:a3d286bf94e5 159 int pico_notify_frag_expired(struct pico_frame *f)
tass 152:a3d286bf94e5 160 {
tass 152:a3d286bf94e5 161 if (0) {}
tass 152:a3d286bf94e5 162
tass 152:a3d286bf94e5 163 #ifdef PICO_SUPPORT_ICMP4
tass 152:a3d286bf94e5 164 else if (IS_IPV4(f)) {
tass 152:a3d286bf94e5 165 pico_icmp4_frag_expired(f);
tass 152:a3d286bf94e5 166 }
tass 152:a3d286bf94e5 167 #endif
tass 152:a3d286bf94e5 168 #ifdef PICO_SUPPORT_ICMP6
tass 152:a3d286bf94e5 169 else if (IS_IPV6(f)) {
tass 152:a3d286bf94e5 170 pico_icmp6_frag_expired(f);
tass 152:a3d286bf94e5 171 }
tass 152:a3d286bf94e5 172 #endif
tass 152:a3d286bf94e5 173 return 0;
tass 152:a3d286bf94e5 174 }
tass 152:a3d286bf94e5 175
tass 152:a3d286bf94e5 176 int pico_notify_pkt_too_big(struct pico_frame *f)
tass 152:a3d286bf94e5 177 {
tass 152:a3d286bf94e5 178 if (0) {}
tass 152:a3d286bf94e5 179
tass 152:a3d286bf94e5 180 #ifdef PICO_SUPPORT_ICMP4
tass 152:a3d286bf94e5 181 else if (IS_IPV4(f)) {
tass 152:a3d286bf94e5 182 pico_icmp4_mtu_exceeded(f);
tass 152:a3d286bf94e5 183 }
tass 152:a3d286bf94e5 184 #endif
tass 152:a3d286bf94e5 185 #ifdef PICO_SUPPORT_ICMP6
tass 152:a3d286bf94e5 186 else if (IS_IPV6(f)) {
tass 152:a3d286bf94e5 187 pico_icmp6_pkt_too_big(f);
tass 152:a3d286bf94e5 188 }
tass 152:a3d286bf94e5 189 #endif
tass 152:a3d286bf94e5 190 return 0;
tass 152:a3d286bf94e5 191 }
tass 152:a3d286bf94e5 192
tass 68:0847e35d08a6 193
tass 68:0847e35d08a6 194 /* Transport layer */
tass 152:a3d286bf94e5 195 MOCKABLE int32_t pico_transport_receive(struct pico_frame *f, uint8_t proto)
tass 68:0847e35d08a6 196 {
TASS Belgium NV 131:4758606c9316 197 int32_t ret = -1;
TASS Belgium NV 131:4758606c9316 198 switch (proto) {
tass 68:0847e35d08a6 199
tass 68:0847e35d08a6 200 #ifdef PICO_SUPPORT_ICMP4
TASS Belgium NV 131:4758606c9316 201 case PICO_PROTO_ICMP4:
TASS Belgium NV 131:4758606c9316 202 ret = pico_enqueue(pico_proto_icmp4.q_in, f);
TASS Belgium NV 131:4758606c9316 203 break;
tass 68:0847e35d08a6 204 #endif
tass 68:0847e35d08a6 205
tass picotcp@tass.be 149:5f4cb161cec3 206 #ifdef PICO_SUPPORT_ICMP6
tass picotcp@tass.be 149:5f4cb161cec3 207 case PICO_PROTO_ICMP6:
tass picotcp@tass.be 149:5f4cb161cec3 208 ret = pico_enqueue(pico_proto_icmp6.q_in, f);
tass picotcp@tass.be 149:5f4cb161cec3 209 break;
tass picotcp@tass.be 149:5f4cb161cec3 210 #endif
tass picotcp@tass.be 149:5f4cb161cec3 211
tass picotcp@tass.be 149:5f4cb161cec3 212
tass 152:a3d286bf94e5 213 #if defined(PICO_SUPPORT_IGMP) && defined(PICO_SUPPORT_MCAST)
TASS Belgium NV 131:4758606c9316 214 case PICO_PROTO_IGMP:
TASS Belgium NV 131:4758606c9316 215 ret = pico_enqueue(pico_proto_igmp.q_in, f);
TASS Belgium NV 131:4758606c9316 216 break;
tass 68:0847e35d08a6 217 #endif
tass 68:0847e35d08a6 218
tass 68:0847e35d08a6 219 #ifdef PICO_SUPPORT_UDP
TASS Belgium NV 131:4758606c9316 220 case PICO_PROTO_UDP:
TASS Belgium NV 131:4758606c9316 221 ret = pico_enqueue(pico_proto_udp.q_in, f);
TASS Belgium NV 131:4758606c9316 222 break;
tass 68:0847e35d08a6 223 #endif
tass 68:0847e35d08a6 224
tass 68:0847e35d08a6 225 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 226 case PICO_PROTO_TCP:
TASS Belgium NV 131:4758606c9316 227 ret = pico_enqueue(pico_proto_tcp.q_in, f);
TASS Belgium NV 131:4758606c9316 228 break;
tass 68:0847e35d08a6 229 #endif
tass 68:0847e35d08a6 230
TASS Belgium NV 131:4758606c9316 231 default:
TASS Belgium NV 131:4758606c9316 232 /* Protocol not available */
TASS Belgium NV 131:4758606c9316 233 dbg("pkt: no such protocol (%d)\n", proto);
TASS Belgium NV 131:4758606c9316 234 pico_notify_proto_unreachable(f);
TASS Belgium NV 131:4758606c9316 235 pico_frame_discard(f);
TASS Belgium NV 131:4758606c9316 236 ret = -1;
TASS Belgium NV 131:4758606c9316 237 }
TASS Belgium NV 131:4758606c9316 238 return ret;
tass 68:0847e35d08a6 239 }
tass 68:0847e35d08a6 240
tass 70:cd218dd180e5 241 int32_t pico_network_receive(struct pico_frame *f)
tass 68:0847e35d08a6 242 {
TASS Belgium NV 131:4758606c9316 243 if (0) {}
TASS Belgium NV 131:4758606c9316 244
tass 68:0847e35d08a6 245 #ifdef PICO_SUPPORT_IPV4
TASS Belgium NV 131:4758606c9316 246 else if (IS_IPV4(f)) {
TASS Belgium NV 131:4758606c9316 247 pico_enqueue(pico_proto_ipv4.q_in, f);
TASS Belgium NV 131:4758606c9316 248 }
tass 68:0847e35d08a6 249 #endif
tass 68:0847e35d08a6 250 #ifdef PICO_SUPPORT_IPV6
TASS Belgium NV 131:4758606c9316 251 else if (IS_IPV6(f)) {
TASS Belgium NV 131:4758606c9316 252 pico_enqueue(pico_proto_ipv6.q_in, f);
TASS Belgium NV 131:4758606c9316 253 }
tass 68:0847e35d08a6 254 #endif
TASS Belgium NV 131:4758606c9316 255 else {
TASS Belgium NV 131:4758606c9316 256 dbg("Network not found.\n");
TASS Belgium NV 131:4758606c9316 257 pico_frame_discard(f);
TASS Belgium NV 131:4758606c9316 258 return -1;
TASS Belgium NV 131:4758606c9316 259 }
TASS Belgium NV 131:4758606c9316 260 return (int32_t)f->buffer_len;
tass 68:0847e35d08a6 261 }
tass 68:0847e35d08a6 262
tass 68:0847e35d08a6 263 /* Network layer: interface towards socket for frame sending */
tass 88:0e827d0d8017 264 int32_t pico_network_send(struct pico_frame *f)
tass 68:0847e35d08a6 265 {
TASS Belgium NV 131:4758606c9316 266 if (!f || !f->sock || !f->sock->net) {
TASS Belgium NV 131:4758606c9316 267 pico_frame_discard(f);
TASS Belgium NV 131:4758606c9316 268 return -1;
TASS Belgium NV 131:4758606c9316 269 }
TASS Belgium NV 131:4758606c9316 270
TASS Belgium NV 131:4758606c9316 271 return f->sock->net->push(f->sock->net, f);
tass 68:0847e35d08a6 272 }
tass 68:0847e35d08a6 273
tass 68:0847e35d08a6 274 int pico_source_is_local(struct pico_frame *f)
tass 68:0847e35d08a6 275 {
TASS Belgium NV 131:4758606c9316 276 if (0) { }
TASS Belgium NV 131:4758606c9316 277
tass 68:0847e35d08a6 278 #ifdef PICO_SUPPORT_IPV4
TASS Belgium NV 131:4758606c9316 279 else if (IS_IPV4(f)) {
TASS Belgium NV 131:4758606c9316 280 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *)f->net_hdr;
TASS Belgium NV 131:4758606c9316 281 if (hdr->src.addr == PICO_IPV4_INADDR_ANY)
TASS Belgium NV 131:4758606c9316 282 return 1;
TASS Belgium NV 131:4758606c9316 283
TASS Belgium NV 131:4758606c9316 284 if (pico_ipv4_link_find(&hdr->src))
TASS Belgium NV 131:4758606c9316 285 return 1;
TASS Belgium NV 131:4758606c9316 286 }
tass 68:0847e35d08a6 287 #endif
tass 68:0847e35d08a6 288 #ifdef PICO_SUPPORT_IPV6
TASS Belgium NV 131:4758606c9316 289 else if (IS_IPV6(f)) {
tass 152:a3d286bf94e5 290 struct pico_ipv6_hdr *hdr = (struct pico_ipv6_hdr *)f->net_hdr;
tass 152:a3d286bf94e5 291 if (pico_ipv6_is_unspecified(hdr->src.addr) || pico_ipv6_link_find(&hdr->src))
tass 152:a3d286bf94e5 292 return 1;
TASS Belgium NV 131:4758606c9316 293 }
tass 68:0847e35d08a6 294 #endif
TASS Belgium NV 131:4758606c9316 295 return 0;
tass 68:0847e35d08a6 296 }
tass 68:0847e35d08a6 297
tass 152:a3d286bf94e5 298 #ifdef PICO_SUPPORT_ETH
tass 68:0847e35d08a6 299 /* DATALINK LEVEL: interface from network to the device
tass 68:0847e35d08a6 300 * and vice versa.
tass 68:0847e35d08a6 301 */
tass 68:0847e35d08a6 302
TASS Belgium NV 131:4758606c9316 303 /* The pico_ethernet_receive() function is used by
TASS Belgium NV 131:4758606c9316 304 * those devices supporting ETH in order to push packets up
TASS Belgium NV 131:4758606c9316 305 * into the stack.
tass 68:0847e35d08a6 306 */
tass picotcp@tass.be 137:a1c8bfa9d691 307
tass 68:0847e35d08a6 308 static int destination_is_bcast(struct pico_frame *f)
tass 68:0847e35d08a6 309 {
TASS Belgium NV 131:4758606c9316 310 if (!f)
TASS Belgium NV 131:4758606c9316 311 return 0;
tass 68:0847e35d08a6 312
TASS Belgium NV 131:4758606c9316 313 if (IS_IPV6(f))
TASS Belgium NV 131:4758606c9316 314 return 0;
TASS Belgium NV 131:4758606c9316 315
tass 68:0847e35d08a6 316 #ifdef PICO_SUPPORT_IPV4
TASS Belgium NV 131:4758606c9316 317 else {
TASS Belgium NV 131:4758606c9316 318 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr;
TASS Belgium NV 131:4758606c9316 319 return pico_ipv4_is_broadcast(hdr->dst.addr);
TASS Belgium NV 131:4758606c9316 320 }
tass picotcp@tass.be 134:cc4e6d2654d9 321 #else
tass picotcp@tass.be 134:cc4e6d2654d9 322 return 0;
tass 68:0847e35d08a6 323 #endif
tass 68:0847e35d08a6 324 }
tass 68:0847e35d08a6 325
tass 68:0847e35d08a6 326 static int destination_is_mcast(struct pico_frame *f)
tass 68:0847e35d08a6 327 {
tass picotcp@tass.be 149:5f4cb161cec3 328 int ret = 0;
TASS Belgium NV 131:4758606c9316 329 if (!f)
TASS Belgium NV 131:4758606c9316 330 return 0;
tass 68:0847e35d08a6 331
tass picotcp@tass.be 149:5f4cb161cec3 332 #ifdef PICO_SUPPORT_IPV6
tass picotcp@tass.be 149:5f4cb161cec3 333 if (IS_IPV6(f)) {
tass picotcp@tass.be 149:5f4cb161cec3 334 struct pico_ipv6_hdr *hdr = (struct pico_ipv6_hdr *) f->net_hdr;
tass picotcp@tass.be 149:5f4cb161cec3 335 ret = pico_ipv6_is_multicast(hdr->dst.addr);
tass picotcp@tass.be 149:5f4cb161cec3 336 }
TASS Belgium NV 131:4758606c9316 337
tass picotcp@tass.be 149:5f4cb161cec3 338 #endif
tass 68:0847e35d08a6 339 #ifdef PICO_SUPPORT_IPV4
TASS Belgium NV 131:4758606c9316 340 else {
TASS Belgium NV 131:4758606c9316 341 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr;
tass picotcp@tass.be 149:5f4cb161cec3 342 ret = pico_ipv4_is_multicast(hdr->dst.addr);
TASS Belgium NV 131:4758606c9316 343 }
tass 68:0847e35d08a6 344 #endif
tass picotcp@tass.be 149:5f4cb161cec3 345
tass picotcp@tass.be 149:5f4cb161cec3 346 return ret;
tass 68:0847e35d08a6 347 }
tass 68:0847e35d08a6 348
tass 152:a3d286bf94e5 349 #ifdef PICO_SUPPORT_IPV4
tass 152:a3d286bf94e5 350 static int32_t pico_ipv4_ethernet_receive(struct pico_frame *f)
tass 152:a3d286bf94e5 351 {
tass 152:a3d286bf94e5 352 if (IS_IPV4(f)) {
tass 152:a3d286bf94e5 353 pico_enqueue(pico_proto_ipv4.q_in, f);
tass 152:a3d286bf94e5 354 } else {
tass 152:a3d286bf94e5 355 (void)pico_icmp4_param_problem(f, 0);
tass 152:a3d286bf94e5 356 pico_frame_discard(f);
tass 152:a3d286bf94e5 357 return -1;
tass 152:a3d286bf94e5 358 }
tass 152:a3d286bf94e5 359
tass 152:a3d286bf94e5 360 return (int32_t)f->buffer_len;
tass 152:a3d286bf94e5 361 }
tass 152:a3d286bf94e5 362 #endif
tass 152:a3d286bf94e5 363
tass 152:a3d286bf94e5 364 #ifdef PICO_SUPPORT_IPV6
tass 152:a3d286bf94e5 365 static int32_t pico_ipv6_ethernet_receive(struct pico_frame *f)
tass 152:a3d286bf94e5 366 {
tass 152:a3d286bf94e5 367 if (IS_IPV6(f)) {
tass 152:a3d286bf94e5 368 pico_enqueue(pico_proto_ipv6.q_in, f);
tass 152:a3d286bf94e5 369 } else {
tass 152:a3d286bf94e5 370 /* Wrong version for link layer type */
tass 152:a3d286bf94e5 371 pico_frame_discard(f);
tass 152:a3d286bf94e5 372 return -1;
tass 152:a3d286bf94e5 373 }
tass 152:a3d286bf94e5 374
tass 152:a3d286bf94e5 375 return (int32_t)f->buffer_len;
tass 152:a3d286bf94e5 376 }
tass 152:a3d286bf94e5 377 #endif
tass 152:a3d286bf94e5 378
tass 152:a3d286bf94e5 379 static int32_t pico_ll_receive(struct pico_frame *f)
tass 152:a3d286bf94e5 380 {
tass 152:a3d286bf94e5 381 struct pico_eth_hdr *hdr = (struct pico_eth_hdr *) f->datalink_hdr;
tass 152:a3d286bf94e5 382 f->net_hdr = f->datalink_hdr + sizeof(struct pico_eth_hdr);
tass 152:a3d286bf94e5 383
tass 152:a3d286bf94e5 384 #if (defined PICO_SUPPORT_IPV4) && (defined PICO_SUPPORT_ETH)
tass 152:a3d286bf94e5 385 if (hdr->proto == PICO_IDETH_ARP)
tass 152:a3d286bf94e5 386 return pico_arp_receive(f);
tass 152:a3d286bf94e5 387
tass 152:a3d286bf94e5 388 #endif
tass 152:a3d286bf94e5 389
tass 152:a3d286bf94e5 390 #if defined (PICO_SUPPORT_IPV4)
tass 152:a3d286bf94e5 391 if (hdr->proto == PICO_IDETH_IPV4)
tass 152:a3d286bf94e5 392 return pico_ipv4_ethernet_receive(f);
tass 152:a3d286bf94e5 393
tass 152:a3d286bf94e5 394 #endif
tass 152:a3d286bf94e5 395
tass 152:a3d286bf94e5 396 #if defined (PICO_SUPPORT_IPV6)
tass 152:a3d286bf94e5 397 if (hdr->proto == PICO_IDETH_IPV6)
tass 152:a3d286bf94e5 398 return pico_ipv6_ethernet_receive(f);
tass 152:a3d286bf94e5 399
tass 152:a3d286bf94e5 400 #endif
tass 152:a3d286bf94e5 401
tass 152:a3d286bf94e5 402 pico_frame_discard(f);
tass 152:a3d286bf94e5 403 return -1;
tass 152:a3d286bf94e5 404 }
tass 152:a3d286bf94e5 405
tass 152:a3d286bf94e5 406 static void pico_ll_check_bcast(struct pico_frame *f)
tass 152:a3d286bf94e5 407 {
tass 152:a3d286bf94e5 408 struct pico_eth_hdr *hdr = (struct pico_eth_hdr *) f->datalink_hdr;
tass 152:a3d286bf94e5 409 /* Indicate a link layer broadcast packet */
tass 152:a3d286bf94e5 410 if (memcmp(hdr->daddr, PICO_ETHADDR_ALL, PICO_SIZE_ETH) == 0)
tass 152:a3d286bf94e5 411 f->flags |= PICO_FRAME_FLAG_BCAST;
tass 152:a3d286bf94e5 412 }
tass 152:a3d286bf94e5 413
tass 152:a3d286bf94e5 414 int32_t pico_ethernet_receive(struct pico_frame *f)
tass 152:a3d286bf94e5 415 {
tass 152:a3d286bf94e5 416 struct pico_eth_hdr *hdr;
tass 152:a3d286bf94e5 417 if (!f || !f->dev || !f->datalink_hdr)
tass 152:a3d286bf94e5 418 {
tass 152:a3d286bf94e5 419 pico_frame_discard(f);
tass 152:a3d286bf94e5 420 return -1;
tass 152:a3d286bf94e5 421 }
tass 152:a3d286bf94e5 422
tass 152:a3d286bf94e5 423 hdr = (struct pico_eth_hdr *) f->datalink_hdr;
tass 152:a3d286bf94e5 424 if ((memcmp(hdr->daddr, f->dev->eth->mac.addr, PICO_SIZE_ETH) != 0) &&
tass 152:a3d286bf94e5 425 (memcmp(hdr->daddr, PICO_ETHADDR_MCAST, PICO_SIZE_MCAST) != 0) &&
tass 152:a3d286bf94e5 426 #ifdef PICO_SUPPORT_IPV6
tass 152:a3d286bf94e5 427 (memcmp(hdr->daddr, PICO_ETHADDR_MCAST6, PICO_SIZE_MCAST6) != 0) &&
tass 152:a3d286bf94e5 428 #endif
tass 152:a3d286bf94e5 429 (memcmp(hdr->daddr, PICO_ETHADDR_ALL, PICO_SIZE_ETH) != 0))
tass 152:a3d286bf94e5 430 {
tass 152:a3d286bf94e5 431 pico_frame_discard(f);
tass 152:a3d286bf94e5 432 return -1;
tass 152:a3d286bf94e5 433 }
tass 152:a3d286bf94e5 434
tass 152:a3d286bf94e5 435 pico_ll_check_bcast(f);
tass 152:a3d286bf94e5 436 return pico_ll_receive(f);
tass 152:a3d286bf94e5 437 }
tass 152:a3d286bf94e5 438
tass 68:0847e35d08a6 439 static struct pico_eth *pico_ethernet_mcast_translate(struct pico_frame *f, uint8_t *pico_mcast_mac)
tass 68:0847e35d08a6 440 {
TASS Belgium NV 131:4758606c9316 441 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr;
tass 68:0847e35d08a6 442
TASS Belgium NV 131:4758606c9316 443 /* place 23 lower bits of IP in lower 23 bits of MAC */
tass picotcp@tass.be 149:5f4cb161cec3 444 pico_mcast_mac[5] = (long_be(hdr->dst.addr) & 0x000000FFu);
tass picotcp@tass.be 149:5f4cb161cec3 445 pico_mcast_mac[4] = (uint8_t)((long_be(hdr->dst.addr) & 0x0000FF00u) >> 8u);
tass picotcp@tass.be 149:5f4cb161cec3 446 pico_mcast_mac[3] = (uint8_t)((long_be(hdr->dst.addr) & 0x007F0000u) >> 16u);
tass 68:0847e35d08a6 447
TASS Belgium NV 131:4758606c9316 448 return (struct pico_eth *)pico_mcast_mac;
tass 68:0847e35d08a6 449 }
tass 68:0847e35d08a6 450
tass 68:0847e35d08a6 451
tass picotcp@tass.be 149:5f4cb161cec3 452 #ifdef PICO_SUPPORT_IPV6
tass picotcp@tass.be 149:5f4cb161cec3 453 static struct pico_eth *pico_ethernet_mcast6_translate(struct pico_frame *f, uint8_t *pico_mcast6_mac)
tass picotcp@tass.be 149:5f4cb161cec3 454 {
tass picotcp@tass.be 149:5f4cb161cec3 455 struct pico_ipv6_hdr *hdr = (struct pico_ipv6_hdr *)f->net_hdr;
tass picotcp@tass.be 137:a1c8bfa9d691 456
tass picotcp@tass.be 149:5f4cb161cec3 457 /* first 2 octets are 0x33, last four are the last four of dst */
tass picotcp@tass.be 149:5f4cb161cec3 458 pico_mcast6_mac[5] = hdr->dst.addr[PICO_SIZE_IP6 - 1];
tass picotcp@tass.be 149:5f4cb161cec3 459 pico_mcast6_mac[4] = hdr->dst.addr[PICO_SIZE_IP6 - 2];
tass picotcp@tass.be 149:5f4cb161cec3 460 pico_mcast6_mac[3] = hdr->dst.addr[PICO_SIZE_IP6 - 3];
tass picotcp@tass.be 149:5f4cb161cec3 461 pico_mcast6_mac[2] = hdr->dst.addr[PICO_SIZE_IP6 - 4];
tass picotcp@tass.be 149:5f4cb161cec3 462
tass picotcp@tass.be 149:5f4cb161cec3 463 return (struct pico_eth *)pico_mcast6_mac;
tass picotcp@tass.be 149:5f4cb161cec3 464 }
tass picotcp@tass.be 149:5f4cb161cec3 465 #endif
tass picotcp@tass.be 149:5f4cb161cec3 466
tass 152:a3d286bf94e5 467 static int pico_ethernet_ipv6_dst(struct pico_frame *f, struct pico_eth *const dstmac)
tass picotcp@tass.be 137:a1c8bfa9d691 468 {
tass 152:a3d286bf94e5 469 int retval = -1;
tass 152:a3d286bf94e5 470 if (!dstmac)
tass 152:a3d286bf94e5 471 return -1;
tass 152:a3d286bf94e5 472
tass picotcp@tass.be 149:5f4cb161cec3 473 #ifdef PICO_SUPPORT_IPV6
tass picotcp@tass.be 149:5f4cb161cec3 474 if (destination_is_mcast(f)) {
tass picotcp@tass.be 149:5f4cb161cec3 475 uint8_t pico_mcast6_mac[6] = {
tass picotcp@tass.be 149:5f4cb161cec3 476 0x33, 0x33, 0x00, 0x00, 0x00, 0x00
tass picotcp@tass.be 149:5f4cb161cec3 477 };
tass 152:a3d286bf94e5 478 pico_ethernet_mcast6_translate(f, pico_mcast6_mac);
tass 152:a3d286bf94e5 479 memcpy(dstmac, pico_mcast6_mac, PICO_SIZE_ETH);
tass 152:a3d286bf94e5 480 retval = 0;
tass picotcp@tass.be 149:5f4cb161cec3 481 } else {
tass 152:a3d286bf94e5 482 struct pico_eth *neighbor = pico_ipv6_get_neighbor(f);
tass 152:a3d286bf94e5 483 if (neighbor)
tass 152:a3d286bf94e5 484 {
tass 152:a3d286bf94e5 485 memcpy(dstmac, neighbor, PICO_SIZE_ETH);
tass 152:a3d286bf94e5 486 retval = 0;
tass 152:a3d286bf94e5 487 }
tass picotcp@tass.be 149:5f4cb161cec3 488 }
tass picotcp@tass.be 149:5f4cb161cec3 489
tass picotcp@tass.be 149:5f4cb161cec3 490 #else
tass picotcp@tass.be 137:a1c8bfa9d691 491 (void)f;
tass picotcp@tass.be 149:5f4cb161cec3 492 pico_err = PICO_ERR_EPROTONOSUPPORT;
tass picotcp@tass.be 149:5f4cb161cec3 493 #endif
tass 152:a3d286bf94e5 494 return retval;
tass picotcp@tass.be 137:a1c8bfa9d691 495 }
tass picotcp@tass.be 137:a1c8bfa9d691 496
tass picotcp@tass.be 137:a1c8bfa9d691 497
tass 152:a3d286bf94e5 498 /* Ethernet send, first attempt: try our own address.
tass 152:a3d286bf94e5 499 * Returns 0 if the packet is not for us.
tass 152:a3d286bf94e5 500 * Returns 1 if the packet is cloned to our own receive queue, so the caller can discard the original frame.
tass 152:a3d286bf94e5 501 * */
tass 152:a3d286bf94e5 502 static int32_t pico_ethsend_local(struct pico_frame *f, struct pico_eth_hdr *hdr)
tass 152:a3d286bf94e5 503 {
tass 152:a3d286bf94e5 504 if (!hdr)
tass 152:a3d286bf94e5 505 return 0;
tass 68:0847e35d08a6 506
tass picotcp@tass.be 137:a1c8bfa9d691 507 /* Check own mac */
tass picotcp@tass.be 137:a1c8bfa9d691 508 if(!memcmp(hdr->daddr, hdr->saddr, PICO_SIZE_ETH)) {
tass 152:a3d286bf94e5 509 struct pico_frame *clone = pico_frame_copy(f);
tass picotcp@tass.be 137:a1c8bfa9d691 510 dbg("sending out packet destined for our own mac\n");
tass 152:a3d286bf94e5 511 (void)pico_ethernet_receive(clone);
tass picotcp@tass.be 137:a1c8bfa9d691 512 return 1;
tass picotcp@tass.be 137:a1c8bfa9d691 513 }
tass picotcp@tass.be 137:a1c8bfa9d691 514
tass picotcp@tass.be 137:a1c8bfa9d691 515 return 0;
tass picotcp@tass.be 137:a1c8bfa9d691 516 }
tass picotcp@tass.be 137:a1c8bfa9d691 517
tass 152:a3d286bf94e5 518 /* Ethernet send, second attempt: try bcast.
tass 152:a3d286bf94e5 519 * Returns 0 if the packet is not bcast, so it will be handled somewhere else.
tass 152:a3d286bf94e5 520 * Returns 1 if the packet is handled by the pico_device_broadcast() function, so it can be discarded.
tass 152:a3d286bf94e5 521 * */
tass 152:a3d286bf94e5 522 static int32_t pico_ethsend_bcast(struct pico_frame *f)
tass picotcp@tass.be 137:a1c8bfa9d691 523 {
tass picotcp@tass.be 137:a1c8bfa9d691 524 if (IS_LIMITED_BCAST(f)) {
tass 152:a3d286bf94e5 525 (void)pico_device_broadcast(f); /* We can discard broadcast even if it's not sent. */
tass picotcp@tass.be 137:a1c8bfa9d691 526 return 1;
tass picotcp@tass.be 137:a1c8bfa9d691 527 }
tass picotcp@tass.be 137:a1c8bfa9d691 528
tass picotcp@tass.be 137:a1c8bfa9d691 529 return 0;
tass picotcp@tass.be 137:a1c8bfa9d691 530 }
tass picotcp@tass.be 137:a1c8bfa9d691 531
tass 152:a3d286bf94e5 532 /* Ethernet send, third attempt: try unicast.
tass 152:a3d286bf94e5 533 * If the device driver is busy, we return 0, so the stack won't discard the frame.
tass 152:a3d286bf94e5 534 * In case of success, we can safely return 1.
tass 152:a3d286bf94e5 535 */
tass 152:a3d286bf94e5 536 static int32_t pico_ethsend_dispatch(struct pico_frame *f)
tass picotcp@tass.be 137:a1c8bfa9d691 537 {
tass 152:a3d286bf94e5 538 int ret = f->dev->send(f->dev, f->start, (int) f->len);
tass 152:a3d286bf94e5 539 if (ret <= 0)
tass 152:a3d286bf94e5 540 return 0; /* Failure to deliver! */
tass picotcp@tass.be 137:a1c8bfa9d691 541 else {
tass 152:a3d286bf94e5 542 return 1; /* Frame is in flight by now. */
tass picotcp@tass.be 137:a1c8bfa9d691 543 }
tass picotcp@tass.be 137:a1c8bfa9d691 544 }
tass picotcp@tass.be 137:a1c8bfa9d691 545
tass 152:a3d286bf94e5 546
tass 152:a3d286bf94e5 547
tass 152:a3d286bf94e5 548
tass 152:a3d286bf94e5 549 /* This function looks for the destination mac address
tass 152:a3d286bf94e5 550 * in order to send the frame being processed.
tass 152:a3d286bf94e5 551 */
tass 152:a3d286bf94e5 552
tass 152:a3d286bf94e5 553 int32_t MOCKABLE pico_ethernet_send(struct pico_frame *f)
tass 68:0847e35d08a6 554 {
tass 152:a3d286bf94e5 555 struct pico_eth dstmac;
tass 152:a3d286bf94e5 556 uint8_t dstmac_valid = 0;
tass picotcp@tass.be 149:5f4cb161cec3 557 uint16_t proto = PICO_IDETH_IPV4;
tass 68:0847e35d08a6 558
tass 152:a3d286bf94e5 559 #ifdef PICO_SUPPORT_IPV6
tass 152:a3d286bf94e5 560 /* Step 1: If the frame has an IPv6 packet,
tass 152:a3d286bf94e5 561 * destination address is taken from the ND tables
tass 152:a3d286bf94e5 562 */
tass picotcp@tass.be 149:5f4cb161cec3 563 if (IS_IPV6(f)) {
tass 152:a3d286bf94e5 564 if (pico_ethernet_ipv6_dst(f, &dstmac) < 0)
tass 152:a3d286bf94e5 565 {
tass 152:a3d286bf94e5 566 pico_ipv6_nd_postpone(f);
tass 152:a3d286bf94e5 567 return 0; /* I don't care if frame was actually postponed. If there is no room in the ND table, discard safely. */
tass 152:a3d286bf94e5 568 }
tass picotcp@tass.be 137:a1c8bfa9d691 569
tass 152:a3d286bf94e5 570 dstmac_valid = 1;
tass picotcp@tass.be 149:5f4cb161cec3 571 proto = PICO_IDETH_IPV6;
tass picotcp@tass.be 149:5f4cb161cec3 572 }
tass 152:a3d286bf94e5 573 else
tass 152:a3d286bf94e5 574 #endif
tass picotcp@tass.be 149:5f4cb161cec3 575
tass 152:a3d286bf94e5 576 /* In case of broadcast (IPV4 only), dst mac is FF:FF:... */
tass 152:a3d286bf94e5 577 if (IS_BCAST(f) || destination_is_bcast(f))
tass 152:a3d286bf94e5 578 {
tass 152:a3d286bf94e5 579 memcpy(&dstmac, PICO_ETHADDR_ALL, PICO_SIZE_ETH);
tass 152:a3d286bf94e5 580 dstmac_valid = 1;
tass 152:a3d286bf94e5 581 }
tass picotcp@tass.be 137:a1c8bfa9d691 582
tass 152:a3d286bf94e5 583 /* In case of multicast, dst mac is translated from the group address */
tass picotcp@tass.be 137:a1c8bfa9d691 584 else if (destination_is_mcast(f)) {
tass picotcp@tass.be 137:a1c8bfa9d691 585 uint8_t pico_mcast_mac[6] = {
tass picotcp@tass.be 137:a1c8bfa9d691 586 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00
tass picotcp@tass.be 137:a1c8bfa9d691 587 };
tass 152:a3d286bf94e5 588 pico_ethernet_mcast_translate(f, pico_mcast_mac);
tass 152:a3d286bf94e5 589 memcpy(&dstmac, pico_mcast_mac, PICO_SIZE_ETH);
tass 152:a3d286bf94e5 590 dstmac_valid = 1;
tass picotcp@tass.be 137:a1c8bfa9d691 591 }
tass 152:a3d286bf94e5 592
tass 152:a3d286bf94e5 593 #if (defined PICO_SUPPORT_IPV4)
tass picotcp@tass.be 137:a1c8bfa9d691 594 else {
tass 152:a3d286bf94e5 595 struct pico_eth *arp_get;
tass 152:a3d286bf94e5 596 arp_get = pico_arp_get(f);
tass 152:a3d286bf94e5 597 if (arp_get) {
tass 152:a3d286bf94e5 598 memcpy(&dstmac, arp_get, PICO_SIZE_ETH);
tass 152:a3d286bf94e5 599 dstmac_valid = 1;
tass 152:a3d286bf94e5 600 } else {
tass 152:a3d286bf94e5 601 /* At this point, ARP will discard the frame in any case.
tass 152:a3d286bf94e5 602 * It is safe to return without discarding.
tass 152:a3d286bf94e5 603 */
tass 152:a3d286bf94e5 604 pico_arp_postpone(f);
tass 152:a3d286bf94e5 605 return 0;
tass 152:a3d286bf94e5 606 /* Same case as for IPv6 ... */
tass 152:a3d286bf94e5 607 }
tass 152:a3d286bf94e5 608
tass 152:a3d286bf94e5 609 }
tass picotcp@tass.be 149:5f4cb161cec3 610 #endif
TASS Belgium NV 131:4758606c9316 611
tass picotcp@tass.be 137:a1c8bfa9d691 612 /* This sets destination and source address, then pushes the packet to the device. */
tass 152:a3d286bf94e5 613 if (dstmac_valid) {
tass picotcp@tass.be 137:a1c8bfa9d691 614 struct pico_eth_hdr *hdr;
tass picotcp@tass.be 137:a1c8bfa9d691 615 hdr = (struct pico_eth_hdr *) f->datalink_hdr;
tass 152:a3d286bf94e5 616 if ((f->start > f->buffer) && ((f->start - f->buffer) >= PICO_SIZE_ETHHDR))
tass 152:a3d286bf94e5 617 {
tass 152:a3d286bf94e5 618 f->start -= PICO_SIZE_ETHHDR;
tass 152:a3d286bf94e5 619 f->len += PICO_SIZE_ETHHDR;
tass 152:a3d286bf94e5 620 f->datalink_hdr = f->start;
tass 152:a3d286bf94e5 621 hdr = (struct pico_eth_hdr *) f->datalink_hdr;
tass 152:a3d286bf94e5 622 memcpy(hdr->saddr, f->dev->eth->mac.addr, PICO_SIZE_ETH);
tass 152:a3d286bf94e5 623 memcpy(hdr->daddr, &dstmac, PICO_SIZE_ETH);
tass 152:a3d286bf94e5 624 hdr->proto = proto;
tass 152:a3d286bf94e5 625 }
tass 68:0847e35d08a6 626
tass 152:a3d286bf94e5 627 if (pico_ethsend_local(f, hdr) || pico_ethsend_bcast(f) || pico_ethsend_dispatch(f)) {
tass 152:a3d286bf94e5 628 /* one of the above functions has delivered the frame accordingly. (returned != 0)
tass 152:a3d286bf94e5 629 * It is safe to directly return success.
tass 152:a3d286bf94e5 630 * */
tass 152:a3d286bf94e5 631 return 0;
TASS Belgium NV 131:4758606c9316 632 }
tass picotcp@tass.be 137:a1c8bfa9d691 633 }
TASS Belgium NV 131:4758606c9316 634
tass 152:a3d286bf94e5 635 /* Failure: do not dequeue the frame, keep it for later. */
TASS Belgium NV 131:4758606c9316 636 return -1;
tass 68:0847e35d08a6 637 }
tass 68:0847e35d08a6 638
tass 152:a3d286bf94e5 639 #endif /* PICO_SUPPORT_ETH */
tass 152:a3d286bf94e5 640
tass 152:a3d286bf94e5 641
tass 68:0847e35d08a6 642 void pico_store_network_origin(void *src, struct pico_frame *f)
tass 68:0847e35d08a6 643 {
tass 68:0847e35d08a6 644 #ifdef PICO_SUPPORT_IPV4
TASS Belgium NV 131:4758606c9316 645 struct pico_ip4 *ip4;
tass 68:0847e35d08a6 646 #endif
tass 68:0847e35d08a6 647
tass 68:0847e35d08a6 648 #ifdef PICO_SUPPORT_IPV6
TASS Belgium NV 131:4758606c9316 649 struct pico_ip6 *ip6;
tass 68:0847e35d08a6 650 #endif
tass 68:0847e35d08a6 651
tass 68:0847e35d08a6 652 #ifdef PICO_SUPPORT_IPV4
TASS Belgium NV 131:4758606c9316 653 if (IS_IPV4(f)) {
TASS Belgium NV 131:4758606c9316 654 struct pico_ipv4_hdr *hdr;
TASS Belgium NV 131:4758606c9316 655 hdr = (struct pico_ipv4_hdr *) f->net_hdr;
TASS Belgium NV 131:4758606c9316 656 ip4 = (struct pico_ip4 *) src;
TASS Belgium NV 131:4758606c9316 657 ip4->addr = hdr->src.addr;
TASS Belgium NV 131:4758606c9316 658 }
TASS Belgium NV 131:4758606c9316 659
tass 68:0847e35d08a6 660 #endif
tass 68:0847e35d08a6 661 #ifdef PICO_SUPPORT_IPV6
TASS Belgium NV 131:4758606c9316 662 if (IS_IPV6(f)) {
TASS Belgium NV 131:4758606c9316 663 struct pico_ipv6_hdr *hdr;
TASS Belgium NV 131:4758606c9316 664 hdr = (struct pico_ipv6_hdr *) f->net_hdr;
TASS Belgium NV 131:4758606c9316 665 ip6 = (struct pico_ip6 *) src;
TASS Belgium NV 131:4758606c9316 666 memcpy(ip6->addr, hdr->src.addr, PICO_SIZE_IP6);
TASS Belgium NV 131:4758606c9316 667 }
TASS Belgium NV 131:4758606c9316 668
tass 68:0847e35d08a6 669 #endif
tass 68:0847e35d08a6 670 }
tass 68:0847e35d08a6 671
tass 152:a3d286bf94e5 672 int pico_address_compare(union pico_address *a, union pico_address *b, uint16_t proto)
tass 152:a3d286bf94e5 673 {
tass 152:a3d286bf94e5 674 #ifdef PICO_SUPPORT_IPV6
tass 152:a3d286bf94e5 675 if (proto == PICO_PROTO_IPV6) {
tass 152:a3d286bf94e5 676 return pico_ipv6_compare(&a->ip6, &b->ip6);
tass 152:a3d286bf94e5 677 }
tass 152:a3d286bf94e5 678
tass 152:a3d286bf94e5 679 #endif
tass 152:a3d286bf94e5 680 #ifdef PICO_SUPPORT_IPV4
tass 152:a3d286bf94e5 681 if (proto == PICO_PROTO_IPV4) {
tass 152:a3d286bf94e5 682 return pico_ipv4_compare(&a->ip4, &b->ip4);
tass 152:a3d286bf94e5 683 }
tass 152:a3d286bf94e5 684
tass 152:a3d286bf94e5 685 #endif
tass 152:a3d286bf94e5 686 return 0;
tass 152:a3d286bf94e5 687
tass 152:a3d286bf94e5 688 }
tass 152:a3d286bf94e5 689
tass 152:a3d286bf94e5 690 int pico_frame_dst_is_unicast(struct pico_frame *f)
tass 152:a3d286bf94e5 691 {
tass 152:a3d286bf94e5 692 if (0) {
tass 152:a3d286bf94e5 693 return 0;
tass 152:a3d286bf94e5 694 }
tass 152:a3d286bf94e5 695
tass 152:a3d286bf94e5 696 #ifdef PICO_SUPPORT_IPV4
tass 152:a3d286bf94e5 697 if (IS_IPV4(f)) {
tass 152:a3d286bf94e5 698 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *)f->net_hdr;
tass 152:a3d286bf94e5 699 if (pico_ipv4_is_multicast(hdr->dst.addr) || pico_ipv4_is_broadcast(hdr->dst.addr))
tass 152:a3d286bf94e5 700 return 0;
tass 152:a3d286bf94e5 701
tass 152:a3d286bf94e5 702 return 1;
tass 152:a3d286bf94e5 703 }
tass 152:a3d286bf94e5 704
tass 152:a3d286bf94e5 705 #endif
tass 152:a3d286bf94e5 706
tass 152:a3d286bf94e5 707 #ifdef PICO_SUPPORT_IPV6
tass 152:a3d286bf94e5 708 if (IS_IPV6(f)) {
tass 152:a3d286bf94e5 709 struct pico_ipv6_hdr *hdr = (struct pico_ipv6_hdr *)f->net_hdr;
tass 152:a3d286bf94e5 710 if (pico_ipv6_is_multicast(hdr->dst.addr) || pico_ipv6_is_unspecified(hdr->dst.addr))
tass 152:a3d286bf94e5 711 return 0;
tass 152:a3d286bf94e5 712
tass 152:a3d286bf94e5 713 return 1;
tass 152:a3d286bf94e5 714 }
tass 152:a3d286bf94e5 715
tass 152:a3d286bf94e5 716 #endif
tass 152:a3d286bf94e5 717 else return 0;
tass 152:a3d286bf94e5 718 }
tass 152:a3d286bf94e5 719
tass 68:0847e35d08a6 720
tass 68:0847e35d08a6 721 /* LOWEST LEVEL: interface towards devices. */
tass 68:0847e35d08a6 722 /* Device driver will call this function which returns immediately.
tass 68:0847e35d08a6 723 * Incoming packet will be processed later on in the dev loop.
tass 68:0847e35d08a6 724 */
tass 70:cd218dd180e5 725 int32_t pico_stack_recv(struct pico_device *dev, uint8_t *buffer, uint32_t len)
tass 68:0847e35d08a6 726 {
TASS Belgium NV 131:4758606c9316 727 struct pico_frame *f;
TASS Belgium NV 131:4758606c9316 728 int32_t ret;
tass 154:6c0e92a80c4a 729 if (len == 0)
TASS Belgium NV 131:4758606c9316 730 return -1;
tass 68:0847e35d08a6 731
TASS Belgium NV 131:4758606c9316 732 f = pico_frame_alloc(len);
TASS Belgium NV 131:4758606c9316 733 if (!f)
tass picotcp@tass.be 137:a1c8bfa9d691 734 {
tass picotcp@tass.be 137:a1c8bfa9d691 735 dbg("Cannot alloc incoming frame!\n");
TASS Belgium NV 131:4758606c9316 736 return -1;
tass picotcp@tass.be 137:a1c8bfa9d691 737 }
TASS Belgium NV 131:4758606c9316 738
TASS Belgium NV 131:4758606c9316 739 /* Association to the device that just received the frame. */
TASS Belgium NV 131:4758606c9316 740 f->dev = dev;
tass 68:0847e35d08a6 741
tass picotcp@tass.be 137:a1c8bfa9d691 742 /* Setup the start pointer, length. */
TASS Belgium NV 131:4758606c9316 743 f->start = f->buffer;
TASS Belgium NV 131:4758606c9316 744 f->len = f->buffer_len;
TASS Belgium NV 131:4758606c9316 745 if (f->len > 8) {
tass 152:a3d286bf94e5 746 uint32_t rand, mid_frame = (f->buffer_len >> 2) << 1;
TASS Belgium NV 131:4758606c9316 747 mid_frame -= (mid_frame % 4);
tass 152:a3d286bf94e5 748 memcpy(&rand, f->buffer + mid_frame, sizeof(uint32_t));
tass 152:a3d286bf94e5 749 pico_rand_feed(rand);
TASS Belgium NV 131:4758606c9316 750 }
TASS Belgium NV 131:4758606c9316 751
TASS Belgium NV 131:4758606c9316 752 memcpy(f->buffer, buffer, len);
TASS Belgium NV 131:4758606c9316 753 ret = pico_enqueue(dev->q_in, f);
TASS Belgium NV 131:4758606c9316 754 if (ret <= 0) {
TASS Belgium NV 131:4758606c9316 755 pico_frame_discard(f);
TASS Belgium NV 131:4758606c9316 756 }
TASS Belgium NV 131:4758606c9316 757
TASS Belgium NV 131:4758606c9316 758 return ret;
tass 68:0847e35d08a6 759 }
tass 68:0847e35d08a6 760
tass 152:a3d286bf94e5 761 static int32_t _pico_stack_recv_zerocopy(struct pico_device *dev, uint8_t *buffer, uint32_t len, int ext_buffer, void (*notify_free)(uint8_t *))
tass picotcp@tass.be 149:5f4cb161cec3 762 {
tass picotcp@tass.be 149:5f4cb161cec3 763 struct pico_frame *f;
tass picotcp@tass.be 149:5f4cb161cec3 764 int ret;
tass 154:6c0e92a80c4a 765 if (len == 0)
tass picotcp@tass.be 149:5f4cb161cec3 766 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 767
tass 152:a3d286bf94e5 768 f = pico_frame_alloc_skeleton(len, ext_buffer);
tass picotcp@tass.be 149:5f4cb161cec3 769 if (!f)
tass picotcp@tass.be 149:5f4cb161cec3 770 {
tass picotcp@tass.be 149:5f4cb161cec3 771 dbg("Cannot alloc incoming frame!\n");
tass picotcp@tass.be 149:5f4cb161cec3 772 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 773 }
tass picotcp@tass.be 149:5f4cb161cec3 774
tass picotcp@tass.be 149:5f4cb161cec3 775 if (pico_frame_skeleton_set_buffer(f, buffer) < 0)
tass picotcp@tass.be 149:5f4cb161cec3 776 {
tass picotcp@tass.be 149:5f4cb161cec3 777 dbg("Invalid zero-copy buffer!\n");
tass picotcp@tass.be 149:5f4cb161cec3 778 PICO_FREE(f->usage_count);
tass picotcp@tass.be 149:5f4cb161cec3 779 PICO_FREE(f);
tass picotcp@tass.be 149:5f4cb161cec3 780 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 781 }
tass picotcp@tass.be 149:5f4cb161cec3 782
tass 152:a3d286bf94e5 783 if (notify_free) {
tass 152:a3d286bf94e5 784 f->notify_free = notify_free;
tass 152:a3d286bf94e5 785 }
tass 152:a3d286bf94e5 786
tass picotcp@tass.be 149:5f4cb161cec3 787 f->dev = dev;
tass picotcp@tass.be 149:5f4cb161cec3 788 ret = pico_enqueue(dev->q_in, f);
tass picotcp@tass.be 149:5f4cb161cec3 789 if (ret <= 0) {
tass picotcp@tass.be 149:5f4cb161cec3 790 pico_frame_discard(f);
tass picotcp@tass.be 149:5f4cb161cec3 791 }
tass picotcp@tass.be 149:5f4cb161cec3 792
tass picotcp@tass.be 149:5f4cb161cec3 793 return ret;
tass picotcp@tass.be 149:5f4cb161cec3 794 }
tass picotcp@tass.be 149:5f4cb161cec3 795
tass 152:a3d286bf94e5 796 int32_t pico_stack_recv_zerocopy(struct pico_device *dev, uint8_t *buffer, uint32_t len)
tass 152:a3d286bf94e5 797 {
tass 152:a3d286bf94e5 798 return _pico_stack_recv_zerocopy(dev, buffer, len, 0, NULL);
tass 152:a3d286bf94e5 799 }
tass 152:a3d286bf94e5 800
tass 152:a3d286bf94e5 801 int32_t pico_stack_recv_zerocopy_ext_buffer(struct pico_device *dev, uint8_t *buffer, uint32_t len)
tass 152:a3d286bf94e5 802 {
tass 152:a3d286bf94e5 803 return _pico_stack_recv_zerocopy(dev, buffer, len, 1, NULL);
tass 152:a3d286bf94e5 804 }
tass 152:a3d286bf94e5 805
tass 152:a3d286bf94e5 806 int32_t pico_stack_recv_zerocopy_ext_buffer_notify(struct pico_device *dev, uint8_t *buffer, uint32_t len, void (*notify_free)(uint8_t *buffer))
tass 152:a3d286bf94e5 807 {
tass 152:a3d286bf94e5 808 return _pico_stack_recv_zerocopy(dev, buffer, len, 1, notify_free);
tass 152:a3d286bf94e5 809 }
tass 152:a3d286bf94e5 810
tass 70:cd218dd180e5 811 int32_t pico_sendto_dev(struct pico_frame *f)
tass 68:0847e35d08a6 812 {
TASS Belgium NV 131:4758606c9316 813 if (!f->dev) {
TASS Belgium NV 131:4758606c9316 814 pico_frame_discard(f);
TASS Belgium NV 131:4758606c9316 815 return -1;
TASS Belgium NV 131:4758606c9316 816 } else {
TASS Belgium NV 131:4758606c9316 817 if (f->len > 8) {
tass 152:a3d286bf94e5 818 uint32_t rand, mid_frame = (f->buffer_len >> 2) << 1;
TASS Belgium NV 131:4758606c9316 819 mid_frame -= (mid_frame % 4);
tass 152:a3d286bf94e5 820 memcpy(&rand, f->buffer + mid_frame, sizeof(uint32_t));
tass 152:a3d286bf94e5 821 pico_rand_feed(rand);
TASS Belgium NV 131:4758606c9316 822 }
TASS Belgium NV 131:4758606c9316 823
TASS Belgium NV 131:4758606c9316 824 return pico_enqueue(f->dev->q_out, f);
tass 68:0847e35d08a6 825 }
tass 68:0847e35d08a6 826 }
tass 68:0847e35d08a6 827
tass 68:0847e35d08a6 828 struct pico_timer
tass 68:0847e35d08a6 829 {
TASS Belgium NV 131:4758606c9316 830 void *arg;
TASS Belgium NV 131:4758606c9316 831 void (*timer)(pico_time timestamp, void *arg);
tass 68:0847e35d08a6 832 };
tass 68:0847e35d08a6 833
tass 70:cd218dd180e5 834 struct pico_timer_ref
tass 70:cd218dd180e5 835 {
TASS Belgium NV 131:4758606c9316 836 pico_time expire;
TASS Belgium NV 131:4758606c9316 837 struct pico_timer *tmr;
tass 70:cd218dd180e5 838 };
tass 68:0847e35d08a6 839
tass 70:cd218dd180e5 840 typedef struct pico_timer_ref pico_timer_ref;
tass 68:0847e35d08a6 841
tass 70:cd218dd180e5 842 DECLARE_HEAP(pico_timer_ref, expire);
tass 70:cd218dd180e5 843
tass 70:cd218dd180e5 844 static heap_pico_timer_ref *Timers;
tass 68:0847e35d08a6 845
tass 152:a3d286bf94e5 846 int32_t pico_seq_compare(uint32_t a, uint32_t b)
tass 152:a3d286bf94e5 847 {
tass 152:a3d286bf94e5 848 uint32_t thresh = ((uint32_t)(-1)) >> 1;
tass 152:a3d286bf94e5 849
tass 152:a3d286bf94e5 850 if (a > b) /* return positive number, if not wrapped */
tass 152:a3d286bf94e5 851 {
tass 152:a3d286bf94e5 852 if ((a - b) > thresh) /* b wrapped */
tass 152:a3d286bf94e5 853 return -(int32_t)(b - a); /* b = very small, a = very big */
tass 152:a3d286bf94e5 854 else
tass 152:a3d286bf94e5 855 return (int32_t)(a - b); /* a = biggest, b = a bit smaller */
tass 152:a3d286bf94e5 856
tass 152:a3d286bf94e5 857 }
tass 152:a3d286bf94e5 858
tass 152:a3d286bf94e5 859 if (a < b) /* return negative number, if not wrapped */
tass 152:a3d286bf94e5 860 {
tass 152:a3d286bf94e5 861 if ((b - a) > thresh) /* a wrapped */
tass 152:a3d286bf94e5 862 return (int32_t)(a - b); /* a = very small, b = very big */
tass 152:a3d286bf94e5 863 else
tass 152:a3d286bf94e5 864 return -(int32_t)(b - a); /* b = biggest, a = a bit smaller */
tass 152:a3d286bf94e5 865
tass 152:a3d286bf94e5 866 }
tass 152:a3d286bf94e5 867
tass 152:a3d286bf94e5 868 return 0;
tass 152:a3d286bf94e5 869 }
tass 152:a3d286bf94e5 870
tass 152:a3d286bf94e5 871 static void pico_check_timers(void)
tass 68:0847e35d08a6 872 {
TASS Belgium NV 131:4758606c9316 873 struct pico_timer *t;
TASS Belgium NV 131:4758606c9316 874 struct pico_timer_ref tref_unused, *tref = heap_first(Timers);
TASS Belgium NV 131:4758606c9316 875 pico_tick = PICO_TIME_MS();
TASS Belgium NV 131:4758606c9316 876 while((tref) && (tref->expire < pico_tick)) {
TASS Belgium NV 131:4758606c9316 877 t = tref->tmr;
TASS Belgium NV 131:4758606c9316 878 if (t && t->timer)
TASS Belgium NV 131:4758606c9316 879 t->timer(pico_tick, t->arg);
TASS Belgium NV 131:4758606c9316 880
TASS Belgium NV 131:4758606c9316 881 if (t)
tass 152:a3d286bf94e5 882 {
tass picotcp@tass.be 149:5f4cb161cec3 883 PICO_FREE(t);
tass 152:a3d286bf94e5 884 }
TASS Belgium NV 131:4758606c9316 885
TASS Belgium NV 131:4758606c9316 886 t = NULL;
TASS Belgium NV 131:4758606c9316 887 heap_peek(Timers, &tref_unused);
TASS Belgium NV 131:4758606c9316 888 tref = heap_first(Timers);
TASS Belgium NV 131:4758606c9316 889 }
tass 70:cd218dd180e5 890 }
tass 70:cd218dd180e5 891
tass 152:a3d286bf94e5 892 void MOCKABLE pico_timer_cancel(struct pico_timer *t)
tass 70:cd218dd180e5 893 {
TASS Belgium NV 131:4758606c9316 894 uint32_t i;
TASS Belgium NV 131:4758606c9316 895 struct pico_timer_ref *tref = Timers->top;
TASS Belgium NV 131:4758606c9316 896 if (!t)
TASS Belgium NV 131:4758606c9316 897 return;
TASS Belgium NV 131:4758606c9316 898
TASS Belgium NV 131:4758606c9316 899 for (i = 1; i <= Timers->n; i++) {
TASS Belgium NV 131:4758606c9316 900 if (tref[i].tmr == t) {
TASS Belgium NV 131:4758606c9316 901 Timers->top[i].tmr = NULL;
tass picotcp@tass.be 149:5f4cb161cec3 902 PICO_FREE(t);
TASS Belgium NV 131:4758606c9316 903 break;
TASS Belgium NV 131:4758606c9316 904 }
tass 70:cd218dd180e5 905 }
tass 68:0847e35d08a6 906 }
tass 68:0847e35d08a6 907
tass 68:0847e35d08a6 908 #define PROTO_DEF_NR 11
tass 68:0847e35d08a6 909 #define PROTO_DEF_AVG_NR 4
tass 68:0847e35d08a6 910 #define PROTO_DEF_SCORE 32
tass 68:0847e35d08a6 911 #define PROTO_MIN_SCORE 32
tass 68:0847e35d08a6 912 #define PROTO_MAX_SCORE 128
tass 152:a3d286bf94e5 913 #define PROTO_LAT_IND 3 /* latency indication 0-3 (lower is better latency performance), x1, x2, x4, x8 */
TASS Belgium NV 131:4758606c9316 914 #define PROTO_MAX_LOOP (PROTO_MAX_SCORE << PROTO_LAT_IND) /* max global loop score, so per tick */
tass 68:0847e35d08a6 915
tass 68:0847e35d08a6 916 static int calc_score(int *score, int *index, int avg[][PROTO_DEF_AVG_NR], int *ret)
tass 68:0847e35d08a6 917 {
TASS Belgium NV 131:4758606c9316 918 int temp, i, j, sum;
TASS Belgium NV 131:4758606c9316 919 int max_total = PROTO_MAX_LOOP, total = 0;
tass 68:0847e35d08a6 920
TASS Belgium NV 131:4758606c9316 921 /* dbg("USED SCORES> "); */
tass 68:0847e35d08a6 922
TASS Belgium NV 131:4758606c9316 923 for (i = 0; i < PROTO_DEF_NR; i++) {
tass 68:0847e35d08a6 924
TASS Belgium NV 131:4758606c9316 925 /* if used looped score */
TASS Belgium NV 131:4758606c9316 926 if (ret[i] < score[i]) {
TASS Belgium NV 131:4758606c9316 927 temp = score[i] - ret[i]; /* remaining loop score */
TASS Belgium NV 131:4758606c9316 928
TASS Belgium NV 131:4758606c9316 929 /* dbg("%3d - ",temp); */
tass 68:0847e35d08a6 930
TASS Belgium NV 131:4758606c9316 931 if (index[i] >= PROTO_DEF_AVG_NR)
TASS Belgium NV 131:4758606c9316 932 index[i] = 0; /* reset index */
TASS Belgium NV 131:4758606c9316 933
TASS Belgium NV 131:4758606c9316 934 j = index[i];
TASS Belgium NV 131:4758606c9316 935 avg[i][j] = temp;
tass 68:0847e35d08a6 936
TASS Belgium NV 131:4758606c9316 937 index[i]++;
tass 68:0847e35d08a6 938
tass picotcp@tass.be 149:5f4cb161cec3 939 if (ret[i] == 0 && ((score[i] * 2) <= PROTO_MAX_SCORE) && ((total + (score[i] * 2)) < max_total)) { /* used all loop score -> increase next score directly */
tass picotcp@tass.be 149:5f4cb161cec3 940 score[i] *= 2;
TASS Belgium NV 131:4758606c9316 941 total += score[i];
TASS Belgium NV 131:4758606c9316 942 continue;
TASS Belgium NV 131:4758606c9316 943 }
tass 68:0847e35d08a6 944
TASS Belgium NV 131:4758606c9316 945 sum = 0;
TASS Belgium NV 131:4758606c9316 946 for (j = 0; j < PROTO_DEF_AVG_NR; j++)
TASS Belgium NV 131:4758606c9316 947 sum += avg[i][j]; /* calculate sum */
tass 68:0847e35d08a6 948
tass picotcp@tass.be 149:5f4cb161cec3 949 sum /= 4; /* divide by 4 to get average used score */
tass 68:0847e35d08a6 950
TASS Belgium NV 131:4758606c9316 951 /* criterion to increase next loop score */
tass picotcp@tass.be 149:5f4cb161cec3 952 if (sum > (score[i] - (score[i] / 4)) && ((score[i] * 2) <= PROTO_MAX_SCORE) && ((total + (score[i] / 2)) < max_total)) { /* > 3/4 */
tass picotcp@tass.be 149:5f4cb161cec3 953 score[i] *= 2; /* double loop score */
TASS Belgium NV 131:4758606c9316 954 total += score[i];
TASS Belgium NV 131:4758606c9316 955 continue;
TASS Belgium NV 131:4758606c9316 956 }
tass 68:0847e35d08a6 957
TASS Belgium NV 131:4758606c9316 958 /* criterion to decrease next loop score */
tass picotcp@tass.be 149:5f4cb161cec3 959 if ((sum < (score[i] / 4)) && ((score[i] / 2) >= PROTO_MIN_SCORE)) { /* < 1/4 */
tass picotcp@tass.be 149:5f4cb161cec3 960 score[i] /= 2; /* half loop score */
TASS Belgium NV 131:4758606c9316 961 total += score[i];
TASS Belgium NV 131:4758606c9316 962 continue;
TASS Belgium NV 131:4758606c9316 963 }
tass 68:0847e35d08a6 964
TASS Belgium NV 131:4758606c9316 965 /* also add non-changed scores */
TASS Belgium NV 131:4758606c9316 966 total += score[i];
TASS Belgium NV 131:4758606c9316 967 }
TASS Belgium NV 131:4758606c9316 968 else if (ret[i] == score[i]) {
TASS Belgium NV 131:4758606c9316 969 /* no used loop score - gradually decrease */
tass 68:0847e35d08a6 970
TASS Belgium NV 131:4758606c9316 971 /* dbg("%3d - ",0); */
TASS Belgium NV 131:4758606c9316 972
TASS Belgium NV 131:4758606c9316 973 if (index[i] >= PROTO_DEF_AVG_NR)
TASS Belgium NV 131:4758606c9316 974 index[i] = 0; /* reset index */
TASS Belgium NV 131:4758606c9316 975
TASS Belgium NV 131:4758606c9316 976 j = index[i];
TASS Belgium NV 131:4758606c9316 977 avg[i][j] = 0;
tass 68:0847e35d08a6 978
TASS Belgium NV 131:4758606c9316 979 index[i]++;
tass 68:0847e35d08a6 980
TASS Belgium NV 131:4758606c9316 981 sum = 0;
TASS Belgium NV 131:4758606c9316 982 for (j = 0; j < PROTO_DEF_AVG_NR; j++)
TASS Belgium NV 131:4758606c9316 983 sum += avg[i][j]; /* calculate sum */
tass 68:0847e35d08a6 984
tass picotcp@tass.be 149:5f4cb161cec3 985 sum /= 2; /* divide by 4 to get average used score */
tass 68:0847e35d08a6 986
tass picotcp@tass.be 149:5f4cb161cec3 987 if ((sum == 0) && ((score[i] / 2) >= PROTO_MIN_SCORE)) {
tass picotcp@tass.be 149:5f4cb161cec3 988 score[i] /= 2; /* half loop score */
TASS Belgium NV 131:4758606c9316 989 total += score[i];
TASS Belgium NV 131:4758606c9316 990 for (j = 0; j < PROTO_DEF_AVG_NR; j++)
TASS Belgium NV 131:4758606c9316 991 avg[i][j] = score[i];
TASS Belgium NV 131:4758606c9316 992 }
TASS Belgium NV 131:4758606c9316 993
TASS Belgium NV 131:4758606c9316 994 }
tass 68:0847e35d08a6 995 }
TASS Belgium NV 131:4758606c9316 996 /* dbg("\n"); */
tass 68:0847e35d08a6 997
TASS Belgium NV 131:4758606c9316 998 return 0;
tass 68:0847e35d08a6 999 }
tass 68:0847e35d08a6 1000
tass 68:0847e35d08a6 1001 void pico_stack_tick(void)
tass 68:0847e35d08a6 1002 {
TASS Belgium NV 131:4758606c9316 1003 static int score[PROTO_DEF_NR] = {
TASS Belgium NV 131:4758606c9316 1004 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 1005 };
TASS Belgium NV 131:4758606c9316 1006 static int index[PROTO_DEF_NR] = {
TASS Belgium NV 131:4758606c9316 1007 0, 0, 0, 0, 0, 0
TASS Belgium NV 131:4758606c9316 1008 };
tass 68:0847e35d08a6 1009 static int avg[PROTO_DEF_NR][PROTO_DEF_AVG_NR];
TASS Belgium NV 131:4758606c9316 1010 static int ret[PROTO_DEF_NR] = {
TASS Belgium NV 131:4758606c9316 1011 0
TASS Belgium NV 131:4758606c9316 1012 };
tass 68:0847e35d08a6 1013
tass 68:0847e35d08a6 1014 pico_check_timers();
tass 68:0847e35d08a6 1015
TASS Belgium NV 131:4758606c9316 1016 /* 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 1017
TASS Belgium NV 131:4758606c9316 1018 /* score = pico_protocols_loop(100); */
tass 68:0847e35d08a6 1019
TASS Belgium NV 131:4758606c9316 1020 ret[0] = pico_devices_loop(score[0], PICO_LOOP_DIR_IN);
tass 70:cd218dd180e5 1021 pico_rand_feed((uint32_t)ret[0]);
tass 68:0847e35d08a6 1022
tass 68:0847e35d08a6 1023 ret[1] = pico_protocol_datalink_loop(score[1], PICO_LOOP_DIR_IN);
tass 70:cd218dd180e5 1024 pico_rand_feed((uint32_t)ret[1]);
tass 68:0847e35d08a6 1025
tass 68:0847e35d08a6 1026 ret[2] = pico_protocol_network_loop(score[2], PICO_LOOP_DIR_IN);
tass 70:cd218dd180e5 1027 pico_rand_feed((uint32_t)ret[2]);
tass 68:0847e35d08a6 1028
tass 68:0847e35d08a6 1029 ret[3] = pico_protocol_transport_loop(score[3], PICO_LOOP_DIR_IN);
tass 70:cd218dd180e5 1030 pico_rand_feed((uint32_t)ret[3]);
tass 68:0847e35d08a6 1031
tass 68:0847e35d08a6 1032
tass 68:0847e35d08a6 1033 ret[5] = score[5];
tass 68:0847e35d08a6 1034 #if defined (PICO_SUPPORT_IPV4) || defined (PICO_SUPPORT_IPV6)
tass 68:0847e35d08a6 1035 #if defined (PICO_SUPPORT_TCP) || defined (PICO_SUPPORT_UDP)
TASS Belgium NV 131:4758606c9316 1036 ret[5] = pico_sockets_loop(score[5]); /* swapped */
tass 70:cd218dd180e5 1037 pico_rand_feed((uint32_t)ret[5]);
tass 68:0847e35d08a6 1038 #endif
tass 68:0847e35d08a6 1039 #endif
tass 68:0847e35d08a6 1040
tass 68:0847e35d08a6 1041 ret[4] = pico_protocol_socket_loop(score[4], PICO_LOOP_DIR_IN);
tass 70:cd218dd180e5 1042 pico_rand_feed((uint32_t)ret[4]);
tass 68:0847e35d08a6 1043
tass 68:0847e35d08a6 1044
tass 68:0847e35d08a6 1045 ret[6] = pico_protocol_socket_loop(score[6], PICO_LOOP_DIR_OUT);
tass 70:cd218dd180e5 1046 pico_rand_feed((uint32_t)ret[6]);
tass 68:0847e35d08a6 1047
tass 68:0847e35d08a6 1048 ret[7] = pico_protocol_transport_loop(score[7], PICO_LOOP_DIR_OUT);
tass 70:cd218dd180e5 1049 pico_rand_feed((uint32_t)ret[7]);
tass 68:0847e35d08a6 1050
tass 68:0847e35d08a6 1051 ret[8] = pico_protocol_network_loop(score[8], PICO_LOOP_DIR_OUT);
tass 70:cd218dd180e5 1052 pico_rand_feed((uint32_t)ret[8]);
tass 68:0847e35d08a6 1053
tass 68:0847e35d08a6 1054 ret[9] = pico_protocol_datalink_loop(score[9], PICO_LOOP_DIR_OUT);
tass 70:cd218dd180e5 1055 pico_rand_feed((uint32_t)ret[9]);
tass 68:0847e35d08a6 1056
TASS Belgium NV 131:4758606c9316 1057 ret[10] = pico_devices_loop(score[10], PICO_LOOP_DIR_OUT);
tass 70:cd218dd180e5 1058 pico_rand_feed((uint32_t)ret[10]);
tass 68:0847e35d08a6 1059
tass 68:0847e35d08a6 1060 /* calculate new loop scores for next iteration */
TASS Belgium NV 131:4758606c9316 1061 calc_score(score, index, (int (*)[])avg, ret);
tass 68:0847e35d08a6 1062 }
tass 68:0847e35d08a6 1063
tass 68:0847e35d08a6 1064 void pico_stack_loop(void)
tass 68:0847e35d08a6 1065 {
TASS Belgium NV 131:4758606c9316 1066 while(1) {
TASS Belgium NV 131:4758606c9316 1067 pico_stack_tick();
TASS Belgium NV 131:4758606c9316 1068 PICO_IDLE();
TASS Belgium NV 131:4758606c9316 1069 }
tass 68:0847e35d08a6 1070 }
tass 68:0847e35d08a6 1071
tass 152:a3d286bf94e5 1072 MOCKABLE struct pico_timer *pico_timer_add(pico_time expire, void (*timer)(pico_time, void *), void *arg)
tass 68:0847e35d08a6 1073 {
tass picotcp@tass.be 149:5f4cb161cec3 1074 struct pico_timer *t = PICO_ZALLOC(sizeof(struct pico_timer));
TASS Belgium NV 131:4758606c9316 1075 struct pico_timer_ref tref;
TASS Belgium NV 131:4758606c9316 1076 if (!t) {
TASS Belgium NV 131:4758606c9316 1077 pico_err = PICO_ERR_ENOMEM;
TASS Belgium NV 131:4758606c9316 1078 return NULL;
TASS Belgium NV 131:4758606c9316 1079 }
TASS Belgium NV 131:4758606c9316 1080
TASS Belgium NV 131:4758606c9316 1081 tref.expire = PICO_TIME_MS() + expire;
TASS Belgium NV 131:4758606c9316 1082 t->arg = arg;
TASS Belgium NV 131:4758606c9316 1083 t->timer = timer;
TASS Belgium NV 131:4758606c9316 1084 tref.tmr = t;
tass picotcp@tass.be 138:0a7a449980e6 1085 heap_insert(Timers, &tref);
TASS Belgium NV 131:4758606c9316 1086 if (Timers->n > PICO_MAX_TIMERS) {
tass 152:a3d286bf94e5 1087 dbg("Warning: I have %d timers\n", (int)Timers->n);
TASS Belgium NV 131:4758606c9316 1088 }
TASS Belgium NV 131:4758606c9316 1089
TASS Belgium NV 131:4758606c9316 1090 return t;
tass 68:0847e35d08a6 1091 }
tass 68:0847e35d08a6 1092
tass picotcp@tass.be 149:5f4cb161cec3 1093 int pico_stack_init(void)
tass 68:0847e35d08a6 1094 {
tass 68:0847e35d08a6 1095
tass 68:0847e35d08a6 1096 #ifdef PICO_SUPPORT_IPV4
TASS Belgium NV 131:4758606c9316 1097 pico_protocol_init(&pico_proto_ipv4);
tass 68:0847e35d08a6 1098 #endif
tass 68:0847e35d08a6 1099
tass 68:0847e35d08a6 1100 #ifdef PICO_SUPPORT_IPV6
TASS Belgium NV 131:4758606c9316 1101 pico_protocol_init(&pico_proto_ipv6);
tass 68:0847e35d08a6 1102 #endif
tass 68:0847e35d08a6 1103
tass 68:0847e35d08a6 1104 #ifdef PICO_SUPPORT_ICMP4
TASS Belgium NV 131:4758606c9316 1105 pico_protocol_init(&pico_proto_icmp4);
tass 68:0847e35d08a6 1106 #endif
tass 68:0847e35d08a6 1107
tass picotcp@tass.be 149:5f4cb161cec3 1108 #ifdef PICO_SUPPORT_ICMP6
tass picotcp@tass.be 149:5f4cb161cec3 1109 pico_protocol_init(&pico_proto_icmp6);
tass picotcp@tass.be 149:5f4cb161cec3 1110 #endif
tass picotcp@tass.be 149:5f4cb161cec3 1111
tass 152:a3d286bf94e5 1112 #if defined(PICO_SUPPORT_IGMP) && defined(PICO_SUPPORT_MCAST)
TASS Belgium NV 131:4758606c9316 1113 pico_protocol_init(&pico_proto_igmp);
tass 68:0847e35d08a6 1114 #endif
tass 68:0847e35d08a6 1115
tass 68:0847e35d08a6 1116 #ifdef PICO_SUPPORT_UDP
TASS Belgium NV 131:4758606c9316 1117 pico_protocol_init(&pico_proto_udp);
tass 68:0847e35d08a6 1118 #endif
tass 68:0847e35d08a6 1119
tass 68:0847e35d08a6 1120 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 1121 pico_protocol_init(&pico_proto_tcp);
tass 68:0847e35d08a6 1122 #endif
tass 68:0847e35d08a6 1123
tass 68:0847e35d08a6 1124 #ifdef PICO_SUPPORT_DNS_CLIENT
TASS Belgium NV 131:4758606c9316 1125 pico_dns_client_init();
tass 68:0847e35d08a6 1126 #endif
tass 68:0847e35d08a6 1127
TASS Belgium NV 131:4758606c9316 1128 pico_rand_feed(123456);
tass 68:0847e35d08a6 1129
TASS Belgium NV 131:4758606c9316 1130 /* Initialize timer heap */
TASS Belgium NV 131:4758606c9316 1131 Timers = heap_init();
tass picotcp@tass.be 149:5f4cb161cec3 1132 if (!Timers)
tass picotcp@tass.be 149:5f4cb161cec3 1133 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 1134
tass picotcp@tass.be 149:5f4cb161cec3 1135 #if ((defined PICO_SUPPORT_IPV4) && (defined PICO_SUPPORT_ETH))
tass picotcp@tass.be 149:5f4cb161cec3 1136 /* Initialize ARP module */
tass picotcp@tass.be 133:5b075f5e141a 1137 pico_arp_init();
tass picotcp@tass.be 149:5f4cb161cec3 1138 #endif
tass picotcp@tass.be 149:5f4cb161cec3 1139
tass picotcp@tass.be 149:5f4cb161cec3 1140 #ifdef PICO_SUPPORT_IPV6
tass picotcp@tass.be 149:5f4cb161cec3 1141 /* Initialize Neighbor discovery module */
tass picotcp@tass.be 149:5f4cb161cec3 1142 pico_ipv6_nd_init();
tass picotcp@tass.be 149:5f4cb161cec3 1143 #endif
tass 152:a3d286bf94e5 1144
tass 152:a3d286bf94e5 1145 #ifdef PICO_SUPPORT_OLSR
tass 152:a3d286bf94e5 1146 pico_olsr_init();
tass 152:a3d286bf94e5 1147 #endif
tass 152:a3d286bf94e5 1148 #ifdef PICO_SUPPORT_AODV
tass 152:a3d286bf94e5 1149 pico_aodv_init();
tass 152:a3d286bf94e5 1150 #endif
tass 152:a3d286bf94e5 1151
TASS Belgium NV 131:4758606c9316 1152 pico_stack_tick();
TASS Belgium NV 131:4758606c9316 1153 pico_stack_tick();
TASS Belgium NV 131:4758606c9316 1154 pico_stack_tick();
tass picotcp@tass.be 149:5f4cb161cec3 1155 return 0;
tass 68:0847e35d08a6 1156 }
tass 68:0847e35d08a6 1157