Free (GPLv2) TCP/IP stack developed by TASS Belgium

Dependents:   lpc1768-picotcp-demo ZeroMQ_PicoTCP_Publisher_demo TCPSocket_HelloWorld_PicoTCP Pico_TCP_UDP_Test ... more

PicoTCP. Copyright (c) 2013 TASS Belgium NV.

Released under the GNU General Public License, version 2.

Different licensing models may exist, at the sole discretion of the Copyright holders.

Official homepage: http://www.picotcp.com

Bug tracker: https://github.com/tass-belgium/picotcp/issues

Development steps:

  • initial integration with mbed RTOS
  • generic mbed Ethernet driver
  • high performance NXP LPC1768 specific Ethernet driver
  • Multi-threading support for mbed RTOS
  • Berkeley sockets and integration with the New Socket API
  • Fork of the apps running on top of the New Socket API
  • Scheduling optimizations
  • Debugging/benchmarking/testing

Demo application (measuring TCP sender performance):

Import programlpc1768-picotcp-demo

A PicoTCP demo app testing the ethernet throughput on the lpc1768 mbed board.

Committer:
tass picotcp@tass.be
Date:
Fri Feb 07 11:21:12 2014 +0100
Revision:
137:a1c8bfa9d691
Parent:
133:5b075f5e141a
Child:
138:0a7a449980e6
Update from masterbranch

Who changed what in which revision?

