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 May 17 12:09:59 2013 +0000
Revision:
1:cfe8984a32b4
Parent:
libraries/picotcp/stack/pico_device.c@0:d7f2341ab245
Update for smaller SOCKETQ

Who changed what in which revision?

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