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