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:
Thu Jan 16 10:13:37 2014 +0100
Revision:
133:5b075f5e141a
Parent:
131:4758606c9316
Child:
137:a1c8bfa9d691
Update from master branch

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