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:
daniele
Date:
Fri May 24 15:25:25 2013 +0000
Revision:
3:b4047e8a0123
Updated from main repo + fixed Mutexes;

Who changed what in which revision?

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