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 #include "pico_config.h"
tass 68:0847e35d08a6 11 #include "pico_device.h"
tass 68:0847e35d08a6 12 #include "pico_stack.h"
tass 68:0847e35d08a6 13 #include "pico_protocol.h"
tass 68:0847e35d08a6 14 #include "pico_tree.h"
tass picotcp@tass.be 149:5f4cb161cec3 15 #include "pico_ipv6.h"
tass picotcp@tass.be 149:5f4cb161cec3 16 #include "pico_ipv4.h"
tass picotcp@tass.be 149:5f4cb161cec3 17 #include "pico_icmp6.h"
tass 152:a3d286bf94e5 18 #include "pico_eth.h"
tass 152:a3d286bf94e5 19 #define PICO_DEVICE_DEFAULT_MTU (1500)
tass 68:0847e35d08a6 20
tass picotcp@tass.be 137:a1c8bfa9d691 21 struct pico_devices_rr_info {
tass picotcp@tass.be 137:a1c8bfa9d691 22 struct pico_tree_node *node_in, *node_out;
tass picotcp@tass.be 137:a1c8bfa9d691 23 };
tass picotcp@tass.be 137:a1c8bfa9d691 24
tass picotcp@tass.be 137:a1c8bfa9d691 25 static struct pico_devices_rr_info Devices_rr_info = {
tass picotcp@tass.be 137:a1c8bfa9d691 26 NULL, NULL
tass picotcp@tass.be 137:a1c8bfa9d691 27 };
tass 68:0847e35d08a6 28
tass 68:0847e35d08a6 29 static int pico_dev_cmp(void *ka, void *kb)
tass 68:0847e35d08a6 30 {
TASS Belgium NV 131:4758606c9316 31 struct pico_device *a = ka, *b = kb;
TASS Belgium NV 131:4758606c9316 32 if (a->hash < b->hash)
TASS Belgium NV 131:4758606c9316 33 return -1;
TASS Belgium NV 131:4758606c9316 34
TASS Belgium NV 131:4758606c9316 35 if (a->hash > b->hash)
TASS Belgium NV 131:4758606c9316 36 return 1;
TASS Belgium NV 131:4758606c9316 37
TASS Belgium NV 131:4758606c9316 38 return 0;
tass 68:0847e35d08a6 39 }
tass 68:0847e35d08a6 40
TASS Belgium NV 131:4758606c9316 41 PICO_TREE_DECLARE(Device_tree, pico_dev_cmp);
tass 68:0847e35d08a6 42
tass 152:a3d286bf94e5 43 #ifdef PICO_SUPPORT_IPV6
tass 152:a3d286bf94e5 44 static void device_init_ipv6_final(struct pico_device *dev, struct pico_ip6 *linklocal)
tass 152:a3d286bf94e5 45 {
tass 152:a3d286bf94e5 46 dev->hostvars.basetime = PICO_ND_REACHABLE_TIME;
tass 152:a3d286bf94e5 47 /* RFC 4861 $6.3.2 value between 0.5 and 1.5 times basetime */
tass 152:a3d286bf94e5 48 dev->hostvars.reachabletime = ((5 + (pico_rand() % 10)) * PICO_ND_REACHABLE_TIME) / 10;
tass 152:a3d286bf94e5 49 dev->hostvars.retranstime = PICO_ND_RETRANS_TIMER;
tass 152:a3d286bf94e5 50 pico_icmp6_router_solicitation(dev, linklocal);
tass 152:a3d286bf94e5 51 dev->hostvars.hoplimit = PICO_IPV6_DEFAULT_HOP;
tass 152:a3d286bf94e5 52 }
tass 152:a3d286bf94e5 53
tass 152:a3d286bf94e5 54 struct pico_ipv6_link *pico_ipv6_link_add_local(struct pico_device *dev, const struct pico_ip6 *prefix)
tass 152:a3d286bf94e5 55 {
tass 152:a3d286bf94e5 56 struct pico_ip6 newaddr;
tass 152:a3d286bf94e5 57 struct pico_ip6 netmask64 = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
tass 152:a3d286bf94e5 58 struct pico_ipv6_link *link;
tass 152:a3d286bf94e5 59 memcpy(newaddr.addr, prefix->addr, PICO_SIZE_IP6);
tass 152:a3d286bf94e5 60 /* modified EUI-64 + invert universal/local bit */
tass 152:a3d286bf94e5 61 newaddr.addr[8] = (dev->eth->mac.addr[0] ^ 0x02);
tass 152:a3d286bf94e5 62 newaddr.addr[9] = dev->eth->mac.addr[1];
tass 152:a3d286bf94e5 63 newaddr.addr[10] = dev->eth->mac.addr[2];
tass 152:a3d286bf94e5 64 newaddr.addr[11] = 0xff;
tass 152:a3d286bf94e5 65 newaddr.addr[12] = 0xfe;
tass 152:a3d286bf94e5 66 newaddr.addr[13] = dev->eth->mac.addr[3];
tass 152:a3d286bf94e5 67 newaddr.addr[14] = dev->eth->mac.addr[4];
tass 152:a3d286bf94e5 68 newaddr.addr[15] = dev->eth->mac.addr[5];
tass 152:a3d286bf94e5 69 link = pico_ipv6_link_add(dev, newaddr, netmask64);
tass 152:a3d286bf94e5 70 if (link) {
tass 152:a3d286bf94e5 71 device_init_ipv6_final(dev, &newaddr);
tass 152:a3d286bf94e5 72 }
tass 152:a3d286bf94e5 73
tass 152:a3d286bf94e5 74 return link;
tass 152:a3d286bf94e5 75 }
tass 152:a3d286bf94e5 76 #endif
tass 152:a3d286bf94e5 77
tass 152:a3d286bf94e5 78 static int device_init_mac(struct pico_device *dev, uint8_t *mac)
tass 152:a3d286bf94e5 79 {
tass 152:a3d286bf94e5 80 #ifdef PICO_SUPPORT_IPV6
tass 152:a3d286bf94e5 81 struct pico_ip6 linklocal = {{0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xff, 0xfe, 0xaa, 0xaa, 0xaa}};
tass 152:a3d286bf94e5 82 #endif
tass 152:a3d286bf94e5 83 dev->eth = PICO_ZALLOC(sizeof(struct pico_ethdev));
tass 152:a3d286bf94e5 84 if (dev->eth) {
tass 152:a3d286bf94e5 85 memcpy(dev->eth->mac.addr, mac, PICO_SIZE_ETH);
tass 152:a3d286bf94e5 86 #ifdef PICO_SUPPORT_IPV6
tass 152:a3d286bf94e5 87 if (pico_ipv6_link_add_local(dev, &linklocal) == NULL) {
tass 152:a3d286bf94e5 88 PICO_FREE(dev->q_in);
tass 152:a3d286bf94e5 89 PICO_FREE(dev->q_out);
tass 152:a3d286bf94e5 90 PICO_FREE(dev->eth);
tass 152:a3d286bf94e5 91 return -1;
tass 152:a3d286bf94e5 92 }
tass 152:a3d286bf94e5 93
tass 152:a3d286bf94e5 94 #endif
tass 152:a3d286bf94e5 95 } else {
tass 152:a3d286bf94e5 96 pico_err = PICO_ERR_ENOMEM;
tass 152:a3d286bf94e5 97 return -1;
tass 152:a3d286bf94e5 98 }
tass 152:a3d286bf94e5 99
tass 152:a3d286bf94e5 100 return 0;
tass 152:a3d286bf94e5 101 }
tass 152:a3d286bf94e5 102
tass 152:a3d286bf94e5 103 int pico_device_ipv6_random_ll(struct pico_device *dev)
tass 68:0847e35d08a6 104 {
tass picotcp@tass.be 149:5f4cb161cec3 105 #ifdef PICO_SUPPORT_IPV6
tass picotcp@tass.be 149:5f4cb161cec3 106 struct pico_ip6 linklocal = {{0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xff, 0xfe, 0xaa, 0xaa, 0xaa}};
tass picotcp@tass.be 149:5f4cb161cec3 107 struct pico_ip6 netmask6 = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
tass 152:a3d286bf94e5 108 uint32_t len = (uint32_t)strlen(dev->name);
tass 152:a3d286bf94e5 109 if (strcmp(dev->name, "loop")) {
tass 152:a3d286bf94e5 110 do {
tass 152:a3d286bf94e5 111 /* privacy extension + unset universal/local and individual/group bit */
tass 152:a3d286bf94e5 112 len = pico_rand();
tass 152:a3d286bf94e5 113 linklocal.addr[8] = (uint8_t)((len & 0xffu) & (uint8_t)(~0x03));
tass 152:a3d286bf94e5 114 linklocal.addr[9] = (uint8_t)(len >> 8);
tass 152:a3d286bf94e5 115 linklocal.addr[10] = (uint8_t)(len >> 16);
tass 152:a3d286bf94e5 116 linklocal.addr[11] = (uint8_t)(len >> 24);
tass 152:a3d286bf94e5 117 len = pico_rand();
tass 152:a3d286bf94e5 118 linklocal.addr[12] = (uint8_t)len;
tass 152:a3d286bf94e5 119 linklocal.addr[13] = (uint8_t)(len >> 8);
tass 152:a3d286bf94e5 120 linklocal.addr[14] = (uint8_t)(len >> 16);
tass 152:a3d286bf94e5 121 linklocal.addr[15] = (uint8_t)(len >> 24);
tass 152:a3d286bf94e5 122 pico_rand_feed(dev->hash);
tass 152:a3d286bf94e5 123 } while (pico_ipv6_link_get(&linklocal));
tass 152:a3d286bf94e5 124
tass 152:a3d286bf94e5 125 if (pico_ipv6_link_add(dev, linklocal, netmask6) == NULL) {
tass 152:a3d286bf94e5 126 return -1;
tass 152:a3d286bf94e5 127 }
tass 152:a3d286bf94e5 128 }
tass 152:a3d286bf94e5 129
tass picotcp@tass.be 149:5f4cb161cec3 130 #endif
tass 152:a3d286bf94e5 131 return 0;
tass 152:a3d286bf94e5 132 }
tass 152:a3d286bf94e5 133
tass 152:a3d286bf94e5 134 static int device_init_nomac(struct pico_device *dev)
tass 152:a3d286bf94e5 135 {
tass 152:a3d286bf94e5 136 if (pico_device_ipv6_random_ll(dev) < 0) {
tass 152:a3d286bf94e5 137 PICO_FREE(dev->q_in);
tass 152:a3d286bf94e5 138 PICO_FREE(dev->q_out);
tass 152:a3d286bf94e5 139 return -1;
tass 152:a3d286bf94e5 140 }
tass 152:a3d286bf94e5 141
tass 152:a3d286bf94e5 142 dev->eth = NULL;
tass 152:a3d286bf94e5 143 return 0;
tass 152:a3d286bf94e5 144 }
tass 152:a3d286bf94e5 145
tass 152:a3d286bf94e5 146 int pico_device_init(struct pico_device *dev, const char *name, uint8_t *mac)
tass 152:a3d286bf94e5 147 {
tass picotcp@tass.be 149:5f4cb161cec3 148
TASS Belgium NV 131:4758606c9316 149 uint32_t len = (uint32_t)strlen(name);
tass 152:a3d286bf94e5 150 int ret = 0;
TASS Belgium NV 131:4758606c9316 151 if(len > MAX_DEVICE_NAME)
TASS Belgium NV 131:4758606c9316 152 len = MAX_DEVICE_NAME;
tass 68:0847e35d08a6 153
TASS Belgium NV 131:4758606c9316 154 memcpy(dev->name, name, len);
tass picotcp@tass.be 133:5b075f5e141a 155 dev->hash = pico_hash(dev->name, len);
TASS Belgium NV 131:4758606c9316 156
tass picotcp@tass.be 137:a1c8bfa9d691 157 Devices_rr_info.node_in = NULL;
tass picotcp@tass.be 137:a1c8bfa9d691 158 Devices_rr_info.node_out = NULL;
tass picotcp@tass.be 149:5f4cb161cec3 159 dev->q_in = PICO_ZALLOC(sizeof(struct pico_queue));
tass 152:a3d286bf94e5 160 if (!dev->q_in)
tass picotcp@tass.be 149:5f4cb161cec3 161 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 162
tass 152:a3d286bf94e5 163 dev->q_out = PICO_ZALLOC(sizeof(struct pico_queue));
tass 152:a3d286bf94e5 164 if (!dev->q_out) {
tass 152:a3d286bf94e5 165 PICO_FREE(dev->q_in);
tass 152:a3d286bf94e5 166 return -1;
tass 152:a3d286bf94e5 167 }
tass 152:a3d286bf94e5 168
tass picotcp@tass.be 149:5f4cb161cec3 169 pico_tree_insert(&Device_tree, dev);
tass 152:a3d286bf94e5 170 if (!dev->mtu)
tass 152:a3d286bf94e5 171 dev->mtu = PICO_DEVICE_DEFAULT_MTU;
tass 68:0847e35d08a6 172
TASS Belgium NV 131:4758606c9316 173 if (mac) {
tass 152:a3d286bf94e5 174 ret = device_init_mac(dev, mac);
TASS Belgium NV 131:4758606c9316 175 } else {
tass 152:a3d286bf94e5 176 ret = device_init_nomac(dev);
TASS Belgium NV 131:4758606c9316 177 }
tass 68:0847e35d08a6 178
tass 152:a3d286bf94e5 179 return ret;
tass 68:0847e35d08a6 180 }
tass 68:0847e35d08a6 181
tass picotcp@tass.be 137:a1c8bfa9d691 182 static void pico_queue_destroy(struct pico_queue *q)
tass picotcp@tass.be 137:a1c8bfa9d691 183 {
tass picotcp@tass.be 137:a1c8bfa9d691 184 if (q) {
tass picotcp@tass.be 137:a1c8bfa9d691 185 pico_queue_empty(q);
tass picotcp@tass.be 149:5f4cb161cec3 186 PICO_FREE(q);
tass picotcp@tass.be 137:a1c8bfa9d691 187 }
tass picotcp@tass.be 137:a1c8bfa9d691 188 }
tass picotcp@tass.be 137:a1c8bfa9d691 189
tass 68:0847e35d08a6 190 void pico_device_destroy(struct pico_device *dev)
tass 68:0847e35d08a6 191 {
TASS Belgium NV 131:4758606c9316 192 if (dev->destroy)
TASS Belgium NV 131:4758606c9316 193 dev->destroy(dev);
TASS Belgium NV 131:4758606c9316 194
tass picotcp@tass.be 137:a1c8bfa9d691 195 pico_queue_destroy(dev->q_in);
tass picotcp@tass.be 137:a1c8bfa9d691 196 pico_queue_destroy(dev->q_out);
tass 68:0847e35d08a6 197
TASS Belgium NV 131:4758606c9316 198 if (dev->eth)
tass picotcp@tass.be 149:5f4cb161cec3 199 PICO_FREE(dev->eth);
tass picotcp@tass.be 149:5f4cb161cec3 200
tass picotcp@tass.be 149:5f4cb161cec3 201 #ifdef PICO_SUPPORT_IPV4
tass picotcp@tass.be 149:5f4cb161cec3 202 pico_ipv4_cleanup_links(dev);
tass picotcp@tass.be 149:5f4cb161cec3 203 #endif
tass picotcp@tass.be 149:5f4cb161cec3 204 #ifdef PICO_SUPPORT_IPV6
tass picotcp@tass.be 149:5f4cb161cec3 205 pico_ipv6_cleanup_links(dev);
tass picotcp@tass.be 149:5f4cb161cec3 206 #endif
tass picotcp@tass.be 149:5f4cb161cec3 207 pico_tree_delete(&Device_tree, dev);
tass picotcp@tass.be 149:5f4cb161cec3 208
tass picotcp@tass.be 137:a1c8bfa9d691 209 Devices_rr_info.node_in = NULL;
tass picotcp@tass.be 137:a1c8bfa9d691 210 Devices_rr_info.node_out = NULL;
tass picotcp@tass.be 149:5f4cb161cec3 211 PICO_FREE(dev);
tass 68:0847e35d08a6 212 }
tass 68:0847e35d08a6 213
tass picotcp@tass.be 137:a1c8bfa9d691 214 static int check_dev_serve_interrupt(struct pico_device *dev, int loop_score)
tass 68:0847e35d08a6 215 {
TASS Belgium NV 131:4758606c9316 216 if ((dev->__serving_interrupt) && (dev->dsr)) {
TASS Belgium NV 131:4758606c9316 217 /* call dsr routine */
TASS Belgium NV 131:4758606c9316 218 loop_score = dev->dsr(dev, loop_score);
TASS Belgium NV 131:4758606c9316 219 }
TASS Belgium NV 131:4758606c9316 220
tass picotcp@tass.be 137:a1c8bfa9d691 221 return loop_score;
tass picotcp@tass.be 137:a1c8bfa9d691 222 }
tass picotcp@tass.be 137:a1c8bfa9d691 223
tass picotcp@tass.be 137:a1c8bfa9d691 224 static int check_dev_serve_polling(struct pico_device *dev, int loop_score)
tass picotcp@tass.be 137:a1c8bfa9d691 225 {
TASS Belgium NV 131:4758606c9316 226 if (dev->poll) {
TASS Belgium NV 131:4758606c9316 227 loop_score = dev->poll(dev, loop_score);
tass 68:0847e35d08a6 228 }
tass 68:0847e35d08a6 229
TASS Belgium NV 131:4758606c9316 230 return loop_score;
tass 68:0847e35d08a6 231 }
tass 68:0847e35d08a6 232
tass picotcp@tass.be 137:a1c8bfa9d691 233 static int devloop_in(struct pico_device *dev, int loop_score)
tass picotcp@tass.be 137:a1c8bfa9d691 234 {
tass picotcp@tass.be 137:a1c8bfa9d691 235 struct pico_frame *f;
tass picotcp@tass.be 137:a1c8bfa9d691 236 while(loop_score > 0) {
tass 154:6c0e92a80c4a 237 if (dev->q_in->frames == 0)
tass picotcp@tass.be 137:a1c8bfa9d691 238 break;
tass picotcp@tass.be 137:a1c8bfa9d691 239
tass picotcp@tass.be 137:a1c8bfa9d691 240 /* Receive */
tass picotcp@tass.be 137:a1c8bfa9d691 241 f = pico_dequeue(dev->q_in);
tass picotcp@tass.be 137:a1c8bfa9d691 242 if (f) {
tass picotcp@tass.be 137:a1c8bfa9d691 243 if (dev->eth) {
tass picotcp@tass.be 137:a1c8bfa9d691 244 f->datalink_hdr = f->buffer;
tass 152:a3d286bf94e5 245 (void)pico_ethernet_receive(f);
tass picotcp@tass.be 137:a1c8bfa9d691 246 } else {
tass picotcp@tass.be 137:a1c8bfa9d691 247 f->net_hdr = f->buffer;
tass picotcp@tass.be 137:a1c8bfa9d691 248 pico_network_receive(f);
tass picotcp@tass.be 137:a1c8bfa9d691 249 }
tass picotcp@tass.be 137:a1c8bfa9d691 250
tass picotcp@tass.be 137:a1c8bfa9d691 251 loop_score--;
tass picotcp@tass.be 137:a1c8bfa9d691 252 }
tass picotcp@tass.be 137:a1c8bfa9d691 253 }
tass picotcp@tass.be 137:a1c8bfa9d691 254 return loop_score;
tass picotcp@tass.be 137:a1c8bfa9d691 255 }
tass picotcp@tass.be 137:a1c8bfa9d691 256
tass picotcp@tass.be 137:a1c8bfa9d691 257 static int devloop_sendto_dev(struct pico_device *dev, struct pico_frame *f)
tass picotcp@tass.be 137:a1c8bfa9d691 258 {
tass picotcp@tass.be 137:a1c8bfa9d691 259
tass picotcp@tass.be 137:a1c8bfa9d691 260 if (dev->eth) {
tass 152:a3d286bf94e5 261 /* Ethernet: pass management of the frame to the pico_ethernet_send() rdv function */
tass 152:a3d286bf94e5 262 return pico_ethernet_send(f);
tass picotcp@tass.be 137:a1c8bfa9d691 263 } else {
tass 152:a3d286bf94e5 264 /* non-ethernet: no post-processing needed */
tass 152:a3d286bf94e5 265 return (dev->send(dev, f->start, (int)f->len) <= 0); /* Return 0 upon success, which is dev->send() > 0 */
tass picotcp@tass.be 137:a1c8bfa9d691 266 }
tass picotcp@tass.be 137:a1c8bfa9d691 267 }
tass picotcp@tass.be 137:a1c8bfa9d691 268
tass picotcp@tass.be 137:a1c8bfa9d691 269 static int devloop_out(struct pico_device *dev, int loop_score)
tass picotcp@tass.be 137:a1c8bfa9d691 270 {
tass picotcp@tass.be 137:a1c8bfa9d691 271 struct pico_frame *f;
tass picotcp@tass.be 137:a1c8bfa9d691 272 while(loop_score > 0) {
tass 154:6c0e92a80c4a 273 if (dev->q_out->frames == 0)
tass picotcp@tass.be 137:a1c8bfa9d691 274 break;
tass picotcp@tass.be 137:a1c8bfa9d691 275
tass picotcp@tass.be 137:a1c8bfa9d691 276 /* Device dequeue + send */
tass 152:a3d286bf94e5 277 f = pico_queue_peek(dev->q_out);
tass picotcp@tass.be 137:a1c8bfa9d691 278 if (!f)
tass picotcp@tass.be 137:a1c8bfa9d691 279 break;
tass picotcp@tass.be 137:a1c8bfa9d691 280
tass 152:a3d286bf94e5 281 if (devloop_sendto_dev(dev, f) == 0) { /* success. */
tass 152:a3d286bf94e5 282 f = pico_dequeue(dev->q_out);
tass 152:a3d286bf94e5 283 pico_frame_discard(f); /* SINGLE POINT OF DISCARD for OUTGOING FRAMES */
tass 152:a3d286bf94e5 284 loop_score--;
tass 152:a3d286bf94e5 285 } else
tass 152:a3d286bf94e5 286 break; /* Don't discard */
tass picotcp@tass.be 138:0a7a449980e6 287
tass picotcp@tass.be 137:a1c8bfa9d691 288 }
tass picotcp@tass.be 137:a1c8bfa9d691 289 return loop_score;
tass picotcp@tass.be 137:a1c8bfa9d691 290 }
tass picotcp@tass.be 137:a1c8bfa9d691 291
tass picotcp@tass.be 137:a1c8bfa9d691 292 static int devloop(struct pico_device *dev, int loop_score, int direction)
tass picotcp@tass.be 137:a1c8bfa9d691 293 {
tass picotcp@tass.be 137:a1c8bfa9d691 294 /* If device supports interrupts, read the value of the condition and trigger the dsr */
tass picotcp@tass.be 137:a1c8bfa9d691 295 loop_score = check_dev_serve_interrupt(dev, loop_score);
tass picotcp@tass.be 137:a1c8bfa9d691 296
tass picotcp@tass.be 137:a1c8bfa9d691 297 /* If device supports polling, give control. Loop score is managed internally,
tass picotcp@tass.be 137:a1c8bfa9d691 298 * remaining loop points are returned. */
tass picotcp@tass.be 137:a1c8bfa9d691 299 loop_score = check_dev_serve_polling(dev, loop_score);
tass picotcp@tass.be 137:a1c8bfa9d691 300
tass picotcp@tass.be 137:a1c8bfa9d691 301 if (direction == PICO_LOOP_DIR_OUT)
tass picotcp@tass.be 137:a1c8bfa9d691 302 loop_score = devloop_out(dev, loop_score);
tass picotcp@tass.be 137:a1c8bfa9d691 303 else
tass picotcp@tass.be 137:a1c8bfa9d691 304 loop_score = devloop_in(dev, loop_score);
tass picotcp@tass.be 137:a1c8bfa9d691 305
tass picotcp@tass.be 137:a1c8bfa9d691 306 return loop_score;
tass picotcp@tass.be 137:a1c8bfa9d691 307 }
tass picotcp@tass.be 137:a1c8bfa9d691 308
tass picotcp@tass.be 137:a1c8bfa9d691 309
tass picotcp@tass.be 137:a1c8bfa9d691 310 static struct pico_tree_node *pico_dev_roundrobin_start(int direction)
tass picotcp@tass.be 137:a1c8bfa9d691 311 {
tass picotcp@tass.be 137:a1c8bfa9d691 312 if (Devices_rr_info.node_in == NULL)
tass picotcp@tass.be 137:a1c8bfa9d691 313 Devices_rr_info.node_in = pico_tree_firstNode(Device_tree.root);
tass picotcp@tass.be 137:a1c8bfa9d691 314
tass picotcp@tass.be 137:a1c8bfa9d691 315 if (Devices_rr_info.node_out == NULL)
tass picotcp@tass.be 137:a1c8bfa9d691 316 Devices_rr_info.node_out = pico_tree_firstNode(Device_tree.root);
tass picotcp@tass.be 137:a1c8bfa9d691 317
tass picotcp@tass.be 137:a1c8bfa9d691 318 if (direction == PICO_LOOP_DIR_IN)
tass picotcp@tass.be 137:a1c8bfa9d691 319 return Devices_rr_info.node_in;
tass picotcp@tass.be 137:a1c8bfa9d691 320 else
tass picotcp@tass.be 137:a1c8bfa9d691 321 return Devices_rr_info.node_out;
tass picotcp@tass.be 137:a1c8bfa9d691 322 }
tass picotcp@tass.be 137:a1c8bfa9d691 323
tass picotcp@tass.be 137:a1c8bfa9d691 324 static void pico_dev_roundrobin_end(int direction, struct pico_tree_node *last)
tass picotcp@tass.be 137:a1c8bfa9d691 325 {
tass picotcp@tass.be 137:a1c8bfa9d691 326 if (direction == PICO_LOOP_DIR_IN)
tass picotcp@tass.be 137:a1c8bfa9d691 327 Devices_rr_info.node_in = last;
tass picotcp@tass.be 137:a1c8bfa9d691 328 else
tass picotcp@tass.be 137:a1c8bfa9d691 329 Devices_rr_info.node_out = last;
tass picotcp@tass.be 137:a1c8bfa9d691 330 }
tass 68:0847e35d08a6 331
tass 68:0847e35d08a6 332 #define DEV_LOOP_MIN 16
tass 68:0847e35d08a6 333
tass 68:0847e35d08a6 334 int pico_devices_loop(int loop_score, int direction)
tass 68:0847e35d08a6 335 {
tass picotcp@tass.be 137:a1c8bfa9d691 336 struct pico_device *start, *next;
tass picotcp@tass.be 137:a1c8bfa9d691 337 struct pico_tree_node *next_node = pico_dev_roundrobin_start(direction);
TASS Belgium NV 131:4758606c9316 338
tass picotcp@tass.be 137:a1c8bfa9d691 339 if (!next_node)
tass picotcp@tass.be 137:a1c8bfa9d691 340 return loop_score;
tass 68:0847e35d08a6 341
tass picotcp@tass.be 137:a1c8bfa9d691 342 next = next_node->keyValue;
TASS Belgium NV 131:4758606c9316 343 start = next;
tass 68:0847e35d08a6 344
TASS Belgium NV 131:4758606c9316 345 /* round-robin all devices, break if traversed all devices */
tass picotcp@tass.be 137:a1c8bfa9d691 346 while ((loop_score > DEV_LOOP_MIN) && (next != NULL)) {
TASS Belgium NV 131:4758606c9316 347 loop_score = devloop(next, loop_score, direction);
TASS Belgium NV 131:4758606c9316 348 next_node = pico_tree_next(next_node);
TASS Belgium NV 131:4758606c9316 349 next = next_node->keyValue;
TASS Belgium NV 131:4758606c9316 350 if (next == NULL)
TASS Belgium NV 131:4758606c9316 351 {
TASS Belgium NV 131:4758606c9316 352 next_node = pico_tree_firstNode(Device_tree.root);
TASS Belgium NV 131:4758606c9316 353 next = next_node->keyValue;
TASS Belgium NV 131:4758606c9316 354 }
tass 68:0847e35d08a6 355
TASS Belgium NV 131:4758606c9316 356 if (next == start)
TASS Belgium NV 131:4758606c9316 357 break;
tass 68:0847e35d08a6 358 }
tass picotcp@tass.be 137:a1c8bfa9d691 359 pico_dev_roundrobin_end(direction, next_node);
TASS Belgium NV 131:4758606c9316 360 return loop_score;
tass 68:0847e35d08a6 361 }
tass 68:0847e35d08a6 362
tass picotcp@tass.be 137:a1c8bfa9d691 363 struct pico_device *pico_get_device(const char*name)
tass 68:0847e35d08a6 364 {
TASS Belgium NV 131:4758606c9316 365 struct pico_device *dev;
TASS Belgium NV 131:4758606c9316 366 struct pico_tree_node *index;
TASS Belgium NV 131:4758606c9316 367 pico_tree_foreach(index, &Device_tree){
TASS Belgium NV 131:4758606c9316 368 dev = index->keyValue;
TASS Belgium NV 131:4758606c9316 369 if(strcmp(name, dev->name) == 0)
TASS Belgium NV 131:4758606c9316 370 return dev;
TASS Belgium NV 131:4758606c9316 371 }
TASS Belgium NV 131:4758606c9316 372 return NULL;
tass 68:0847e35d08a6 373 }
tass 68:0847e35d08a6 374
TASS Belgium NV 131:4758606c9316 375 int32_t pico_device_broadcast(struct pico_frame *f)
tass 68:0847e35d08a6 376 {
TASS Belgium NV 131:4758606c9316 377 struct pico_tree_node *index;
TASS Belgium NV 131:4758606c9316 378 int32_t ret = -1;
tass 68:0847e35d08a6 379
TASS Belgium NV 131:4758606c9316 380 pico_tree_foreach(index, &Device_tree)
TASS Belgium NV 131:4758606c9316 381 {
TASS Belgium NV 131:4758606c9316 382 struct pico_device *dev = index->keyValue;
TASS Belgium NV 131:4758606c9316 383 if(dev != f->dev)
TASS Belgium NV 131:4758606c9316 384 {
TASS Belgium NV 131:4758606c9316 385 struct pico_frame *copy = pico_frame_copy(f);
tass 68:0847e35d08a6 386
TASS Belgium NV 131:4758606c9316 387 if(!copy)
tass 152:a3d286bf94e5 388 break;
tass 68:0847e35d08a6 389
TASS Belgium NV 131:4758606c9316 390 copy->dev = dev;
TASS Belgium NV 131:4758606c9316 391 copy->dev->send(copy->dev, copy->start, (int)copy->len);
TASS Belgium NV 131:4758606c9316 392 pico_frame_discard(copy);
TASS Belgium NV 131:4758606c9316 393 }
TASS Belgium NV 131:4758606c9316 394 else
TASS Belgium NV 131:4758606c9316 395 {
tass picotcp@tass.be 137:a1c8bfa9d691 396 ret = f->dev->send(f->dev, f->start, (int)f->len);
TASS Belgium NV 131:4758606c9316 397 }
TASS Belgium NV 131:4758606c9316 398 }
TASS Belgium NV 131:4758606c9316 399 return ret;
tass 68:0847e35d08a6 400 }
tass 152:a3d286bf94e5 401
tass 152:a3d286bf94e5 402 int pico_device_link_state(struct pico_device *dev)
tass 152:a3d286bf94e5 403 {
tass 152:a3d286bf94e5 404 if (!dev->link_state)
tass 152:a3d286bf94e5 405 return 1; /* Not supported, assuming link is always up */
tass 152:a3d286bf94e5 406
tass 152:a3d286bf94e5 407 return dev->link_state(dev);
tass 152:a3d286bf94e5 408 }