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