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:
Fri Sep 27 12:43:36 2013 +0000
Revision:
73:dfb737147f6e
Parent:
70:cd218dd180e5
Child:
74:c146c4e346c4
Import from master branch.

Who changed what in which revision?

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