You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
221 lines
5.7 KiB
221 lines
5.7 KiB
/********************************************************************* |
|
PicoTCP. Copyright (c) 2012-2015 Altran Intelligent Systems. Some rights reserved. |
|
See LICENSE and COPYING for usage. |
|
|
|
. |
|
|
|
Authors: Daniele Lacamera |
|
*********************************************************************/ |
|
|
|
|
|
#include "pico_protocol.h" |
|
#include "pico_tree.h" |
|
|
|
/* |
|
static pico_err_t get_pico_err() |
|
{ |
|
return pico_err; |
|
} |
|
*/ |
|
|
|
struct pico_proto_rr |
|
{ |
|
struct pico_tree *t; |
|
struct pico_tree_node *node_in, *node_out; |
|
}; |
|
|
|
|
|
static int pico_proto_cmp(void *ka, void *kb) |
|
{ |
|
struct pico_protocol *a = ka, *b = kb; |
|
if (a->hash < b->hash) |
|
return -1; |
|
|
|
if (a->hash > b->hash) |
|
return 1; |
|
|
|
return 0; |
|
} |
|
|
|
PICO_TREE_DECLARE(Datalink_proto_tree, pico_proto_cmp); |
|
PICO_TREE_DECLARE(Network_proto_tree, pico_proto_cmp); |
|
PICO_TREE_DECLARE(Transport_proto_tree, pico_proto_cmp); |
|
PICO_TREE_DECLARE(Socket_proto_tree, pico_proto_cmp); |
|
|
|
/* Static variables to keep track of the round robin loop */ |
|
static struct pico_proto_rr proto_rr_datalink = { |
|
&Datalink_proto_tree, NULL, NULL |
|
}; |
|
static struct pico_proto_rr proto_rr_network = { |
|
&Network_proto_tree, NULL, NULL |
|
}; |
|
static struct pico_proto_rr proto_rr_transport = { |
|
&Transport_proto_tree, NULL, NULL |
|
}; |
|
static struct pico_proto_rr proto_rr_socket = { |
|
&Socket_proto_tree, NULL, NULL |
|
}; |
|
|
|
static int proto_loop_in(struct pico_protocol *proto, int loop_score) |
|
{ |
|
struct pico_frame *f; |
|
while(loop_score > 0) { |
|
if (proto->q_in->frames == 0) |
|
break; |
|
|
|
f = pico_dequeue(proto->q_in); |
|
if ((f) && (proto->process_in(proto, f) > 0)) { |
|
loop_score--; |
|
} |
|
} |
|
return loop_score; |
|
} |
|
|
|
static int proto_loop_out(struct pico_protocol *proto, int loop_score) |
|
{ |
|
struct pico_frame *f; |
|
while(loop_score > 0) { |
|
if (proto->q_out->frames == 0) |
|
break; |
|
|
|
f = pico_dequeue(proto->q_out); |
|
if ((f) && (proto->process_out(proto, f) > 0)) { |
|
loop_score--; |
|
} |
|
} |
|
return loop_score; |
|
} |
|
|
|
static int proto_loop(struct pico_protocol *proto, int loop_score, int direction) |
|
{ |
|
|
|
if (direction == PICO_LOOP_DIR_IN) |
|
loop_score = proto_loop_in(proto, loop_score); |
|
else if (direction == PICO_LOOP_DIR_OUT) |
|
loop_score = proto_loop_out(proto, loop_score); |
|
|
|
return loop_score; |
|
} |
|
|
|
static struct pico_tree_node *roundrobin_init(struct pico_proto_rr *rr, int direction) |
|
{ |
|
struct pico_tree_node *next_node = NULL; |
|
/* Initialization (takes place only once) */ |
|
if (rr->node_in == NULL) |
|
rr->node_in = pico_tree_firstNode(rr->t->root); |
|
|
|
if (rr->node_out == NULL) |
|
rr->node_out = pico_tree_firstNode(rr->t->root); |
|
|
|
if (direction == PICO_LOOP_DIR_IN) |
|
next_node = rr->node_in; |
|
else |
|
next_node = rr->node_out; |
|
|
|
return next_node; |
|
} |
|
|
|
static void roundrobin_end(struct pico_proto_rr *rr, int direction, struct pico_tree_node *last) |
|
{ |
|
if (direction == PICO_LOOP_DIR_IN) |
|
rr->node_in = last; |
|
else |
|
rr->node_out = last; |
|
} |
|
|
|
static int pico_protocol_generic_loop(struct pico_proto_rr *rr, int loop_score, int direction) |
|
{ |
|
struct pico_protocol *start, *next; |
|
struct pico_tree_node *next_node = roundrobin_init(rr, direction); |
|
|
|
if (!next_node) |
|
return loop_score; |
|
|
|
next = next_node->keyValue; |
|
|
|
/* init start node */ |
|
start = next; |
|
|
|
/* round-robin all layer protocols, break if traversed all protocols */ |
|
while (loop_score > 1 && next != NULL) { |
|
loop_score = proto_loop(next, loop_score, direction); |
|
next_node = pico_tree_next(next_node); |
|
next = next_node->keyValue; |
|
if (next == NULL) |
|
{ |
|
next_node = pico_tree_firstNode(rr->t->root); |
|
next = next_node->keyValue; |
|
} |
|
|
|
if (next == start) |
|
break; |
|
} |
|
roundrobin_end(rr, direction, next_node); |
|
return loop_score; |
|
} |
|
|
|
int pico_protocol_datalink_loop(int loop_score, int direction) |
|
{ |
|
return pico_protocol_generic_loop(&proto_rr_datalink, loop_score, direction); |
|
} |
|
|
|
int pico_protocol_network_loop(int loop_score, int direction) |
|
{ |
|
return pico_protocol_generic_loop(&proto_rr_network, loop_score, direction); |
|
} |
|
|
|
int pico_protocol_transport_loop(int loop_score, int direction) |
|
{ |
|
return pico_protocol_generic_loop(&proto_rr_transport, loop_score, direction); |
|
} |
|
|
|
int pico_protocol_socket_loop(int loop_score, int direction) |
|
{ |
|
return pico_protocol_generic_loop(&proto_rr_socket, loop_score, direction); |
|
} |
|
|
|
int pico_protocols_loop(int loop_score) |
|
{ |
|
/* |
|
loop_score = pico_protocol_datalink_loop(loop_score); |
|
loop_score = pico_protocol_network_loop(loop_score); |
|
loop_score = pico_protocol_transport_loop(loop_score); |
|
loop_score = pico_protocol_socket_loop(loop_score); |
|
*/ |
|
return loop_score; |
|
} |
|
|
|
static void proto_layer_rr_reset(struct pico_proto_rr *rr) |
|
{ |
|
rr->node_in = NULL; |
|
rr->node_out = NULL; |
|
} |
|
|
|
void pico_protocol_init(struct pico_protocol *p) |
|
{ |
|
if (!p) |
|
return; |
|
|
|
p->hash = pico_hash(p->name, (uint32_t)strlen(p->name)); |
|
switch (p->layer) { |
|
case PICO_LAYER_DATALINK: |
|
pico_tree_insert(&Datalink_proto_tree, p); |
|
proto_layer_rr_reset(&proto_rr_datalink); |
|
break; |
|
case PICO_LAYER_NETWORK: |
|
pico_tree_insert(&Network_proto_tree, p); |
|
proto_layer_rr_reset(&proto_rr_network); |
|
break; |
|
case PICO_LAYER_TRANSPORT: |
|
pico_tree_insert(&Transport_proto_tree, p); |
|
proto_layer_rr_reset(&proto_rr_transport); |
|
break; |
|
case PICO_LAYER_SOCKET: |
|
pico_tree_insert(&Socket_proto_tree, p); |
|
proto_layer_rr_reset(&proto_rr_socket); |
|
break; |
|
} |
|
dbg("Protocol %s registered (layer: %d).\n", p->name, p->layer); |
|
|
|
} |
|
|
|
|