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:
Thu Sep 19 13:26:14 2013 +0000
Revision:
68:0847e35d08a6
Child:
131:4758606c9316
Imported from masterbranch, again

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