Free (GPLv2) TCP/IP stack developed by TASS Belgium

Fork of PicoTCP by Daniele Lacamera

Committer:
daniele
Date:
Sat Aug 03 08:50:27 2013 +0000
Revision:
51:18637a3d071f
Parent:
3:b4047e8a0123
Branch for CDC-ECM: Work in progress

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 {
daniele 3:b4047e8a0123 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) {
daniele 3:b4047e8a0123 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 {
daniele 3:b4047e8a0123 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 {
daniele 3:b4047e8a0123 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 {
daniele 3:b4047e8a0123 104 next_node = pico_tree_firstNode(Datalink_proto_tree.root);
daniele 3:b4047e8a0123 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 {
daniele 3:b4047e8a0123 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 {
daniele 3:b4047e8a0123 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) {
daniele 3:b4047e8a0123 140 out_node = pico_tree_firstNode(Network_proto_tree.root);
daniele 3:b4047e8a0123 141 if (out_node)
daniele 3:b4047e8a0123 142 next_out = out_node->keyValue;
daniele 3:b4047e8a0123 143 }
daniele 3:b4047e8a0123 144 if (direction == PICO_LOOP_DIR_IN)
daniele 3:b4047e8a0123 145 {
daniele 3:b4047e8a0123 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 {
daniele 3:b4047e8a0123 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 {
daniele 3:b4047e8a0123 167 next_node = pico_tree_firstNode(Network_proto_tree.root);
daniele 3:b4047e8a0123 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 {
daniele 3:b4047e8a0123 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 {
daniele 3:b4047e8a0123 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) {
daniele 3:b4047e8a0123 197 in_node = pico_tree_firstNode(Transport_proto_tree.root);
daniele 3:b4047e8a0123 198 if (in_node)
daniele 3:b4047e8a0123 199 next_in = in_node->keyValue;
daniele 3:b4047e8a0123 200 }
daniele 3:b4047e8a0123 201 if (next_out == NULL) {
daniele 3:b4047e8a0123 202 out_node = pico_tree_firstNode(Transport_proto_tree.root);
daniele 3:b4047e8a0123 203 if (out_node)
daniele 3:b4047e8a0123 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 {
daniele 3:b4047e8a0123 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 {
daniele 3:b4047e8a0123 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 {
daniele 3:b4047e8a0123 231 next_node = pico_tree_firstNode(Transport_proto_tree.root);
daniele 3:b4047e8a0123 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 {
daniele 3:b4047e8a0123 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 {
daniele 3:b4047e8a0123 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) {
daniele 3:b4047e8a0123 262 in_node = pico_tree_firstNode(Socket_proto_tree.root);
daniele 3:b4047e8a0123 263 if(in_node)
daniele 3:b4047e8a0123 264 next_in = in_node->keyValue;
daniele 3:b4047e8a0123 265 }
daniele 3:b4047e8a0123 266 if (next_out == NULL) {
daniele 3:b4047e8a0123 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 {
daniele 3:b4047e8a0123 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 {
daniele 3:b4047e8a0123 279 next_node = out_node;
daniele 3:b4047e8a0123 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);
daniele 3:b4047e8a0123 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 {
daniele 3:b4047e8a0123 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 {
daniele 3:b4047e8a0123 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