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

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

PicoTCP. Copyright (c) 2013 TASS Belgium NV.

Released under the GNU General Public License, version 2.

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

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

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

Development steps:

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

Demo application (measuring TCP sender performance):

Import programlpc1768-picotcp-demo

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

Committer:
tass picotcp@tass.be
Date:
Fri Feb 07 11:24:45 2014 +0100
Revision:
138:0a7a449980e6
Parent:
137:a1c8bfa9d691
Child:
149:5f4cb161cec3
Update from masterbranch

Who changed what in which revision?

UserRevisionLine numberNew contents of line
tass 68:0847e35d08a6 1 /*********************************************************************
TASS Belgium NV 131:4758606c9316 2 PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved.
TASS Belgium NV 131:4758606c9316 3 See LICENSE and COPYING for usage.
tass 68:0847e35d08a6 4
TASS Belgium NV 131:4758606c9316 5 .
tass 68:0847e35d08a6 6
TASS Belgium NV 131:4758606c9316 7 Authors: Daniele Lacamera
TASS Belgium NV 131:4758606c9316 8 *********************************************************************/
tass 68:0847e35d08a6 9
tass 68:0847e35d08a6 10
tass 68:0847e35d08a6 11 #include "pico_config.h"
tass 68:0847e35d08a6 12 #include "pico_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 138:0a7a449980e6 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 138:0a7a449980e6 155 /* non-ethernet */
tass picotcp@tass.be 138:0a7a449980e6 156 if (dev->send(dev, f->start, (int)f->len) <= 0)
tass picotcp@tass.be 138:0a7a449980e6 157 return -1;
tass picotcp@tass.be 138:0a7a449980e6 158
tass picotcp@tass.be 137:a1c8bfa9d691 159 pico_frame_discard(f);
tass picotcp@tass.be 137:a1c8bfa9d691 160 return 1;
tass picotcp@tass.be 137:a1c8bfa9d691 161 }
tass picotcp@tass.be 137:a1c8bfa9d691 162 }
tass picotcp@tass.be 137:a1c8bfa9d691 163
tass picotcp@tass.be 137:a1c8bfa9d691 164 static int devloop_out(struct pico_device *dev, int loop_score)
tass picotcp@tass.be 137:a1c8bfa9d691 165 {
tass picotcp@tass.be 137:a1c8bfa9d691 166 struct pico_frame *f;
tass picotcp@tass.be 137:a1c8bfa9d691 167 while(loop_score > 0) {
tass picotcp@tass.be 137:a1c8bfa9d691 168 if (dev->q_out->frames <= 0)
tass picotcp@tass.be 137:a1c8bfa9d691 169 break;
tass picotcp@tass.be 137:a1c8bfa9d691 170
tass picotcp@tass.be 137:a1c8bfa9d691 171 /* Device dequeue + send */
tass picotcp@tass.be 137:a1c8bfa9d691 172 f = pico_dequeue(dev->q_out);
tass picotcp@tass.be 137:a1c8bfa9d691 173 if (!f)
tass picotcp@tass.be 137:a1c8bfa9d691 174 break;
tass picotcp@tass.be 137:a1c8bfa9d691 175
tass picotcp@tass.be 138:0a7a449980e6 176 if (devloop_sendto_dev(dev, f) < 0)
tass picotcp@tass.be 138:0a7a449980e6 177 break;
tass picotcp@tass.be 138:0a7a449980e6 178
tass picotcp@tass.be 138:0a7a449980e6 179 loop_score--;
tass picotcp@tass.be 137:a1c8bfa9d691 180 }
tass picotcp@tass.be 137:a1c8bfa9d691 181 return loop_score;
tass picotcp@tass.be 137:a1c8bfa9d691 182 }
tass picotcp@tass.be 137:a1c8bfa9d691 183
tass picotcp@tass.be 137:a1c8bfa9d691 184 static int devloop(struct pico_device *dev, int loop_score, int direction)
tass picotcp@tass.be 137:a1c8bfa9d691 185 {
tass picotcp@tass.be 137:a1c8bfa9d691 186 /* If device supports interrupts, read the value of the condition and trigger the dsr */
tass picotcp@tass.be 137:a1c8bfa9d691 187 loop_score = check_dev_serve_interrupt(dev, loop_score);
tass picotcp@tass.be 137:a1c8bfa9d691 188
tass picotcp@tass.be 137:a1c8bfa9d691 189 /* If device supports polling, give control. Loop score is managed internally,
tass picotcp@tass.be 137:a1c8bfa9d691 190 * remaining loop points are returned. */
tass picotcp@tass.be 137:a1c8bfa9d691 191 loop_score = check_dev_serve_polling(dev, loop_score);
tass picotcp@tass.be 137:a1c8bfa9d691 192
tass picotcp@tass.be 137:a1c8bfa9d691 193 if (direction == PICO_LOOP_DIR_OUT)
tass picotcp@tass.be 137:a1c8bfa9d691 194 loop_score = devloop_out(dev, loop_score);
tass picotcp@tass.be 137:a1c8bfa9d691 195 else
tass picotcp@tass.be 137:a1c8bfa9d691 196 loop_score = devloop_in(dev, loop_score);
tass picotcp@tass.be 137:a1c8bfa9d691 197
tass picotcp@tass.be 137:a1c8bfa9d691 198 return loop_score;
tass picotcp@tass.be 137:a1c8bfa9d691 199 }
tass picotcp@tass.be 137:a1c8bfa9d691 200
tass picotcp@tass.be 137:a1c8bfa9d691 201
tass picotcp@tass.be 137:a1c8bfa9d691 202 static struct pico_tree_node *pico_dev_roundrobin_start(int direction)
tass picotcp@tass.be 137:a1c8bfa9d691 203 {
tass picotcp@tass.be 137:a1c8bfa9d691 204 if (Devices_rr_info.node_in == NULL)
tass picotcp@tass.be 137:a1c8bfa9d691 205 Devices_rr_info.node_in = pico_tree_firstNode(Device_tree.root);
tass picotcp@tass.be 137:a1c8bfa9d691 206
tass picotcp@tass.be 137:a1c8bfa9d691 207 if (Devices_rr_info.node_out == NULL)
tass picotcp@tass.be 137:a1c8bfa9d691 208 Devices_rr_info.node_out = pico_tree_firstNode(Device_tree.root);
tass picotcp@tass.be 137:a1c8bfa9d691 209
tass picotcp@tass.be 137:a1c8bfa9d691 210 if (direction == PICO_LOOP_DIR_IN)
tass picotcp@tass.be 137:a1c8bfa9d691 211 return Devices_rr_info.node_in;
tass picotcp@tass.be 137:a1c8bfa9d691 212 else
tass picotcp@tass.be 137:a1c8bfa9d691 213 return Devices_rr_info.node_out;
tass picotcp@tass.be 137:a1c8bfa9d691 214 }
tass picotcp@tass.be 137:a1c8bfa9d691 215
tass picotcp@tass.be 137:a1c8bfa9d691 216 static void pico_dev_roundrobin_end(int direction, struct pico_tree_node *last)
tass picotcp@tass.be 137:a1c8bfa9d691 217 {
tass picotcp@tass.be 137:a1c8bfa9d691 218 if (direction == PICO_LOOP_DIR_IN)
tass picotcp@tass.be 137:a1c8bfa9d691 219 Devices_rr_info.node_in = last;
tass picotcp@tass.be 137:a1c8bfa9d691 220 else
tass picotcp@tass.be 137:a1c8bfa9d691 221 Devices_rr_info.node_out = last;
tass picotcp@tass.be 137:a1c8bfa9d691 222 }
tass 68:0847e35d08a6 223
tass 68:0847e35d08a6 224 #define DEV_LOOP_MIN 16
tass 68:0847e35d08a6 225
tass 68:0847e35d08a6 226 int pico_devices_loop(int loop_score, int direction)
tass 68:0847e35d08a6 227 {
tass picotcp@tass.be 137:a1c8bfa9d691 228 struct pico_device *start, *next;
tass picotcp@tass.be 137:a1c8bfa9d691 229 struct pico_tree_node *next_node = pico_dev_roundrobin_start(direction);
TASS Belgium NV 131:4758606c9316 230
tass picotcp@tass.be 137:a1c8bfa9d691 231 if (!next_node)
tass picotcp@tass.be 137:a1c8bfa9d691 232 return loop_score;
tass 68:0847e35d08a6 233
tass picotcp@tass.be 137:a1c8bfa9d691 234 next = next_node->keyValue;
TASS Belgium NV 131:4758606c9316 235 start = next;
tass 68:0847e35d08a6 236
TASS Belgium NV 131:4758606c9316 237 /* round-robin all devices, break if traversed all devices */
tass picotcp@tass.be 137:a1c8bfa9d691 238 while ((loop_score > DEV_LOOP_MIN) && (next != NULL)) {
TASS Belgium NV 131:4758606c9316 239 loop_score = devloop(next, loop_score, direction);
TASS Belgium NV 131:4758606c9316 240 next_node = pico_tree_next(next_node);
TASS Belgium NV 131:4758606c9316 241 next = next_node->keyValue;
TASS Belgium NV 131:4758606c9316 242 if (next == NULL)
TASS Belgium NV 131:4758606c9316 243 {
TASS Belgium NV 131:4758606c9316 244 next_node = pico_tree_firstNode(Device_tree.root);
TASS Belgium NV 131:4758606c9316 245 next = next_node->keyValue;
TASS Belgium NV 131:4758606c9316 246 }
tass 68:0847e35d08a6 247
TASS Belgium NV 131:4758606c9316 248 if (next == start)
TASS Belgium NV 131:4758606c9316 249 break;
tass 68:0847e35d08a6 250 }
tass picotcp@tass.be 137:a1c8bfa9d691 251 pico_dev_roundrobin_end(direction, next_node);
TASS Belgium NV 131:4758606c9316 252 return loop_score;
tass 68:0847e35d08a6 253 }
tass 68:0847e35d08a6 254
tass picotcp@tass.be 137:a1c8bfa9d691 255 struct pico_device *pico_get_device(const char*name)
tass 68:0847e35d08a6 256 {
TASS Belgium NV 131:4758606c9316 257 struct pico_device *dev;
TASS Belgium NV 131:4758606c9316 258 struct pico_tree_node *index;
TASS Belgium NV 131:4758606c9316 259 pico_tree_foreach(index, &Device_tree){
TASS Belgium NV 131:4758606c9316 260 dev = index->keyValue;
TASS Belgium NV 131:4758606c9316 261 if(strcmp(name, dev->name) == 0)
TASS Belgium NV 131:4758606c9316 262 return dev;
TASS Belgium NV 131:4758606c9316 263 }
TASS Belgium NV 131:4758606c9316 264 return NULL;
tass 68:0847e35d08a6 265 }
tass 68:0847e35d08a6 266
TASS Belgium NV 131:4758606c9316 267 int32_t pico_device_broadcast(struct pico_frame *f)
tass 68:0847e35d08a6 268 {
TASS Belgium NV 131:4758606c9316 269 struct pico_tree_node *index;
TASS Belgium NV 131:4758606c9316 270 int32_t ret = -1;
tass 68:0847e35d08a6 271
TASS Belgium NV 131:4758606c9316 272 pico_tree_foreach(index, &Device_tree)
TASS Belgium NV 131:4758606c9316 273 {
TASS Belgium NV 131:4758606c9316 274 struct pico_device *dev = index->keyValue;
TASS Belgium NV 131:4758606c9316 275 if(dev != f->dev)
TASS Belgium NV 131:4758606c9316 276 {
TASS Belgium NV 131:4758606c9316 277 struct pico_frame *copy = pico_frame_copy(f);
tass 68:0847e35d08a6 278
TASS Belgium NV 131:4758606c9316 279 if(!copy)
TASS Belgium NV 131:4758606c9316 280 return -1;
tass 68:0847e35d08a6 281
TASS Belgium NV 131:4758606c9316 282 copy->dev = dev;
TASS Belgium NV 131:4758606c9316 283 copy->dev->send(copy->dev, copy->start, (int)copy->len);
TASS Belgium NV 131:4758606c9316 284 pico_frame_discard(copy);
TASS Belgium NV 131:4758606c9316 285 }
TASS Belgium NV 131:4758606c9316 286 else
TASS Belgium NV 131:4758606c9316 287 {
tass picotcp@tass.be 137:a1c8bfa9d691 288 ret = f->dev->send(f->dev, f->start, (int)f->len);
TASS Belgium NV 131:4758606c9316 289 }
TASS Belgium NV 131:4758606c9316 290 }
TASS Belgium NV 131:4758606c9316 291
TASS Belgium NV 131:4758606c9316 292 return ret;
tass 68:0847e35d08a6 293 }