From 134806f7924a468e3ebef661f39ae7bc50aa4ad3 Mon Sep 17 00:00:00 2001 From: sangorrin Date: Mon, 17 Nov 2008 17:33:36 +0000 Subject: [PATCH] add group negotiations to frescan and change all the requests and messages to map to group negotiations.. improve the mode change protocol, prepare architecture for reservation-commit NOTE: the code compiles but havent been tested, now ill test each module and then the whole protocol git-svn-id: http://www.frescor.org/private/svn/frescor/fna/trunk@1398 35b4ef3e-fd22-0410-ab77-dab3279adceb --- src_frescan/Makefile | 2 - src_frescan/TODO | 3 +- src_frescan/frescan.c | 60 +- src_frescan/frescan.h | 92 +-- src_frescan/frescan_bwres.c | 232 +++--- src_frescan/frescan_bwres.h | 20 +- src_frescan/frescan_bwres_analysis.c | 63 +- src_frescan/frescan_bwres_analysis.h | 42 +- src_frescan/frescan_bwres_fna.c | 145 +++- src_frescan/frescan_bwres_messages.c | 733 ++++++++++--------- src_frescan/frescan_bwres_messages.h | 9 +- src_frescan/frescan_bwres_mode_change.c | 300 ++++---- src_frescan/frescan_bwres_mode_change.h | 24 +- src_frescan/frescan_bwres_requests.c | 50 +- src_frescan/frescan_bwres_requests.h | 95 +-- src_frescan/frescan_bwres_robjs.c | 26 +- src_frescan/frescan_bwres_robjs.h | 16 +- src_frescan/frescan_bwres_threads.c | 387 +++++----- src_frescan/frescan_bwres_threads.h | 5 +- src_frescan/frescan_config.h | 28 +- src_frescan/frescan_data.c | 25 +- src_frescan/frescan_data.h | 225 +----- src_frescan/frescan_debug.h | 21 +- src_frescan/frescan_hw_buffer.c | 16 +- src_frescan/frescan_hw_buffer.h | 2 +- src_frescan/frescan_packets.h | 85 +-- src_frescan/frescan_queues.c | 23 +- src_frescan/frescan_queues.h | 7 +- src_frescan/frescan_servers.c | 54 +- src_frescan/frescan_servers.h | 4 +- src_frescan/frescan_servers_replenishments.c | 12 +- src_frescan/frescan_servers_replenishments.h | 7 +- src_frescan/frescan_types.h | 500 +++++++++++++ 33 files changed, 1705 insertions(+), 1608 deletions(-) create mode 100644 src_frescan/frescan_types.h diff --git a/src_frescan/Makefile b/src_frescan/Makefile index 1af38c0..af1fd60 100644 --- a/src_frescan/Makefile +++ b/src_frescan/Makefile @@ -11,8 +11,6 @@ libfrescan: $(OBJS) @exec echo -e "\n>> Building FRESCAN:"; ld -r -o libfrescan.o *.o @mv libfrescan.o $(FNA_PATH)/lib -# ar -rc libfrescan.a *.o -# @mv libfrescan.a $(FNA_PATH)/lib @exec echo ">> [OK]" %.o: %.c $(SRCS) $(HDRS) diff --git a/src_frescan/TODO b/src_frescan/TODO index 3559dcf..f4fae0b 100644 --- a/src_frescan/TODO +++ b/src_frescan/TODO @@ -4,4 +4,5 @@ * CTU corrections * fna_vres_id_t will be frsh_vres_index_T - integrate with frsh_sa scheduling analysis module and spare capacity -- oh, i forgot CAN priorities are assigned inversely!! map them! \ No newline at end of file +- oh, i forgot CAN priorities are assigned inversely!! map them! +- when linking, hide symbols that are not needed externally (objcopy -G..) \ No newline at end of file diff --git a/src_frescan/frescan.c b/src_frescan/frescan.c index 3c6fc8b..69f3a23 100644 --- a/src_frescan/frescan.c +++ b/src_frescan/frescan.c @@ -75,7 +75,7 @@ #include // can_chip_t, can_frame_t #include "frescan.h" // frescan_init_params_t, frescan_send_params_t #include "frescan_queues.h" // init, enqueue, requeue -#include "frescan_data.h" // init, the_networks +#include "frescan_data.h" // init, frescan_data #include "frescan_servers.h" // init, frame_sent #include "frescan_debug.h" // DEBUG #include "frescan_id.h" // frescan_id_set_field, frescan_id_get_field @@ -183,7 +183,7 @@ int frescan_init(frescan_init_params_t *params) return -1; } - ret = frescan_queues_init(&the_networks[params->net].queues, params); + ret = frescan_queues_init(&frescan_data[params->net].queues, params); if (ret != 0) { FRESCAN_ERROR("could not initialize the queues\n"); return -1; @@ -227,9 +227,9 @@ int frescan_send(const frescan_send_params_t *params, DEBUG(FRESCAN_SEND_ENABLE_DEBUG, "allocating a packet\n"); - FRESCAN_ACQUIRE_LOCK(&the_networks[params->net].lock); + FRESCAN_ACQUIRE_LOCK(&frescan_data[params->net].lock); packet = frescan_packets_alloc(); - FRESCAN_RELEASE_LOCK(&the_networks[params->net].lock); + FRESCAN_RELEASE_LOCK(&frescan_data[params->net].lock); if (packet == NULL) { FRESCAN_ERROR("could not allocate packet\n"); @@ -239,9 +239,9 @@ int frescan_send(const frescan_send_params_t *params, DEBUG(FRESCAN_SEND_ENABLE_DEBUG, "allocating a frame\n"); - FRESCAN_ACQUIRE_LOCK(&the_networks[params->net].lock); + FRESCAN_ACQUIRE_LOCK(&frescan_data[params->net].lock); packet->frame = can_framespool_alloc(); - FRESCAN_RELEASE_LOCK(&the_networks[params->net].lock); + FRESCAN_RELEASE_LOCK(&frescan_data[params->net].lock); if (packet->frame == NULL) { FRESCAN_ERROR("could not allocate frame\n"); @@ -276,7 +276,7 @@ int frescan_send(const frescan_send_params_t *params, frescan_id_set_field(&packet->frame->id, FRESCAN_FIELD_SRC, - (uint32_t)the_networks[params->net].local_node); + (uint32_t)frescan_data[params->net].local_node); frescan_id_set_field(&packet->frame->id, FRESCAN_FIELD_CHAN, @@ -296,22 +296,22 @@ int frescan_send(const frescan_send_params_t *params, packet->buffer_read_pointer = packet->buffer_head; packet->buffer_pending_bytes = size; - pqueue = the_networks[params->net].queues.tx_fp_queue; + pqueue = frescan_data[params->net].queues.tx_fp_queue; DEBUG(FRESCAN_SEND_ENABLE_DEBUG, "enqueue the packet\n"); if (packet->flags & FRESCAN_FP) { - FRESCAN_ACQUIRE_LOCK(&the_networks[params->net].lock); + FRESCAN_ACQUIRE_LOCK(&frescan_data[params->net].lock); ret = frescan_pqueue_enqueue(pqueue, packet, params->prio); - FRESCAN_RELEASE_LOCK(&the_networks[params->net].lock); + FRESCAN_RELEASE_LOCK(&frescan_data[params->net].lock); if (ret != 0) { FRESCAN_ERROR("could not enqueue the packet\n"); return -1; } } else { - FRESCAN_ACQUIRE_LOCK(&the_networks[params->net].lock); + FRESCAN_ACQUIRE_LOCK(&frescan_data[params->net].lock); ret = frescan_servers_enqueue(params->net, params->ss, packet); - FRESCAN_RELEASE_LOCK(&the_networks[params->net].lock); + FRESCAN_RELEASE_LOCK(&frescan_data[params->net].lock); if (ret != 0) { FRESCAN_ERROR("could not enqueue the packet\n"); @@ -319,9 +319,9 @@ int frescan_send(const frescan_send_params_t *params, } } - FRESCAN_ACQUIRE_LOCK(&the_networks[params->net].lock); + FRESCAN_ACQUIRE_LOCK(&frescan_data[params->net].lock); ret = frescan_hw_buffer_update(params->net); - FRESCAN_RELEASE_LOCK(&the_networks[params->net].lock); + FRESCAN_RELEASE_LOCK(&frescan_data[params->net].lock); if (ret != 0) { FRESCAN_ERROR("could not update hw buffer\n"); @@ -367,7 +367,7 @@ int frescan_recv(const frescan_recv_params_t *params, blocking = false; } - pqueue = the_networks[params->net].queues.rx_channel_queues + pqueue = frescan_data[params->net].queues.rx_channel_queues [params->channel]; ret = frescan_pqueue_dequeue(pqueue, &head, prio, blocking); @@ -393,7 +393,7 @@ int frescan_recv(const frescan_recv_params_t *params, *recv_bytes = 0; - FRESCAN_ACQUIRE_LOCK(&the_networks[params->net].lock); + FRESCAN_ACQUIRE_LOCK(&frescan_data[params->net].lock); list_for_each_entry(packet, &head->msg_list, msg_list) { // TODO: memory checks, delete the packets @@ -423,7 +423,7 @@ int frescan_recv(const frescan_recv_params_t *params, ret = frescan_packets_free(head); - FRESCAN_RELEASE_LOCK(&the_networks[params->net].lock); + FRESCAN_RELEASE_LOCK(&frescan_data[params->net].lock); if (ret != 0) { FRESCAN_ERROR("could not free head packet\n"); @@ -490,9 +490,9 @@ static int frescan_hook_frame_recv (const struct can_chip_t *chip, packet->frame = frame; if (frag_id == FRESCAN_MX_IDS) { - head = the_networks[net].id_fp_queues[src][prio]; + head = frescan_data[net].id_fp_queues[src][prio]; } else { - head = the_networks[net].id_queues[src][frag_id]; + head = frescan_data[net].id_queues[src][frag_id]; } if (head == NULL) { @@ -503,9 +503,9 @@ static int frescan_hook_frame_recv (const struct can_chip_t *chip, INIT_LIST_HEAD(&head->msg_list); if (frag_id == FRESCAN_MX_IDS) { - the_networks[net].id_fp_queues[src][prio] = head; + frescan_data[net].id_fp_queues[src][prio] = head; } else { - the_networks[net].id_queues[src][frag_id] = head; + frescan_data[net].id_queues[src][frag_id] = head; } } @@ -516,7 +516,7 @@ static int frescan_hook_frame_recv (const struct can_chip_t *chip, FRESCAN_FRAG_ENABLE_DEBUG, "message complete, move msg to channel\n"); // TODO: select the highest priority?? - pqueue = the_networks[net].queues.rx_channel_queues[channel]; + pqueue = frescan_data[net].queues.rx_channel_queues[channel]; ret = frescan_pqueue_enqueue(pqueue, head, prio); if (ret != 0) { FRESCAN_ERROR("could not enqueue message in channel queue\n"); @@ -524,9 +524,9 @@ static int frescan_hook_frame_recv (const struct can_chip_t *chip, } if (frag_id == FRESCAN_MX_IDS) { - the_networks[net].id_fp_queues[src][prio] = NULL; + frescan_data[net].id_fp_queues[src][prio] = NULL; } else { - the_networks[net].id_queues[src][frag_id] = NULL; + frescan_data[net].id_queues[src][frag_id] = NULL; } } else { @@ -557,7 +557,7 @@ static int frescan_hook_frame_sent(const struct can_chip_t *chip) frescan_prio_t prio; frescan_ss_t id; - packet = the_networks[chip->minor].last_packet; + packet = frescan_data[chip->minor].last_packet; id = frescan_id_get_field(packet->frame->id, FRESCAN_FIELD_FRAG_ID); @@ -589,7 +589,7 @@ static int frescan_hook_frame_sent(const struct can_chip_t *chip) DEBUG(FRESCAN_FRAG_ENABLE_DEBUG, "requeue fp packet, prio:%u\n", prio); - pqueue = the_networks[chip->minor].queues.tx_fp_queue; + pqueue = frescan_data[chip->minor].queues.tx_fp_queue; ret = frescan_pqueue_requeue(pqueue, packet, prio); if (ret != 0) { FRESCAN_ERROR("could not requeue the packet\n"); @@ -626,7 +626,7 @@ static int frescan_hook_frame_sent(const struct can_chip_t *chip) // TODO: signal semaphore for send_sync } - the_networks[chip->minor].last_packet = NULL; + frescan_data[chip->minor].last_packet = NULL; ret = frescan_hw_buffer_update(chip->minor); if (ret != 0) { @@ -653,7 +653,7 @@ static int frescan_hook_frame_aborted(const struct can_chip_t *chip) frescan_prio_t prio; frescan_ss_t id; - packet = the_networks[chip->minor].last_packet; + packet = frescan_data[chip->minor].last_packet; id = frescan_id_get_field(packet->frame->id, FRESCAN_FIELD_FRAG_ID); @@ -669,7 +669,7 @@ static int frescan_hook_frame_aborted(const struct can_chip_t *chip) DEBUG(FRESCAN_FRAG_ENABLE_DEBUG, "requeue fp packet, prio:%u\n", prio); - pqueue = the_networks[chip->minor].queues.tx_fp_queue; + pqueue = frescan_data[chip->minor].queues.tx_fp_queue; ret = frescan_pqueue_requeue(pqueue, packet, prio); if (ret != 0) { FRESCAN_ERROR("could not requeue the packet\n"); @@ -689,7 +689,7 @@ static int frescan_hook_frame_aborted(const struct can_chip_t *chip) return -1; } - the_networks[chip->minor].last_packet = NULL; + frescan_data[chip->minor].last_packet = NULL; ret = frescan_hw_buffer_update(chip->minor); if (ret != 0) { diff --git a/src_frescan/frescan.h b/src_frescan/frescan.h index 57676af..e2f59da 100644 --- a/src_frescan/frescan.h +++ b/src_frescan/frescan.h @@ -66,94 +66,10 @@ * */ -#ifndef _MARTE_FRESCAN_H_ -#define _MARTE_FRESCAN_H_ +#ifndef _FRESCAN_H_ +#define _FRESCAN_H_ -#include // uint8_t -#include // bool -#include // size_t - -typedef uint8_t frescan_network_t; -typedef uint8_t frescan_node_t; -typedef uint8_t frescan_channel_t; -typedef uint8_t frescan_prio_t; -typedef uint8_t frescan_ss_t; -typedef uint32_t frescan_budget_t; - -/** - * frescan_flags_t - frescan flags - * - * @FRESCAN_SS: send the message using sporadic servers - * @FRESCAN_FP: send the message using fixed priorities - * @FRESCAN_POLL: no buffer copy, only pointer and use the ID to poll status - * @FRESCAN_SYNC: no buffer copy, only pointer and block until it is sent - * @FRESCAN_ASYNC: use buffer copy and return immediately - */ - -typedef enum { - FRESCAN_SS = 1<<4, // sporadic server - FRESCAN_FP = 1<<3, // fixed priorities - FRESCAN_POLL = 1<<2, // polling - FRESCAN_SYNC = 1<<1, // synchronous - FRESCAN_ASYNC = 1 // asynchronous -} frescan_flags_t; - -/** - * frescan_send_params_t - send parameters - * - * @net: the network to use - * @to: the node where the message shoud be sent to - * @channel: the channel in 'to' where the message shoud be sent to - * @flags: the flags (see frescan_flags_t) - * @prio: the priority for the message if (flags & FRESCAN_FP) - * @ss: the sporadic server for the message if (flags & FRESCAN_SS) - */ - -typedef struct { - frescan_network_t net; - frescan_node_t to; - frescan_channel_t channel; - frescan_flags_t flags; - union { - frescan_prio_t prio; - frescan_ss_t ss; - }; -} frescan_send_params_t; - -/** - * frescan_recv_params_t - receive parameters - * - * @net: the network to use - * @channel: the channel from which we want to extract a message - * @flags: FRESCAN_SYNC/ASYNC - */ - -typedef struct { - frescan_network_t net; - frescan_channel_t channel; - frescan_flags_t flags; -} frescan_recv_params_t; - -/** - * frescan_init_params_t - initialization parameters - * - * @net: network to initialize (minor number ie: /dev/can0 -> 0) - * @node: set the local node identificator - * @tx_fp_max_prio: maximum number of priorities for the fixed priority - * transmission queues. (prio = 0 .. max_prio - 1) - * @rx_num_of_channels: number of rx channels (0 .. rx_num_of_channels - 1) - * @rx_channel_max_prio: array (range rx_num_of_channels) saying the number - * of priorities for each channel. If this parameter is - * NULL tx_fp_max_prio will be used for all queues. - */ - -typedef struct { - frescan_network_t net; - frescan_node_t node; - uint32_t tx_fp_max_prio; - uint32_t rx_num_of_channels; - uint32_t *rx_channel_max_prio; -} frescan_init_params_t; +#include "frescan_types.h" /** * frescan_init - initializes the network and the internal structures @@ -199,4 +115,4 @@ int frescan_recv(const frescan_recv_params_t *params, frescan_node_t *from, frescan_prio_t *prio); -#endif // _MARTE_FRESCAN_H_ +#endif // _FRESCAN_H_ diff --git a/src_frescan/frescan_bwres.c b/src_frescan/frescan_bwres.c index ccc5a71..23bc3c9 100644 --- a/src_frescan/frescan_bwres.c +++ b/src_frescan/frescan_bwres.c @@ -66,6 +66,7 @@ #include "frescan_bwres.h" #include "frescan_bwres_requests.h" +#include "frescan_bwres_robjs.h" #include "frescan_bwres_messages.h" #include "frescan_bwres_threads.h" #include "frescan_bwres_analysis.h" @@ -84,14 +85,16 @@ int frescan_bwres_init(frescan_network_t net) { int ret; frescan_server_params_t server_params; // TODO: improve this... - frescan_sa_init_params_t sa_init_params; // TODO: improve this... + frescan_bwres_sa_init_params_t init_params; // TODO: improve this... - sa_init_params.max_prio = 30; - sa_init_params.min_prio = 1; + init_params.max_prio = 30; + init_params.min_prio = 1; - ret = frescan_sa_init(&the_networks[net].scenario, - &sa_init_params); - if (ret != 0) return ret; + if (frescan_data[net].local_node == FRESCAN_BWRES_MASTER_NODE) { + ret = frescan_bwres_sa_init(&frescan_data[net].scenario, + &init_params); + if (ret != 0) return ret; + } server_params.budget = 5; server_params.period.tv_sec = 1; @@ -99,15 +102,15 @@ int frescan_bwres_init(frescan_network_t net) server_params.prio = FRESCAN_BWRES_NEG_MESSAGES_PRIO; ret = frescan_servers_create(net, &server_params, - &the_networks[net].neg_messages_ss_id); + &frescan_data[net].neg_messages_ss_id); if (ret != 0) return ret; // TODO: we have to add this negotiation contracts to the sa table - ret = frescan_bwres_robjs_init(FRESCAN_REPLY_OBJECTS_MX_CEILING); + ret = frescan_bwres_robjs_init(FRESCAN_BWRES_ROBJS_MX_CEILING); if (ret != 0) return ret; - ret = frescan_requests_init(FRESCAN_REQUESTS_MX_CEILING); + ret = frescan_bwres_requests_init(FRESCAN_BWRES_REQ_MX_CEILING); if (ret != 0) return ret; ret = frescan_messages_init(net); @@ -123,55 +126,54 @@ int frescan_bwres_init(frescan_network_t net) } /** - * frescan_bwres_negotiate() + * frescan_bwres_group_change_mode_sync() * - * to negotiate a contract we follow the next steps: - * - * 1.- prepare a request + * 1.- allocate and prepare the GN request * 2.- enqueue the request * 3.- wait in the reply object for a reply - * 4.- return the final values and free the request + * (unless there are only cancellations) + * 4.- free the request */ -int frescan_bwres_negotiate(frescan_network_t net, - const frsh_contract_t *contract, - frescan_ss_t *ss, - bool *accepted) +int frescan_bwres_group_change_mode_sync + (frescan_network_t net, + const frsh_contracts_group_t *contracts_to_neg, + const frsh_contracts_group_t *contracts_to_reneg, + const frescan_ss_group_t *ss_to_reneg, + const frescan_ss_group_t *ss_to_cancel, + frescan_ss_group_t *ss_new, + bool *accepted) { int ret; - frescan_request_id_t req; - frescan_request_data_t *req_data; - frescan_server_params_t server_params; + frescan_bwres_request_id_t req; + frescan_bwres_request_data_t *req_data; - DEBUG(FRESCAN_BWRES_ENABLE_DEBUG, "preparing a negotiation request\n"); + DEBUG(FRESCAN_BWRES_ENABLE_DEBUG, "preparing a GN request\n"); - ret = frescan_requests_alloc(&req); + ret = frescan_bwres_requests_alloc(&req); if (ret != 0) return ret; - ret = frescan_requests_get_data(req, &req_data); + ret = frescan_bwres_requests_get_data(req, &req_data); if (ret != 0) return ret; - req_data->type = FRESCAN_REQ_NEG; - req_data->req = req; - req_data->contract = (frsh_contract_t *)contract; - req_data->request_node = the_networks[net].local_node; req_data->net = net; + req_data->type = FRESCAN_BWRES_REQ_GN; + req_data->req = req; + req_data->request_node = frescan_data[net].local_node; + req_data->contracts_to_neg = (frsh_contracts_group_t *) + contracts_to_neg; + req_data->contracts_to_reneg = (frsh_contracts_group_t *) + contracts_to_reneg; + req_data->ss_to_reneg = (frescan_ss_group_t *)ss_to_reneg; + req_data->ss_to_cancel = (frescan_ss_group_t *)ss_to_cancel; + req_data->ss_new = ss_new; ret = frescan_bwres_robjs_alloc(&req_data->robj, FRESCAN_BWRES_MX_PRIO); if (ret != 0) return ret; - // NOTE: we preallocate a server for the negotiation process - server_params.budget = 0; - server_params.period.tv_sec = 0; - server_params.period.tv_nsec = 0; - server_params.prio = 0; - - ret = frescan_servers_create(net, &server_params, &req_data->ss); - if (ret != 0) return ret; - DEBUG(FRESCAN_BWRES_ENABLE_DEBUG, "enqueue the negotiation request\n"); - ret = frescan_requests_enqueue(req); + ret = frescan_bwres_requests_enqueue(req); if (ret != 0) return ret; DEBUG(FRESCAN_BWRES_ENABLE_DEBUG, "wait for a reply\n"); @@ -183,90 +185,74 @@ int frescan_bwres_negotiate(frescan_network_t net, if (ret != 0) return ret; switch (req_data->return_value) { - case FRESCAN_REQ_ACCEPTED: - DEBUG(FRESCAN_BWRES_ENABLE_DEBUG, "negotiation OK\n"); - *accepted = true; - *ss = req_data->ss; - break; - - case FRESCAN_REQ_NOT_ACCEPTED: - DEBUG(FRESCAN_BWRES_ENABLE_DEBUG, "negotiation FAIL\n"); - *accepted = false; - ret = frescan_servers_destroy(net, req_data->ss); - if (ret != 0) return ret; - break; - - default: - FRESCAN_ERROR("return_value unknown\n"); - return -1; + case FRESCAN_BWRES_REQ_ACCEPTED: + DEBUG(FRESCAN_BWRES_ENABLE_DEBUG, "negotiation OK\n"); + *accepted = true; + break; + + case FRESCAN_BWRES_REQ_NOT_ACCEPTED: + DEBUG(FRESCAN_BWRES_ENABLE_DEBUG, "negotiation FAIL\n"); + *accepted = false; + break; + + default: + FRESCAN_ERROR("return_value unknown\n"); + return -1; } - frescan_requests_free(req); + frescan_bwres_requests_free(req); return 0; } /** - * frescan_bwres_renegotiate() + * frescan_bwres_negotiate() */ -int frescan_bwres_renegotiate(frescan_network_t net, - const frsh_contract_t *contract, - frescan_ss_t ss, - bool *accepted) +int frescan_bwres_negotiate(frescan_network_t net, + const frsh_contract_t *contract, + frescan_ss_t *ss, + bool *accepted) { int ret; - frescan_request_id_t req; - frescan_request_data_t *req_data; + frsh_contracts_group_t contracts_to_neg; + frescan_ss_group_t ss_new; - DEBUG(FRESCAN_BWRES_ENABLE_DEBUG, "preparing renegotiation request\n"); + contracts_to_neg.size = 1; + contracts_to_neg.contracts[0] = *contract; - ret = frescan_requests_alloc(&req); + ret = frescan_bwres_group_change_mode_sync + (net, &contracts_to_neg, NULL, NULL, + NULL, &ss_new, accepted); if (ret != 0) return ret; - ret = frescan_requests_get_data(req, &req_data); - if (ret != 0) return ret; - - req_data->type = FRESCAN_REQ_RENEG; - req_data->req = req; - req_data->contract = (frsh_contract_t *)contract; - req_data->request_node = the_networks[net].local_node; - req_data->net = net; - req_data->ss = ss; - - ret = frescan_bwres_robjs_alloc(&req_data->robj, FRESCAN_BWRES_MX_PRIO); - if (ret != 0) return ret; - - DEBUG(FRESCAN_BWRES_ENABLE_DEBUG, "enqueue renegotiation request\n"); + if (*accepted) { + *ss = ss_new.ss[0]; + } - ret = frescan_requests_enqueue(req); - if (ret != 0) return ret; + return 0; +} - DEBUG(FRESCAN_BWRES_ENABLE_DEBUG, "wait for a reply\n"); +/** + * frescan_bwres_renegotiate() + */ - ret = frescan_bwres_robjs_wait(req_data->robj); - if (ret != 0) return ret; +int frescan_bwres_renegotiate(frescan_network_t net, + const frsh_contract_t *contract, + frescan_ss_t ss, + bool *accepted) +{ + frsh_contracts_group_t contracts_to_reneg; + frescan_ss_group_t ss_to_reneg; - ret = frescan_bwres_robjs_free(req_data->robj); - if (ret != 0) return ret; + contracts_to_reneg.size = 1; + contracts_to_reneg.contracts[0] = *contract; - switch (req_data->return_value) { - case FRESCAN_REQ_ACCEPTED: - DEBUG(FRESCAN_BWRES_ENABLE_DEBUG, "renegotiation OK\n"); - *accepted = true; - break; - - case FRESCAN_REQ_NOT_ACCEPTED: - DEBUG(FRESCAN_BWRES_ENABLE_DEBUG, "renegotiation FAIL\n"); - *accepted = false; - break; - - default: - FRESCAN_ERROR("return_value unknown\n"); - return -1; - } + ss_to_reneg.size = 1; + ss_to_reneg.ss[0] = ss; - frescan_requests_free(req); - return 0; + return frescan_bwres_group_change_mode_sync + (net, NULL, &contracts_to_reneg, &ss_to_reneg, + NULL, NULL, accepted); } /** @@ -276,43 +262,11 @@ int frescan_bwres_renegotiate(frescan_network_t net, int frescan_bwres_cancel(frescan_network_t net, frescan_ss_t ss) { - int ret; - frescan_request_id_t req; - frescan_request_data_t *req_data; - - DEBUG(FRESCAN_BWRES_ENABLE_DEBUG, "preparing cancel request\n"); - - ret = frescan_requests_alloc(&req); - if (ret != 0) return ret; - - ret = frescan_requests_get_data(req, &req_data); - if (ret != 0) return ret; - - req_data->type = FRESCAN_REQ_CANCEL; - req_data->req = req; - req_data->request_node = the_networks[net].local_node; - req_data->net = net; - req_data->ss = ss; - - ret = frescan_bwres_robjs_alloc(&req_data->robj, FRESCAN_BWRES_MX_PRIO); - if (ret != 0) return ret; - - DEBUG(FRESCAN_BWRES_ENABLE_DEBUG, "enqueue cancel request\n"); - - ret = frescan_requests_enqueue(req); - if (ret != 0) return ret; + frescan_ss_group_t ss_to_cancel; - DEBUG(FRESCAN_BWRES_ENABLE_DEBUG, "wait for a signal\n"); + ss_to_cancel.size = 1; + ss_to_cancel.ss[0] = ss; - ret = frescan_bwres_robjs_wait(req_data->robj); - if (ret != 0) return ret; - - ret = frescan_bwres_robjs_free(req_data->robj); - if (ret != 0) return ret; - - ret = frescan_servers_destroy(net, ss); - if (ret != 0) return ret; - - frescan_requests_free(req); - return 0; + return frescan_bwres_group_change_mode_sync + (net, NULL, NULL, NULL, &ss_to_cancel, NULL, NULL); } diff --git a/src_frescan/frescan_bwres.h b/src_frescan/frescan_bwres.h index dc87d4d..5cd5328 100644 --- a/src_frescan/frescan_bwres.h +++ b/src_frescan/frescan_bwres.h @@ -64,14 +64,22 @@ * */ -#ifndef _FRESCAN_BANDWIDTH_RESERVATION_H_ -#define _FRESCAN_BANDWIDTH_RESERVATION_H_ +#ifndef _FRESCAN_BWRES_H_ +#define _FRESCAN_BWRES_H_ -#include "frescan.h" -#include "frescan_data.h" +#include "frescan_types.h" extern int frescan_bwres_init(frescan_network_t net); +extern int frescan_bwres_group_change_mode_sync + (frescan_network_t net, + const frsh_contracts_group_t *contracts_to_neg, + const frsh_contracts_group_t *contracts_to_reneg, + const frescan_ss_group_t *ss_to_reneg, + const frescan_ss_group_t *ss_to_cancel, + frescan_ss_group_t *ss_new, + bool *accepted); + extern int frescan_bwres_negotiate(frescan_network_t net, const frsh_contract_t *contract, frescan_ss_t *ss, @@ -85,6 +93,6 @@ extern int frescan_bwres_renegotiate(frescan_network_t net, extern int frescan_bwres_cancel(frescan_network_t net, frescan_ss_t ss); -// TODO: add other functions: renegotiate_async +// TODO: add functions for reservation requests -#endif // _FRESCAN_BANDWIDTH_RESERVATION_H_ +#endif // _FRESCAN_BWRES_H_ diff --git a/src_frescan/frescan_bwres_analysis.c b/src_frescan/frescan_bwres_analysis.c index e55b835..c77d616 100644 --- a/src_frescan/frescan_bwres_analysis.c +++ b/src_frescan/frescan_bwres_analysis.c @@ -79,13 +79,13 @@ #include "frescan_debug.h" /** - * frescan_sa_init() - init the scenario + * frescan_bwres_sa_init() - init the scenario * * Initialize the vres list and copy the initialization parameters */ -int frescan_sa_init(frescan_sa_scenario_t *scenario, - const frescan_sa_init_params_t *params) +int frescan_bwres_sa_init(frescan_bwres_sa_scenario_t *scenario, + const frescan_bwres_sa_init_params_t *params) { int ret; frsh_sa_scenario_init_data_t fsa_scenario_init_data; @@ -93,7 +93,7 @@ int frescan_sa_init(frescan_sa_scenario_t *scenario, INIT_LIST_HEAD(&scenario->vres_head.list); scenario->init_params = *params; - ret = freelist_init(&scenario->fsa_id_freelist, + ret = freelist_init(&scenario->fsa_vres_global_id_freelist, FRESCAN_MX_NODES*FRESCAN_MX_IDS); if (ret != 0) return ret; @@ -110,25 +110,25 @@ int frescan_sa_init(frescan_sa_scenario_t *scenario, } /** - * frescan_sa_add_contract() - add a contract to the scenario + * frescan_bwres_sa_add_contract() - add a contract to the scenario * * create the corresponding vres structure and set its values, and add the * vres to the vres list */ -int frescan_sa_add_contract(frescan_sa_scenario_t *scenario, - frescan_ss_t ss, - frescan_node_t node, - const frsh_contract_t *contract) +int frescan_bwres_sa_add_contract(frescan_bwres_sa_scenario_t *scenario, + frescan_ss_t ss, + frescan_node_t node, + const frsh_contract_t *contract) { int ret; - frescan_sa_vres_t *sa_vres = &scenario->vres_pool[node][ss]; + frescan_bwres_vres_t *sa_vres = &scenario->vres_pool[node][ss]; sa_vres->contract = *contract; sa_vres->node = node; sa_vres->ss = ss; - ret = freelist_alloc(&scenario->fsa_id_freelist); + ret = freelist_alloc(&scenario->fsa_vres_global_id_freelist); if (ret < 0) return -1; sa_vres->fsa_vres_global_id = (frsh_sa_vres_id_t)ret; @@ -145,17 +145,17 @@ int frescan_sa_add_contract(frescan_sa_scenario_t *scenario, } /** - * frescan_sa_update_contract() - update a contract in the scenario + * frescan_bwres_sa_update_contract() - update a contract in the scenario */ -int frescan_sa_update_contract(frescan_sa_scenario_t *scenario, - frescan_ss_t ss, - frescan_node_t node, - const frsh_contract_t *contract, - frsh_contract_t *old_contract) +int frescan_bwres_sa_update_contract(frescan_bwres_sa_scenario_t *scenario, + frescan_ss_t ss, + frescan_node_t node, + const frsh_contract_t *contract, + frsh_contract_t *old_contract) { int ret; - frescan_sa_vres_t *sa_vres = &scenario->vres_pool[node][ss]; + frescan_bwres_vres_t *sa_vres = &scenario->vres_pool[node][ss]; if (old_contract != NULL) { *old_contract = sa_vres->contract; @@ -172,21 +172,26 @@ int frescan_sa_update_contract(frescan_sa_scenario_t *scenario, } /** - * frescan_sa_remove_contract() - remove a contract from the scenario + * frescan_bwres_sa_remove_contract() - remove a contract from the scenario */ -int frescan_sa_remove_contract(frescan_sa_scenario_t *scenario, - frescan_ss_t ss, - frescan_node_t node) +int frescan_bwres_sa_remove_contract(frescan_bwres_sa_scenario_t *scenario, + frescan_ss_t ss, + frescan_node_t node, + frsh_contract_t *contract) { int ret; - frescan_sa_vres_t *sa_vres = &scenario->vres_pool[node][ss]; + frescan_bwres_vres_t *sa_vres = &scenario->vres_pool[node][ss]; + + if (contract != NULL) { + *contract = sa_vres->contract; + } ret = frsh_sa_scenario_del_vres(&scenario->fsa_scenario, sa_vres->fsa_vres_global_id); if (ret != 0) return -1; - ret = freelist_free(&scenario->fsa_id_freelist, + ret = freelist_free(&scenario->fsa_vres_global_id_freelist, sa_vres->fsa_vres_global_id); if (ret < 0) return -1; @@ -196,12 +201,12 @@ int frescan_sa_remove_contract(frescan_sa_scenario_t *scenario, } /** - * frescan_sa_sched_test() - perform a scheduling test on the scenario + * frescan_bwres_sa_sched_test() - perform a scheduling test on the scenario * */ -int frescan_sa_sched_test(frescan_sa_scenario_t *scenario, - bool *is_schedulable) +int frescan_bwres_sa_sched_test(frescan_bwres_sa_scenario_t *scenario, + bool *is_schedulable) { int ret; @@ -218,10 +223,10 @@ int frescan_sa_sched_test(frescan_sa_scenario_t *scenario, } /** - * frescan_sa_spare_capacity() - distribute the spare capacity + * frescan_bwres_sa_spare_capacity() - distribute the spare capacity */ -int frescan_sa_spare_capacity(frescan_sa_scenario_t *scenario) +int frescan_bwres_sa_spare_capacity(frescan_bwres_sa_scenario_t *scenario) { int ret; diff --git a/src_frescan/frescan_bwres_analysis.h b/src_frescan/frescan_bwres_analysis.h index e932601..8b721bb 100644 --- a/src_frescan/frescan_bwres_analysis.h +++ b/src_frescan/frescan_bwres_analysis.h @@ -74,21 +74,21 @@ #ifndef _FRESCAN_BWRES_ANALYSIS_H_ #define _FRESCAN_BWRES_ANALYSIS_H_ -#include "frescan.h" -#include "frescan_data.h" +#include "frescan_types.h" /** - * frescan_sa_init() - init the scenario + * frescan_bwres_sa_init() - init the scenario * * @scenario: the scenario (in out) * @params: init params (in) */ -extern int frescan_sa_init(frescan_sa_scenario_t *scenario, - const frescan_sa_init_params_t *params); +extern int frescan_bwres_sa_init + (frescan_bwres_sa_scenario_t *scenario, + const frescan_bwres_sa_init_params_t *params); /** - * frescan_sa_add_contract() - add a contract to the scenario + * frescan_bwres_sa_add_contract() - add a contract to the scenario * * @scenario: the scenario (in out) * @ss: the preallocated ss identificator (in) @@ -96,13 +96,14 @@ extern int frescan_sa_init(frescan_sa_scenario_t *scenario, * @contract: the new contract (in) */ -extern int frescan_sa_add_contract(frescan_sa_scenario_t *scenario, +extern int frescan_bwres_sa_add_contract + (frescan_bwres_sa_scenario_t *scenario, frescan_ss_t ss, frescan_node_t node, const frsh_contract_t *contract); /** - * frescan_sa_update_contract() - update a contract in the scenario + * frescan_bwres_sa_update_contract() - update a contract in the scenario * * @scenario: the scenario (in out) * @ss: the ss identificator (in) @@ -112,40 +113,45 @@ extern int frescan_sa_add_contract(frescan_sa_scenario_t *scenario, * no contract is returned (out) */ -extern int frescan_sa_update_contract(frescan_sa_scenario_t *scenario, +extern int frescan_bwres_sa_update_contract + (frescan_bwres_sa_scenario_t *scenario, frescan_ss_t ss, frescan_node_t node, const frsh_contract_t *contract, frsh_contract_t *old_contract); /** - * frescan_sa_remove_contract() - remove a contract from the scenario + * frescan_bwres_sa_remove_contract() - remove a contract from the scenario * * @scenario: the scenario (in out) * @ss: the ss to remove (in) * @node: the node this contract belongs to (in) + * @contract: if not null, returns a copy of the contract (out) */ -extern int frescan_sa_remove_contract(frescan_sa_scenario_t *scenario, - frescan_ss_t ss, - frescan_node_t node); +extern int frescan_bwres_sa_remove_contract + (frescan_bwres_sa_scenario_t *scenario, + frescan_ss_t ss, + frescan_node_t node, + frsh_contract_t *contract); /** - * frescan_sa_sched_test() - perform a scheduling test on the scenario + * frescan_bwres_sa_sched_test() - perform a scheduling test on the scenario * * @scenario: the scenario (in out) * @is_schedulable: if the scenario is schedulable or not (out) */ -extern int frescan_sa_sched_test(frescan_sa_scenario_t *scenario, - bool *is_schedulable); +extern int frescan_bwres_sa_sched_test(frescan_bwres_sa_scenario_t *scenario, + bool *is_schedulable); /** - * frescan_sa_spare_capacity() - distribute the spare capacity + * frescan_bwres_sa_spare_capacity() - distribute the spare capacity * * @scenario: the scenario (in out) */ -extern int frescan_sa_spare_capacity(frescan_sa_scenario_t *scenario); +extern int frescan_bwres_sa_spare_capacity + (frescan_bwres_sa_scenario_t *scenario); #endif // _FRESCAN_BWRES_ANALYSIS_H_ diff --git a/src_frescan/frescan_bwres_fna.c b/src_frescan/frescan_bwres_fna.c index 995e436..98f564b 100644 --- a/src_frescan/frescan_bwres_fna.c +++ b/src_frescan/frescan_bwres_fna.c @@ -68,6 +68,7 @@ #include "frsh.h" /* frsh_resource_id_t, .. */ #include "frescan.h" /* frescan_init, ... */ #include "frescan_bwres.h" /* frescan_bwres_init, ... */ +#include "frescan_types.h" #include "fna.h" /* fna_vres_id_t, fna_endpoint_data_t */ #include "frescan_debug.h" /* DEBUG, FRESCAN_ERROR */ @@ -105,12 +106,13 @@ int frescan_fna_init(const frsh_resource_id_t resource_id) init_params.rx_num_of_channels = 10; init_params.rx_channel_max_prio = NULL; - DEBUG(FRESCAN_FNA_ENABLE_DEBUG, "Initializing FRESCAN\n"); + DEBUG(FRESCAN_BWRES_FNA_ENABLE_DEBUG, + "Initializing FRESCAN FNA node%u\n", FRSH_CPU_ID_DEFAULT); ret = frescan_init(&init_params); if (ret != 0) FRESCAN_ERROR ("could not init FRESCAN"); - DEBUG(FRESCAN_FNA_ENABLE_DEBUG, "Initializing BWRES\n"); + DEBUG(FRESCAN_BWRES_FNA_ENABLE_DEBUG, "Initializing BWRES\n"); ret = frescan_bwres_init(init_params.net); if (ret != 0) FRESCAN_ERROR ("could not init BWRES"); @@ -122,6 +124,86 @@ int frescan_fna_init(const frsh_resource_id_t resource_id) // VIRTUAL RESOURCES /////////////////////////////////////////////////////////////////// +int frescan_fna_group_change_mode_sync + (const frsh_resource_id_t resource_id, + const frsh_contracts_group_t *contracts_to_neg, + const frsh_contracts_group_t *contracts_to_reneg, + const fna_vres_group_t *vres_to_reneg, + const fna_vres_group_t *vres_to_cancel, + fna_vres_group_t *new_vres) +{ + int ret, i; + bool accepted; + frescan_ss_group_t ss_to_reneg, ss_to_cancel, ss_new; + + // convert fna_vres to ss + if (vres_to_reneg == NULL) { + ss_to_reneg.size = 0; + } else { + ss_to_reneg.size = vres_to_reneg->size; + if (ss_to_reneg.size > FRESCAN_BWRES_MAX_GROUP_OPS) { + FRESCAN_ERROR("FRESCAN_BWRES_MAX_GROUP_OPS small\n"); + return -1; + } + + for(i=0; ivres[i]; + } + } + + if (vres_to_cancel == NULL) { + ss_to_cancel.size = 0; + } else { + ss_to_cancel.size = vres_to_cancel->size; + if (ss_to_cancel.size > FRESCAN_BWRES_MAX_GROUP_OPS) { + FRESCAN_ERROR("FRESCAN_BWRES_MAX_GROUP_OPS small\n"); + return -1; + } + + for(i=0; ivres[i]; + } + } + + if ((contracts_to_neg != NULL) && (new_vres == NULL)) { + FRESCAN_ERROR("new_vres is NULL\n"); + return -1; + } + + // negotiate + DEBUG(FRESCAN_BWRES_FNA_ENABLE_DEBUG, + "calling frescan_bwres_group_change_mode_sync\n"); + + ret = frescan_bwres_group_change_mode_sync + ((frescan_network_t)resource_id, + contracts_to_neg, + contracts_to_reneg, + &ss_to_reneg, + &ss_to_cancel, + &ss_new, + &accepted); + if (ret != 0) return -1; + + if (accepted == false) { + DEBUG(FRESCAN_BWRES_FNA_ENABLE_DEBUG, "negotiation not accepted\n"); + return -1; // TODO: change to constant FNA_REJECTED + } + + DEBUG(FRESCAN_BWRES_FNA_ENABLE_DEBUG, "negotiation accepted\n"); + + // convert new ss to fna_vres + if (contracts_to_neg != NULL) { + new_vres->size = ss_new.size; + for(i=0; isize; i++) { + new_vres->vres[i] = (fna_vres_id_t)ss_new.ss[i]; + } + } + + return 0; +} + /** * frescan_fna_contract_negotiate() * @@ -161,24 +243,18 @@ int frescan_fna_contract_negotiate fna_vres_id_t *vres) { int ret; - bool accepted; - frescan_ss_t ss; + frsh_contracts_group_t contracts_to_neg; + fna_vres_group_t new_vres; - DEBUG(FRESCAN_FNA_ENABLE_DEBUG, "calling frescan_bwres_negotiate\n"); - ret = frescan_bwres_negotiate((frescan_network_t)resource_id, - contract, - &ss, - &accepted); - if (ret != 0) return -1; + contracts_to_neg.size = 1; + contracts_to_neg.contracts[0] = *contract; - if (accepted == true) { - DEBUG(FRESCAN_FNA_ENABLE_DEBUG, "contract accepted\n"); - *vres = (fna_vres_id_t)ss; - return 0; - } else { - DEBUG(FRESCAN_FNA_ENABLE_DEBUG, "contract not accepted\n"); - return -1; // TODO: change to constant FNA_REJECTED - } + ret = frescan_fna_group_change_mode_sync + (resource_id, &contracts_to_neg, NULL, NULL, NULL, &new_vres); + if (ret != 0) return ret; + + *vres = new_vres.vres[0]; + return 0; } /** @@ -216,8 +292,17 @@ int frescan_fna_contract_renegotiate_sync const fna_vres_id_t vres, const frsh_contract_t *new_contract) { - FRESCAN_ERROR("not implemented\n"); - return -1; + frsh_contracts_group_t contracts_to_reneg; + fna_vres_group_t vres_to_reneg; + + contracts_to_reneg.size = 1; + contracts_to_reneg.contracts[0] = *new_contract; + vres_to_reneg.size = 1; + vres_to_reneg.vres[0] = vres; + + return frescan_fna_group_change_mode_sync + (resource_id, NULL, &contracts_to_reneg, + &vres_to_reneg, NULL, NULL); } /** @@ -334,8 +419,13 @@ int frescan_fna_vres_destroy (const frsh_resource_id_t resource_id, const fna_vres_id_t vres) { - FRESCAN_ERROR("not implemented\n"); - return -1; + fna_vres_group_t vres_to_cancel; + + vres_to_cancel.size = 1; + vres_to_cancel.vres[0] = vres; + + return frescan_fna_group_change_mode_sync + (resource_id, NULL, NULL, NULL, &vres_to_cancel, NULL); } /** @@ -638,7 +728,7 @@ int frescan_fna_send_async int ret; frescan_send_params_t params; - DEBUG(FRESCAN_FNA_ENABLE_DEBUG, + DEBUG(FRESCAN_BWRES_FNA_ENABLE_DEBUG, "net:%u dest:%u chan:%u size:%u ss:%u\n", endpoint->resource_id, endpoint->destination, endpoint->stream_id, size, endpoint->vres); @@ -711,7 +801,7 @@ int frescan_fna_receive_sync params.channel = (frescan_channel_t)endpoint->stream_id; params.flags = FRESCAN_SYNC; - DEBUG(FRESCAN_FNA_ENABLE_DEBUG, + DEBUG(FRESCAN_BWRES_FNA_ENABLE_DEBUG, "net:%u chan:%u size:%u\n", endpoint->resource_id, endpoint->stream_id, buffer_size); @@ -725,7 +815,7 @@ int frescan_fna_receive_sync *from = (frsh_network_address_t)frescan_from; - DEBUG(FRESCAN_FNA_ENABLE_DEBUG, + DEBUG(FRESCAN_BWRES_FNA_ENABLE_DEBUG, "msg received, from:%u bytes:%u prio:%u\n", *from, *received_bytes, prio); @@ -819,7 +909,7 @@ int frescan_fna_send_endpoint_get_status int frescan_fna_receive_endpoint_created (fna_endpoint_data_t *endpoint) { - DEBUG(FRESCAN_FNA_ENABLE_DEBUG, "receive endpoint created\n"); + DEBUG(FRESCAN_BWRES_FNA_ENABLE_DEBUG, "receive endpoint created\n"); return 0; } @@ -930,7 +1020,7 @@ int frescan_fna_network_bytes_to_budget *budget = frsh_usec_to_rel_time((long)FRESCAN_FRAME_TX_TIME_US * number_of_packets); - DEBUG(FRESCAN_FNA_ENABLE_DEBUG, + DEBUG(FRESCAN_BWRES_FNA_ENABLE_DEBUG, "bytes: %d -> budget: %ld us\n", nbytes, frsh_rel_time_to_usec(*budget)); @@ -1021,6 +1111,7 @@ int frescan_fna_network_get_min_eff_budget fna_operations_t frescan_fna_operations = { .fna_init = frescan_fna_init, + .fna_group_change_mode_sync = frescan_fna_group_change_mode_sync, .fna_contract_negotiate = frescan_fna_contract_negotiate, .fna_contract_renegotiate_sync = frescan_fna_contract_renegotiate_sync, .fna_contract_renegotiate_async = frescan_fna_contract_renegotiate_async, diff --git a/src_frescan/frescan_bwres_messages.c b/src_frescan/frescan_bwres_messages.c index b8f7455..7bef5f0 100644 --- a/src_frescan/frescan_bwres_messages.c +++ b/src_frescan/frescan_bwres_messages.c @@ -69,10 +69,12 @@ #include "frescan_bwres_messages.h" #include "frescan_bwres_requests.h" #include "frescan.h" +#include "frescan_data.h" #include "frescan_config.h" #include "frescan_debug.h" +#include "frsh_distributed.h" -#define FRESCAN_BWRES_MX_MSG_SIZE 3000 // TODO: adjust to the minimum +#define FRESCAN_BWRES_MX_MSG_SIZE 5000 // TODO: adjust to the accurate value /** * frescan_messages_init() @@ -83,394 +85,440 @@ static frescan_recv_params_t recv_params[FRESCAN_MX_NETWORKS]; int frescan_messages_init(frescan_network_t net) { - DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "initialization\n"); + DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, "initialization\n"); send_params[net].net = net; - send_params[net].channel = FRESCAN_NEG_CHANNEL; + send_params[net].channel = FRESCAN_BWRES_NEG_CHANNEL; send_params[net].flags = FRESCAN_SS | FRESCAN_ASYNC; - send_params[net].ss = the_networks[net].neg_messages_ss_id; - send_params[net].to = FRESCAN_NEG_MASTER_NODE; + send_params[net].ss = frescan_data[net].neg_messages_ss_id; + send_params[net].to = FRESCAN_BWRES_MASTER_NODE; recv_params[net].net = net; - recv_params[net].channel = FRESCAN_NEG_CHANNEL; + recv_params[net].channel = FRESCAN_BWRES_NEG_CHANNEL; recv_params[net].flags = FRESCAN_SYNC; return 0; } /** - * - * FRESCAN_REQ_NEG MESSAGE - * ======================= + * FRESCAN_BWRES_REQ_GN + * ==================== * This message is sent from a SLAVE to the MASTER when the slave wants - * to negotiate a new contract. It contains the type (a negotiation 'NEG' - * request), the LOCAL request id (so the MASTER can use it in the reply - * to identify to which request is replying), a preallocated sporadic - * server id (the MASTER will store it in its table together with the - * node so we can perform renegotiations and spare capacity distribution - * in the future) and the contract. - * - * 1 2 2 N - * +-----------------------------+ - * | 'NEG' | REQ | SS | CONTRACT | - * +-----------------------------+ - * + * to make a negotiation (including creating new vres, renegotiations and + * cancellations). */ -struct frescan_req_neg_message_t { - frescan_request_type_t type; - frescan_request_id_t req; - frescan_ss_t ss; -} __attribute__ ((packed)); - -static int frescan_request_to_neg_message(const frescan_request_data_t *data, - uint8_t *msg) +static int frescan_request_to_gn_message + (const frescan_bwres_request_data_t *data, + uint8_t *msg, + size_t *size) { - int ret; - struct frescan_req_neg_message_t *neg_msg; - size_t req_size, contract_size; - - neg_msg = (struct frescan_req_neg_message_t *)msg; - req_size = sizeof(struct frescan_req_neg_message_t); - - neg_msg->type = FRESCAN_REQ_NEG; - neg_msg->req = data->req; - neg_msg->ss = data->ss; - - ret = frsh_contract_marshal(data->contract, - msg + req_size, - FRESCAN_BWRES_MX_MSG_SIZE - req_size, - &contract_size); - if (ret != 0) { - FRESCAN_ERROR("frsh_contract_marshal return -1\n"); - return -1; - } + int ret, i; + uint8_t *msg_begin, *msg_tmp; + size_t bytes_written; - DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "type:%d req:%d ss:%d csize:%u\n", - neg_msg->type, neg_msg->req, neg_msg->ss, contract_size); + msg_begin = msg; - return req_size + contract_size; -} + // type: FRESCAN_GN_MESSAGE + *((uint8_t *)msg) = (uint8_t)FRESCAN_BWRES_REQ_GN; + bytes_written = sizeof(uint8_t); + msg = msg + bytes_written; -static int frescan_neg_message_to_request(const uint8_t *msg, - frescan_request_data_t *data, - size_t size) -{ - int ret; - struct frescan_req_neg_message_t *neg_msg; - size_t req_size; - - neg_msg = (struct frescan_req_neg_message_t *)msg; - req_size = sizeof(struct frescan_req_neg_message_t); - - data->type = FRESCAN_REQ_NEG; - data->req = neg_msg->req; - data->ss = neg_msg->ss; - - ret = frsh_contract_unmarshal(data->contract, - msg + req_size, // pointer to contract - size - req_size); // size marshal ' ' - if (ret != 0) { - FRESCAN_ERROR("frsh_contract_unmarshal return -1\n"); - return -1; - } + // req + *((frescan_bwres_request_id_t *)msg) = data->req; + bytes_written = sizeof(frescan_bwres_request_id_t); + msg = msg + bytes_written; - DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "type:%d req:%d ss:%d\n", - data->type, data->req, data->ss); + DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, + "GN message req:%u\n", data->req); - return 0; -} + // NEG-GROUP + DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, + "NEG-GROUP num contracts:%u\n", data->contracts_to_neg->size); -/** - * - * FRESCAN_REQ_RENEG MESSAGE - * ========================= - * This message is sent from a SLAVE to the MASTER when the slave wants - * to renegotiate a contract. It contains the type (a renegotiation 'RENEG' - * request), the LOCAL request id (so the MASTER can use it in the reply - * to identify to which request is replying), the sporadic server id - * (the MASTER will look up its table together with the node to find the - * appropiate entry) and the contract. - * - * 1 2 2 N - * +-------------------------------+ - * | 'RENEG' | REQ | SS | CONTRACT | - * +-------------------------------+ - * - */ + *((uint8_t *)msg) = (uint8_t)data->contracts_to_neg->size; + bytes_written = sizeof(uint8_t); + msg = msg + bytes_written; -struct frescan_req_reneg_message_t { - frescan_request_type_t type; - frescan_request_id_t req; - frescan_ss_t ss; -} __attribute__ ((packed)); + for (i=0; icontracts_to_neg->size; i++) { + // reserve 2 bytes for the size of the marshalled contract + msg_tmp = msg; + msg = msg + sizeof(uint16_t); + // marshal the contract + ret = frsh_contract_marshal + (&data->contracts_to_neg->contracts[i], + msg, + FRESCAN_BWRES_MX_MSG_SIZE - (msg - msg_begin), + &bytes_written); + if (ret != 0) { + FRESCAN_ERROR("frsh_contract_marshal return -1\n"); + return -1; + } + // write the size and update the message pointer msg + *((uint16_t *)msg_tmp) = (uint16_t)bytes_written; + msg = msg + bytes_written; -static int frescan_request_to_reneg_message(const frescan_request_data_t *data, - uint8_t *msg) -{ - int ret; - size_t req_size, contract_size; - struct frescan_req_reneg_message_t *reneg_msg; - - reneg_msg = (struct frescan_req_reneg_message_t *)msg; - req_size = sizeof(struct frescan_req_reneg_message_t); - - reneg_msg->type = FRESCAN_REQ_RENEG; - reneg_msg->req = data->req; - reneg_msg->ss = data->ss; - - ret = frsh_contract_marshal(data->contract, - msg + req_size, - FRESCAN_BWRES_MX_MSG_SIZE - req_size, - &contract_size); - if (ret != 0) { - FRESCAN_ERROR("frsh_contract_marshal return -1\n"); - return -1; + DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, + "contract[%d].size:%u\n", i, bytes_written); } - DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "type:%d req:%d ss:%d csize:%u\n", - reneg_msg->type, reneg_msg->req, reneg_msg->ss, contract_size); + // RENEG-GROUP + DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, + "RENEG-GROUP num contracts:%u\n",data->contracts_to_reneg->size); - return req_size + contract_size; -} + *((uint8_t *)msg) = (uint8_t)data->contracts_to_reneg->size; + bytes_written = sizeof(uint8_t); + msg = msg + bytes_written; -static int frescan_reneg_message_to_request(const uint8_t *msg, - frescan_request_data_t *data, - size_t size) -{ - int ret; - struct frescan_req_reneg_message_t *reneg_msg; - size_t req_size; - - reneg_msg = (struct frescan_req_reneg_message_t *)msg; - req_size = sizeof(struct frescan_req_neg_message_t); - - data->type = FRESCAN_REQ_RENEG; - data->req = reneg_msg->req; - data->ss = reneg_msg->ss; - - ret = frsh_contract_unmarshal(data->contract, - msg + req_size, - size - req_size); - if (ret != 0) { - FRESCAN_ERROR("frsh_contract_unmarshal return -1\n"); - return -1; + for (i=0; icontracts_to_reneg->size; i++) { + // write the ss + *((uint16_t *)msg) = (uint16_t)data->ss_to_reneg->ss[i]; + bytes_written = sizeof(uint16_t); + msg = msg + bytes_written; + // reserve 2 bytes for the size of the marshalled contract + msg_tmp = msg; + msg = msg + sizeof(uint16_t); + // marshal the contract + ret = frsh_contract_marshal + (&data->contracts_to_reneg->contracts[i], + msg, + FRESCAN_BWRES_MX_MSG_SIZE - (msg - msg_begin), + &bytes_written); + if (ret != 0) { + FRESCAN_ERROR("frsh_contract_marshal return -1\n"); + return -1; + } + // write the size and update the message pointer msg + *((uint16_t *)msg_tmp) = (uint16_t)bytes_written; + msg = msg + bytes_written; + + DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, + "contract[%d].size:%u ss[%d]:%u\n", + i, bytes_written, i, data->ss_to_reneg->ss[i]); } - DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "type:%d req:%d ss:%d\n", - data->type, data->req, data->ss); + // CANCEL-GROUP + DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, "CANCEL-GROUP num ss:%u\n", + data->ss_to_cancel->size); - return 0; -} + *((uint8_t *)msg) = (uint8_t)data->ss_to_cancel->size; + bytes_written = sizeof(uint8_t); + msg = msg + bytes_written; -/** - * FRESCAN_REQ_CANCEL MESSAGE - * ========================== - * This message is sent from a SLAVE to the MASTER to cancel a contract. - * It contains the type, 'CANCEL' and the sporadic server id (the MASTER will - * have to look it up in the table). The MASTER doesnt need to reply this - * message. - * - * +---------------+ - * | 'CANCEL' | SS | - * +---------------+ - * - */ + for (i=0; iss_to_cancel->size; i++) { + // write the ss + *((uint16_t *)msg) = (uint16_t)data->ss_to_cancel->ss[i]; + bytes_written = sizeof(uint16_t); + msg = msg + bytes_written; + + DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, + "ss[%d]:%u\n", data->ss_to_cancel->ss[i]); + } + + *size = msg - msg_begin; -struct frescan_req_cancel_message_t { - frescan_request_type_t type; - frescan_ss_t ss; -} __attribute__ ((packed)); + DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, "size:%u\n", *size); -static int frescan_request_to_cancel_message(const frescan_request_data_t *data, - uint8_t *msg) + return 0; +} + +static int frescan_gn_message_to_request(const uint8_t *msg_to_parse, + frescan_bwres_request_data_t *data, + size_t size) { - struct frescan_req_cancel_message_t *cancel_msg; + int ret, i; + uint8_t *msg; + size_t bytes_read, contract_size; + + msg = (uint8_t *)msg_to_parse; + + data->contracts_to_neg = &data->contracts_to_neg_data; + data->contracts_to_reneg = &data->contracts_to_reneg_data; + data->ss_to_reneg = &data->ss_to_reneg_data; + data->ss_to_cancel = &data->ss_to_cancel_data; + data->ss_new = &data->ss_new_data; + + // req + data->req = *((frescan_bwres_request_id_t *)msg); + bytes_read = sizeof(frescan_bwres_request_id_t); + msg = msg + bytes_read; + + DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, + "GN message req:%u\n", data->req); + + // NEG-GROUP + data->contracts_to_neg->size = *((uint8_t *)msg); + bytes_read = sizeof(uint8_t); + msg = msg + bytes_read; + + DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, + "NEG-GROUP num contracts:%u\n", data->contracts_to_neg->size); + + for (i=0; icontracts_to_neg->size; i++) { + contract_size = *((uint16_t *)msg); + bytes_read = sizeof(uint16_t); + msg = msg + bytes_read; + + // unmarshal the contract + ret = frsh_contract_unmarshal + (&data->contracts_to_neg->contracts[i], + msg, + contract_size); + if (ret != 0) { + FRESCAN_ERROR("frsh_contract_unmarshal return -1\n"); + return -1; + } + + bytes_read = contract_size; + msg = msg + bytes_read; - cancel_msg = (struct frescan_req_cancel_message_t *)msg; + DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, + "contract[%d].size:%u\n", i, contract_size); + } - cancel_msg->type = FRESCAN_REQ_CANCEL; - cancel_msg->ss = data->ss; + // RENEG-GROUP + data->contracts_to_reneg->size = *((uint8_t *)msg); + bytes_read = sizeof(uint8_t); + msg = msg + bytes_read; + + DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, + "RENEG-GROUP num contracts:%u\n",data->contracts_to_reneg->size); + + for (i=0; icontracts_to_reneg->size; i++) { + data->ss_to_reneg->ss[i] = *((uint16_t *)msg); + bytes_read = sizeof(uint16_t); + msg = msg + bytes_read; + + contract_size = *((uint16_t *)msg); + bytes_read = sizeof(uint16_t); + msg = msg + bytes_read; + + // unmarshal the contract + ret = frsh_contract_unmarshal + (&data->contracts_to_reneg->contracts[i], + msg, + contract_size); + if (ret != 0) { + FRESCAN_ERROR("frsh_contract_unmarshal return -1\n"); + return -1; + } - DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "type:%d ss:%d\n", - cancel_msg->type, cancel_msg->ss); + bytes_read = contract_size; + msg = msg + bytes_read; - return sizeof(struct frescan_req_cancel_message_t); -} + DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, + "contract[%d].size:%u ss[%d]:%u\n", + i, contract_size, i, data->ss_to_reneg->ss[i]); + } -static int frescan_cancel_message_to_request(const uint8_t *msg, - frescan_request_data_t *data) -{ - struct frescan_req_cancel_message_t *cancel_msg; + // CANCEL-GROUP + data->ss_to_cancel->size = *((uint8_t *)msg); + bytes_read = sizeof(uint8_t); + msg = msg + bytes_read; - cancel_msg = (struct frescan_req_cancel_message_t *)msg; + DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, + "CANCEL-GROUP num ss:%u\n", data->ss_to_cancel->size); - data->type = FRESCAN_REQ_CANCEL; - data->ss = cancel_msg->ss; + for (i=0; iss_to_cancel->size; i++) { + // write the ss + data->ss_to_cancel->ss[i] = *((uint16_t *)msg); + bytes_read = sizeof(uint16_t); + msg = msg + bytes_read; - DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "type:%d ss:%d\n", - data->type, data->ss); + DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, + "ss[%d]:%u\n", data->ss_to_cancel->ss[i]); + } return 0; } /** - * - * FRESCAN_REP_INC_BUDGET / FRESCAN_REP_DEC_BUDGET - * =============================================== + * FRESCAN_BWRES_REQ_MC + * ==================== * This message is sent from the MASTER to a slave when there is a change * in the budget value assigned by the spare capacity algorithm. - * - * +---------------------------------------------------+ - * | 'INC/DEC' | SS | NEW_B | SS | NEW_B | SS | NEW_B | - * +---------------------------------------------------+ - * */ -static int frescan_request_to_repchange_message - (const frescan_request_data_t *data, uint8_t *msg) +static int frescan_request_to_mc_message + (const frescan_bwres_request_data_t *data, + uint8_t *msg, + size_t *size) { - int bytes_written; - struct list_head *the_mode_change_list; - frescan_sa_vres_t *vres; + frescan_bwres_vres_t *vres; uint8_t *msg_begin; - - if (data->type == FRESCAN_REP_INC_BUDGET) { - the_mode_change_list = &the_networks[data->net]. - mode_change_budget_inc_list_head - [data->request_node]; - } else { - the_mode_change_list = &the_networks[data->net]. - mode_change_budget_dec_list_head - [data->request_node]; - } - - if (list_empty(the_mode_change_list)) { - return 0; // nothing to send - } + size_t bytes_written; msg_begin = msg; - *((frescan_request_type_t *)msg) = data->type; - bytes_written = sizeof(frescan_request_type_t); + // type: FRESCAN_GN_MESSAGE + *((uint8_t *)msg) = (uint8_t)FRESCAN_BWRES_REQ_MC; + bytes_written = sizeof(uint8_t); msg = msg + bytes_written; + // write the SS-mode_change_type-values fields list_for_each_entry(vres, - the_mode_change_list, + &frescan_data[data->net].mode_change_list + [data->request_node], mode_change_list) { + if ((vres->mode_change_type & data->mode_change_type) != + data->mode_change_type) continue; + *((frescan_ss_t *)msg) = vres->ss; bytes_written = sizeof(frescan_ss_t); msg = msg + bytes_written; - *((frsh_sa_time_t *)msg) = vres->old_c; - bytes_written = sizeof(frsh_sa_time_t); + *((uint8_t *)msg) = (uint8_t)data->mode_change_type; + bytes_written = sizeof(uint8_t); msg = msg + bytes_written; + + if (data->mode_change_type & (FRESCAN_BWRES_MC_BUDGET_INC | + FRESCAN_BWRES_MC_BUDGET_DEC)) { + *((frsh_sa_time_t *)msg) = vres->old_c; + bytes_written = sizeof(frsh_sa_time_t); + msg = msg + bytes_written; + } + + if (data->mode_change_type & (FRESCAN_BWRES_MC_PERIOD_INC | + FRESCAN_BWRES_MC_PERIOD_DEC)) { + *((frsh_sa_time_t *)msg) = vres->old_t; + bytes_written = sizeof(frsh_sa_time_t); + msg = msg + bytes_written; + } + + if (data->mode_change_type & (FRESCAN_BWRES_MC_PRIO_INC | + FRESCAN_BWRES_MC_PRIO_DEC)) { + *((frsh_sa_prio_t *)msg) = vres->old_p; + bytes_written = sizeof(frsh_sa_prio_t); + msg = msg + bytes_written; + } } - return (msg - msg_begin); + *size = msg - msg_begin; + + DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, "size:%u\n", *size); + + return 0; } -static int frescan_repchange_message_to_request(const uint8_t *msg, - frescan_request_data_t *data, - size_t size) +static int frescan_mc_message_to_request(const uint8_t *msg_to_parse, + frescan_bwres_request_data_t *data, + size_t size) { - struct list_head *the_mode_change_list; - frescan_node_t me = the_networks[data->net].local_node; - frescan_sa_vres_t *vres; - int bytes_read; - uint8_t *msg_pointer; + uint8_t *msg; + size_t bytes_read; frescan_ss_t ss; + frescan_bwres_vres_t *vres; + frescan_node_t me; - data->type = *((frescan_request_type_t *)msg); + DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, "MC message\n"); - if (data->type == FRESCAN_REP_INC_BUDGET) { - the_mode_change_list = &the_networks[data->net]. - mode_change_budget_inc_list_head[me]; - } else { - the_mode_change_list = &the_networks[data->net]. - mode_change_budget_dec_list_head[me]; - } - - INIT_LIST_HEAD(the_mode_change_list); - - msg_pointer = (uint8_t *)msg; + msg = (uint8_t *)msg_to_parse; + me = frescan_data[data->net].local_node; + data->mode_change_type = 0; - while(msg_pointer < msg + size) { - ss = *((frescan_ss_t *)msg_pointer); + while(msg < msg_to_parse + size) { + ss = *((frescan_ss_t *)msg); bytes_read = sizeof(frescan_ss_t); - msg_pointer = msg_pointer + bytes_read; - - vres = &the_networks[data->net].scenario.vres_pool[me][ss]; - - vres->old_c = *((frsh_sa_time_t *)msg_pointer); - bytes_read = sizeof(frsh_sa_time_t); - msg_pointer = msg_pointer + bytes_read; + msg = msg + bytes_read; + + vres = &frescan_data[data->net].scenario.vres_pool[me][ss]; + + vres->mode_change_type = *((uint8_t *)msg); + bytes_read = sizeof(uint8_t); + msg = msg + bytes_read; + + if (vres->mode_change_type & (FRESCAN_BWRES_MC_BUDGET_INC | + FRESCAN_BWRES_MC_BUDGET_DEC)) { + vres->old_c = *((frsh_sa_time_t *)msg); + bytes_read = sizeof(frsh_sa_time_t); + msg = msg + bytes_read; + } + + if (data->mode_change_type & (FRESCAN_BWRES_MC_PERIOD_INC | + FRESCAN_BWRES_MC_PERIOD_DEC)) { + vres->old_t = *((frsh_sa_time_t *)msg); + bytes_read = sizeof(frsh_sa_time_t); + msg = msg + bytes_read; + } + + if (data->mode_change_type & (FRESCAN_BWRES_MC_PRIO_INC | + FRESCAN_BWRES_MC_PRIO_DEC)) { + vres->old_p = *((frsh_sa_prio_t *)msg); + bytes_read = sizeof(frsh_sa_prio_t); + msg = msg + bytes_read; + } + + if (vres->mode_change_type != 0) { + list_add_tail(&(vres->mode_change_list), + &(frescan_data[data->net]. + mode_change_list[me])); + } + + data->mode_change_type |= vres->mode_change_type; } return 0; } /** - * - * FRESCAN_REP_NEG MESSAGE - * ======================= + * FRESCAN_BWRES_REP_GN + * ==================== * This message is sent from the MASTER to a slave as a reply to a - * FRESCAN_REQ_NEG or a FRESCAN_REQ_RENEG, to say if they were admited. - * It contains the type 'REPNEG', the request ID of the slave, a - * return value to say if the contract is admited or not, and the final - * values if it was admited - * - * +-------------------------------------------+ - * | 'REPNEG' | REQ | RET_VALUE | FINAL_VALUES | + FRESCAN_REP_INC/DEC_BUDGET - * +-------------------------------------------+ - * + * FRESCAN_BWRES_REQ_GN message */ -struct frescan_rep_neg_message_t { - frescan_request_type_t type; - frescan_request_id_t req; - frescan_request_retval_t return_value; - frescan_server_params_t final_values; -} __attribute__ ((packed)); - -static int frescan_request_to_repneg_message(const frescan_request_data_t *data, - uint8_t *msg) +static int frescan_request_to_rep_gn_message + (const frescan_bwres_request_data_t *data, + uint8_t *msg, + size_t *size) { - struct frescan_rep_neg_message_t *repneg_msg; + uint8_t *msg_begin; + size_t bytes_written; + + msg_begin = msg; - repneg_msg = (struct frescan_rep_neg_message_t *)msg; + // type + *((uint8_t *)msg) = (uint8_t)FRESCAN_BWRES_REP_GN; + bytes_written = sizeof(uint8_t); + msg = msg + bytes_written; - repneg_msg->type = FRESCAN_REP_NEG; - repneg_msg->req = data->req; - repneg_msg->return_value = data->return_value; - repneg_msg->final_values = data->final_values; + // req + *((frescan_bwres_request_id_t *)msg) = data->req; + bytes_written = sizeof(frescan_bwres_request_id_t); + msg = msg + bytes_written; - if (data->return_value == FRESCAN_REQ_ACCEPTED) { - } + // return value + *((uint8_t *)msg) = data->return_value; + bytes_written = sizeof(uint8_t); + msg = msg + bytes_written; + *size = msg - msg_begin; - DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "type:%d req:%d ret:%d\n", - repneg_msg->type, repneg_msg->req, repneg_msg->return_value); + DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, "size:%u\n", *size); - return sizeof(struct frescan_rep_neg_message_t); + return 0; } -static int frescan_repneg_message_to_request(const uint8_t *msg, - frescan_request_data_t *data) +static int frescan_rep_gn_message_to_request + (const uint8_t *msg_to_parse, + frescan_bwres_request_data_t *data, + size_t size) { - struct frescan_rep_neg_message_t *repneg_msg; + uint8_t *msg; + size_t bytes_read; - repneg_msg = (struct frescan_rep_neg_message_t *)msg; + msg = (uint8_t *)msg_to_parse; - data->type = FRESCAN_REP_NEG; - data->req = repneg_msg->req; - data->return_value = repneg_msg->return_value; - // TODO: use final values only if it was accepted! - data->final_values = repneg_msg->final_values; + // req + data->req = *((frescan_bwres_request_id_t *)msg); + bytes_read = sizeof(frescan_bwres_request_id_t); + msg = msg + bytes_read; - DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "type:%d req:%d ret:%d\n", - data->type, data->req, data->return_value); + // return_value + data->return_value = *((uint8_t *)msg); + bytes_read = sizeof(uint8_t); + msg = msg + bytes_read; return 0; } @@ -485,35 +533,38 @@ static int frescan_repneg_message_to_request(const uint8_t *msg, * */ -int frescan_messages_send_request(const frescan_request_data_t *req_data) +int frescan_messages_send_request(const frescan_bwres_request_data_t *req_data) { int ret; uint8_t msg[FRESCAN_BWRES_MX_MSG_SIZE]; size_t size; switch(req_data->type) { - case FRESCAN_REQ_NEG: - size = frescan_request_to_neg_message(req_data, msg); - send_params[req_data->net].to = FRESCAN_NEG_MASTER_NODE; + case FRESCAN_BWRES_REQ_GN: + ret = frescan_request_to_gn_message + (req_data, msg, &size); + if (ret != 0) return ret; + send_params[req_data->net].to = + FRESCAN_BWRES_MASTER_NODE; break; - case FRESCAN_REQ_RENEG: - size = frescan_request_to_reneg_message(req_data, msg); - send_params[req_data->net].to = FRESCAN_NEG_MASTER_NODE; - break; - case FRESCAN_REQ_CANCEL: - size = frescan_request_to_cancel_message(req_data, msg); - send_params[req_data->net].to = FRESCAN_NEG_MASTER_NODE; - break; - case FRESCAN_REP_DEC_BUDGET: - case FRESCAN_REP_INC_BUDGET: - size = frescan_request_to_repchange_message - (req_data, msg); + case FRESCAN_BWRES_REQ_MC: + ret = frescan_request_to_mc_message + (req_data, msg, &size); + if (ret != 0) return ret; send_params[req_data->net].to = req_data->request_node; break; - case FRESCAN_REP_NEG: - size = frescan_request_to_repneg_message(req_data, msg); + case FRESCAN_BWRES_REP_GN: + ret = frescan_request_to_rep_gn_message + (req_data, msg, &size); + if (ret != 0) return ret; send_params[req_data->net].to = req_data->request_node; break; + case FRESCAN_BWRES_REQ_RES: + case FRESCAN_BWRES_REQ_RES_GET: + case FRESCAN_BWRES_REP_RES_GET: + case FRESCAN_BWRES_REQ_RES_SET: + case FRESCAN_BWRES_REQ_RES_COMMIT: + case FRESCAN_BWRES_REQ_RES_CANCEL: default: FRESCAN_ERROR("request type not supported\n"); return -1; @@ -522,8 +573,8 @@ int frescan_messages_send_request(const frescan_request_data_t *req_data) ret = frescan_send(&send_params[req_data->net], msg, size); if (ret != 0) return ret; - DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "sent request, type:%X size:%d\n", - *(frescan_request_type_t *)msg, size); + DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, "sent request, type:%X size:%u\n", + *(frescan_bwres_request_type_t *)msg, size); return 0; } @@ -539,19 +590,20 @@ int frescan_messages_send_request(const frescan_request_data_t *req_data) */ int frescan_messages_recv_request(frescan_network_t net, - frescan_request_id_t *req) + frescan_bwres_request_id_t *req) { int ret; uint8_t msg[FRESCAN_BWRES_MX_MSG_SIZE]; + uint8_t *msg_to_parse; size_t recv_bytes; frescan_node_t from; frescan_prio_t prio; - frescan_request_data_t *req_data; + frescan_bwres_request_data_t *req_data; - ret = frescan_requests_alloc(req); + ret = frescan_bwres_requests_alloc(req); if (ret != 0) return ret; - ret = frescan_requests_get_data(*req, &req_data); + ret = frescan_bwres_requests_get_data(*req, &req_data); if (ret != 0) return ret; ret = frescan_recv(&recv_params[net], @@ -562,35 +614,40 @@ int frescan_messages_recv_request(frescan_network_t net, &prio); if (ret != 0) return ret; - DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, + DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, "msg received! from:%u size:%u prio:%u chan:%u flags:%X\n", from, recv_bytes, prio, recv_params[net].channel, recv_params[net].flags); req_data->request_node = from; - req_data->net = net; - - switch(*((frescan_request_type_t *)msg)) { - case FRESCAN_REQ_NEG: - return frescan_neg_message_to_request(msg, - req_data, - recv_bytes); - case FRESCAN_REQ_RENEG: - return frescan_reneg_message_to_request(msg, - req_data, - recv_bytes); - case FRESCAN_REQ_CANCEL: - return frescan_cancel_message_to_request(msg, req_data); - case FRESCAN_REP_DEC_BUDGET: - case FRESCAN_REP_INC_BUDGET: - return frescan_repchange_message_to_request(msg, - req_data, - recv_bytes); - case FRESCAN_REP_NEG: - return frescan_repneg_message_to_request(msg, req_data); + req_data->net = net; + req_data->type = *((uint8_t *)msg); + + msg_to_parse = msg + sizeof(uint8_t); + recv_bytes = recv_bytes - sizeof(uint8_t); + + switch(req_data->type) { + case FRESCAN_BWRES_REQ_GN: + return frescan_gn_message_to_request(msg_to_parse, + req_data, + recv_bytes); + case FRESCAN_BWRES_REQ_MC: + return frescan_mc_message_to_request(msg_to_parse, + req_data, + recv_bytes); + case FRESCAN_BWRES_REP_GN: + return frescan_rep_gn_message_to_request(msg_to_parse, + req_data, + recv_bytes); + case FRESCAN_BWRES_REQ_RES: + case FRESCAN_BWRES_REQ_RES_GET: + case FRESCAN_BWRES_REP_RES_GET: + case FRESCAN_BWRES_REQ_RES_SET: + case FRESCAN_BWRES_REQ_RES_COMMIT: + case FRESCAN_BWRES_REQ_RES_CANCEL: default: - FRESCAN_ERROR("request type %X not supported\n", - *(frescan_request_type_t *)msg); + FRESCAN_ERROR("request type %d not supported\n", + req_data->type); return -1; } } diff --git a/src_frescan/frescan_bwres_messages.h b/src_frescan/frescan_bwres_messages.h index 99bd639..1191219 100644 --- a/src_frescan/frescan_bwres_messages.h +++ b/src_frescan/frescan_bwres_messages.h @@ -68,9 +68,7 @@ #ifndef _FRESCAN_BWRES_MESSAGES_H_ #define _FRESCAN_BWRES_MESSAGES_H_ -#include -#include "frescan_bwres_requests.h" -#include "frescan_data.h" +#include "frescan_types.h" /** * frescan_messages_init() - initialization function for the module @@ -88,7 +86,8 @@ extern int frescan_messages_init(frescan_network_t net); * */ -extern int frescan_messages_send_request(const frescan_request_data_t *req_data); +extern int frescan_messages_send_request + (const frescan_bwres_request_data_t *req_data); /** * frescan_messages_recv_request() @@ -102,6 +101,6 @@ extern int frescan_messages_send_request(const frescan_request_data_t *req_data) */ extern int frescan_messages_recv_request(frescan_network_t net, - frescan_request_id_t *req); + frescan_bwres_request_id_t *req); #endif // _FRESCAN_BWRES_MESSAGES_H_ diff --git a/src_frescan/frescan_bwres_mode_change.c b/src_frescan/frescan_bwres_mode_change.c index 0bfb7e9..e4eb1a5 100644 --- a/src_frescan/frescan_bwres_mode_change.c +++ b/src_frescan/frescan_bwres_mode_change.c @@ -73,111 +73,106 @@ #include "frescan_bwres_messages.h" #include "frescan_bwres_mode_change.h" #include "frescan_debug.h" +#include "frescan_config.h" -int frescan_bwres_budget_change(frescan_request_data_t *req_data, - frescan_node_t node, - frescan_sa_mode_change_type_t mode_change_type); +static int frescan_bwres_send_mc_messages + (frescan_network_t net, + frescan_bwres_mode_change_type_t mode_change_type); /** - * frescan_bwres_mode_change_protocol() - performs the mode change - * - * Follow the mode change protocol described in the paper. - * + * frescan_bwres_mode_change_protocol() - performs the mode change protocol */ -int frescan_bwres_mode_change_protocol(frescan_request_data_t *req_data) +int frescan_bwres_mode_change_protocol(frescan_bwres_request_data_t *req_data) { - int ret, i; + int ret; frescan_node_t node; - frescan_sa_vres_t *vres; + frescan_bwres_vres_t *vres; frsh_sa_vres_data_t *sa_vres_data; frsh_sa_time_t max_period_in_budget_dec; frsh_sa_time_t max_period_in_budget_inc; struct timespec start_timestamp, next_activation; - DEBUG(FRESCAN_MODECHANGE_ENABLE_DEBUG, "starting mode change\n"); + DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG, "START MODE CHANGE PROTOCOL\n"); for(node=0; nodenet]. - mode_change_budget_inc_list_head[node]); + INIT_LIST_HEAD(&frescan_data[req_data->net]. + mode_change_list[node]); - INIT_LIST_HEAD(&the_networks[req_data->net]. - mode_change_budget_dec_list_head[node]); + frescan_data[req_data->net].mode_change_type[node] = 0; } max_period_in_budget_dec = (frsh_sa_time_t)0; max_period_in_budget_inc = (frsh_sa_time_t)0; + DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG, "1.- adding vres to mc list\n"); + list_for_each_entry (vres, - &the_networks[req_data->net].scenario.vres_head.list, + &frescan_data[req_data->net].scenario.vres_head.list, list) { - sa_vres_data = &the_networks[req_data->net]. + sa_vres_data = &frescan_data[req_data->net]. scenario.fsa_scenario.sa_vres_alloc [vres->fsa_vres_global_id]; - vres->mode_change_type = 0; if (sa_vres_data->c > vres->old_c) { - vres->mode_change_type |= FRESCAN_SA_BUDGET_INC; - + vres->mode_change_type |= FRESCAN_BWRES_MC_BUDGET_INC; if (sa_vres_data->t > max_period_in_budget_inc) { max_period_in_budget_inc = sa_vres_data->t; } - - list_add_tail - (&(vres->mode_change_list), - &(the_networks[req_data->net]. - mode_change_budget_inc_list_head[vres->node])); } else if (sa_vres_data->c < vres->old_c) { - vres->mode_change_type |= FRESCAN_SA_BUDGET_DEC; - + vres->mode_change_type |= FRESCAN_BWRES_MC_BUDGET_DEC; if (sa_vres_data->t > max_period_in_budget_dec) { max_period_in_budget_dec = sa_vres_data->t; } - - list_add_tail - (&(vres->mode_change_list), - &(the_networks[req_data->net]. - mode_change_budget_dec_list_head[vres->node])); } if (sa_vres_data->t > vres->old_t) { - vres->mode_change_type |= FRESCAN_SA_PERIOD_INC; + vres->mode_change_type |= FRESCAN_BWRES_MC_PERIOD_INC; } else if (sa_vres_data->t < vres->old_t) { - vres->mode_change_type |= FRESCAN_SA_PERIOD_DEC; + vres->mode_change_type |= FRESCAN_BWRES_MC_PERIOD_DEC; } if (sa_vres_data->p > vres->old_p) { - vres->mode_change_type |= FRESCAN_SA_PRIO_INC; + vres->mode_change_type |= FRESCAN_BWRES_MC_PRIO_INC; } else if (sa_vres_data->p < vres->old_p) { - vres->mode_change_type |= FRESCAN_SA_PRIO_DEC; + vres->mode_change_type |= FRESCAN_BWRES_MC_PRIO_DEC; } + if (vres->mode_change_type == 0) continue; + vres->old_c = sa_vres_data->c; vres->old_t = sa_vres_data->t; vres->old_p = sa_vres_data->p; - DEBUG(FRESCAN_MODECHANGE_ENABLE_DEBUG, - "vres: %u type: %X budget_change: %s\n", - vres->fsa_vres_global_id, - vres->mode_change_type, - ((vres->mode_change_type & FRESCAN_SA_BUDGET_INC) == - FRESCAN_SA_BUDGET_INC) ? "inc" : "dec"); - } + list_add_tail(&(vres->mode_change_list), + &(frescan_data[req_data->net]. + mode_change_list[vres->node])); - // 1.- mode change for B- members - for(i=(FRESCAN_MX_NODES-1); i>=0; i--) { - ret = frescan_bwres_budget_change(req_data, - (frescan_node_t)i, - FRESCAN_SA_BUDGET_DEC); - if (ret != 0) return -1; + frescan_data[req_data->net].mode_change_type[vres->node] |= + vres->mode_change_type; + + DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG, + "vres:%u node:%u ss:%u mc_type:0x%X\n", + vres->fsa_vres_global_id, vres->node, + vres->ss, vres->mode_change_type); } - // 2.- wait the time needed to keep schedulability - ret = clock_gettime(CLOCK_MONOTONIC, - &start_timestamp); + DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG, "2.- Budget decrease\n"); + + ret = frescan_bwres_send_mc_messages(req_data->net, + FRESCAN_BWRES_MC_BUDGET_DEC); + if (ret != 0) return -1; + + ret = frescan_bwres_mode_change_local(req_data->net, + FRESCAN_BWRES_MC_BUDGET_DEC); + if (ret != 0) return -1; + + DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG, "3.- Wait max_period\n"); + + ret = clock_gettime(CLOCK_MONOTONIC, &start_timestamp); if (ret != 0) return -1; add_timespec(next_activation, @@ -188,56 +183,83 @@ int frescan_bwres_mode_change_protocol(frescan_request_data_t *req_data) incr_timespec(next_activation, start_timestamp); - ret = clock_nanosleep(CLOCK_MONOTONIC, - TIMER_ABSTIME, - &next_activation, - NULL); + ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, + &next_activation, NULL); if (ret != 0) return -1; - // 3-. mode change for B+ members - for(i=(FRESCAN_MX_NODES-1); i>=0; i--) { - ret = frescan_bwres_budget_change(req_data, - (frescan_node_t)i, - FRESCAN_SA_BUDGET_INC); + DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG, "4.- Budget increase\n"); + + ret = frescan_bwres_send_mc_messages(req_data->net, + FRESCAN_BWRES_MC_BUDGET_INC); + if (ret != 0) return -1; + + ret = frescan_bwres_mode_change_local(req_data->net, + FRESCAN_BWRES_MC_BUDGET_INC); + if (ret != 0) return -1; + + return 0; +} + +/** + * frescan_bwres_send_mc_messages() + * + * This function is executed at the master node to send mode change + * messages to the slaves + */ + +static int frescan_bwres_send_mc_messages + (frescan_network_t net, + frescan_bwres_mode_change_type_t mode_change_type) +{ + int ret; + frescan_node_t node; + frescan_bwres_request_data_t tmp_req_data; + + tmp_req_data.net = net; + tmp_req_data.type = FRESCAN_BWRES_REQ_MC; + tmp_req_data.mode_change_type = mode_change_type; + + for(node=0; nodenet].local_node; - bool is_increase; - - is_increase = (mode_change_type & FRESCAN_SA_BUDGET_INC) == - FRESCAN_SA_BUDGET_INC; - - DEBUG(FRESCAN_MODECHANGE_ENABLE_DEBUG, - "budget change node: %u (me: %u) type: '%s'\n", - node, me, is_increase ? "inc" : "dec"); - - if (is_increase) { - the_mode_change_list = &the_networks[req_data->net]. - mode_change_budget_inc_list_head[node]; - } else { - the_mode_change_list = &the_networks[req_data->net]. - mode_change_budget_dec_list_head[node]; - } + frescan_node_t me = frescan_data[net].local_node; - list_for_each_entry(vres, the_mode_change_list, mode_change_list) + list_for_each_entry(vres, + &frescan_data[net].mode_change_list[me], + mode_change_list) { - DEBUG(FRESCAN_MODECHANGE_ENABLE_DEBUG, - "vres %u\n", vres->fsa_vres_global_id); + if ((vres->mode_change_type & mode_change_type) != + mode_change_type) continue; server_params.budget = frsh_rel_time_to_usec( frsh_sa_time_to_rel_time(vres->old_c)) / @@ -245,77 +267,51 @@ int frescan_bwres_budget_change server_params.period = frsh_sa_time_to_rel_time(vres->old_t); server_params.prio = vres->old_p; - if (node == me) { - if (is_increase) { - DEBUG(FRESCAN_MODECHANGE_ENABLE_DEBUG, - "Local: update server\n"); - ret = frescan_servers_update(req_data->net, - &server_params, - vres->ss); - if (ret != 0) return ret; - } else { - DEBUG(FRESCAN_MODECHANGE_ENABLE_DEBUG, - "Local: set perceived\n"); - ret = frescan_servers_set_perceived - (req_data->net, &server_params, vres->ss); - if (ret != 0) return ret; - } + if (mode_change_type == FRESCAN_BWRES_MC_BUDGET_INC) { + DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG, + "commit ss:%u\n", vres->ss); + ret = frescan_servers_update(net, + &server_params, + vres->ss); + if (ret != 0) return ret; } else { - if ((node == req_data->request_node) && - (vres->ss == req_data->ss)) { - DEBUG(FRESCAN_MODECHANGE_ENABLE_DEBUG, - "External: send reply to reneg\n"); - req_data->type = FRESCAN_REP_NEG; - req_data->final_values = server_params; - - ret = frescan_messages_send_request(req_data); - if (ret != 0) return -1; - } else { - DEBUG(FRESCAN_MODECHANGE_ENABLE_DEBUG, - "External: send SC change update\n"); - tmp_req_data.net = req_data->net; - tmp_req_data.request_node = node; - - if (is_increase) { - tmp_req_data.type = - FRESCAN_REP_INC_BUDGET; - } else { - tmp_req_data.type = - FRESCAN_REP_DEC_BUDGET; - } - - ret = frescan_messages_send_request - (&tmp_req_data); - if (ret != 0) return -1; - } + DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG, + "set perceived ss:%u\n", vres->ss); + ret = frescan_servers_set_perceived(net, + &server_params, + vres->ss); + if (ret != 0) return ret; } } - if (is_increase) return 0; + if (mode_change_type == FRESCAN_BWRES_MC_BUDGET_INC) return 0; + + ret = clock_gettime(CLOCK_MONOTONIC, &start_timestamp); + if (ret != 0) return -1; + + list_for_each_entry(vres, + &frescan_data[net].mode_change_list[me], + mode_change_list) + { + if ((vres->mode_change_type & mode_change_type) != + mode_change_type) continue; + + DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG, + "wait ss:%u period\n", vres->ss); + + add_timespec(next_activation, start_timestamp, + frsh_rel_time_to_timespec( + frsh_sa_time_to_rel_time(vres->old_t))); - if (node == me) { - ret = clock_gettime(CLOCK_MONOTONIC, &start_timestamp); + ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, + &next_activation, NULL); if (ret != 0) return -1; - list_for_each_entry - (vres, the_mode_change_list, mode_change_list) - { - add_timespec(next_activation, - start_timestamp, - frsh_rel_time_to_timespec - (frsh_sa_time_to_rel_time - (vres->old_t))); - - ret = clock_nanosleep(CLOCK_MONOTONIC, - TIMER_ABSTIME, - &next_activation, - NULL); - if (ret != 0) return -1; - - ret = frescan_servers_commit_perceived(req_data->net, - vres->ss); - if (ret != 0) return ret; - } + DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG, + "commit ss:%u\n", vres->ss); + + ret = frescan_servers_commit_perceived(net, vres->ss); + if (ret != 0) return ret; } return 0; diff --git a/src_frescan/frescan_bwres_mode_change.h b/src_frescan/frescan_bwres_mode_change.h index 117ba51..9e635d5 100644 --- a/src_frescan/frescan_bwres_mode_change.h +++ b/src_frescan/frescan_bwres_mode_change.h @@ -68,23 +68,27 @@ #ifndef _FRESCAN_BWRES_MODE_CHANGE_H_ #define _FRESCAN_BWRES_MODE_CHANGE_H_ -#include "frescan.h" -#include "frescan_data.h" -#include "frescan_bwres_requests.h" +#include "frescan_types.h" /** - * frescan_bwres_budget_change() - performs the budget change + * frescan_bwres_mode_change_protocol() + * + * Performs the mode change protocol. This function is called by the master + * node who coordinates all the process. */ -extern int frescan_bwres_budget_change - (frescan_request_data_t *req_data, - frescan_node_t node, - frescan_sa_mode_change_type_t mode_change_type); +extern int frescan_bwres_mode_change_protocol + (frescan_bwres_request_data_t *req_data); /** - * frescan_bwres_mode_change_protocol() - performs the mode change + * frescan_bwres_mode_change_local() + * + * This function updates local vres. When a slave receives a change mode + * message to change the values of any vres this function is called. */ -extern int frescan_bwres_mode_change_protocol(frescan_request_data_t *req_data); +extern int frescan_bwres_mode_change_local + (frescan_network_t net, + frescan_bwres_mode_change_type_t mode_change_type); #endif // _FRESCAN_BWRES_MODE_CHANGE_H_ diff --git a/src_frescan/frescan_bwres_requests.c b/src_frescan/frescan_bwres_requests.c index b32b227..16a1b00 100644 --- a/src_frescan/frescan_bwres_requests.c +++ b/src_frescan/frescan_bwres_requests.c @@ -83,7 +83,7 @@ static bool is_initialized = false; **/ struct request_t { - frescan_request_data_t request_data; + frescan_bwres_request_data_t request_data; struct list_head request_list; int pool_pos; }; @@ -91,19 +91,19 @@ struct request_t { static fosa_mutex_t requests_mutex; static fosa_cond_t requests_cond; -static struct request_t the_requests_pool[FRESCAN_MX_REQUESTS]; +static struct request_t the_requests_pool[FRESCAN_BWRES_MX_REQUESTS]; static freelist_t freelist; static struct request_t the_requests_list; /** - * frescan_requests_init() + * frescan_bwres_requests_init() * * Init the freelist, requests list, cond var and mutex. * **/ -int frescan_requests_init(int max_ceiling) +int frescan_bwres_requests_init(int max_ceiling) { int err; @@ -113,7 +113,7 @@ int frescan_requests_init(int max_ceiling) err = fosa_cond_init(&requests_cond); if (err != 0) return err; - err = freelist_init(&freelist, FRESCAN_MX_REQUESTS); + err = freelist_init(&freelist, FRESCAN_BWRES_MX_REQUESTS); if (err != 0) return err; INIT_LIST_HEAD(&the_requests_list.request_list); @@ -123,17 +123,17 @@ int frescan_requests_init(int max_ceiling) } /** - * frescan_requests_alloc() + * frescan_bwres_requests_alloc() * * Allocate a request with the mutex locked * **/ -int frescan_requests_alloc(frescan_request_id_t *req) +int frescan_bwres_requests_alloc(frescan_bwres_request_id_t *req) { int err, pos; - DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG, "alloc\n"); + DEBUG(FRESCAN_BWRES_REQUESTS_ENABLE_DEBUG, "alloc\n"); if (is_initialized == false) return -1; @@ -157,17 +157,17 @@ locked_error: } /** - * frescan_requests_free() + * frescan_bwres_requests_free() * * free the request from the pool * **/ -int frescan_requests_free(frescan_request_id_t req) +int frescan_bwres_requests_free(frescan_bwres_request_id_t req) { int err; - DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG, "free\n"); + DEBUG(FRESCAN_BWRES_REQUESTS_ENABLE_DEBUG, "free\n"); if (is_initialized == false) return -1; @@ -188,38 +188,38 @@ locked_error: } /** - * frescan_requests_get_data() - gets the data of the request + * frescan_bwres_requests_get_data() - gets the data of the request * */ -int frescan_requests_get_data(frescan_request_id_t req, - frescan_request_data_t **data) +int frescan_bwres_requests_get_data(frescan_bwres_request_id_t req, + frescan_bwres_request_data_t **data) { - DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG, "request id:%d\n", req); + DEBUG(FRESCAN_BWRES_REQUESTS_ENABLE_DEBUG, "request id:%d\n", req); *data = &the_requests_pool[req].request_data; return 0; } /** - * frescan_requests_enqueue() + * frescan_bwres_requests_enqueue() * **/ -int frescan_requests_enqueue(frescan_request_id_t req) +int frescan_bwres_requests_enqueue(frescan_bwres_request_id_t req) { int err; err = fosa_mutex_lock(&requests_mutex); if (err != 0) return err; - DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG, + DEBUG(FRESCAN_BWRES_REQUESTS_ENABLE_DEBUG, "is list empty A? %d\n", list_empty(&the_requests_list.request_list)); list_add_tail(&the_requests_pool[req].request_list, &the_requests_list.request_list); - DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG, + DEBUG(FRESCAN_BWRES_REQUESTS_ENABLE_DEBUG, "is list empty B? %d\n", list_empty(&the_requests_list.request_list)); @@ -237,11 +237,11 @@ locked_error: } /** - * frescan_requestqueue_dequeue() + * frescan_bwres_requestqueue_dequeue() * **/ -int frescan_requests_dequeue(frescan_request_id_t *req) +int frescan_bwres_requests_dequeue(frescan_bwres_request_id_t *req) { int err; struct list_head *pos; @@ -250,15 +250,15 @@ int frescan_requests_dequeue(frescan_request_id_t *req) err = fosa_mutex_lock(&requests_mutex); if (err != 0) return err; - DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG, "entering\n"); + DEBUG(FRESCAN_BWRES_REQUESTS_ENABLE_DEBUG, "entering\n"); while (list_empty(&the_requests_list.request_list)) { err = fosa_cond_wait(&requests_cond, &requests_mutex); if (err != 0) goto locked_error; - DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG, "received signal\n"); + DEBUG(FRESCAN_BWRES_REQUESTS_ENABLE_DEBUG, "received signal\n"); } - DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG, "dequeueing a request\n"); + DEBUG(FRESCAN_BWRES_REQUESTS_ENABLE_DEBUG, "dequeueing a request\n"); list_for_each(pos, &the_requests_list.request_list) { request = list_entry(pos, struct request_t, request_list); @@ -269,7 +269,7 @@ int frescan_requests_dequeue(frescan_request_id_t *req) *req = request->pool_pos; - DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG, + DEBUG(FRESCAN_BWRES_REQUESTS_ENABLE_DEBUG, "is list empty now? %d\n", list_empty(&the_requests_list.request_list)); diff --git a/src_frescan/frescan_bwres_requests.h b/src_frescan/frescan_bwres_requests.h index 002dd91..207d325 100644 --- a/src_frescan/frescan_bwres_requests.h +++ b/src_frescan/frescan_bwres_requests.h @@ -67,81 +67,16 @@ #ifndef _FRESCAN_BWRES_REQUESTS_H_ #define _FRESCAN_BWRES_REQUESTS_H_ -#include -#include "frescan_bwres_robjs.h" // frescan_robj_id_t -#include "frescan_data.h" // frescan_ss_t +#include "frescan_types.h" -/** - * frescan_request_data_t - * - * This are the data contained in a request to perform the negotiation of - * contracts. - * - * @type: indicates the type of the request - * @contract: a pointer to the contract to (re)negotiate - * @ss: the local sporadic server ID - * @request_node: the node that performed the request - * @req: the request id of the SLAVE to identify the request in the reply - * @return_value: the value returned in a Reply (accepted or not) - * @final_values: the values for the ss after the negotiation - * @net: the network instance where this request belongs to - * @robj: a reply object to wait until a negotiation is completed - * - */ - -typedef uint16_t frescan_request_id_t; /* 0 .. MX_REQUESTS */ - -typedef enum { - FRESCAN_REQ_NEG = 0, // Negotiate a contract - FRESCAN_REQ_RENEG = 1, // Renegotiate a contract - FRESCAN_REQ_CANCEL = 2, // Cancel a contract - FRESCAN_REP_DEC_BUDGET = 3, // Mode Change B- - FRESCAN_REP_INC_BUDGET = 4, // Mode Change B+ - FRESCAN_REP_NEG = 5, // Reply to (Re)Negotiate a contract -} frescan_request_type_t; - -typedef enum { - FRESCAN_REQ_ACCEPTED = 0, // the (re)negotiation is accepted - FRESCAN_REQ_NOT_ACCEPTED = 1, // the (re)negotiation is not accepted -} frescan_request_retval_t; - -typedef struct { - frescan_request_type_t type; - frsh_contract_t *contract; - frescan_ss_t ss; - frescan_node_t request_node; - frescan_request_id_t req; - frescan_request_retval_t return_value; - frescan_server_params_t final_values; - frescan_network_t net; - frescan_robj_id_t robj; -} frescan_request_data_t; +extern int frescan_bwres_requests_init(int max_ceiling); +extern int frescan_bwres_requests_alloc(frescan_bwres_request_id_t *req); +extern int frescan_bwres_requests_free(frescan_bwres_request_id_t req); +extern int frescan_bwres_requests_enqueue(frescan_bwres_request_id_t req); +extern int frescan_bwres_requests_dequeue(frescan_bwres_request_id_t *req); /** - * frescan_requests_init() - initializes the requests - * - * This function must be called at initialization time, before the rest of - * functions of this module. - * - * @max_ceiling: the max priority of the threads using this module - */ - -extern int frescan_requests_init(int max_ceiling); - -/** - * frescan_requests_alloc() - allocates a request - */ - -extern int frescan_requests_alloc(frescan_request_id_t *req); - -/** - * frescan_requests_free() - frees a request - */ - -extern int frescan_requests_free(frescan_request_id_t req); - -/** - * frescan_requests_get_data() - gets the data of the request + * frescan_bwres_requests_get_data() - gets the data of the request * * @data: the data is obtained as a pointer an manipulated directly * accesing to the members of the structure. Note that this is @@ -149,19 +84,7 @@ extern int frescan_requests_free(frescan_request_id_t req); * will just access to the members of the struc directly */ -extern int frescan_requests_get_data(frescan_request_id_t req, - frescan_request_data_t **data); - -/** - * frescan_requests_enqueue() - enqueue a request - */ - -extern int frescan_requests_enqueue(frescan_request_id_t req); - -/** - * frescan_requests_dequeue() - dequeue a request - */ - -extern int frescan_requests_dequeue(frescan_request_id_t *req); +extern int frescan_bwres_requests_get_data(frescan_bwres_request_id_t req, + frescan_bwres_request_data_t **data); #endif // _FRESCAN_BWRES_REQUESTS_H_ diff --git a/src_frescan/frescan_bwres_robjs.c b/src_frescan/frescan_bwres_robjs.c index d2784da..cdf2915 100644 --- a/src_frescan/frescan_bwres_robjs.c +++ b/src_frescan/frescan_bwres_robjs.c @@ -93,7 +93,7 @@ struct replyobj_t { fosa_mutex_t mutex; }; -static struct replyobj_t the_reply_objects[FRESCAN_MX_REPLY_OBJECTS]; +static struct replyobj_t the_reply_objects[FRESCAN_BWRES_MX_REPLY_OBJECTS]; static freelist_t freelist; /** @@ -112,7 +112,7 @@ int frescan_bwres_robjs_init(int max_ceiling) err = fosa_mutex_init(&freelist_mutex, max_ceiling); if (err != 0) return err; - err = freelist_init(&freelist, FRESCAN_MX_REPLY_OBJECTS); + err = freelist_init(&freelist, FRESCAN_BWRES_MX_REPLY_OBJECTS); if (err != 0) return err; is_initialized = true; @@ -128,11 +128,11 @@ int frescan_bwres_robjs_init(int max_ceiling) * **/ -int frescan_bwres_robjs_alloc(frescan_robj_id_t *id, int ceiling) +int frescan_bwres_robjs_alloc(frescan_bwres_robj_id_t *id, int ceiling) { int err, pos; - DEBUG(FRESCAN_ROBJS_ENABLE_DEBUG, + DEBUG(FRESCAN_BWRES_ROBJS_ENABLE_DEBUG, "allocating reply object, is_initialized=%d\n", is_initialized); if (is_initialized == false) return -1; @@ -155,7 +155,7 @@ int frescan_bwres_robjs_alloc(frescan_robj_id_t *id, int ceiling) err = fosa_mutex_init(&the_reply_objects[pos].mutex, ceiling); if (err != 0) return err; - DEBUG(FRESCAN_ROBJS_ENABLE_DEBUG, + DEBUG(FRESCAN_BWRES_ROBJS_ENABLE_DEBUG, "reply object allocated, id=%d\n", *id); return 0; @@ -172,11 +172,11 @@ locked_error: * **/ -int frescan_bwres_robjs_free(frescan_robj_id_t id) +int frescan_bwres_robjs_free(frescan_bwres_robj_id_t id) { int err; - DEBUG(FRESCAN_ROBJS_ENABLE_DEBUG, + DEBUG(FRESCAN_BWRES_ROBJS_ENABLE_DEBUG, "free reply id=%d, is_initialized=%d\n", id, is_initialized); if (is_initialized == false) return -1; @@ -212,22 +212,22 @@ locked_error: * **/ -int frescan_bwres_robjs_signal(frescan_robj_id_t id) +int frescan_bwres_robjs_signal(frescan_bwres_robj_id_t id) { int err; - DEBUG(FRESCAN_ROBJS_ENABLE_DEBUG, + DEBUG(FRESCAN_BWRES_ROBJS_ENABLE_DEBUG, "is_initialized=%d\n", is_initialized); if (is_initialized == false) return -1; - DEBUG(FRESCAN_ROBJS_ENABLE_DEBUG, + DEBUG(FRESCAN_BWRES_ROBJS_ENABLE_DEBUG, "taking mutex of the reply id=%d\n", id); err = fosa_mutex_lock(&the_reply_objects[id].mutex); if (err != 0) return err; the_reply_objects[id].is_work_done = true; - DEBUG(FRESCAN_ROBJS_ENABLE_DEBUG, + DEBUG(FRESCAN_BWRES_ROBJS_ENABLE_DEBUG, "signal the cond variable\n"); err = fosa_cond_signal(&the_reply_objects[id].cond); if (err != 0) goto locked_error; @@ -250,7 +250,7 @@ locked_error: * **/ -int frescan_bwres_robjs_wait(frescan_robj_id_t id) +int frescan_bwres_robjs_wait(frescan_bwres_robj_id_t id) { int err; @@ -284,7 +284,7 @@ locked_error: * **/ -int frescan_bwres_robjs_timedwait(frescan_robj_id_t id, +int frescan_bwres_robjs_timedwait(frescan_bwres_robj_id_t id, const struct timespec *abstime) { int err; diff --git a/src_frescan/frescan_bwres_robjs.h b/src_frescan/frescan_bwres_robjs.h index 941735c..ceb0395 100644 --- a/src_frescan/frescan_bwres_robjs.h +++ b/src_frescan/frescan_bwres_robjs.h @@ -68,18 +68,14 @@ #ifndef _FRESCAN_BWRES_ROBJS_H_ #define _FRESCAN_BWRES_ROBJS_H_ -#include /* for timespec */ -#include "fosa_opaque_types.h" /* for FOSA_ETIMEDOUT */ - -typedef unsigned int frescan_robj_id_t; /* 0 .. MX_REPLY_OBJECTS-1 */ -#define FRESCAN_ETIMEDOUT FOSA_ETIMEDOUT +#include "frescan_types.h" extern int frescan_bwres_robjs_init(int max_ceiling); -extern int frescan_bwres_robjs_alloc(frescan_robj_id_t *id, int ceiling); -extern int frescan_bwres_robjs_free(frescan_robj_id_t id); -extern int frescan_bwres_robjs_signal(frescan_robj_id_t id); -extern int frescan_bwres_robjs_wait(frescan_robj_id_t id); -extern int frescan_bwres_robjs_timedwait(frescan_robj_id_t id, +extern int frescan_bwres_robjs_alloc(frescan_bwres_robj_id_t *id, int ceiling); +extern int frescan_bwres_robjs_free(frescan_bwres_robj_id_t id); +extern int frescan_bwres_robjs_signal(frescan_bwres_robj_id_t id); +extern int frescan_bwres_robjs_wait(frescan_bwres_robj_id_t id); +extern int frescan_bwres_robjs_timedwait(frescan_bwres_robj_id_t id, const struct timespec *abstime); #endif // _FRESCAN_BWRES_ROBJS_H_ diff --git a/src_frescan/frescan_bwres_threads.c b/src_frescan/frescan_bwres_threads.c index fed6212..38bcc21 100644 --- a/src_frescan/frescan_bwres_threads.c +++ b/src_frescan/frescan_bwres_threads.c @@ -69,6 +69,7 @@ #include "frescan_bwres_threads.h" #include "frescan_bwres_messages.h" #include "frescan_bwres_requests.h" +#include "frescan_bwres_robjs.h" #include "frescan_bwres_analysis.h" #include "frescan_bwres_mode_change.h" #include "frescan_config.h" @@ -76,6 +77,21 @@ #include "frescan_data.h" #include "frescan_servers.h" +static void *frescan_manager_thread(void *arg); +static void *frescan_acceptor_thread(void *arg); + +static void frescan_manager_gn_prepare_scenario + (frescan_bwres_sa_scenario_t *scenario, + frescan_bwres_request_data_t *req_data); + +static void frescan_manager_gn_restore_scenario + (frescan_bwres_sa_scenario_t *scenario, + frescan_bwres_request_data_t *req_data); + +static void frescan_manager_req_gn(frescan_bwres_request_data_t *req_data); +static void frescan_manager_rep_gn(frescan_bwres_request_data_t *req_data); +static void frescan_manager_req_mc(frescan_bwres_request_data_t *req_data); + /** * frescan_manager_thread_create() * @@ -83,8 +99,6 @@ * in a request queue for LOCAL or EXTERNAL requests. */ -static void *frescan_manager_thread(void *arg); - int frescan_manager_thread_create(frescan_network_t net) { int ret; @@ -93,10 +107,10 @@ int frescan_manager_thread_create(frescan_network_t net) ret = fosa_thread_attr_init(&attr); if (ret != 0) return ret; - ret = fosa_thread_attr_set_prio(&attr, FRESCAN_NEG_THREAD_PRIO); + ret = fosa_thread_attr_set_prio(&attr, FRESCAN_BWRES_NEG_THREAD_PRIO); if (ret != 0) return ret; - ret = fosa_thread_create(&the_networks[net].manager_thread_id, + ret = fosa_thread_create(&frescan_data[net].manager_thread_id, &attr, frescan_manager_thread, (void *)(uint32_t)net); @@ -115,8 +129,6 @@ int frescan_manager_thread_create(frescan_network_t net) * messages from the network and converting them into requests. */ -static void *frescan_acceptor_thread(void *arg); - int frescan_acceptor_thread_create(frescan_network_t net) { int ret; @@ -125,10 +137,10 @@ int frescan_acceptor_thread_create(frescan_network_t net) ret = fosa_thread_attr_init(&attr); if (ret != 0) return ret; - ret = fosa_thread_attr_set_prio(&attr, FRESCAN_ACCEPTOR_THREAD_PRIO); + ret = fosa_thread_attr_set_prio(&attr, FRESCAN_BWRES_ACCEPTOR_PRIO); if (ret != 0) return ret; - ret = fosa_thread_create(&the_networks[net].acceptor_thread_id, + ret = fosa_thread_create(&frescan_data[net].acceptor_thread_id, &attr, frescan_acceptor_thread, (void *)(uint32_t)net); @@ -144,54 +156,47 @@ int frescan_acceptor_thread_create(frescan_network_t net) * frescan_manager_thread */ -static void frescan_manager_neg(frescan_request_data_t *req_data); -static void frescan_manager_reneg(frescan_request_data_t *req_data); -static void frescan_manager_cancel(frescan_request_data_t *req_data); -static void frescan_manager_repneg(frescan_request_data_t *req_data); -static void frescan_manager_budget_change(frescan_request_data_t *req_data); - static void *frescan_manager_thread(void *arg) { int ret; - frescan_request_id_t req; - frescan_request_data_t *req_data; + frescan_bwres_request_id_t req; + frescan_bwres_request_data_t *req_data; frescan_network_t net = (uint32_t)arg; - DEBUG(FRESCAN_MANAGER_ENABLE_DEBUG, "manager thread starts\n"); + DEBUG(FRESCAN_BWRES_MANAGER_ENABLE_DEBUG, "manager thread starts\n"); while(1) { - DEBUG(FRESCAN_MANAGER_ENABLE_DEBUG, "wait for a request\n"); + DEBUG(FRESCAN_BWRES_MANAGER_ENABLE_DEBUG, "wait for a request\n"); - ret = frescan_requests_dequeue(&req); + ret = frescan_bwres_requests_dequeue(&req); assert(ret == 0); - ret = frescan_requests_get_data(req, &req_data); + ret = frescan_bwres_requests_get_data(req, &req_data); assert(ret == 0); switch(req_data->type) { - case FRESCAN_REQ_NEG: - frescan_manager_neg(req_data); - break; - case FRESCAN_REQ_RENEG: - frescan_manager_reneg(req_data); - break; - case FRESCAN_REQ_CANCEL: - frescan_manager_cancel(req_data); + case FRESCAN_BWRES_REQ_GN: + frescan_manager_req_gn(req_data); break; - case FRESCAN_REP_DEC_BUDGET: - case FRESCAN_REP_INC_BUDGET: - frescan_manager_budget_change(req_data); + case FRESCAN_BWRES_REP_GN: + frescan_manager_rep_gn(req_data); break; - case FRESCAN_REP_NEG: - frescan_manager_repneg(req_data); + case FRESCAN_BWRES_REQ_MC: + frescan_manager_req_mc(req_data); break; + case FRESCAN_BWRES_REQ_RES: + case FRESCAN_BWRES_REQ_RES_GET: + case FRESCAN_BWRES_REP_RES_GET: + case FRESCAN_BWRES_REQ_RES_SET: + case FRESCAN_BWRES_REQ_RES_COMMIT: + case FRESCAN_BWRES_REQ_RES_CANCEL: default: FRESCAN_ERROR("request type not supported\n"); assert(0); } - if(req_data->request_node != the_networks[net].local_node) { - ret = frescan_requests_free(req); // acceptor request + if(req_data->request_node != frescan_data[net].local_node) { + ret = frescan_bwres_requests_free(req); assert(ret == 0); } } @@ -204,16 +209,16 @@ static void *frescan_manager_thread(void *arg) static void *frescan_acceptor_thread(void *arg) { int ret; - frescan_request_id_t req; + frescan_bwres_request_id_t req; frescan_network_t net = (uint32_t)arg; - DEBUG(FRESCAN_ACCEPTOR_ENABLE_DEBUG, "acceptor thread starts\n"); + DEBUG(FRESCAN_BWRES_ACCEPTOR_ENABLE_DEBUG, "acceptor thread starts\n"); while(1) { ret = frescan_messages_recv_request(net, &req); assert(ret == 0); - ret = frescan_requests_enqueue(req); + ret = frescan_bwres_requests_enqueue(req); assert(ret == 0); } @@ -221,256 +226,200 @@ static void *frescan_acceptor_thread(void *arg) } /** - * frescan_manager_neg + * frescan_manager_req_gn */ -static void frescan_manager_neg(frescan_request_data_t *req_data) +static void frescan_manager_req_gn(frescan_bwres_request_data_t *req_data) { int ret; + frescan_node_t me; bool accepted; - frescan_sa_scenario_t *scenario; - - DEBUG(FRESCAN_MANAGER_ENABLE_DEBUG, "negotiation request\n"); - - scenario = &the_networks[req_data->net].scenario; + frescan_bwres_sa_scenario_t *scenario; - if (the_networks[req_data->net].local_node == FRESCAN_NEG_MASTER_NODE) { - DEBUG(FRESCAN_MANAGER_ENABLE_DEBUG, - "add contract to scenario\n"); + me = frescan_data[req_data->net].local_node; - ret = frescan_sa_add_contract - (scenario, - req_data->ss, - req_data->request_node, - req_data->contract); + if (me != FRESCAN_BWRES_MASTER_NODE) { + DEBUG(FRESCAN_BWRES_MANAGER_ENABLE_DEBUG, + "send gn req to master\n"); + ret = frescan_messages_send_request(req_data); assert(ret == 0); + return; + } - DEBUG(FRESCAN_MANAGER_ENABLE_DEBUG, - "perform sched analysis\n"); - - ret = frescan_sa_sched_test(scenario, &accepted); - assert(ret == 0); + scenario = &frescan_data[req_data->net].scenario; - if (accepted) { - DEBUG(FRESCAN_MANAGER_ENABLE_DEBUG, - "schedulable! distribute spare capacity\n"); + DEBUG(FRESCAN_BWRES_MANAGER_ENABLE_DEBUG, "prepare new scenario\n"); + frescan_manager_gn_prepare_scenario(scenario, req_data); - ret = frescan_sa_spare_capacity(scenario); - assert(ret == 0); + DEBUG(FRESCAN_BWRES_MANAGER_ENABLE_DEBUG, "perform sched analysis\n"); + ret = frescan_bwres_sa_sched_test(scenario, &accepted); + assert(ret == 0); - req_data->return_value = FRESCAN_REQ_ACCEPTED; + if (accepted) { + DEBUG(FRESCAN_BWRES_MANAGER_ENABLE_DEBUG, "ACCEPTED!\n"); + req_data->return_value = FRESCAN_BWRES_REQ_ACCEPTED; - DEBUG(FRESCAN_MANAGER_ENABLE_DEBUG, - "perform the mode change protocol!\n"); + DEBUG(FRESCAN_BWRES_MANAGER_ENABLE_DEBUG, + "spare capacity and mode change\n"); - ret = frescan_bwres_mode_change_protocol(req_data); - assert(ret == 0); + ret = frescan_bwres_sa_spare_capacity(scenario); + assert(ret == 0); - if (req_data->request_node == FRESCAN_NEG_MASTER_NODE) { - DEBUG(FRESCAN_MANAGER_ENABLE_DEBUG, - "signal local request\n"); - ret = frescan_bwres_robjs_signal - (req_data->robj); - assert(ret == 0); - } - } else { - DEBUG(FRESCAN_MANAGER_ENABLE_DEBUG, - "not schedulable!\n"); - - ret = frescan_sa_remove_contract - (scenario, - req_data->ss, - req_data->request_node); - assert(ret == 0); + ret = frescan_bwres_mode_change_protocol(req_data); + assert(ret == 0); + } else { + DEBUG(FRESCAN_BWRES_MANAGER_ENABLE_DEBUG, "FAILED!\n"); + req_data->return_value = FRESCAN_BWRES_REQ_NOT_ACCEPTED; + frescan_manager_gn_restore_scenario(scenario, req_data); + } - req_data->return_value = FRESCAN_REQ_NOT_ACCEPTED; - - if (req_data->request_node == FRESCAN_NEG_MASTER_NODE) { - DEBUG(FRESCAN_MANAGER_ENABLE_DEBUG, - "signal local request\n"); - ret = frescan_bwres_robjs_signal(req_data->robj); - assert(ret == 0); - } else { - DEBUG(FRESCAN_MANAGER_ENABLE_DEBUG, - "sending reply\n"); - req_data->type = FRESCAN_REP_NEG; - ret = frescan_messages_send_request(req_data); - assert(ret == 0); - } - } + if (req_data->request_node == me) { + DEBUG(FRESCAN_BWRES_MANAGER_ENABLE_DEBUG, "signal robj\n"); + ret = frescan_bwres_robjs_signal(req_data->robj); + assert(ret == 0); } else { - DEBUG(FRESCAN_MANAGER_ENABLE_DEBUG, - "send negotiation request to master\n"); + DEBUG(FRESCAN_BWRES_MANAGER_ENABLE_DEBUG, "send reply\n"); + req_data->type = FRESCAN_BWRES_REP_GN; ret = frescan_messages_send_request(req_data); assert(ret == 0); } } /** - * frescan_manager_reneg + * frescan_manager_gn_prepare_scenario */ -static void frescan_manager_reneg(frescan_request_data_t *req_data) +static void frescan_manager_gn_prepare_scenario + (frescan_bwres_sa_scenario_t *scenario, + frescan_bwres_request_data_t *req_data) { - int ret; - bool is_schedulable; - frsh_contract_t old_contract; - frescan_sa_scenario_t *scenario; - - DEBUG(FRESCAN_MANAGER_ENABLE_DEBUG, "renegotiation request\n"); - - scenario = &the_networks[req_data->net].scenario; + int ret, i; + frescan_server_params_t server_params; + + // NEG-GROUP + server_params.budget = 0; + server_params.period.tv_sec = 0; + server_params.period.tv_nsec = 0; + server_params.prio = 0; + + for(i=0; icontracts_to_neg->size; i++) { + ret = frescan_servers_create(req_data->net, + &server_params, + &req_data->ss_new->ss[i]); + assert(ret == 0); - if (the_networks[req_data->net].local_node == FRESCAN_NEG_MASTER_NODE) { - // scheduling analysis - ret = frescan_sa_update_contract + ret = frescan_bwres_sa_add_contract (scenario, - req_data->ss, + req_data->ss_new->ss[i], req_data->request_node, - req_data->contract, - &old_contract); + &req_data->contracts_to_neg->contracts[i]); assert(ret == 0); + } - DEBUG(FRESCAN_MANAGER_ENABLE_DEBUG, - "perform sched analysis\n"); - - ret = frescan_sa_sched_test(scenario, &is_schedulable); + // RENEG-GROUP + scenario->backup_contracts_to_reneg.size = + req_data->contracts_to_reneg->size; + + for(i=0; icontracts_to_reneg->size; i++) { + ret = frescan_bwres_sa_update_contract + (scenario, + req_data->ss_to_reneg->ss[i], + req_data->request_node, + &req_data->contracts_to_reneg->contracts[i], + &scenario->backup_contracts_to_reneg.contracts[i]); assert(ret == 0); + } - if (is_schedulable) { - DEBUG(FRESCAN_MANAGER_ENABLE_DEBUG, - "schedulable! distribute spare capacity\n"); - - ret = frescan_sa_spare_capacity(scenario); - assert(ret == 0); - - req_data->return_value = FRESCAN_REQ_ACCEPTED; - - DEBUG(FRESCAN_MANAGER_ENABLE_DEBUG, - "perform the mode change protocol!\n"); + // CANCEL-GROUP + scenario->backup_contracts_to_cancel.size = + req_data->ss_to_cancel->size; - ret = frescan_bwres_mode_change_protocol(req_data); - assert(ret == 0); - } else { - ret = frescan_sa_update_contract - (scenario, - req_data->ss, - req_data->request_node, - &old_contract, - NULL); - assert(ret == 0); - req_data->return_value = FRESCAN_REQ_NOT_ACCEPTED; - } - - // signal or reply the results - if (req_data->request_node == FRESCAN_NEG_MASTER_NODE) { - DEBUG(FRESCAN_MANAGER_ENABLE_DEBUG, "master local\n"); - ret = frescan_bwres_robjs_signal(req_data->robj); - assert(ret == 0); - } - } else { - DEBUG(FRESCAN_MANAGER_ENABLE_DEBUG, - "send renegotiation request to master\n"); - ret = frescan_messages_send_request(req_data); + for(i=0; iss_to_cancel->size; i++) { + ret = frescan_bwres_sa_remove_contract + (scenario, + req_data->ss_to_cancel->ss[i], + req_data->request_node, + &scenario->backup_contracts_to_cancel.contracts[i]); assert(ret == 0); } } /** - * frescan_manager_cancel + * frescan_manager_gn_restore_scenario */ -static void frescan_manager_cancel(frescan_request_data_t *req_data) +static void frescan_manager_gn_restore_scenario + (frescan_bwres_sa_scenario_t *scenario, + frescan_bwres_request_data_t *req_data) { - int ret; - bool is_schedulable; - frescan_sa_scenario_t *scenario; - - DEBUG(FRESCAN_MANAGER_ENABLE_DEBUG, "cancel request\n"); + int ret, i; - scenario = &the_networks[req_data->net].scenario; - - if (the_networks[req_data->net].local_node == FRESCAN_NEG_MASTER_NODE) { - ret = frescan_sa_remove_contract + // NEG-GROUP + for(i=0; icontracts_to_neg->size; i++) { + ret = frescan_bwres_sa_remove_contract (scenario, - req_data->ss, - req_data->request_node); - assert(ret == 0); - - DEBUG(FRESCAN_MANAGER_ENABLE_DEBUG, - "assign priorities\n"); - - DEBUG(FRESCAN_MANAGER_ENABLE_DEBUG, - "perform sched analysis\n"); - - ret = frescan_sa_sched_test(scenario, &is_schedulable); + req_data->ss_new->ss[i], + req_data->request_node, + NULL); assert(ret == 0); - assert(is_schedulable == true); - - DEBUG(FRESCAN_MANAGER_ENABLE_DEBUG, - "redistribute spare capacity\n"); - - ret = frescan_sa_spare_capacity(scenario); + ret = frescan_servers_destroy(req_data->net, + req_data->ss_new->ss[i]); assert(ret == 0); + } - ret = frescan_bwres_mode_change_protocol(req_data); - assert(ret == 0); - } else { - DEBUG(FRESCAN_MANAGER_ENABLE_DEBUG, - "send cancel request to master\n"); - ret = frescan_messages_send_request(req_data); + // RENEG-GROUP + for(i=0; icontracts_to_reneg->size; i++) { + ret = frescan_bwres_sa_update_contract + (scenario, + req_data->ss_to_reneg->ss[i], + req_data->request_node, + &scenario->backup_contracts_to_reneg.contracts[i], + NULL); assert(ret == 0); } - if (req_data->request_node == the_networks[req_data->net].local_node) { - ret = frescan_bwres_robjs_signal(req_data->robj); + // CANCEL-GROUP + for(i=0; iss_to_cancel->size; i++) { + ret = frescan_bwres_sa_add_contract + (scenario, + req_data->ss_to_cancel->ss[i], + req_data->request_node, + &scenario->backup_contracts_to_cancel.contracts[i]); assert(ret == 0); } } /** - * frescan_manager_budget_change + * frescan_manager_rep_gn */ -static void frescan_manager_budget_change(frescan_request_data_t *req_data) +static void frescan_manager_rep_gn(frescan_bwres_request_data_t *req_data) { int ret; - frescan_sa_mode_change_type_t mode_change_type; - frescan_node_t me = the_networks[req_data->net].local_node; + frescan_bwres_request_data_t *orig_req_data; - DEBUG(FRESCAN_MANAGER_ENABLE_DEBUG, "budget change request\n"); + ret = frescan_bwres_requests_get_data(req_data->req, &orig_req_data); + assert(ret == 0); - if (req_data->type == FRESCAN_REP_INC_BUDGET) { - mode_change_type = FRESCAN_SA_BUDGET_INC; - } else { - mode_change_type = FRESCAN_SA_BUDGET_DEC; - } + DEBUG(FRESCAN_BWRES_MANAGER_ENABLE_DEBUG, + "reply to gn, return value:%d\n", req_data->return_value); + + orig_req_data->return_value = req_data->return_value; - ret = frescan_bwres_budget_change(req_data, - me, - mode_change_type); + ret = frescan_bwres_robjs_signal(orig_req_data->robj); assert(ret == 0); } /** - * frescan_manager_repneg + * frescan_manager_req_mc */ -static void frescan_manager_repneg(frescan_request_data_t *req_data) +static void frescan_manager_req_mc(frescan_bwres_request_data_t *req_data) { -// int ret; -// frescan_request_data_t *neg_req_data; -// -// DEBUG(FRESCAN_MANAGER_ENABLE_DEBUG, "reply to neg request\n"); -// -// ret = frescan_requests_get_data(req_data->req, &neg_req_data); -// assert(ret == 0); -// -// neg_req_data->return_value = req_data->return_value; -// neg_req_data->final_values = req_data->final_values; -// -// ret = frescan_bwres_robjs_signal(neg_req_data->robj); -// assert(ret == 0); + int ret; + ret = frescan_bwres_mode_change_local(req_data->net, + req_data->mode_change_type); + assert(ret == 0); } diff --git a/src_frescan/frescan_bwres_threads.h b/src_frescan/frescan_bwres_threads.h index 969a181..2657ad0 100644 --- a/src_frescan/frescan_bwres_threads.h +++ b/src_frescan/frescan_bwres_threads.h @@ -67,7 +67,7 @@ #ifndef _FRESCAN_BWRES_THREADS_H_ #define _FRESCAN_BWRES_THREADS_H_ -#include "frescan.h" +#include "frescan_types.h" /** * frescan_manager_thread_create() @@ -82,7 +82,8 @@ extern int frescan_manager_thread_create(frescan_network_t net); * frescan_acceptor_thread_create() * * This call creates the acceptor thread which will be waiting negotiation - * messages from the network and converting them into requests. + * messages from the network and converting them into EXTERNAL requests for + * the manager thread. */ extern int frescan_acceptor_thread_create(frescan_network_t net); diff --git a/src_frescan/frescan_config.h b/src_frescan/frescan_config.h index 6b13eea..45af923 100644 --- a/src_frescan/frescan_config.h +++ b/src_frescan/frescan_config.h @@ -80,22 +80,26 @@ #define FRESCAN_MX_PRIOS 32 #define FRESCAN_REPL_SIGNAL_NUM FOSA_SIGNAL_MIN + 10 // real-time signal #define FRESCAN_BACKGROUND_PRIO 0 -#define FRESCAN_MX_REPLY_OBJECTS 40 #define FRESCAN_REPL_THREAD_PRIO 60 -#define FRESCAN_NEG_THREAD_PRIO 50 -#define FRESCAN_MX_REQUESTS 40 -#define FRESCAN_NEG_MASTER_NODE 0 -#define FRESCAN_REPLY_OBJECTS_MX_CEILING 90 -#define FRESCAN_REQUESTS_MX_CEILING 90 -#define FRESCAN_BWRES_MX_PRIO 60 -#define FRESCAN_ACCEPTOR_THREAD_PRIO FRESCAN_NEG_THREAD_PRIO - 1 -#define FRESCAN_BWRES_NEG_MESSAGES_PRIO 8 -#define FRESCAN_NEG_CHANNEL 0 #define FRESCAN_MX_NODES 2 -#define FRESCAN_MX_CONTRACTS (FRESCAN_MX_NODES*FRESCAN_MX_IDS) #define FRESCAN_MX_REPL_OPS FRESCAN_MX_IDS*10 -#define FRESCAN_FRAME_TX_TIME_US 200 // measured transmission time of an 8byte frame +// Configuration values for FRESCAN_BWRES +#define FRESCAN_BWRES_MX_REPLY_OBJECTS 40 +#define FRESCAN_BWRES_MX_REQUESTS 40 +#define FRESCAN_BWRES_MASTER_NODE 0 +#define FRESCAN_BWRES_ROBJS_MX_CEILING 90 +#define FRESCAN_BWRES_REQ_MX_CEILING 90 +#define FRESCAN_BWRES_MX_PRIO 60 +#define FRESCAN_BWRES_NEG_THREAD_PRIO 50 +#define FRESCAN_BWRES_ACCEPTOR_PRIO FRESCAN_BWRES_NEG_THREAD_PRIO - 1 +#define FRESCAN_BWRES_NEG_MESSAGES_PRIO 8 +#define FRESCAN_BWRES_NEG_CHANNEL 0 +#define FRESCAN_BWRES_MX_CONTRACTS (FRESCAN_MX_NODES*FRESCAN_MX_IDS) +#define FRESCAN_BWRES_MAX_GROUP_OPS 5 + +// FRESCAN_FRAME_TX_TIME_US: measured transmission time of an 8byte frame +#define FRESCAN_FRAME_TX_TIME_US 200 #define FRESCAN_MLOCK_T unsigned #define FRESCAN_CREATE_LOCK(l) diff --git a/src_frescan/frescan_data.c b/src_frescan/frescan_data.c index b35c441..3679238 100644 --- a/src_frescan/frescan_data.c +++ b/src_frescan/frescan_data.c @@ -68,17 +68,8 @@ */ #include "frescan_data.h" -#include "frescan_debug.h" -frescan_network_data_t the_networks[FRESCAN_MX_NETWORKS]; -frescan_server_data_t the_servers_pool[FRESCAN_MX_NETWORKS][FRESCAN_MX_IDS]; -freelist_t the_servers_pool_freelist[FRESCAN_MX_NETWORKS]; -frescan_server_data_t the_active_servers[FRESCAN_MX_NETWORKS]; - -/** - * frescan_data_init() - init the data global variables - * - */ +frescan_network_data_t frescan_data[FRESCAN_MX_NETWORKS]; int frescan_data_init(int fd, frescan_init_params_t *params) { @@ -86,22 +77,22 @@ int frescan_data_init(int fd, frescan_init_params_t *params) frescan_prio_t prio; frescan_node_t src; - the_networks[params->net].fd = fd; - the_networks[params->net].local_node = params->node; - the_networks[params->net].last_packet = NULL; - the_networks[params->net].last_packet_prio = 0; + frescan_data[params->net].fd = fd; + frescan_data[params->net].local_node = params->node; + frescan_data[params->net].last_packet = NULL; + frescan_data[params->net].last_packet_prio = 0; - FRESCAN_CREATE_LOCK(&the_networks[params->net].lock); + FRESCAN_CREATE_LOCK(&frescan_data[params->net].lock); for(id=0; idnet].id_queues[src][id] = NULL; + frescan_data[params->net].id_queues[src][id] = NULL; } } for(prio=0; prionet].id_fp_queues[src][prio] = NULL; + frescan_data[params->net].id_fp_queues[src][prio] = NULL; } } diff --git a/src_frescan/frescan_data.h b/src_frescan/frescan_data.h index b4c0463..c035f98 100644 --- a/src_frescan/frescan_data.h +++ b/src_frescan/frescan_data.h @@ -70,231 +70,10 @@ #ifndef _MARTE_FRESCAN_DATA_H_ #define _MARTE_FRESCAN_DATA_H_ -#include // uint32_t -#include // sem_t -#include // struct timespec, timer_t -#include "fosa_threads_and_signals.h" // fosa_thread_id_t - -#include // struct list_head -#include // freelist_t - -#include "frescan.h" // frescan_node_t, _prio_t, _budget_t +#include "frescan_types.h" // frescan_node_t, _prio_t, _budget_t #include "frescan_config.h" // FRESCAN_MLOCK_T, FRESCAN_MX_XXX -#include "frescan_packets.h" // frescan_packet_t - -#include "frsh.h" // for frsh_contract_t -#include "fsa.h" // for frsh_sa_scenario_t - -/** - * frescan_repl_op_t - a replenishment operation - * - * @when: when the replenishment operation is programmed at - * @amount: number of frames to add to the available budget - * @repl_list: to chain the replenishments for a certain sporadic server - * @pool_pos: to know how to free it from the replenishment pool - */ - -typedef struct { - struct timespec when; - frescan_budget_t amount; - struct list_head repl_list; - int pool_pos; -} frescan_repl_op_t; - -/** - * frescan_server_params_t - server parameters - * - * @budget: the budget in CAN 8-byte frames - * @period: the replenishment period for the server - * @prio: the priority of the server - */ - -typedef struct { - frescan_budget_t budget; - struct timespec period; - frescan_prio_t prio; -} frescan_server_params_t; - -/** - * frescan_server_data_t - server data - * - * @committed_params: the committed params (C,T,Prio) for the server - * @perceived_params: the params perceived by the user (we can lie to him) - * @current_priority: the current priority (0=background) - * @repl_list: the list of pending replenishment operations - * @repl_timer: the timer for the replenishments associated to this server - * NOTE: we could use a single timer for all but for now this is simpler - * @act_time: the last activation time for the server - * @packet_list: the packets enqueued on this server - * @servers_list: the list of servers - */ - -typedef struct { - frescan_server_params_t committed_params; - frescan_server_params_t perceived_params; - frescan_network_t net; - frescan_ss_t id; - frescan_prio_t current_priority; - frescan_budget_t pending_packets; - frescan_repl_op_t replenishments; - timer_t repl_timer; - struct timespec act_time; - frescan_packet_t packet_list; - struct list_head servers_list; -} frescan_server_data_t; - -/** - * the_servers_pool - pool of servers structure - */ - -extern frescan_server_data_t the_servers_pool[FRESCAN_MX_NETWORKS][FRESCAN_MX_IDS]; -extern freelist_t the_servers_pool_freelist[FRESCAN_MX_NETWORKS]; -extern frescan_server_data_t the_active_servers[FRESCAN_MX_NETWORKS]; - -/** - * frescan_sa_vres_t - a frescan vres - * - * @contract: the contract of the virtual resource - * @node: the node where the vres belongs to - * @ss: the sporadic server identifier - * @list: the list of vres. Note that this is the list of all the vres - * in the network instace. As this is a master-slave protocol the master - * knows everything about the contracts of the rest of nodes. - */ - -typedef enum { - FRESCAN_SA_PERIOD_DEC = 1<<5, - FRESCAN_SA_PERIOD_INC = 1<<4, - FRESCAN_SA_BUDGET_DEC = 1<<3, - FRESCAN_SA_BUDGET_INC = 1<<2, - FRESCAN_SA_PRIO_DEC = 1<<1, - FRESCAN_SA_PRIO_INC = 1 -} frescan_sa_mode_change_type_t; - -typedef struct { - frsh_contract_t contract; - frescan_node_t node; - frescan_ss_t ss; - frsh_sa_vres_id_t fsa_vres_global_id; - struct list_head list; - // mode change variables - frsh_sa_time_t old_c; - frsh_sa_time_t old_t; - frsh_sa_prio_t old_p; - frescan_sa_mode_change_type_t mode_change_type; - struct list_head mode_change_list; -} frescan_sa_vres_t; -/** - * frescan_sa_scenario_t - the scheduling analysis scenario - */ - -typedef struct { - frescan_prio_t max_prio; - frescan_prio_t min_prio; -} frescan_sa_init_params_t; - -typedef struct { - frescan_sa_init_params_t init_params; - frescan_sa_vres_t vres_pool[FRESCAN_MX_NODES][FRESCAN_MX_IDS]; - frescan_sa_vres_t vres_head; - freelist_t fsa_id_freelist; - frsh_sa_scenario_t fsa_scenario; -} frescan_sa_scenario_t; - -/** - * frescan_prio_queue_t - priority queue - * - * FRESCAN priority queues are implemented as an array of one 'fifo_queue' for - * each priority. Where the 'fifo_queues' are implemented using the - * 'struct list_head fifo_list;' field of each packet structure (Linux lists). - * - * So far mutual exclusion is achieved by disabling interrupts and - * synchronization is done using a semaphore. This is because the queues - * are accesed concurrently from user threads and the IRQ handler. - * - * @net: the network this priority queue belongs to (mainly for locking) - * @fifo_queues: an array of packets for each priority where each packet - * is just the head of a fifo_list. The array is allocated - * from the heap, using malloc, at initialization with range - * 0..max_prio-1 - * @max_prio: defines the number of priorities as (0 .. max_prio - 1) - * @sem: semaphore used for synchronization - */ - -typedef struct { - frescan_network_t net; - frescan_packet_t *fifo_queues; - uint32_t max_prio; - sem_t sem; -} frescan_prio_queue_t; - -/** - * frescan_queues_t - the set of FRESCAN queues for each instance of a protocol - * - * @tx_fp_queue: priority queue for the fixed priority packets - * @rx_channel_queues: a priority queue for each receiving channel - * - * TODO: add here the sporadic server queues... - */ - -typedef struct { - frescan_prio_queue_t *tx_fp_queue; - frescan_prio_queue_t **rx_channel_queues; - uint32_t num_rx_channels; -} frescan_queues_t; - -/** - * frescan_network_data_t - data for each network instance - * - * @local_node: the local node id for that network. The implementation does not - * support several interfaces for the same network. - * @fd: file descriptor associated to /dev/canXX - * @repl_thread_id: replenishment thread id - * @manager_thread_id: manager thread id - * @acceptor_thread_id: acceptor thread id - * @neg_messages_ss_id: sporadic server for negotiation messages - * @queues: the queues of this network instance - * @last_packet: pointer to the last packet from which a frame was inserted - * in the chip and its transmission is not complete. - * @last_packet_prio: prio of the packet in the buffer - * @id_queues: queues to store received packets while the whole message is - * not complete (fragmentation). (id = 0 .. FRESCAN_MX_IDS - 1) - * @id_fp_queues: the same as id_queues but for fp messages, which have - * id=FRESCAN_MX_IDS and are distinguised through their - * priorities. - * @scenario: the scheduling analysis scenario for the network - * - * the implementation can handle several FRESCAN networks at the same time - * in the same node, so we need a place to store its internal data. The data - * is allocated as an array where the index is the MINOR number (which also - * identifies the /dev/canx device for that network) - */ - -typedef struct { - FRESCAN_MLOCK_T lock; - frescan_node_t local_node; - int fd; - fosa_thread_id_t repl_thread_id; - fosa_thread_id_t manager_thread_id; - fosa_thread_id_t acceptor_thread_id; - frescan_ss_t neg_messages_ss_id; - frescan_queues_t queues; - frescan_packet_t *last_packet; - frescan_prio_t last_packet_prio; - frescan_packet_t *id_queues[FRESCAN_MX_NODES][FRESCAN_MX_IDS]; // TODO: alloc at init - frescan_packet_t *id_fp_queues[FRESCAN_MX_NODES][FRESCAN_MX_PRIOS]; // TODO: alloc at init - frescan_sa_scenario_t scenario; - struct list_head mode_change_budget_inc_list_head[FRESCAN_MX_NODES]; - struct list_head mode_change_budget_dec_list_head[FRESCAN_MX_NODES]; -} frescan_network_data_t; - -extern frescan_network_data_t the_networks[FRESCAN_MX_NETWORKS]; - -/** - * frescan_data_init() - init the data global variables - * - */ +extern frescan_network_data_t frescan_data[FRESCAN_MX_NETWORKS]; extern int frescan_data_init(int fd, frescan_init_params_t *params); diff --git a/src_frescan/frescan_debug.h b/src_frescan/frescan_debug.h index cb11efc..0f2222b 100644 --- a/src_frescan/frescan_debug.h +++ b/src_frescan/frescan_debug.h @@ -97,20 +97,21 @@ #define FRESCAN_QUEUES_ENABLE_DEBUG false #define FRESCAN_HW_BUFFER_ENABLE_DEBUG false #define FRESCAN_REPLENSH_ENABLE_DEBUG false -#define FRESCAN_ROBJS_ENABLE_DEBUG false -#define FRESCAN_BWRES_ENABLE_DEBUG true -#define FRESCAN_REQUESTS_ENABLE_DEBUG false -#define FRESCAN_MANAGER_ENABLE_DEBUG true -#define FRESCAN_ACCEPTOR_ENABLE_DEBUG false -#define FRESCAN_MODECHANGE_ENABLE_DEBUG true -#define FRESCAN_FNA_ENABLE_DEBUG false -#define FRESCAN_MESSAGES_ENABLE_DEBUG false -#define FRESCAN_SA_ENABLE_DEBUG false + +#define FRESCAN_BWRES_ENABLE_DEBUG false +#define FRESCAN_BWRES_ROBJS_ENABLE_DEBUG false +#define FRESCAN_BWRES_REQUESTS_ENABLE_DEBUG false +#define FRESCAN_BWRES_MANAGER_ENABLE_DEBUG false +#define FRESCAN_BWRES_ACCEPTOR_ENABLE_DEBUG false +#define FRESCAN_BWRES_MC_ENABLE_DEBUG false +#define FRESCAN_BWRES_FNA_ENABLE_DEBUG false +#define FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG false +#define FRESCAN_BWRES_SA_ENABLE_DEBUG false /** * MEASUREMENT FLAGS */ -#define FRESCAN_MEASURE_REPL_TH true +#define FRESCAN_MEASURE_REPL_TH false #define FRESCAN_MEASURE_REPL_PROGRAM false #endif // _MARTE_FRESCAN_DEBUG_H_ diff --git a/src_frescan/frescan_hw_buffer.c b/src_frescan/frescan_hw_buffer.c index 3608cf5..6fc886e 100644 --- a/src_frescan/frescan_hw_buffer.c +++ b/src_frescan/frescan_hw_buffer.c @@ -73,7 +73,7 @@ #include // memcpy -#include "frescan_data.h" // the_networks +#include "frescan_data.h" // frescan_data #include "frescan_debug.h" // DEBUG, FRESCAN_ERROR #include "frescan_servers.h" // frescan_servers_get_highest_prio #include "frescan_queues.h" // frescan_pqueue_xxx, frescan_servers_dequeue @@ -95,7 +95,7 @@ int frescan_hw_buffer_abort(frescan_network_t net) { int ret; - ret = ioctl(the_networks[net].fd, CAN_IOCTL_ABORT_FRAME, NULL); + ret = ioctl(frescan_data[net].fd, CAN_IOCTL_ABORT_FRAME, NULL); if (ret == -1) { FRESCAN_ERROR ("could not abort the frame\n"); return -1; @@ -126,7 +126,7 @@ int frescan_hw_buffer_update(frescan_network_t net) ret = frescan_servers_get_highest_prio(net, &id, &sprio); if (ret != 0) return ret; - pqueue = the_networks[net].queues.tx_fp_queue; + pqueue = frescan_data[net].queues.tx_fp_queue; ret = frescan_pqueue_get_highest_prio(pqueue, &packet, &fprio); if (ret != 0) return ret; @@ -152,10 +152,10 @@ int frescan_hw_buffer_update(frescan_network_t net) } prio = (is_fp_highest_prio) ? fprio : sprio; - is_frame_in_chip = (the_networks[net].last_packet != NULL); + is_frame_in_chip = (frescan_data[net].last_packet != NULL); if (is_frame_in_chip && - (prio > the_networks[net].last_packet_prio)) { + (prio > frescan_data[net].last_packet_prio)) { DEBUG(FRESCAN_HW_BUFFER_ENABLE_DEBUG,"abort frame\n"); ret = frescan_hw_buffer_abort(net); if (ret != 0) { @@ -194,8 +194,8 @@ int frescan_hw_buffer_update(frescan_network_t net) frescan_id_set_field (&packet->frame->id, FRESCAN_FIELD_FRAG_FLAG, frag_flag); - the_networks[net].last_packet = packet; - the_networks[net].last_packet_prio = prio; + frescan_data[net].last_packet = packet; + frescan_data[net].last_packet_prio = prio; DEBUG(FRESCAN_HW_BUFFER_ENABLE_DEBUG, "frame->id:0x%X pend_bytes:%u dlc:%u fflag:%u\n", @@ -204,7 +204,7 @@ int frescan_hw_buffer_update(frescan_network_t net) packet->frame->dlc, frag_flag); - ret = write(the_networks[net].fd, + ret = write(frescan_data[net].fd, (void *)packet->frame, sizeof(struct can_frame_t)); diff --git a/src_frescan/frescan_hw_buffer.h b/src_frescan/frescan_hw_buffer.h index e0c179f..d6eb2ca 100644 --- a/src_frescan/frescan_hw_buffer.h +++ b/src_frescan/frescan_hw_buffer.h @@ -72,7 +72,7 @@ #ifndef _MARTE_FRESCAN_HW_BUFFER_H_ #define _MARTE_FRESCAN_HW_BUFFER_H_ -#include "frescan.h" +#include "frescan_types.h" extern int frescan_hw_buffer_update(frescan_network_t net); diff --git a/src_frescan/frescan_packets.h b/src_frescan/frescan_packets.h index dc1c408..049a7b3 100644 --- a/src_frescan/frescan_packets.h +++ b/src_frescan/frescan_packets.h @@ -68,90 +68,13 @@ * */ -#ifndef _MARTE_FRESCAN_PACKETS_H_ -#define _MARTE_FRESCAN_PACKETS_H_ +#ifndef _FRESCAN_PACKETS_H_ +#define _FRESCAN_PACKETS_H_ -#include // struct timespec -#include // uint8_t ... -#include "frescan.h" // frescan_flags_t -#include // struct list_head -#include // can_frame_t - -/** - * frescan_packet_t - a frescan packet - * - * This structure is very important and it is used to store a FRESCAN packet. - * As we support fragmentation, a FRESCAN packet can be composed of several - * CAN frames. This 'frescan_packet_t' structure is used in two main cases: - * - * 1.- When we are sending data. In this case, the buffer pointers store the - * real data we want to sent and we use a 'buffer_read_pointer' to know - * how many bytes of the buffer we already sent. In 'frame', we store the - * last sent frame (with the corresponding CAN id fields). We will have - * to update the fragmentation fields as long as we send more packets. - * The 'fifo_list' is used to chained frescan packets of the same priority - * or that belong to the same sporadic server. Finally, 'flags', specify - * if we are sending ASYNC or SYNC. If we are sending SYNC the buffer - * pointers are pointing to the buffer sent by the user (zero copying), - * while if we use ASYNC, a copy of the data is done to the buffer. - * - * 2.- When we are receiving data, we only use 'frame' and 'fifo_list' fields. - * The IRQ handler of the chip allocates a CAN frame and calls to our hook. - * We store the pointer to that frame in 'frame' and we make a chain with - * frames of the same message (using the fragmentation fields). When we - * have all of them, we move the packet list to the corresponding - * receiving channel to wait for the user to perform a receive operation - * when we will copy the data and free both the packets and the frames. - * - * @flags: to know if the packet is to be sent SYNC or ASYNC, FP or SERVER... - * @frame: pointer to the last sent frame or the received frame - * @fifo_list: list to put several packets together - * @msg_list: list to put packets of the same message together - * @buffer_head: pointer to first byte of the buffer that is going to be sent - * @buffer_read_pointer: pointer to the part of the buffer being read - * @buffer_pending_bytes: bytes waiting to be sent - * @timestamp: time when the packet was enqueued (activation time) - * @pool_pos: position in the packets pool to know how to free it - * - * NOTE: the buffers could also be used on the receiving part to support - * sequential reads, instead of reading the whole message at once. - * - */ - -typedef struct { - frescan_flags_t flags; - struct can_frame_t *frame; - struct list_head fifo_list; - struct list_head msg_list; - uint8_t *buffer_head; // only for sending packets - uint8_t *buffer_read_pointer; // only for sending packets - uint32_t buffer_pending_bytes; // only for sending packets - struct timespec timestamp; - int pool_pos; -} frescan_packet_t; - -/** - * frescan_packets_init - * - * Initializes a pool of packets that will be managed internally - */ +#include "frescan_types.h" extern int frescan_packets_init(); - -/** - * frescan_packets_alloc - * - * Allocates a frame from the pool of packets. On error it returns NULL - */ - extern frescan_packet_t *frescan_packets_alloc(); - -/** - * frescan_packets_free - * - * Frees a frame and returns it to the pool of packets. - */ - extern int frescan_packets_free(frescan_packet_t *packet); -#endif // _MARTE_FRESCAN_PACKETS_H_ +#endif // _FRESCAN_PACKETS_H_ diff --git a/src_frescan/frescan_queues.c b/src_frescan/frescan_queues.c index 2206cd6..fc29e59 100644 --- a/src_frescan/frescan_queues.c +++ b/src_frescan/frescan_queues.c @@ -76,6 +76,7 @@ #include "frescan_packets.h" #include "frescan_debug.h" #include "frescan_id.h" +#include "frescan_data.h" /** * frescan_pqueue_create() - creates a priority queue @@ -260,7 +261,7 @@ int frescan_pqueue_dequeue(frescan_prio_queue_t *pqueue, // calls are made from a context with no interrupts (when updating // the buffer at 'frescan_hw_buffer_update' which is always called // with interrupts disabled) - if (blocking) FRESCAN_ACQUIRE_LOCK(&the_networks[pqueue->net].lock); + if (blocking) FRESCAN_ACQUIRE_LOCK(&frescan_data[pqueue->net].lock); for(prio=pqueue->max_prio-1; prio >= 0; prio--) { if (!list_empty(&pqueue->fifo_queues[prio].fifo_list)) { @@ -276,7 +277,7 @@ int frescan_pqueue_dequeue(frescan_prio_queue_t *pqueue, } } - if (blocking) FRESCAN_RELEASE_LOCK(&the_networks[pqueue->net].lock); + if (blocking) FRESCAN_RELEASE_LOCK(&frescan_data[pqueue->net].lock); DEBUG(FRESCAN_QUEUES_ENABLE_DEBUG, "dequeued prio %u\n", prio); *packet_prio = prio; @@ -332,7 +333,7 @@ int frescan_servers_enqueue(frescan_network_t net, frescan_ss_t id, frescan_packet_t *packet) { - frescan_server_data_t *server = &the_servers_pool[net][id]; + frescan_ss_data_t *server = &frescan_data[net].ss_data[id]; clock_gettime (CLOCK_MONOTONIC, &packet->timestamp); @@ -347,7 +348,7 @@ int frescan_servers_enqueue(frescan_network_t net, DEBUG(FRESCAN_SERVERS_ENABLE_DEBUG, "ss becomes active act_time=timestamp\n"); list_add_tail(&server->servers_list, - &the_active_servers[net].servers_list); + &frescan_data[net].ss_active_head.servers_list); server->act_time = packet->timestamp; } @@ -373,18 +374,18 @@ int frescan_servers_requeue(frescan_network_t net, // add the packet to the server fifo list list_add(&packet->fifo_list, - &the_servers_pool[net][id].packet_list.fifo_list); + &frescan_data[net].ss_data[id].packet_list.fifo_list); // if the server was inactive (no packets to send) put it active // (in the active list) - if (the_servers_pool[net][id].pending_packets == 0) { + if (frescan_data[net].ss_data[id].pending_packets == 0) { DEBUG(FRESCAN_SERVERS_ENABLE_DEBUG, "server was inactive, put in the active list\n"); - list_add(&the_servers_pool[net][id].servers_list, - &the_active_servers[net].servers_list); + list_add(&frescan_data[net].ss_data[id].servers_list, + &frescan_data[net].ss_active_head.servers_list); } - the_servers_pool[net][id].pending_packets++; + frescan_data[net].ss_data[id].pending_packets++; return 0; } @@ -404,9 +405,9 @@ int frescan_servers_dequeue(frescan_network_t net, frescan_prio_t *packet_prio) { struct list_head *pos; - frescan_server_data_t *server; + frescan_ss_data_t *server; - server = &the_servers_pool[net][id]; + server = &frescan_data[net].ss_data[id]; if (list_empty(&server->packet_list.fifo_list)) { FRESCAN_ERROR("no packet in server %d fifo list\n", id); diff --git a/src_frescan/frescan_queues.h b/src_frescan/frescan_queues.h index ffc9bb7..93fd58d 100644 --- a/src_frescan/frescan_queues.h +++ b/src_frescan/frescan_queues.h @@ -70,12 +70,7 @@ #ifndef _MARTE_FRESCAN_QUEUES_H_ #define _MARTE_FRESCAN_QUEUES_H_ -#include // uint8_t -#include // bool - -#include "frescan.h" // frescan_prio_t -#include "frescan_packets.h" // frescan_packet_t -#include "frescan_data.h" +#include "frescan_types.h" /** * frescan_queues_init() - initialize the queues diff --git a/src_frescan/frescan_servers.c b/src_frescan/frescan_servers.c index f1cc09d..8f8d3bf 100644 --- a/src_frescan/frescan_servers.c +++ b/src_frescan/frescan_servers.c @@ -71,6 +71,7 @@ #include "frescan_servers.h" #include "frescan_servers_replenishments.h" // frescan_replenishments_xxx #include "frescan_debug.h" +#include "frescan_packets.h" #include "frescan_data.h" #include #include @@ -89,11 +90,11 @@ int frescan_servers_init(frescan_network_t net) DEBUG(FRESCAN_SERVERS_ENABLE_DEBUG, "initializing servers\n"); - ret = freelist_init(&the_servers_pool_freelist[net], FRESCAN_MX_IDS); + ret = freelist_init(&frescan_data[net].ss_id_freelist, FRESCAN_MX_IDS); if (ret != 0) return ret; for (i=0; inet = net; server->id = *id; - server->committed_params = *params; + server->committed_params = *params; server->perceived_params = server->committed_params; server->current_priority = params->prio; - server->pending_packets = 0; + server->pending_packets = 0; // the first act_time is set to the server creation time clock_gettime (CLOCK_MONOTONIC, &server->act_time); @@ -191,7 +192,7 @@ int frescan_servers_set_perceived(frescan_network_t net, const frescan_server_params_t *params, frescan_ss_t id) { - the_servers_pool[net][id].perceived_params = *params; + frescan_data[net].ss_data[id].perceived_params = *params; return 0; } @@ -209,12 +210,12 @@ int frescan_servers_commit_perceived(frescan_network_t net, frescan_ss_t id) { int i, ret; - frescan_server_data_t *server; + frescan_ss_data_t *server; int budget_variation; - frescan_repl_op_t *repl; + frescan_repl_op_t *repl = NULL; struct list_head *pos; - server = &the_servers_pool[net][id]; + server = &frescan_data[net].ss_data[id]; budget_variation = server->perceived_params.budget - server->committed_params.budget; @@ -286,9 +287,9 @@ int frescan_servers_destroy(frescan_network_t net, frescan_ss_t id) int ret; frescan_repl_op_t *repl; frescan_packet_t *packet; - frescan_server_data_t *server; + frescan_ss_data_t *server; - server = &the_servers_pool[net][id]; + server = &frescan_data[net].ss_data[id]; ret = timer_delete (server->repl_timer); if (ret != 0) { @@ -317,10 +318,10 @@ int frescan_servers_destroy(frescan_network_t net, frescan_ss_t id) } INIT_LIST_HEAD(&server->replenishments.repl_list); - FRESCAN_ACQUIRE_LOCK(&the_networks[net].lock); + FRESCAN_ACQUIRE_LOCK(&frescan_data[net].lock); list_del(&server->servers_list); - ret = freelist_free(&the_servers_pool_freelist[net], id); - FRESCAN_RELEASE_LOCK(&the_networks[net].lock); + ret = freelist_free(&frescan_data[net].ss_id_freelist, id); + FRESCAN_RELEASE_LOCK(&frescan_data[net].lock); if (ret != 0) { FRESCAN_ERROR("could not free server data from pool\n"); @@ -343,7 +344,7 @@ int frescan_servers_get_data(frescan_network_t net, frescan_server_params_t *params, frescan_ss_t id) { - *params = the_servers_pool[net][id].perceived_params; + *params = frescan_data[net].ss_data[id].perceived_params; return 0; } @@ -369,10 +370,10 @@ int frescan_servers_get_current_budget(frescan_network_t net, { struct timespec now; frescan_repl_op_t *repl; - frescan_server_data_t *server; + frescan_ss_data_t *server; int count; - server = &the_servers_pool[net][id]; + server = &frescan_data[net].ss_data[id]; // first we get the current real budget in the capacity queue clock_gettime (CLOCK_MONOTONIC, &now); @@ -417,16 +418,17 @@ int frescan_servers_get_highest_prio(frescan_network_t net, frescan_ss_t *id, frescan_prio_t *prio) { - frescan_server_data_t *server; + frescan_ss_data_t *server; - if (list_empty(&the_active_servers->servers_list)) { + if (list_empty(&frescan_data[net].ss_active_head.servers_list)) { DEBUG(FRESCAN_SERVERS_ENABLE_DEBUG, "server list is empty\n"); *id = FRESCAN_MX_IDS; return 0; } *prio = 0; - list_for_each_entry(server, &the_active_servers[net].servers_list, + list_for_each_entry(server, + &frescan_data[net].ss_active_head.servers_list, servers_list) { if (server->current_priority >= *prio) { *id = server->id; @@ -461,9 +463,9 @@ int frescan_servers_frame_sent(frescan_network_t net, { int ret; struct timespec *repl_time; - frescan_server_data_t *server; + frescan_ss_data_t *server; - server = &the_servers_pool[net][id]; + server = &frescan_data[net].ss_data[id]; if (server->current_priority != FRESCAN_BACKGROUND_PRIO) { if (smaller_timespec(packet->timestamp, server->act_time)) { diff --git a/src_frescan/frescan_servers.h b/src_frescan/frescan_servers.h index 0ecaed8..0e967cb 100644 --- a/src_frescan/frescan_servers.h +++ b/src_frescan/frescan_servers.h @@ -71,9 +71,7 @@ #ifndef _MARTE_FRESCAN_SERVERS_H_ #define _MARTE_FRESCAN_SERVERS_H_ -#include "frescan.h" // frescan_prio_t, frescan_ss_t -#include "frescan_packets.h" // frescan_packet_t -#include "frescan_data.h" +#include "frescan_types.h" /** * frescan_servers_init() - initialize server structures diff --git a/src_frescan/frescan_servers_replenishments.c b/src_frescan/frescan_servers_replenishments.c index 3ae76ab..b2e75f4 100644 --- a/src_frescan/frescan_servers_replenishments.c +++ b/src_frescan/frescan_servers_replenishments.c @@ -136,7 +136,7 @@ static void *frescan_repl_thread(void *arg) siginfo_t siginfo; frescan_ss_t id; frescan_network_t net; - frescan_server_data_t *server; + frescan_ss_data_t *server; struct itimerspec timerdata; net = (frescan_network_t)(uint32_t)arg; @@ -164,7 +164,7 @@ static void *frescan_repl_thread(void *arg) siginfo.si_value.sival_int); // the server id id = siginfo.si_value.sival_int; - server = &the_servers_pool[net][id]; + server = &frescan_data[net].ss_data[id]; DEBUG(FRESCAN_REPLENSH_ENABLE_DEBUG, "id:%u current_prio:%u\n", id, server->current_priority); @@ -239,7 +239,7 @@ int frescan_replenishments_init(frescan_network_t net) return ret; } - ret = fosa_thread_create(&the_networks[net].repl_thread_id, + ret = fosa_thread_create(&frescan_data[net].repl_thread_id, &attr, frescan_repl_thread, (void *)(uint32_t)net); @@ -265,13 +265,13 @@ int frescan_replenishments_init(frescan_network_t net) */ int frescan_replenishment_program(frescan_network_t net, - frescan_ss_t ss, + frescan_ss_t id, const struct timespec *timestamp) { int ret; frescan_repl_op_t *repl = NULL; struct itimerspec timerdata; - frescan_server_data_t *server; + frescan_ss_data_t *server; struct list_head *pos; struct timespec now; @@ -280,7 +280,7 @@ int frescan_replenishment_program(frescan_network_t net, assert(ret == 0); #endif - server = &the_servers_pool[net][ss]; + server = &frescan_data[net].ss_data[id]; // extract the head list_for_each(pos, &server->replenishments.repl_list) { diff --git a/src_frescan/frescan_servers_replenishments.h b/src_frescan/frescan_servers_replenishments.h index abf2ddd..ecf2791 100644 --- a/src_frescan/frescan_servers_replenishments.h +++ b/src_frescan/frescan_servers_replenishments.h @@ -70,9 +70,7 @@ #ifndef _MARTE_FRESCAN_SERVERS_REPLENISHMENTS_H_ #define _MARTE_FRESCAN_SERVERS_REPLENISHMENTS_H_ -#include -#include "frescan.h" // frescan_network_t -#include "frescan_data.h" +#include "frescan_types.h" /** * frescan_replenishments_init - init the replenishment structures and thread @@ -97,10 +95,11 @@ extern int frescan_repl_op_free(frescan_repl_op_t *repl_op); * * @net: the network instance * @ss: the server + * @timestamp: timestamp */ extern int frescan_replenishment_program(frescan_network_t net, - frescan_ss_t ss, + frescan_ss_t id, const struct timespec *timestamp); #endif // _MARTE_FRESCAN_SERVERS_REPLENISHMENTS_H_ diff --git a/src_frescan/frescan_types.h b/src_frescan/frescan_types.h new file mode 100644 index 0000000..db5c819 --- /dev/null +++ b/src_frescan/frescan_types.h @@ -0,0 +1,500 @@ +/*! + * @file frescan_types.h + * + * @brief types used in FRESCAN + * + * @version 0.01 + * + * @date 16-Nov-2008 + * + * @author + * Daniel Sangorrin + * + * @comments + * + * This file contains the types used in FRESCAN protocol + * + * @license + * + * ----------------------------------------------------------------------- + * Copyright (C) 2006 - 2008 FRESCOR consortium partners: + * + * Universidad de Cantabria, SPAIN + * University of York, UK + * Scuola Superiore Sant'Anna, ITALY + * Kaiserslautern University, GERMANY + * Univ. Politécnica Valencia, SPAIN + * Czech Technical University in Prague, CZECH REPUBLIC + * ENEA SWEDEN + * Thales Communication S.A. FRANCE + * Visual Tools S.A. SPAIN + * Rapita Systems Ltd UK + * Evidence ITALY + * + * See http://www.frescor.org for a link to partners' websites + * + * FRESCOR project (FP6/2005/IST/5-034026) is funded + * in part by the European Union Sixth Framework Programme + * The European Union is not liable of any use that may be + * made of this code. + * + * This file is part of FRESCAN + * + * FRESCAN is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * FRESCAN is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * distributed with FRESCAN; see file COPYING. If not, write to the + * Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * As a special exception, including FRESCAN header files in a file, + * instantiating FRESCAN generics or templates, or linking other files + * with FRESCAN objects to produce an executable application, does not + * by itself cause the resulting executable application to be covered + * by the GNU General Public License. This exception does not + * however invalidate any other reasons why the executable file might be + * covered by the GNU Public License. + * ----------------------------------------------------------------------- + * + */ + +#ifndef _FRESCAN_TYPES_H_ +#define _FRESCAN_TYPES_H_ + +#include // uint8_t, uint32_t.. +#include // bool +#include // size_t +#include // struct timespec, timer_t +#include // sem_t + +#include "frsh.h" // for frsh_contract_t +#include "fsa.h" // for frsh_sa_scenario_t +#include "fosa_opaque_types.h" // for FOSA_ETIMEDOUT +#include "fosa_threads_and_signals.h" // fosa_thread_id_t +#include "frescan_config.h" + +#include // struct list_head +#include // can_frame_t +#include // freelist_t + +typedef uint8_t frescan_network_t; +typedef uint8_t frescan_node_t; +typedef uint8_t frescan_channel_t; +typedef uint8_t frescan_prio_t; +typedef uint8_t frescan_ss_t; +typedef uint32_t frescan_budget_t; + +typedef struct { + int size; + frescan_ss_t ss[FRESCAN_BWRES_MAX_GROUP_OPS]; +} frescan_ss_group_t; + +/** + * frescan_flags_t - frescan flags + * + * @FRESCAN_SS: send the message using sporadic servers + * @FRESCAN_FP: send the message using fixed priorities + * @FRESCAN_POLL: no buffer copy, only pointer and use the ID to poll status + * @FRESCAN_SYNC: no buffer copy, only pointer and block until it is sent + * @FRESCAN_ASYNC: use buffer copy and return immediately + */ + +typedef enum { + FRESCAN_SS = 1<<4, // sporadic server + FRESCAN_FP = 1<<3, // fixed priorities + FRESCAN_POLL = 1<<2, // polling + FRESCAN_SYNC = 1<<1, // synchronous + FRESCAN_ASYNC = 1 // asynchronous +} frescan_flags_t; + +/** + * frescan_send_params_t - send parameters + * + * @net: the network to use + * @to: the node where the message shoud be sent to + * @channel: the channel in 'to' where the message shoud be sent to + * @flags: the flags (see frescan_flags_t) + * @prio: the priority for the message if (flags & FRESCAN_FP) + * @ss: the sporadic server for the message if (flags & FRESCAN_SS) + */ + +typedef struct { + frescan_network_t net; + frescan_node_t to; + frescan_channel_t channel; + frescan_flags_t flags; + union { + frescan_prio_t prio; + frescan_ss_t ss; + }; +} frescan_send_params_t; + +/** + * frescan_recv_params_t - receive parameters + * + * @net: the network to use + * @channel: the channel from which we want to extract a message + * @flags: FRESCAN_SYNC/ASYNC + */ + +typedef struct { + frescan_network_t net; + frescan_channel_t channel; + frescan_flags_t flags; +} frescan_recv_params_t; + +/** + * frescan_init_params_t - initialization parameters + * + * @net: network to initialize (minor number ie: /dev/can0 -> 0) + * @node: set the local node identificator + * @tx_fp_max_prio: maximum number of priorities for the fixed priority + * transmission queues. (prio = 0 .. max_prio - 1) + * @rx_num_of_channels: number of rx channels (0 .. rx_num_of_channels - 1) + * @rx_channel_max_prio: array (range rx_num_of_channels) saying the number + * of priorities for each channel. If this parameter is + * NULL tx_fp_max_prio will be used for all queues. + */ + +typedef struct { + frescan_network_t net; + frescan_node_t node; + uint32_t tx_fp_max_prio; + uint32_t rx_num_of_channels; + uint32_t *rx_channel_max_prio; +} frescan_init_params_t; + +/** + * frescan_packet_t - a frescan packet + * + * This structure is very important and it is used to store a FRESCAN packet. + * As we support fragmentation, a FRESCAN packet can be composed of several + * CAN frames. This 'frescan_packet_t' structure is used in two main cases: + * + * 1.- When we are sending data. In this case, the buffer pointers store the + * real data we want to sent and we use a 'buffer_read_pointer' to know + * how many bytes of the buffer we already sent. In 'frame', we store the + * last sent frame (with the corresponding CAN id fields). We will have + * to update the fragmentation fields as long as we send more packets. + * The 'fifo_list' is used to chained frescan packets of the same priority + * or that belong to the same sporadic server. Finally, 'flags', specify + * if we are sending ASYNC or SYNC. If we are sending SYNC the buffer + * pointers are pointing to the buffer sent by the user (zero copying), + * while if we use ASYNC, a copy of the data is done to the buffer. + * + * 2.- When we are receiving data, we only use 'frame' and 'fifo_list' fields. + * The IRQ handler of the chip allocates a CAN frame and calls to our hook. + * We store the pointer to that frame in 'frame' and we make a chain with + * frames of the same message (using the fragmentation fields). When we + * have all of them, we move the packet list to the corresponding + * receiving channel to wait for the user to perform a receive operation + * when we will copy the data and free both the packets and the frames. + * + * @flags: to know if the packet is to be sent SYNC or ASYNC, FP or SERVER... + * @frame: pointer to the last sent frame or the received frame + * @fifo_list: list to put several packets together + * @msg_list: list to put packets of the same message together + * @buffer_head: pointer to first byte of the buffer that is going to be sent + * @buffer_read_pointer: pointer to the part of the buffer being read + * @buffer_pending_bytes: bytes waiting to be sent + * @timestamp: time when the packet was enqueued (activation time) + * @pool_pos: position in the packets pool to know how to free it + * + * NOTE: the buffers could also be used on the receiving part to support + * sequential reads, instead of reading the whole message at once. + * + */ + +typedef struct { + frescan_flags_t flags; + struct can_frame_t *frame; + struct list_head fifo_list; + struct list_head msg_list; + uint8_t *buffer_head; // only for sending packets + uint8_t *buffer_read_pointer; // only for sending packets + uint32_t buffer_pending_bytes; // only for sending packets + struct timespec timestamp; + int pool_pos; +} frescan_packet_t; + +/** + * frescan_repl_op_t - a replenishment operation + * + * @when: when the replenishment operation is programmed at + * @amount: number of frames to add to the available budget + * @repl_list: to chain the replenishments for a certain sporadic server + * @pool_pos: to know how to free it from the replenishment pool + */ + +typedef struct { + struct timespec when; + frescan_budget_t amount; + struct list_head repl_list; + int pool_pos; +} frescan_repl_op_t; + +/** + * frescan_server_params_t - server parameters + * + * @budget: the budget in CAN 8-byte frames + * @period: the replenishment period for the server + * @prio: the priority of the server + */ + +typedef struct { + frescan_budget_t budget; + struct timespec period; + frescan_prio_t prio; +} frescan_server_params_t; + +/** + * frescan_ss_data_t - sporadic server data + * + * @committed_params: the committed params (C,T,Prio) for the server + * @perceived_params: the params perceived by the user (we can lie to him) + * @current_priority: the current priority (0=background) + * @repl_list: the list of pending replenishment operations + * @repl_timer: the timer for the replenishments associated to this server + * NOTE: we could use a single timer for all but for now this is simpler + * @act_time: the last activation time for the server + * @packet_list: the packets enqueued on this server + * @servers_list: the list of servers + */ + +typedef struct { + frescan_server_params_t committed_params; + frescan_server_params_t perceived_params; + frescan_network_t net; + frescan_ss_t id; + frescan_prio_t current_priority; + frescan_budget_t pending_packets; + frescan_repl_op_t replenishments; // TODO: use struct list_head + timer_t repl_timer; + struct timespec act_time; + frescan_packet_t packet_list; // TODO: use struct list_head + struct list_head servers_list; +} frescan_ss_data_t; + +/** + * frescan_prio_queue_t - priority queue + * + * FRESCAN priority queues are implemented as an array of one 'fifo_queue' for + * each priority. Where the 'fifo_queues' are implemented using the + * 'struct list_head fifo_list;' field of each packet structure (Linux lists). + * + * So far mutual exclusion is achieved by disabling interrupts and + * synchronization is done using a semaphore. This is because the queues + * are accesed concurrently from user threads and the IRQ handler. + * + * @net: the network this priority queue belongs to (mainly for locking) + * @fifo_queues: an array of packets for each priority where each packet + * is just the head of a fifo_list. The array is allocated + * from the heap, using malloc, at initialization with range + * 0..max_prio-1 + * @max_prio: defines the number of priorities as (0 .. max_prio - 1) + * @sem: semaphore used for synchronization + */ + +typedef struct { + frescan_network_t net; + frescan_packet_t *fifo_queues; + uint32_t max_prio; + sem_t sem; +} frescan_prio_queue_t; + +/** + * frescan_queues_t - the set of FRESCAN queues for each instance of a protocol + * + * @tx_fp_queue: priority queue for the fixed priority packets + * @rx_channel_queues: a priority queue for each receiving channel + * + * TODO: add here the sporadic server queues... + */ + +typedef struct { + frescan_prio_queue_t *tx_fp_queue; + frescan_prio_queue_t **rx_channel_queues; + uint32_t num_rx_channels; +} frescan_queues_t; + + +// BWRES TYPES + +typedef unsigned int frescan_bwres_robj_id_t; /* 0 .. MX_REPLY_OBJECTS-1 */ +#define FRESCAN_ETIMEDOUT FOSA_ETIMEDOUT + +/** + * frescan_bwres_vres_t - a frescan virtual resource + * + * @contract: the contract of the virtual resource + * @node: the node where the vres belongs to + * @ss: the sporadic server identifier + * @list: the list of vres. Note that this is the list of all the vres + * in the network instace. As this is a master-slave protocol the master + * knows everything about the contracts of the rest of nodes. + */ + +typedef enum { + FRESCAN_BWRES_MC_PERIOD_DEC = 1<<5, + FRESCAN_BWRES_MC_PERIOD_INC = 1<<4, + FRESCAN_BWRES_MC_BUDGET_DEC = 1<<3, + FRESCAN_BWRES_MC_BUDGET_INC = 1<<2, + FRESCAN_BWRES_MC_PRIO_DEC = 1<<1, + FRESCAN_BWRES_MC_PRIO_INC = 1 +} frescan_bwres_mode_change_type_t; + +typedef struct { + frsh_contract_t contract; + frescan_node_t node; + frescan_ss_t ss; + frsh_sa_vres_id_t fsa_vres_global_id; + struct list_head list; + // mode change variables + frsh_sa_time_t old_c; + frsh_sa_time_t old_t; + frsh_sa_prio_t old_p; + frescan_bwres_mode_change_type_t mode_change_type; + struct list_head mode_change_list; +} frescan_bwres_vres_t; + +/** + * frescan_bwres_request_data_t + * + * This are the data contained in a request to perform the negotiation of + * contracts. + * + * @type: indicates the type of the request + * @contract: a contract to (re)negotiate + * @contract_ref: a pointer to the contract to (re)negotiate (optimization) + * @ss: the local sporadic server ID + * @request_node: the node that performed the request + * @req: the request id of the SLAVE to identify the request in the reply + * @return_value: the value returned in a Reply (accepted or not) + * @final_values: the values for the ss after the negotiation + * @net: the network instance where this request belongs to + * @robj: a reply object to wait until a negotiation is completed + * + */ + +typedef uint16_t frescan_bwres_request_id_t; /* 0 .. MX_REQUESTS */ + +typedef enum { + FRESCAN_BWRES_REQ_GN = 0, // group negotiation + FRESCAN_BWRES_REP_GN = 1, // negotiation reply + FRESCAN_BWRES_REQ_MC = 2, // mode change + FRESCAN_BWRES_REQ_RES = 3, // reservation negotiation + FRESCAN_BWRES_REQ_RES_GET = 4, // reservation get values + FRESCAN_BWRES_REP_RES_GET = 5, // reservation get values reply + FRESCAN_BWRES_REQ_RES_SET = 6, // reservation set values + FRESCAN_BWRES_REQ_RES_COMMIT = 7, // reservation commit + FRESCAN_BWRES_REQ_RES_CANCEL = 8, // reservation cancel +} frescan_bwres_request_type_t; + +typedef enum { + FRESCAN_BWRES_REQ_ACCEPTED = 0, // negotiation accepted + FRESCAN_BWRES_REQ_NOT_ACCEPTED = 1, // negotiation not accepted + FRESCAN_BWRES_REQ_ERROR = 2, // there was an error +} frescan_bwres_request_retval_t; + +typedef struct { + frescan_network_t net; + frescan_bwres_request_type_t type; + frescan_bwres_request_id_t req; + frescan_node_t request_node; + frescan_bwres_request_retval_t return_value; + frescan_bwres_robj_id_t robj; + // contracts and ss groups + frsh_contracts_group_t *contracts_to_neg; + frsh_contracts_group_t *contracts_to_reneg; + frescan_ss_group_t *ss_to_reneg; + frescan_ss_group_t *ss_to_cancel; + frescan_ss_group_t *ss_new; + // contracts and ss groups data (to store the info at master node) + frsh_contracts_group_t contracts_to_neg_data; + frsh_contracts_group_t contracts_to_reneg_data; + frescan_ss_group_t ss_to_reneg_data; + frescan_ss_group_t ss_to_cancel_data; + frescan_ss_group_t ss_new_data; + // for FRESCAN_BWRES_REQ_MC + frescan_bwres_mode_change_type_t mode_change_type; +} frescan_bwres_request_data_t; + +/** + * frescan_bwres_sa_scenario_t - the scheduling analysis scenario + */ + +typedef struct { + frescan_prio_t max_prio; + frescan_prio_t min_prio; +} frescan_bwres_sa_init_params_t; + +typedef struct { + frescan_bwres_sa_init_params_t init_params; + frescan_bwres_vres_t vres_pool[FRESCAN_MX_NODES][FRESCAN_MX_IDS]; + frescan_bwres_vres_t vres_head; // TODO: use struct list_head + freelist_t fsa_vres_global_id_freelist; + frsh_sa_scenario_t fsa_scenario; + frsh_contracts_group_t backup_contracts_to_reneg; + frsh_contracts_group_t backup_contracts_to_cancel; +} frescan_bwres_sa_scenario_t; + +/** + * frescan_network_data_t - data for each network instance + * + * @local_node: the local node id for that network. The implementation does not + * support several interfaces for the same network. + * @fd: file descriptor associated to /dev/canXX + * @repl_thread_id: replenishment thread id + * @manager_thread_id: manager thread id + * @acceptor_thread_id: acceptor thread id + * @neg_messages_ss_id: sporadic server for negotiation messages + * @queues: the queues of this network instance + * @last_packet: pointer to the last packet from which a frame was inserted + * in the chip and its transmission is not complete. + * @last_packet_prio: prio of the packet in the buffer + * @id_queues: queues to store received packets while the whole message is + * not complete (fragmentation). (id = 0 .. FRESCAN_MX_IDS - 1) + * @id_fp_queues: the same as id_queues but for fp messages, which have + * id=FRESCAN_MX_IDS and are distinguised through their + * priorities. + * @scenario: the scheduling analysis scenario for the network + * @mode_change_list: list of sa_vres that have changes to commit + * @mode_change_type: what type of changes are to commit + * + * the implementation can handle several FRESCAN networks at the same time + * in the same node, so we need a place to store its internal data. The data + * is allocated as an array where the index is the MINOR number (which also + * identifies the /dev/canx device for that network) + */ + +typedef struct { + FRESCAN_MLOCK_T lock; + frescan_node_t local_node; + int fd; + fosa_thread_id_t repl_thread_id; + frescan_packet_t *last_packet; + frescan_prio_t last_packet_prio; + frescan_queues_t queues; + frescan_packet_t *id_queues[FRESCAN_MX_NODES][FRESCAN_MX_IDS]; // TODO: alloc at init + frescan_packet_t *id_fp_queues[FRESCAN_MX_NODES][FRESCAN_MX_PRIOS]; // TODO: alloc at init + frescan_ss_data_t ss_data[FRESCAN_MX_IDS]; + freelist_t ss_id_freelist; + frescan_ss_data_t ss_active_head; // TODO: use struct list_head + // BWRES data + fosa_thread_id_t manager_thread_id; + fosa_thread_id_t acceptor_thread_id; + frescan_ss_t neg_messages_ss_id; + frescan_bwres_sa_scenario_t scenario; + struct list_head mode_change_list[FRESCAN_MX_NODES]; + frescan_bwres_mode_change_type_t mode_change_type[FRESCAN_MX_NODES]; +} frescan_network_data_t; + +#endif // _FRESCAN_TYPES_H_ -- 2.39.2