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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pico_protocol.c Source File

pico_protocol.c

00001 /*********************************************************************
00002    PicoTCP. Copyright (c) 2012-2015 Altran Intelligent Systems. Some rights reserved.
00003    See LICENSE and COPYING for usage.
00004 
00005    .
00006 
00007    Authors: Daniele Lacamera
00008  *********************************************************************/
00009 
00010 
00011 #include "pico_protocol.h"
00012 #include "pico_tree.h"
00013 
00014 struct pico_proto_rr
00015 {
00016     struct pico_tree *t;
00017     struct pico_tree_node *node_in, *node_out;
00018 };
00019 
00020 
00021 static int pico_proto_cmp(void *ka, void *kb)
00022 {
00023     struct pico_protocol *a = ka, *b = kb;
00024     if (a->hash < b->hash)
00025         return -1;
00026 
00027     if (a->hash > b->hash)
00028         return 1;
00029 
00030     return 0;
00031 }
00032 
00033 PICO_TREE_DECLARE(Datalink_proto_tree, pico_proto_cmp);
00034 PICO_TREE_DECLARE(Network_proto_tree, pico_proto_cmp);
00035 PICO_TREE_DECLARE(Transport_proto_tree, pico_proto_cmp);
00036 PICO_TREE_DECLARE(Socket_proto_tree, pico_proto_cmp);
00037 
00038 /* Static variables to keep track of the round robin loop */
00039 static struct pico_proto_rr proto_rr_datalink   = {
00040     &Datalink_proto_tree,     NULL, NULL
00041 };
00042 static struct pico_proto_rr proto_rr_network    = {
00043     &Network_proto_tree,      NULL, NULL
00044 };
00045 static struct pico_proto_rr proto_rr_transport  = {
00046     &Transport_proto_tree,    NULL, NULL
00047 };
00048 static struct pico_proto_rr proto_rr_socket     = {
00049     &Socket_proto_tree,       NULL, NULL
00050 };
00051 
00052 static int proto_loop_in(struct pico_protocol *proto, int loop_score)
00053 {
00054     struct pico_frame *f;
00055     while(loop_score > 0) {
00056         if (proto->q_in->frames == 0)
00057             break;
00058 
00059         f = pico_dequeue(proto->q_in);
00060         if ((f) && (proto->process_in(proto, f) > 0)) {
00061             loop_score--;
00062         }
00063     }
00064     return loop_score;
00065 }
00066 
00067 static int proto_loop_out(struct pico_protocol *proto, int loop_score)
00068 {
00069     struct pico_frame *f;
00070     while(loop_score > 0) {
00071         if (proto->q_out->frames == 0)
00072             break;
00073 
00074         f = pico_dequeue(proto->q_out);
00075         if ((f) && (proto->process_out(proto, f) > 0)) {
00076             loop_score--;
00077         }
00078     }
00079     return loop_score;
00080 }
00081 
00082 static int proto_loop(struct pico_protocol *proto, int loop_score, int direction)
00083 {
00084 
00085     if (direction == PICO_LOOP_DIR_IN)
00086         loop_score = proto_loop_in(proto, loop_score);
00087     else if (direction == PICO_LOOP_DIR_OUT)
00088         loop_score = proto_loop_out(proto, loop_score);
00089 
00090     return loop_score;
00091 }
00092 
00093 static struct pico_tree_node *roundrobin_init(struct pico_proto_rr *rr, int direction)
00094 {
00095     struct pico_tree_node *next_node = NULL;
00096     /* Initialization (takes place only once) */
00097     if (rr->node_in == NULL)
00098         rr->node_in = pico_tree_firstNode(rr->t->root);
00099 
00100     if (rr->node_out == NULL)
00101         rr->node_out = pico_tree_firstNode(rr->t->root);
00102 
00103     if (direction == PICO_LOOP_DIR_IN)
00104         next_node = rr->node_in;
00105     else
00106         next_node = rr->node_out;
00107 
00108     return next_node;
00109 }
00110 
00111 static void roundrobin_end(struct pico_proto_rr *rr, int direction, struct pico_tree_node *last)
00112 {
00113     if (direction == PICO_LOOP_DIR_IN)
00114         rr->node_in = last;
00115     else
00116         rr->node_out = last;
00117 }
00118 
00119 static int pico_protocol_generic_loop(struct pico_proto_rr *rr, int loop_score, int direction)
00120 {
00121     struct pico_protocol *start, *next;
00122     struct pico_tree_node *next_node = roundrobin_init(rr, direction);
00123 
00124     if (!next_node)
00125         return loop_score;
00126 
00127     next = next_node->keyValue;
00128 
00129     /* init start node */
00130     start = next;
00131 
00132     /* round-robin all layer protocols, break if traversed all protocols */
00133     while (loop_score > 1 && next != NULL) {
00134         loop_score = proto_loop(next, loop_score, direction);
00135         next_node = pico_tree_next(next_node);
00136         next = next_node->keyValue;
00137         if (next == NULL)
00138         {
00139             next_node = pico_tree_firstNode(rr->t->root);
00140             next = next_node->keyValue;
00141         }
00142 
00143         if (next == start)
00144             break;
00145     }
00146     roundrobin_end(rr, direction, next_node);
00147     return loop_score;
00148 }
00149 
00150 int pico_protocol_datalink_loop(int loop_score, int direction)
00151 {
00152     return pico_protocol_generic_loop(&proto_rr_datalink, loop_score, direction);
00153 }
00154 
00155 int pico_protocol_network_loop(int loop_score, int direction)
00156 {
00157     return pico_protocol_generic_loop(&proto_rr_network, loop_score, direction);
00158 }
00159 
00160 int pico_protocol_transport_loop(int loop_score, int direction)
00161 {
00162     return pico_protocol_generic_loop(&proto_rr_transport, loop_score, direction);
00163 }
00164 
00165 int pico_protocol_socket_loop(int loop_score, int direction)
00166 {
00167     return pico_protocol_generic_loop(&proto_rr_socket, loop_score, direction);
00168 }
00169 
00170 int pico_protocols_loop(int loop_score)
00171 {
00172 /*
00173    loop_score = pico_protocol_datalink_loop(loop_score);
00174    loop_score = pico_protocol_network_loop(loop_score);
00175    loop_score = pico_protocol_transport_loop(loop_score);
00176    loop_score = pico_protocol_socket_loop(loop_score);
00177  */
00178     return loop_score;
00179 }
00180 
00181 static void proto_layer_rr_reset(struct pico_proto_rr *rr)
00182 {
00183     rr->node_in = NULL;
00184     rr->node_out = NULL;
00185 }
00186 
00187 void pico_protocol_init(struct pico_protocol *p)
00188 {
00189     if (!p)
00190         return;
00191 
00192     p->hash = pico_hash(p->name, (uint32_t)strlen(p->name));
00193     switch (p->layer) {
00194     case PICO_LAYER_DATALINK:
00195         pico_tree_insert(&Datalink_proto_tree, p);
00196         proto_layer_rr_reset(&proto_rr_datalink);
00197         break;
00198     case PICO_LAYER_NETWORK:
00199         pico_tree_insert(&Network_proto_tree, p);
00200         proto_layer_rr_reset(&proto_rr_network);
00201         break;
00202     case PICO_LAYER_TRANSPORT:
00203         pico_tree_insert(&Transport_proto_tree, p);
00204         proto_layer_rr_reset(&proto_rr_transport);
00205         break;
00206     case PICO_LAYER_SOCKET:
00207         pico_tree_insert(&Socket_proto_tree, p);
00208         proto_layer_rr_reset(&proto_rr_socket);
00209         break;
00210     }
00211     dbg("Protocol %s registered (layer: %d).\n", p->name, p->layer);
00212 
00213 }
00214