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:
Mon Sep 02 08:02:21 2013 +0000
Revision:
51:ab4529a384a6
Parent:
3:b4047e8a0123
Updated from masterbranch

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_protocol.h"
daniele 3:b4047e8a0123 12 #include "pico_tree.h"
daniele 3:b4047e8a0123 13
daniele 3:b4047e8a0123 14 static int pico_proto_cmp(void *ka, void *kb)
daniele 3:b4047e8a0123 15 {
tass 51:ab4529a384a6 16 struct pico_protocol *a = ka, *b=kb;
daniele 3:b4047e8a0123 17 if (a->hash < b->hash)
daniele 3:b4047e8a0123 18 return -1;
daniele 3:b4047e8a0123 19 if (a->hash > b->hash)
daniele 3:b4047e8a0123 20 return 1;
daniele 3:b4047e8a0123 21 return 0;
daniele 3:b4047e8a0123 22 }
daniele 3:b4047e8a0123 23
daniele 3:b4047e8a0123 24 PICO_TREE_DECLARE(Datalink_proto_tree,pico_proto_cmp);
daniele 3:b4047e8a0123 25 PICO_TREE_DECLARE(Network_proto_tree,pico_proto_cmp);
daniele 3:b4047e8a0123 26 PICO_TREE_DECLARE(Transport_proto_tree,pico_proto_cmp);
daniele 3:b4047e8a0123 27 PICO_TREE_DECLARE(Socket_proto_tree,pico_proto_cmp);
daniele 3:b4047e8a0123 28
daniele 3:b4047e8a0123 29 static int proto_loop(struct pico_protocol *proto, int loop_score, int direction)
daniele 3:b4047e8a0123 30 {
daniele 3:b4047e8a0123 31 struct pico_frame *f;
daniele 3:b4047e8a0123 32
daniele 3:b4047e8a0123 33 if (direction == PICO_LOOP_DIR_IN) {
daniele 3:b4047e8a0123 34
daniele 3:b4047e8a0123 35 while(loop_score >0) {
daniele 3:b4047e8a0123 36 if (proto->q_in->frames <= 0)
daniele 3:b4047e8a0123 37 break;
daniele 3:b4047e8a0123 38
daniele 3:b4047e8a0123 39 f = pico_dequeue(proto->q_in);
daniele 3:b4047e8a0123 40 if ((f) &&(proto->process_in(proto, f) > 0)) {
daniele 3:b4047e8a0123 41 loop_score--;
daniele 3:b4047e8a0123 42 }
daniele 3:b4047e8a0123 43 }
daniele 3:b4047e8a0123 44
daniele 3:b4047e8a0123 45 } else if (direction == PICO_LOOP_DIR_OUT) {
daniele 3:b4047e8a0123 46
daniele 3:b4047e8a0123 47 while(loop_score >0) {
daniele 3:b4047e8a0123 48 if (proto->q_out->frames <= 0)
daniele 3:b4047e8a0123 49 break;
daniele 3:b4047e8a0123 50
daniele 3:b4047e8a0123 51 f = pico_dequeue(proto->q_out);
daniele 3:b4047e8a0123 52 if ((f) &&(proto->process_out(proto, f) > 0)) {
daniele 3:b4047e8a0123 53 loop_score--;
daniele 3:b4047e8a0123 54 }
daniele 3:b4047e8a0123 55 }
daniele 3:b4047e8a0123 56 }
daniele 3:b4047e8a0123 57
daniele 3:b4047e8a0123 58 return loop_score;
daniele 3:b4047e8a0123 59 }
daniele 3:b4047e8a0123 60
daniele 3:b4047e8a0123 61 #define DL_LOOP_MIN 1
daniele 3:b4047e8a0123 62
daniele 3:b4047e8a0123 63 int pico_protocol_datalink_loop(int loop_score, int direction)
daniele 3:b4047e8a0123 64 {
daniele 3:b4047e8a0123 65 struct pico_protocol *start;
daniele 3:b4047e8a0123 66 static struct pico_protocol *next = NULL, *next_in = NULL, *next_out = NULL;
daniele 3:b4047e8a0123 67 static struct pico_tree_node * next_node, * in_node, * out_node;
daniele 3:b4047e8a0123 68
daniele 3:b4047e8a0123 69 if (next_in == NULL) {
tass 51:ab4529a384a6 70 in_node = pico_tree_firstNode(Datalink_proto_tree.root);
daniele 3:b4047e8a0123 71 if (in_node)
daniele 3:b4047e8a0123 72 next_in = in_node->keyValue;
daniele 3:b4047e8a0123 73 }
daniele 3:b4047e8a0123 74 if (next_out == NULL) {
daniele 3:b4047e8a0123 75 out_node = pico_tree_firstNode(Datalink_proto_tree.root);
daniele 3:b4047e8a0123 76 if (out_node)
daniele 3:b4047e8a0123 77 next_out = out_node->keyValue;
daniele 3:b4047e8a0123 78 }
daniele 3:b4047e8a0123 79
daniele 3:b4047e8a0123 80 if (direction == PICO_LOOP_DIR_IN)
daniele 3:b4047e8a0123 81 {
tass 51:ab4529a384a6 82 next_node = in_node;
daniele 3:b4047e8a0123 83 next = next_in;
daniele 3:b4047e8a0123 84 }
daniele 3:b4047e8a0123 85 else if (direction == PICO_LOOP_DIR_OUT)
daniele 3:b4047e8a0123 86 {
tass 51:ab4529a384a6 87 next_node = out_node;
daniele 3:b4047e8a0123 88 next = next_out;
daniele 3:b4047e8a0123 89 }
daniele 3:b4047e8a0123 90
daniele 3:b4047e8a0123 91 /* init start node */
daniele 3:b4047e8a0123 92 start = next;
daniele 3:b4047e8a0123 93
daniele 3:b4047e8a0123 94 /* round-robin all datalink protocols, break if traversed all protocols */
daniele 3:b4047e8a0123 95 while (loop_score > DL_LOOP_MIN && next != NULL) {
daniele 3:b4047e8a0123 96 loop_score = proto_loop(next, loop_score, direction);
daniele 3:b4047e8a0123 97
daniele 3:b4047e8a0123 98 //next = RB_NEXT(pico_protocol_tree, &Datalink_proto_tree, next);
daniele 3:b4047e8a0123 99 next_node = pico_tree_next(next_node);
daniele 3:b4047e8a0123 100 next = next_node->keyValue;
daniele 3:b4047e8a0123 101
daniele 3:b4047e8a0123 102 if (next == NULL)
daniele 3:b4047e8a0123 103 {
tass 51:ab4529a384a6 104 next_node = pico_tree_firstNode(Datalink_proto_tree.root);
tass 51:ab4529a384a6 105 next = next_node->keyValue;
daniele 3:b4047e8a0123 106 }
daniele 3:b4047e8a0123 107 if (next == start)
daniele 3:b4047e8a0123 108 break;
daniele 3:b4047e8a0123 109 }
daniele 3:b4047e8a0123 110
daniele 3:b4047e8a0123 111 if (direction == PICO_LOOP_DIR_IN)
daniele 3:b4047e8a0123 112 {
tass 51:ab4529a384a6 113 in_node = next_node;
daniele 3:b4047e8a0123 114 next_in = next;
daniele 3:b4047e8a0123 115 }
daniele 3:b4047e8a0123 116 else if (direction == PICO_LOOP_DIR_OUT)
daniele 3:b4047e8a0123 117 {
tass 51:ab4529a384a6 118 out_node = next_node;
daniele 3:b4047e8a0123 119 next_out = next;
daniele 3:b4047e8a0123 120 }
daniele 3:b4047e8a0123 121
daniele 3:b4047e8a0123 122 return loop_score;
daniele 3:b4047e8a0123 123 }
daniele 3:b4047e8a0123 124
daniele 3:b4047e8a0123 125
daniele 3:b4047e8a0123 126 #define NW_LOOP_MIN 1
daniele 3:b4047e8a0123 127
daniele 3:b4047e8a0123 128 int pico_protocol_network_loop(int loop_score, int direction)
daniele 3:b4047e8a0123 129 {
daniele 3:b4047e8a0123 130 struct pico_protocol *start;
daniele 3:b4047e8a0123 131 static struct pico_protocol *next = NULL, *next_in = NULL, *next_out = NULL;
daniele 3:b4047e8a0123 132 static struct pico_tree_node * next_node, * in_node, * out_node;
daniele 3:b4047e8a0123 133
daniele 3:b4047e8a0123 134 if (next_in == NULL) {
daniele 3:b4047e8a0123 135 in_node = pico_tree_firstNode(Network_proto_tree.root);
daniele 3:b4047e8a0123 136 if (in_node)
daniele 3:b4047e8a0123 137 next_in = in_node->keyValue;
daniele 3:b4047e8a0123 138 }
daniele 3:b4047e8a0123 139 if (next_out == NULL) {
tass 51:ab4529a384a6 140 out_node = pico_tree_firstNode(Network_proto_tree.root);
daniele 3:b4047e8a0123 141 if (out_node)
tass 51:ab4529a384a6 142 next_out = out_node->keyValue;
daniele 3:b4047e8a0123 143 }
daniele 3:b4047e8a0123 144 if (direction == PICO_LOOP_DIR_IN)
daniele 3:b4047e8a0123 145 {
tass 51:ab4529a384a6 146 next_node = in_node;
daniele 3:b4047e8a0123 147 next = next_in;
daniele 3:b4047e8a0123 148 }
daniele 3:b4047e8a0123 149 else if (direction == PICO_LOOP_DIR_OUT)
daniele 3:b4047e8a0123 150 {
tass 51:ab4529a384a6 151 next_node = out_node;
daniele 3:b4047e8a0123 152 next = next_out;
daniele 3:b4047e8a0123 153 }
daniele 3:b4047e8a0123 154
daniele 3:b4047e8a0123 155 /* init start node */
daniele 3:b4047e8a0123 156 start = next;
daniele 3:b4047e8a0123 157
daniele 3:b4047e8a0123 158 /* round-robin all network protocols, break if traversed all protocols */
daniele 3:b4047e8a0123 159 while (loop_score > NW_LOOP_MIN && next != NULL) {
daniele 3:b4047e8a0123 160 loop_score = proto_loop(next, loop_score, direction);
daniele 3:b4047e8a0123 161
daniele 3:b4047e8a0123 162 next_node = pico_tree_next(next_node);
daniele 3:b4047e8a0123 163 next = next_node->keyValue;
daniele 3:b4047e8a0123 164
daniele 3:b4047e8a0123 165 if (next == NULL)
daniele 3:b4047e8a0123 166 {
tass 51:ab4529a384a6 167 next_node = pico_tree_firstNode(Network_proto_tree.root);
tass 51:ab4529a384a6 168 next = next_node->keyValue;
daniele 3:b4047e8a0123 169 }
daniele 3:b4047e8a0123 170 if (next == start)
daniele 3:b4047e8a0123 171 break;
daniele 3:b4047e8a0123 172 }
daniele 3:b4047e8a0123 173
daniele 3:b4047e8a0123 174 if (direction == PICO_LOOP_DIR_IN)
daniele 3:b4047e8a0123 175 {
tass 51:ab4529a384a6 176 in_node = next_node;
daniele 3:b4047e8a0123 177 next_in = next;
daniele 3:b4047e8a0123 178 }
daniele 3:b4047e8a0123 179 else if (direction == PICO_LOOP_DIR_OUT)
daniele 3:b4047e8a0123 180 {
tass 51:ab4529a384a6 181 out_node = next_node;
daniele 3:b4047e8a0123 182 next_out = next;
daniele 3:b4047e8a0123 183 }
daniele 3:b4047e8a0123 184
daniele 3:b4047e8a0123 185 return loop_score;
daniele 3:b4047e8a0123 186 }
daniele 3:b4047e8a0123 187
daniele 3:b4047e8a0123 188 #define TP_LOOP_MIN 1
daniele 3:b4047e8a0123 189
daniele 3:b4047e8a0123 190 int pico_protocol_transport_loop(int loop_score, int direction)
daniele 3:b4047e8a0123 191 {
daniele 3:b4047e8a0123 192 struct pico_protocol *start;
daniele 3:b4047e8a0123 193 static struct pico_protocol *next = NULL, *next_in = NULL, *next_out = NULL;
daniele 3:b4047e8a0123 194 static struct pico_tree_node * next_node, * in_node, * out_node;
daniele 3:b4047e8a0123 195
daniele 3:b4047e8a0123 196 if (next_in == NULL) {
tass 51:ab4529a384a6 197 in_node = pico_tree_firstNode(Transport_proto_tree.root);
daniele 3:b4047e8a0123 198 if (in_node)
tass 51:ab4529a384a6 199 next_in = in_node->keyValue;
daniele 3:b4047e8a0123 200 }
daniele 3:b4047e8a0123 201 if (next_out == NULL) {
tass 51:ab4529a384a6 202 out_node = pico_tree_firstNode(Transport_proto_tree.root);
daniele 3:b4047e8a0123 203 if (out_node)
tass 51:ab4529a384a6 204 next_out = out_node->keyValue;
daniele 3:b4047e8a0123 205 }
daniele 3:b4047e8a0123 206
daniele 3:b4047e8a0123 207 if (direction == PICO_LOOP_DIR_IN)
daniele 3:b4047e8a0123 208 {
tass 51:ab4529a384a6 209 next_node = in_node;
daniele 3:b4047e8a0123 210 next = next_in;
daniele 3:b4047e8a0123 211 }
daniele 3:b4047e8a0123 212 else if (direction == PICO_LOOP_DIR_OUT)
daniele 3:b4047e8a0123 213 {
tass 51:ab4529a384a6 214 next_node = out_node;
daniele 3:b4047e8a0123 215 next = next_out;
daniele 3:b4047e8a0123 216 }
daniele 3:b4047e8a0123 217
daniele 3:b4047e8a0123 218 /* init start node */
daniele 3:b4047e8a0123 219 start = next;
daniele 3:b4047e8a0123 220
daniele 3:b4047e8a0123 221 /* round-robin all transport protocols, break if traversed all protocols */
daniele 3:b4047e8a0123 222 while (loop_score > DL_LOOP_MIN && next != NULL) {
daniele 3:b4047e8a0123 223 loop_score = proto_loop(next, loop_score, direction);
daniele 3:b4047e8a0123 224
daniele 3:b4047e8a0123 225 //next = RB_NEXT(pico_protocol_tree, &Transport_proto_tree, next);
daniele 3:b4047e8a0123 226 next_node = pico_tree_next(next_node);
daniele 3:b4047e8a0123 227 next = next_node->keyValue;
daniele 3:b4047e8a0123 228
daniele 3:b4047e8a0123 229 if (next == NULL)
daniele 3:b4047e8a0123 230 {
tass 51:ab4529a384a6 231 next_node = pico_tree_firstNode(Transport_proto_tree.root);
tass 51:ab4529a384a6 232 next = next_node->keyValue;
daniele 3:b4047e8a0123 233 }
daniele 3:b4047e8a0123 234 if (next == start)
daniele 3:b4047e8a0123 235 break;
daniele 3:b4047e8a0123 236 }
daniele 3:b4047e8a0123 237
daniele 3:b4047e8a0123 238 if (direction == PICO_LOOP_DIR_IN)
daniele 3:b4047e8a0123 239 {
tass 51:ab4529a384a6 240 in_node = next_node;
daniele 3:b4047e8a0123 241 next_in = next;
daniele 3:b4047e8a0123 242 }
daniele 3:b4047e8a0123 243 else if (direction == PICO_LOOP_DIR_OUT)
daniele 3:b4047e8a0123 244 {
tass 51:ab4529a384a6 245 out_node = next_node;
daniele 3:b4047e8a0123 246 next_out = next;
daniele 3:b4047e8a0123 247 }
daniele 3:b4047e8a0123 248
daniele 3:b4047e8a0123 249 return loop_score;
daniele 3:b4047e8a0123 250 }
daniele 3:b4047e8a0123 251
daniele 3:b4047e8a0123 252
daniele 3:b4047e8a0123 253 #define SOCK_LOOP_MIN 1
daniele 3:b4047e8a0123 254
daniele 3:b4047e8a0123 255 int pico_protocol_socket_loop(int loop_score, int direction)
daniele 3:b4047e8a0123 256 {
daniele 3:b4047e8a0123 257 struct pico_protocol *start;
daniele 3:b4047e8a0123 258 static struct pico_protocol *next = NULL, *next_in = NULL, *next_out = NULL;
daniele 3:b4047e8a0123 259 static struct pico_tree_node * next_node, * in_node, * out_node;
daniele 3:b4047e8a0123 260
daniele 3:b4047e8a0123 261 if (next_in == NULL) {
tass 51:ab4529a384a6 262 in_node = pico_tree_firstNode(Socket_proto_tree.root);
daniele 3:b4047e8a0123 263 if(in_node)
tass 51:ab4529a384a6 264 next_in = in_node->keyValue;
daniele 3:b4047e8a0123 265 }
daniele 3:b4047e8a0123 266 if (next_out == NULL) {
tass 51:ab4529a384a6 267 out_node = pico_tree_firstNode(Socket_proto_tree.root);
daniele 3:b4047e8a0123 268 if(out_node)
daniele 3:b4047e8a0123 269 next_out = out_node->keyValue;
daniele 3:b4047e8a0123 270 }
daniele 3:b4047e8a0123 271
daniele 3:b4047e8a0123 272 if (direction == PICO_LOOP_DIR_IN)
daniele 3:b4047e8a0123 273 {
tass 51:ab4529a384a6 274 next_node = in_node;
daniele 3:b4047e8a0123 275 next = next_in;
daniele 3:b4047e8a0123 276 }
daniele 3:b4047e8a0123 277 else if (direction == PICO_LOOP_DIR_OUT)
daniele 3:b4047e8a0123 278 {
tass 51:ab4529a384a6 279 next_node = out_node;
tass 51:ab4529a384a6 280 next = next_out;
daniele 3:b4047e8a0123 281 }
daniele 3:b4047e8a0123 282
daniele 3:b4047e8a0123 283 /* init start node */
daniele 3:b4047e8a0123 284 start = next;
daniele 3:b4047e8a0123 285
daniele 3:b4047e8a0123 286 /* round-robin all transport protocols, break if traversed all protocols */
daniele 3:b4047e8a0123 287 while (loop_score > SOCK_LOOP_MIN && next != NULL) {
daniele 3:b4047e8a0123 288 loop_score = proto_loop(next, loop_score,direction);
daniele 3:b4047e8a0123 289
daniele 3:b4047e8a0123 290 next_node = pico_tree_next(next_node);
daniele 3:b4047e8a0123 291 next = next_node->keyValue;
daniele 3:b4047e8a0123 292
daniele 3:b4047e8a0123 293 if (next == NULL)
daniele 3:b4047e8a0123 294 {
daniele 3:b4047e8a0123 295 next_node = pico_tree_firstNode(next_node);
tass 51:ab4529a384a6 296 next = next_node->keyValue;
daniele 3:b4047e8a0123 297 }
daniele 3:b4047e8a0123 298 if (next == start)
daniele 3:b4047e8a0123 299 break;
daniele 3:b4047e8a0123 300 }
daniele 3:b4047e8a0123 301
daniele 3:b4047e8a0123 302 if (direction == PICO_LOOP_DIR_IN)
daniele 3:b4047e8a0123 303 {
tass 51:ab4529a384a6 304 in_node = next_node;
daniele 3:b4047e8a0123 305 next_in = next;
daniele 3:b4047e8a0123 306 }
daniele 3:b4047e8a0123 307 else if (direction == PICO_LOOP_DIR_OUT)
daniele 3:b4047e8a0123 308 {
tass 51:ab4529a384a6 309 out_node = next_node;
daniele 3:b4047e8a0123 310 next_out = next;
daniele 3:b4047e8a0123 311 }
daniele 3:b4047e8a0123 312
daniele 3:b4047e8a0123 313 return loop_score;
daniele 3:b4047e8a0123 314 }
daniele 3:b4047e8a0123 315
daniele 3:b4047e8a0123 316 int pico_protocols_loop(int loop_score)
daniele 3:b4047e8a0123 317 {
daniele 3:b4047e8a0123 318 /*
daniele 3:b4047e8a0123 319 loop_score = pico_protocol_datalink_loop(loop_score);
daniele 3:b4047e8a0123 320 loop_score = pico_protocol_network_loop(loop_score);
daniele 3:b4047e8a0123 321 loop_score = pico_protocol_transport_loop(loop_score);
daniele 3:b4047e8a0123 322 loop_score = pico_protocol_socket_loop(loop_score);
daniele 3:b4047e8a0123 323 */
daniele 3:b4047e8a0123 324 return loop_score;
daniele 3:b4047e8a0123 325 }
daniele 3:b4047e8a0123 326
daniele 3:b4047e8a0123 327 void pico_protocol_init(struct pico_protocol *p)
daniele 3:b4047e8a0123 328 {
daniele 3:b4047e8a0123 329 if (!p)
daniele 3:b4047e8a0123 330 return;
daniele 3:b4047e8a0123 331
daniele 3:b4047e8a0123 332 p->hash = pico_hash(p->name);
daniele 3:b4047e8a0123 333 switch (p->layer) {
daniele 3:b4047e8a0123 334 case PICO_LAYER_DATALINK:
daniele 3:b4047e8a0123 335 pico_tree_insert(&Datalink_proto_tree, p);
daniele 3:b4047e8a0123 336 break;
daniele 3:b4047e8a0123 337 case PICO_LAYER_NETWORK:
daniele 3:b4047e8a0123 338 pico_tree_insert(&Network_proto_tree,p);
daniele 3:b4047e8a0123 339 break;
daniele 3:b4047e8a0123 340 case PICO_LAYER_TRANSPORT:
daniele 3:b4047e8a0123 341 pico_tree_insert(&Transport_proto_tree,p);
daniele 3:b4047e8a0123 342 break;
daniele 3:b4047e8a0123 343 case PICO_LAYER_SOCKET:
daniele 3:b4047e8a0123 344 pico_tree_insert(&Socket_proto_tree,p);
daniele 3:b4047e8a0123 345 break;
daniele 3:b4047e8a0123 346 }
daniele 3:b4047e8a0123 347 dbg("Protocol %s registered (layer: %d).\n", p->name, p->layer);
daniele 3:b4047e8a0123 348
daniele 3:b4047e8a0123 349 }
daniele 3:b4047e8a0123 350