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 28 14:14:17 2015 +0200
Revision:
154:6c0e92a80c4a
Parent:
152:a3d286bf94e5
To latest development.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
tass 68:0847e35d08a6 1 /*********************************************************************
tass 152:a3d286bf94e5 2 PicoTCP. Copyright (c) 2012-2015 Altran Intelligent Systems. Some rights reserved.
TASS Belgium NV 131:4758606c9316 3 See LICENSE and COPYING for usage.
tass 68:0847e35d08a6 4
TASS Belgium NV 131:4758606c9316 5 .
tass 68:0847e35d08a6 6
TASS Belgium NV 131:4758606c9316 7 Authors: Daniele Lacamera
TASS Belgium NV 131:4758606c9316 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 picotcp@tass.be 137:a1c8bfa9d691 14 struct pico_proto_rr
tass picotcp@tass.be 137:a1c8bfa9d691 15 {
tass picotcp@tass.be 137:a1c8bfa9d691 16 struct pico_tree *t;
tass picotcp@tass.be 137:a1c8bfa9d691 17 struct pico_tree_node *node_in, *node_out;
tass picotcp@tass.be 137:a1c8bfa9d691 18 };
tass picotcp@tass.be 137:a1c8bfa9d691 19
tass picotcp@tass.be 137:a1c8bfa9d691 20
tass 68:0847e35d08a6 21 static int pico_proto_cmp(void *ka, void *kb)
tass 68:0847e35d08a6 22 {
TASS Belgium NV 131:4758606c9316 23 struct pico_protocol *a = ka, *b = kb;
TASS Belgium NV 131:4758606c9316 24 if (a->hash < b->hash)
TASS Belgium NV 131:4758606c9316 25 return -1;
TASS Belgium NV 131:4758606c9316 26
TASS Belgium NV 131:4758606c9316 27 if (a->hash > b->hash)
TASS Belgium NV 131:4758606c9316 28 return 1;
TASS Belgium NV 131:4758606c9316 29
TASS Belgium NV 131:4758606c9316 30 return 0;
tass 68:0847e35d08a6 31 }
tass 68:0847e35d08a6 32
TASS Belgium NV 131:4758606c9316 33 PICO_TREE_DECLARE(Datalink_proto_tree, pico_proto_cmp);
TASS Belgium NV 131:4758606c9316 34 PICO_TREE_DECLARE(Network_proto_tree, pico_proto_cmp);
TASS Belgium NV 131:4758606c9316 35 PICO_TREE_DECLARE(Transport_proto_tree, pico_proto_cmp);
TASS Belgium NV 131:4758606c9316 36 PICO_TREE_DECLARE(Socket_proto_tree, pico_proto_cmp);
tass 68:0847e35d08a6 37
tass picotcp@tass.be 137:a1c8bfa9d691 38 /* Static variables to keep track of the round robin loop */
tass picotcp@tass.be 137:a1c8bfa9d691 39 static struct pico_proto_rr proto_rr_datalink = {
tass picotcp@tass.be 137:a1c8bfa9d691 40 &Datalink_proto_tree, NULL, NULL
tass picotcp@tass.be 137:a1c8bfa9d691 41 };
tass picotcp@tass.be 137:a1c8bfa9d691 42 static struct pico_proto_rr proto_rr_network = {
tass picotcp@tass.be 137:a1c8bfa9d691 43 &Network_proto_tree, NULL, NULL
tass picotcp@tass.be 137:a1c8bfa9d691 44 };
tass picotcp@tass.be 137:a1c8bfa9d691 45 static struct pico_proto_rr proto_rr_transport = {
tass picotcp@tass.be 137:a1c8bfa9d691 46 &Transport_proto_tree, NULL, NULL
tass picotcp@tass.be 137:a1c8bfa9d691 47 };
tass picotcp@tass.be 137:a1c8bfa9d691 48 static struct pico_proto_rr proto_rr_socket = {
tass picotcp@tass.be 137:a1c8bfa9d691 49 &Socket_proto_tree, NULL, NULL
tass picotcp@tass.be 137:a1c8bfa9d691 50 };
tass picotcp@tass.be 137:a1c8bfa9d691 51
tass picotcp@tass.be 137:a1c8bfa9d691 52 static int proto_loop_in(struct pico_protocol *proto, int loop_score)
tass 68:0847e35d08a6 53 {
TASS Belgium NV 131:4758606c9316 54 struct pico_frame *f;
tass picotcp@tass.be 137:a1c8bfa9d691 55 while(loop_score > 0) {
tass 154:6c0e92a80c4a 56 if (proto->q_in->frames == 0)
tass picotcp@tass.be 137:a1c8bfa9d691 57 break;
tass 68:0847e35d08a6 58
tass picotcp@tass.be 137:a1c8bfa9d691 59 f = pico_dequeue(proto->q_in);
tass picotcp@tass.be 137:a1c8bfa9d691 60 if ((f) && (proto->process_in(proto, f) > 0)) {
tass picotcp@tass.be 137:a1c8bfa9d691 61 loop_score--;
TASS Belgium NV 131:4758606c9316 62 }
tass 68:0847e35d08a6 63 }
tass picotcp@tass.be 137:a1c8bfa9d691 64 return loop_score;
tass picotcp@tass.be 137:a1c8bfa9d691 65 }
tass picotcp@tass.be 137:a1c8bfa9d691 66
tass picotcp@tass.be 137:a1c8bfa9d691 67 static int proto_loop_out(struct pico_protocol *proto, int loop_score)
tass picotcp@tass.be 137:a1c8bfa9d691 68 {
tass picotcp@tass.be 137:a1c8bfa9d691 69 struct pico_frame *f;
tass picotcp@tass.be 137:a1c8bfa9d691 70 while(loop_score > 0) {
tass 154:6c0e92a80c4a 71 if (proto->q_out->frames == 0)
tass picotcp@tass.be 137:a1c8bfa9d691 72 break;
tass picotcp@tass.be 137:a1c8bfa9d691 73
tass picotcp@tass.be 137:a1c8bfa9d691 74 f = pico_dequeue(proto->q_out);
tass picotcp@tass.be 137:a1c8bfa9d691 75 if ((f) && (proto->process_out(proto, f) > 0)) {
tass picotcp@tass.be 137:a1c8bfa9d691 76 loop_score--;
tass picotcp@tass.be 137:a1c8bfa9d691 77 }
tass picotcp@tass.be 137:a1c8bfa9d691 78 }
tass picotcp@tass.be 137:a1c8bfa9d691 79 return loop_score;
tass picotcp@tass.be 137:a1c8bfa9d691 80 }
tass picotcp@tass.be 137:a1c8bfa9d691 81
tass picotcp@tass.be 137:a1c8bfa9d691 82 static int proto_loop(struct pico_protocol *proto, int loop_score, int direction)
tass picotcp@tass.be 137:a1c8bfa9d691 83 {
tass picotcp@tass.be 137:a1c8bfa9d691 84
tass picotcp@tass.be 137:a1c8bfa9d691 85 if (direction == PICO_LOOP_DIR_IN)
tass picotcp@tass.be 137:a1c8bfa9d691 86 loop_score = proto_loop_in(proto, loop_score);
tass picotcp@tass.be 137:a1c8bfa9d691 87 else if (direction == PICO_LOOP_DIR_OUT)
tass picotcp@tass.be 137:a1c8bfa9d691 88 loop_score = proto_loop_out(proto, loop_score);
tass 68:0847e35d08a6 89
TASS Belgium NV 131:4758606c9316 90 return loop_score;
tass 68:0847e35d08a6 91 }
tass 68:0847e35d08a6 92
tass picotcp@tass.be 137:a1c8bfa9d691 93 static struct pico_tree_node *roundrobin_init(struct pico_proto_rr *rr, int direction)
tass 68:0847e35d08a6 94 {
tass picotcp@tass.be 137:a1c8bfa9d691 95 struct pico_tree_node *next_node = NULL;
tass picotcp@tass.be 137:a1c8bfa9d691 96 /* Initialization (takes place only once) */
tass picotcp@tass.be 137:a1c8bfa9d691 97 if (rr->node_in == NULL)
tass picotcp@tass.be 137:a1c8bfa9d691 98 rr->node_in = pico_tree_firstNode(rr->t->root);
TASS Belgium NV 131:4758606c9316 99
tass picotcp@tass.be 137:a1c8bfa9d691 100 if (rr->node_out == NULL)
tass picotcp@tass.be 137:a1c8bfa9d691 101 rr->node_out = pico_tree_firstNode(rr->t->root);
tass 68:0847e35d08a6 102
TASS Belgium NV 131:4758606c9316 103 if (direction == PICO_LOOP_DIR_IN)
tass picotcp@tass.be 137:a1c8bfa9d691 104 next_node = rr->node_in;
tass picotcp@tass.be 137:a1c8bfa9d691 105 else
tass picotcp@tass.be 137:a1c8bfa9d691 106 next_node = rr->node_out;
tass picotcp@tass.be 137:a1c8bfa9d691 107
tass picotcp@tass.be 137:a1c8bfa9d691 108 return next_node;
tass picotcp@tass.be 137:a1c8bfa9d691 109 }
tass picotcp@tass.be 137:a1c8bfa9d691 110
tass picotcp@tass.be 137:a1c8bfa9d691 111 static void roundrobin_end(struct pico_proto_rr *rr, int direction, struct pico_tree_node *last)
tass picotcp@tass.be 137:a1c8bfa9d691 112 {
tass picotcp@tass.be 137:a1c8bfa9d691 113 if (direction == PICO_LOOP_DIR_IN)
tass picotcp@tass.be 137:a1c8bfa9d691 114 rr->node_in = last;
tass picotcp@tass.be 137:a1c8bfa9d691 115 else
tass picotcp@tass.be 137:a1c8bfa9d691 116 rr->node_out = last;
tass picotcp@tass.be 137:a1c8bfa9d691 117 }
tass picotcp@tass.be 137:a1c8bfa9d691 118
tass picotcp@tass.be 137:a1c8bfa9d691 119 static int pico_protocol_generic_loop(struct pico_proto_rr *rr, int loop_score, int direction)
tass picotcp@tass.be 137:a1c8bfa9d691 120 {
tass picotcp@tass.be 137:a1c8bfa9d691 121 struct pico_protocol *start, *next;
tass picotcp@tass.be 137:a1c8bfa9d691 122 struct pico_tree_node *next_node = roundrobin_init(rr, direction);
tass picotcp@tass.be 137:a1c8bfa9d691 123
tass picotcp@tass.be 137:a1c8bfa9d691 124 if (!next_node)
tass picotcp@tass.be 137:a1c8bfa9d691 125 return loop_score;
tass 152:a3d286bf94e5 126
tass 152:a3d286bf94e5 127 next = next_node->keyValue;
TASS Belgium NV 131:4758606c9316 128
TASS Belgium NV 131:4758606c9316 129 /* init start node */
TASS Belgium NV 131:4758606c9316 130 start = next;
tass 68:0847e35d08a6 131
tass picotcp@tass.be 137:a1c8bfa9d691 132 /* round-robin all layer protocols, break if traversed all protocols */
tass picotcp@tass.be 137:a1c8bfa9d691 133 while (loop_score > 1 && next != NULL) {
TASS Belgium NV 131:4758606c9316 134 loop_score = proto_loop(next, loop_score, direction);
TASS Belgium NV 131:4758606c9316 135 next_node = pico_tree_next(next_node);
TASS Belgium NV 131:4758606c9316 136 next = next_node->keyValue;
TASS Belgium NV 131:4758606c9316 137 if (next == NULL)
TASS Belgium NV 131:4758606c9316 138 {
tass picotcp@tass.be 137:a1c8bfa9d691 139 next_node = pico_tree_firstNode(rr->t->root);
TASS Belgium NV 131:4758606c9316 140 next = next_node->keyValue;
TASS Belgium NV 131:4758606c9316 141 }
tass 68:0847e35d08a6 142
TASS Belgium NV 131:4758606c9316 143 if (next == start)
TASS Belgium NV 131:4758606c9316 144 break;
tass 68:0847e35d08a6 145 }
tass picotcp@tass.be 137:a1c8bfa9d691 146 roundrobin_end(rr, direction, next_node);
TASS Belgium NV 131:4758606c9316 147 return loop_score;
tass 68:0847e35d08a6 148 }
tass 68:0847e35d08a6 149
tass picotcp@tass.be 137:a1c8bfa9d691 150 int pico_protocol_datalink_loop(int loop_score, int direction)
tass picotcp@tass.be 137:a1c8bfa9d691 151 {
tass picotcp@tass.be 137:a1c8bfa9d691 152 return pico_protocol_generic_loop(&proto_rr_datalink, loop_score, direction);
tass picotcp@tass.be 137:a1c8bfa9d691 153 }
tass 68:0847e35d08a6 154
tass 68:0847e35d08a6 155 int pico_protocol_network_loop(int loop_score, int direction)
tass 68:0847e35d08a6 156 {
tass picotcp@tass.be 137:a1c8bfa9d691 157 return pico_protocol_generic_loop(&proto_rr_network, loop_score, direction);
tass 68:0847e35d08a6 158 }
tass 68:0847e35d08a6 159
tass 68:0847e35d08a6 160 int pico_protocol_transport_loop(int loop_score, int direction)
tass 68:0847e35d08a6 161 {
tass picotcp@tass.be 137:a1c8bfa9d691 162 return pico_protocol_generic_loop(&proto_rr_transport, loop_score, direction);
tass 68:0847e35d08a6 163 }
tass 68:0847e35d08a6 164
tass 68:0847e35d08a6 165 int pico_protocol_socket_loop(int loop_score, int direction)
tass 68:0847e35d08a6 166 {
tass picotcp@tass.be 137:a1c8bfa9d691 167 return pico_protocol_generic_loop(&proto_rr_socket, loop_score, direction);
tass 68:0847e35d08a6 168 }
tass 68:0847e35d08a6 169
tass 68:0847e35d08a6 170 int pico_protocols_loop(int loop_score)
tass 68:0847e35d08a6 171 {
tass 68:0847e35d08a6 172 /*
TASS Belgium NV 131:4758606c9316 173 loop_score = pico_protocol_datalink_loop(loop_score);
TASS Belgium NV 131:4758606c9316 174 loop_score = pico_protocol_network_loop(loop_score);
TASS Belgium NV 131:4758606c9316 175 loop_score = pico_protocol_transport_loop(loop_score);
TASS Belgium NV 131:4758606c9316 176 loop_score = pico_protocol_socket_loop(loop_score);
TASS Belgium NV 131:4758606c9316 177 */
TASS Belgium NV 131:4758606c9316 178 return loop_score;
tass 68:0847e35d08a6 179 }
tass 68:0847e35d08a6 180
tass picotcp@tass.be 137:a1c8bfa9d691 181 static void proto_layer_rr_reset(struct pico_proto_rr *rr)
tass picotcp@tass.be 137:a1c8bfa9d691 182 {
tass picotcp@tass.be 137:a1c8bfa9d691 183 rr->node_in = NULL;
tass picotcp@tass.be 137:a1c8bfa9d691 184 rr->node_out = NULL;
tass picotcp@tass.be 137:a1c8bfa9d691 185 }
tass picotcp@tass.be 137:a1c8bfa9d691 186
tass 68:0847e35d08a6 187 void pico_protocol_init(struct pico_protocol *p)
tass 68:0847e35d08a6 188 {
TASS Belgium NV 131:4758606c9316 189 if (!p)
TASS Belgium NV 131:4758606c9316 190 return;
tass 68:0847e35d08a6 191
tass picotcp@tass.be 133:5b075f5e141a 192 p->hash = pico_hash(p->name, (uint32_t)strlen(p->name));
TASS Belgium NV 131:4758606c9316 193 switch (p->layer) {
tass 68:0847e35d08a6 194 case PICO_LAYER_DATALINK:
TASS Belgium NV 131:4758606c9316 195 pico_tree_insert(&Datalink_proto_tree, p);
tass picotcp@tass.be 137:a1c8bfa9d691 196 proto_layer_rr_reset(&proto_rr_datalink);
TASS Belgium NV 131:4758606c9316 197 break;
tass 68:0847e35d08a6 198 case PICO_LAYER_NETWORK:
TASS Belgium NV 131:4758606c9316 199 pico_tree_insert(&Network_proto_tree, p);
tass picotcp@tass.be 137:a1c8bfa9d691 200 proto_layer_rr_reset(&proto_rr_network);
TASS Belgium NV 131:4758606c9316 201 break;
tass 68:0847e35d08a6 202 case PICO_LAYER_TRANSPORT:
TASS Belgium NV 131:4758606c9316 203 pico_tree_insert(&Transport_proto_tree, p);
tass picotcp@tass.be 137:a1c8bfa9d691 204 proto_layer_rr_reset(&proto_rr_transport);
TASS Belgium NV 131:4758606c9316 205 break;
tass 68:0847e35d08a6 206 case PICO_LAYER_SOCKET:
TASS Belgium NV 131:4758606c9316 207 pico_tree_insert(&Socket_proto_tree, p);
tass picotcp@tass.be 137:a1c8bfa9d691 208 proto_layer_rr_reset(&proto_rr_socket);
TASS Belgium NV 131:4758606c9316 209 break;
TASS Belgium NV 131:4758606c9316 210 }
TASS Belgium NV 131:4758606c9316 211 dbg("Protocol %s registered (layer: %d).\n", p->name, p->layer);
tass 68:0847e35d08a6 212
tass 68:0847e35d08a6 213 }
tass 68:0847e35d08a6 214