UserRevisionLine numberNew contents of line
tass 68:0847e35d08a6 1 /*********************************************************************
TASS Belgium NV 131:4758606c9316 2 PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved.
TASS Belgium NV 131:4758606c9316 3 See LICENSE and COPYING for usage.
tass 68:0847e35d08a6 4
TASS Belgium NV 131:4758606c9316 5 .
tass 68:0847e35d08a6 6
TASS Belgium NV 131:4758606c9316 7 Authors: Daniele Lacamera
TASS Belgium NV 131:4758606c9316 8 *********************************************************************/
tass 68:0847e35d08a6 9
tass 68:0847e35d08a6 10
tass 68:0847e35d08a6 11 #include "pico_config.h"
tass 68:0847e35d08a6 12 #include "pico_device.h"
tass 68:0847e35d08a6 13 #include "pico_stack.h"
tass 68:0847e35d08a6 14 #include "pico_protocol.h"
tass 68:0847e35d08a6 15 #include "pico_tree.h"
tass 68:0847e35d08a6 16
tass picotcp@tass.be 137:a1c8bfa9d691 17 struct pico_devices_rr_info {
tass picotcp@tass.be 137:a1c8bfa9d691 18 struct pico_tree_node *node_in, *node_out;
tass picotcp@tass.be 137:a1c8bfa9d691 19 };
tass picotcp@tass.be 137:a1c8bfa9d691 20
tass picotcp@tass.be 137:a1c8bfa9d691 21 static struct pico_devices_rr_info Devices_rr_info = {
tass picotcp@tass.be 137:a1c8bfa9d691 22 NULL, NULL
tass picotcp@tass.be 137:a1c8bfa9d691 23 };
tass 68:0847e35d08a6 24
tass 68:0847e35d08a6 25 static int pico_dev_cmp(void *ka, void *kb)
tass 68:0847e35d08a6 26 {
TASS Belgium NV 131:4758606c9316 27 struct pico_device *a = ka, *b = kb;
TASS Belgium NV 131:4758606c9316 28 if (a->hash < b->hash)
TASS Belgium NV 131:4758606c9316 29 return -1;
TASS Belgium NV 131:4758606c9316 30
TASS Belgium NV 131:4758606c9316 31 if (a->hash > b->hash)
TASS Belgium NV 131:4758606c9316 32 return 1;
TASS Belgium NV 131:4758606c9316 33
TASS Belgium NV 131:4758606c9316 34 return 0;
tass 68:0847e35d08a6 35 }
tass 68:0847e35d08a6 36
TASS Belgium NV 131:4758606c9316 37 PICO_TREE_DECLARE(Device_tree, pico_dev_cmp);
tass 68:0847e35d08a6 38
tass 68:0847e35d08a6 39 int pico_device_init(struct pico_device *dev, const char *name, uint8_t *mac)
tass 68:0847e35d08a6 40 {
TASS Belgium NV 131:4758606c9316 41 uint32_t len = (uint32_t)strlen(name);
TASS Belgium NV 131:4758606c9316 42 if(len > MAX_DEVICE_NAME)
TASS Belgium NV 131:4758606c9316 43 len = MAX_DEVICE_NAME;
tass 68:0847e35d08a6 44
TASS Belgium NV 131:4758606c9316 45 memcpy(dev->name, name, len);
tass picotcp@tass.be 133:5b075f5e141a 46 dev->hash = pico_hash(dev->name, len);
TASS Belgium NV 131:4758606c9316 47
TASS Belgium NV 131:4758606c9316 48 pico_tree_insert(&Device_tree, dev);
tass picotcp@tass.be 137:a1c8bfa9d691 49 Devices_rr_info.node_in = NULL;
tass picotcp@tass.be 137:a1c8bfa9d691 50 Devices_rr_info.node_out = NULL;
TASS Belgium NV 131:4758606c9316 51 dev->q_in = pico_zalloc(sizeof(struct pico_queue));
TASS Belgium NV 131:4758606c9316 52 dev->q_out = pico_zalloc(sizeof(struct pico_queue));
tass 68:0847e35d08a6 53
TASS Belgium NV 131:4758606c9316 54 if (mac) {
TASS Belgium NV 131:4758606c9316 55 dev->eth = pico_zalloc(sizeof(struct pico_ethdev));
TASS Belgium NV 131:4758606c9316 56 memcpy(dev->eth->mac.addr, mac, PICO_SIZE_ETH);
TASS Belgium NV 131:4758606c9316 57 } else {
TASS Belgium NV 131:4758606c9316 58 dev->eth = NULL;
TASS Belgium NV 131:4758606c9316 59 }
tass 68:0847e35d08a6 60
TASS Belgium NV 131:4758606c9316 61 if (!dev->q_in || !dev->q_out || (mac && !dev->eth))
TASS Belgium NV 131:4758606c9316 62 return -1;
TASS Belgium NV 131:4758606c9316 63
TASS Belgium NV 131:4758606c9316 64 return 0;
tass 68:0847e35d08a6 65 }
tass 68:0847e35d08a6 66
tass picotcp@tass.be 137:a1c8bfa9d691 67 static void pico_queue_destroy(struct pico_queue *q)
tass picotcp@tass.be 137:a1c8bfa9d691 68 {
tass picotcp@tass.be 137:a1c8bfa9d691 69 if (q) {
tass picotcp@tass.be 137:a1c8bfa9d691 70 pico_queue_empty(q);
tass picotcp@tass.be 137:a1c8bfa9d691 71 pico_free(q);
tass picotcp@tass.be 137:a1c8bfa9d691 72 }
tass picotcp@tass.be 137:a1c8bfa9d691 73 }
tass picotcp@tass.be 137:a1c8bfa9d691 74
tass 68:0847e35d08a6 75 void pico_device_destroy(struct pico_device *dev)
tass 68:0847e35d08a6 76 {
TASS Belgium NV 131:4758606c9316 77 if (dev->destroy)
TASS Belgium NV 131:4758606c9316 78 dev->destroy(dev);
TASS Belgium NV 131:4758606c9316 79
tass picotcp@tass.be 137:a1c8bfa9d691 80 pico_queue_destroy(dev->q_in);
tass picotcp@tass.be 137:a1c8bfa9d691 81 pico_queue_destroy(dev->q_out);
tass 68:0847e35d08a6 82
TASS Belgium NV 131:4758606c9316 83 if (dev->eth)
TASS Belgium NV 131:4758606c9316 84 pico_free(dev->eth);
tass 68:0847e35d08a6 85
TASS Belgium NV 131:4758606c9316 86 pico_tree_delete(&Device_tree, dev);
tass picotcp@tass.be 137:a1c8bfa9d691 87 Devices_rr_info.node_in = NULL;
tass picotcp@tass.be 137:a1c8bfa9d691 88 Devices_rr_info.node_out = NULL;
TASS Belgium NV 131:4758606c9316 89 pico_free(dev);
tass 68:0847e35d08a6 90 }
tass 68:0847e35d08a6 91
tass picotcp@tass.be 137:a1c8bfa9d691 92 static int check_dev_serve_interrupt(struct pico_device *dev, int loop_score)
tass 68:0847e35d08a6 93 {
TASS Belgium NV 131:4758606c9316 94 if ((dev->__serving_interrupt) && (dev->dsr)) {
TASS Belgium NV 131:4758606c9316 95 /* call dsr routine */
TASS Belgium NV 131:4758606c9316 96 loop_score = dev->dsr(dev, loop_score);
TASS Belgium NV 131:4758606c9316 97 }
TASS Belgium NV 131:4758606c9316 98
tass picotcp@tass.be 137:a1c8bfa9d691 99 return loop_score;
tass picotcp@tass.be 137:a1c8bfa9d691 100 }
tass picotcp@tass.be 137:a1c8bfa9d691 101
tass picotcp@tass.be 137:a1c8bfa9d691 102 static int check_dev_serve_polling(struct pico_device *dev, int loop_score)
tass picotcp@tass.be 137:a1c8bfa9d691 103 {
TASS Belgium NV 131:4758606c9316 104 if (dev->poll) {
TASS Belgium NV 131:4758606c9316 105 loop_score = dev->poll(dev, loop_score);
tass 68:0847e35d08a6 106 }
tass 68:0847e35d08a6 107
TASS Belgium NV 131:4758606c9316 108 return loop_score;
tass 68:0847e35d08a6 109 }
tass 68:0847e35d08a6 110
tass picotcp@tass.be 137:a1c8bfa9d691 111 static int devloop_in(struct pico_device *dev, int loop_score)
tass picotcp@tass.be 137:a1c8bfa9d691 112 {
tass picotcp@tass.be 137:a1c8bfa9d691 113 struct pico_frame *f;
tass picotcp@tass.be 137:a1c8bfa9d691 114 while(loop_score > 0) {
tass picotcp@tass.be 137:a1c8bfa9d691 115 if (dev->q_in->frames <= 0)
tass picotcp@tass.be 137:a1c8bfa9d691 116 break;
tass picotcp@tass.be 137:a1c8bfa9d691 117
tass picotcp@tass.be 137:a1c8bfa9d691 118 /* Receive */
tass picotcp@tass.be 137:a1c8bfa9d691 119 f = pico_dequeue(dev->q_in);
tass picotcp@tass.be 137:a1c8bfa9d691 120 if (f) {
tass picotcp@tass.be 137:a1c8bfa9d691 121 if (dev->eth) {
tass picotcp@tass.be 137:a1c8bfa9d691 122 f->datalink_hdr = f->buffer;
tass picotcp@tass.be 137:a1c8bfa9d691 123 pico_ethernet_receive(f);
tass picotcp@tass.be 137:a1c8bfa9d691 124 } else {
tass picotcp@tass.be 137:a1c8bfa9d691 125 f->net_hdr = f->buffer;
tass picotcp@tass.be 137:a1c8bfa9d691 126 pico_network_receive(f);
tass picotcp@tass.be 137:a1c8bfa9d691 127 }
tass picotcp@tass.be 137:a1c8bfa9d691 128
tass picotcp@tass.be 137:a1c8bfa9d691 129 loop_score--;
tass picotcp@tass.be 137:a1c8bfa9d691 130 }
tass picotcp@tass.be 137:a1c8bfa9d691 131 }
tass picotcp@tass.be 137:a1c8bfa9d691 132 return loop_score;
tass picotcp@tass.be 137:a1c8bfa9d691 133 }
tass picotcp@tass.be 137:a1c8bfa9d691 134
tass picotcp@tass.be 137:a1c8bfa9d691 135 static int devloop_sendto_dev(struct pico_device *dev, struct pico_frame *f)
tass picotcp@tass.be 137:a1c8bfa9d691 136 {
tass picotcp@tass.be 137:a1c8bfa9d691 137
tass picotcp@tass.be 137:a1c8bfa9d691 138 int ret;
tass picotcp@tass.be 137:a1c8bfa9d691 139 if (dev->eth) {
tass picotcp@tass.be 137:a1c8bfa9d691 140 ret = pico_ethernet_send(f);
tass picotcp@tass.be 137:a1c8bfa9d691 141 if (0 <= ret) {
tass picotcp@tass.be 137:a1c8bfa9d691 142 return 1;
tass picotcp@tass.be 137:a1c8bfa9d691 143 } else {
tass picotcp@tass.be 137:a1c8bfa9d691 144 if (!pico_source_is_local(f)) {
tass picotcp@tass.be 137:a1c8bfa9d691 145 dbg("Destination unreachable -------> SEND ICMP\n");
tass picotcp@tass.be 137:a1c8bfa9d691 146 pico_notify_dest_unreachable(f);
tass picotcp@tass.be 137:a1c8bfa9d691 147 } else {
tass picotcp@tass.be 137:a1c8bfa9d691 148 dbg("Destination unreachable -------> LOCAL\n");
tass picotcp@tass.be 137:a1c8bfa9d691 149 }
tass picotcp@tass.be 137:a1c8bfa9d691 150
tass picotcp@tass.be 137:a1c8bfa9d691 151 pico_frame_discard(f);
tass picotcp@tass.be 137:a1c8bfa9d691 152 return 1;
tass picotcp@tass.be 137:a1c8bfa9d691 153 }
tass picotcp@tass.be 137:a1c8bfa9d691 154 } else {
tass picotcp@tass.be 137:a1c8bfa9d691 155 dev->send(dev, f->start, (int)f->len);
tass picotcp@tass.be 137:a1c8bfa9d691 156 pico_frame_discard(f);
tass picotcp@tass.be 137:a1c8bfa9d691 157 return 1;
tass picotcp@tass.be 137:a1c8bfa9d691 158 }
tass picotcp@tass.be 137:a1c8bfa9d691 159 }
tass picotcp@tass.be 137:a1c8bfa9d691 160
tass picotcp@tass.be 137:a1c8bfa9d691 161 static int devloop_out(struct pico_device *dev, int loop_score)
tass picotcp@tass.be 137:a1c8bfa9d691 162 {
tass picotcp@tass.be 137:a1c8bfa9d691 163 struct pico_frame *f;
tass picotcp@tass.be 137:a1c8bfa9d691 164 while(loop_score > 0) {
tass picotcp@tass.be 137:a1c8bfa9d691 165 if (dev->q_out->frames <= 0)
tass picotcp@tass.be 137:a1c8bfa9d691 166 break;
tass picotcp@tass.be 137:a1c8bfa9d691 167
tass picotcp@tass.be 137:a1c8bfa9d691 168 /* Device dequeue + send */
tass picotcp@tass.be 137:a1c8bfa9d691 169 f = pico_dequeue(dev->q_out);
tass picotcp@tass.be 137:a1c8bfa9d691 170 if (!f)
tass picotcp@tass.be 137:a1c8bfa9d691 171 break;
tass picotcp@tass.be 137:a1c8bfa9d691 172
tass picotcp@tass.be 137:a1c8bfa9d691 173 loop_score -= devloop_sendto_dev(dev, f);
tass picotcp@tass.be 137:a1c8bfa9d691 174 }
tass picotcp@tass.be 137:a1c8bfa9d691 175 return loop_score;
tass picotcp@tass.be 137:a1c8bfa9d691 176 }
tass picotcp@tass.be 137:a1c8bfa9d691 177
tass picotcp@tass.be 137:a1c8bfa9d691 178 static int devloop(struct pico_device *dev, int loop_score, int direction)
tass picotcp@tass.be 137:a1c8bfa9d691 179 {
tass picotcp@tass.be 137:a1c8bfa9d691 180 /* If device supports interrupts, read the value of the condition and trigger the dsr */
tass picotcp@tass.be 137:a1c8bfa9d691 181 loop_score = check_dev_serve_interrupt(dev, loop_score);
tass picotcp@tass.be 137:a1c8bfa9d691 182
tass picotcp@tass.be 137:a1c8bfa9d691 183 /* If device supports polling, give control. Loop score is managed internally,
tass picotcp@tass.be 137:a1c8bfa9d691 184 * remaining loop points are returned. */
tass picotcp@tass.be 137:a1c8bfa9d691 185 loop_score = check_dev_serve_polling(dev, loop_score);
tass picotcp@tass.be 137:a1c8bfa9d691 186
tass picotcp@tass.be 137:a1c8bfa9d691 187 if (direction == PICO_LOOP_DIR_OUT)
tass picotcp@tass.be 137:a1c8bfa9d691 188 loop_score = devloop_out(dev, loop_score);
tass picotcp@tass.be 137:a1c8bfa9d691 189 else
tass picotcp@tass.be 137:a1c8bfa9d691 190 loop_score = devloop_in(dev, loop_score);
tass picotcp@tass.be 137:a1c8bfa9d691 191
tass picotcp@tass.be 137:a1c8bfa9d691 192 return loop_score;
tass picotcp@tass.be 137:a1c8bfa9d691 193 }
tass picotcp@tass.be 137:a1c8bfa9d691 194
tass picotcp@tass.be 137:a1c8bfa9d691 195
tass picotcp@tass.be 137:a1c8bfa9d691 196 static struct pico_tree_node *pico_dev_roundrobin_start(int direction)
tass picotcp@tass.be 137:a1c8bfa9d691 197 {
tass picotcp@tass.be 137:a1c8bfa9d691 198 if (Devices_rr_info.node_in == NULL)
tass picotcp@tass.be 137:a1c8bfa9d691 199 Devices_rr_info.node_in = pico_tree_firstNode(Device_tree.root);
tass picotcp@tass.be 137:a1c8bfa9d691 200
tass picotcp@tass.be 137:a1c8bfa9d691 201 if (Devices_rr_info.node_out == NULL)
tass picotcp@tass.be 137:a1c8bfa9d691 202 Devices_rr_info.node_out = pico_tree_firstNode(Device_tree.root);
tass picotcp@tass.be 137:a1c8bfa9d691 203
tass picotcp@tass.be 137:a1c8bfa9d691 204 if (direction == PICO_LOOP_DIR_IN)
tass picotcp@tass.be 137:a1c8bfa9d691 205 return Devices_rr_info.node_in;
tass picotcp@tass.be 137:a1c8bfa9d691 206 else
tass picotcp@tass.be 137:a1c8bfa9d691 207 return Devices_rr_info.node_out;
tass picotcp@tass.be 137:a1c8bfa9d691 208 }
tass picotcp@tass.be 137:a1c8bfa9d691 209
tass picotcp@tass.be 137:a1c8bfa9d691 210 static void pico_dev_roundrobin_end(int direction, struct pico_tree_node *last)
tass picotcp@tass.be 137:a1c8bfa9d691 211 {
tass picotcp@tass.be 137:a1c8bfa9d691 212 if (direction == PICO_LOOP_DIR_IN)
tass picotcp@tass.be 137:a1c8bfa9d691 213 Devices_rr_info.node_in = last;
tass picotcp@tass.be 137:a1c8bfa9d691 214 else
tass picotcp@tass.be 137:a1c8bfa9d691 215 Devices_rr_info.node_out = last;
tass picotcp@tass.be 137:a1c8bfa9d691 216 }
tass 68:0847e35d08a6 217
tass 68:0847e35d08a6 218 #define DEV_LOOP_MIN 16
tass 68:0847e35d08a6 219
tass 68:0847e35d08a6 220 int pico_devices_loop(int loop_score, int direction)
tass 68:0847e35d08a6 221 {
tass picotcp@tass.be 137:a1c8bfa9d691 222 struct pico_device *start, *next;
tass picotcp@tass.be 137:a1c8bfa9d691 223 struct pico_tree_node *next_node = pico_dev_roundrobin_start(direction);
TASS Belgium NV 131:4758606c9316 224
tass picotcp@tass.be 137:a1c8bfa9d691 225 if (!next_node)
tass picotcp@tass.be 137:a1c8bfa9d691 226 return loop_score;
tass 68:0847e35d08a6 227
tass picotcp@tass.be 137:a1c8bfa9d691 228 next = next_node->keyValue;
TASS Belgium NV 131:4758606c9316 229 start = next;
tass 68:0847e35d08a6 230
TASS Belgium NV 131:4758606c9316 231 /* round-robin all devices, break if traversed all devices */
tass picotcp@tass.be 137:a1c8bfa9d691 232 while ((loop_score > DEV_LOOP_MIN) && (next != NULL)) {
TASS Belgium NV 131:4758606c9316 233 loop_score = devloop(next, loop_score, direction);
TASS Belgium NV 131:4758606c9316 234 next_node = pico_tree_next(next_node);
TASS Belgium NV 131:4758606c9316 235 next = next_node->keyValue;
TASS Belgium NV 131:4758606c9316 236 if (next == NULL)
TASS Belgium NV 131:4758606c9316 237 {
TASS Belgium NV 131:4758606c9316 238 next_node = pico_tree_firstNode(Device_tree.root);
TASS Belgium NV 131:4758606c9316 239 next = next_node->keyValue;
TASS Belgium NV 131:4758606c9316 240 }
tass 68:0847e35d08a6 241
TASS Belgium NV 131:4758606c9316 242 if (next == start)
TASS Belgium NV 131:4758606c9316 243 break;
tass 68:0847e35d08a6 244 }
tass picotcp@tass.be 137:a1c8bfa9d691 245 pico_dev_roundrobin_end(direction, next_node);
TASS Belgium NV 131:4758606c9316 246 return loop_score;
tass 68:0847e35d08a6 247 }
tass 68:0847e35d08a6 248
tass picotcp@tass.be 137:a1c8bfa9d691 249 struct pico_device *pico_get_device(const char*name)
tass 68:0847e35d08a6 250 {
TASS Belgium NV 131:4758606c9316 251 struct pico_device *dev;
TASS Belgium NV 131:4758606c9316 252 struct pico_tree_node *index;
TASS Belgium NV 131:4758606c9316 253 pico_tree_foreach(index, &Device_tree){
TASS Belgium NV 131:4758606c9316 254 dev = index->keyValue;
TASS Belgium NV 131:4758606c9316 255 if(strcmp(name, dev->name) == 0)
TASS Belgium NV 131:4758606c9316 256 return dev;
TASS Belgium NV 131:4758606c9316 257 }
TASS Belgium NV 131:4758606c9316 258 return NULL;
tass 68:0847e35d08a6 259 }
tass 68:0847e35d08a6 260
TASS Belgium NV 131:4758606c9316 261 int32_t pico_device_broadcast(struct pico_frame *f)
tass 68:0847e35d08a6 262 {
TASS Belgium NV 131:4758606c9316 263 struct pico_tree_node *index;
TASS Belgium NV 131:4758606c9316 264 int32_t ret = -1;
tass 68:0847e35d08a6 265
TASS Belgium NV 131:4758606c9316 266 pico_tree_foreach(index, &Device_tree)
TASS Belgium NV 131:4758606c9316 267 {
TASS Belgium NV 131:4758606c9316 268 struct pico_device *dev = index->keyValue;
TASS Belgium NV 131:4758606c9316 269 if(dev != f->dev)
TASS Belgium NV 131:4758606c9316 270 {
TASS Belgium NV 131:4758606c9316 271 struct pico_frame *copy = pico_frame_copy(f);
tass 68:0847e35d08a6 272
TASS Belgium NV 131:4758606c9316 273 if(!copy)
TASS Belgium NV 131:4758606c9316 274 return -1;
tass 68:0847e35d08a6 275
TASS Belgium NV 131:4758606c9316 276 copy->dev = dev;
TASS Belgium NV 131:4758606c9316 277 copy->dev->send(copy->dev, copy->start, (int)copy->len);
TASS Belgium NV 131:4758606c9316 278 pico_frame_discard(copy);
TASS Belgium NV 131:4758606c9316 279 }
TASS Belgium NV 131:4758606c9316 280 else
TASS Belgium NV 131:4758606c9316 281 {
tass picotcp@tass.be 137:a1c8bfa9d691 282 ret = f->dev->send(f->dev, f->start, (int)f->len);
TASS Belgium NV 131:4758606c9316 283 }
TASS Belgium NV 131:4758606c9316 284 }
TASS Belgium NV 131:4758606c9316 285
TASS Belgium NV 131:4758606c9316 286 return ret;
tass 68:0847e35d08a6 287 }