@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)
* 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
#include <drivers/can.h> // 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
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;
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");
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");
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,
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");
}
}
- 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");
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);
*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
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");
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) {
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;
}
}
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");
}
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 {
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);
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");
// 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) {
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);
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");
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) {
*
*/
-#ifndef _MARTE_FRESCAN_H_
-#define _MARTE_FRESCAN_H_
+#ifndef _FRESCAN_H_
+#define _FRESCAN_H_
-#include <stdint.h> // uint8_t
-#include <stdbool.h> // bool
-#include <unistd.h> // 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
frescan_node_t *from,
frescan_prio_t *prio);
-#endif // _MARTE_FRESCAN_H_
+#endif // _FRESCAN_H_
#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"
{
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;
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);
}
/**
- * 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");
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);
}
/**
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);
}
*
*/
-#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,
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_
#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;
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;
}
/**
- * 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;
}
/**
- * 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;
}
/**
- * 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;
}
/**
- * 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;
}
/**
- * 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;
#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)
* @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)
* 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_
#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 */
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");
// 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; i<ss_to_reneg.size; i++) {
+ ss_to_reneg.ss[i] =
+ (frescan_ss_t)vres_to_reneg->vres[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; i<ss_to_cancel.size; i++) {
+ ss_to_cancel.ss[i] =
+ (frescan_ss_t)vres_to_cancel->vres[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; i<new_vres->size; i++) {
+ new_vres->vres[i] = (fna_vres_id_t)ss_new.ss[i];
+ }
+ }
+
+ return 0;
+}
+
/**
* 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;
}
/**
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);
}
/**
(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);
}
/**
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);
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);
*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);
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;
}
*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));
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,
#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()
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; i<data->contracts_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; i<data->contracts_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; i<data->ss_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; i<data->contracts_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; i<data->contracts_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; i<data->ss_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;
}
*
*/
-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;
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;
}
*/
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],
&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;
}
}
#ifndef _FRESCAN_BWRES_MESSAGES_H_
#define _FRESCAN_BWRES_MESSAGES_H_
-#include <stdint.h>
-#include "frescan_bwres_requests.h"
-#include "frescan_data.h"
+#include "frescan_types.h"
/**
* frescan_messages_init() - initialization function for the module
*
*/
-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()
*/
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_
#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; node<FRESCAN_MX_NODES; node++) {
- INIT_LIST_HEAD(&the_networks[req_data->net].
- 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,
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; node<FRESCAN_MX_NODES; node++) {
+ if (node == FRESCAN_BWRES_MASTER_NODE) continue;
+
+ if ((frescan_data[net].mode_change_type[node] &
+ mode_change_type) != mode_change_type) continue;
+
+ DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG,
+ "send MC message to node:%u\n", node);
+
+ tmp_req_data.request_node = node;
+
+ ret = frescan_messages_send_request(&tmp_req_data);
if (ret != 0) return -1;
}
return 0;
}
-int frescan_bwres_budget_change
- (frescan_request_data_t *req_data,
- frescan_node_t node,
- frescan_sa_mode_change_type_t mode_change_type)
+/**
+ * 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.
+ */
+
+int frescan_bwres_mode_change_local
+ (frescan_network_t net,
+ frescan_bwres_mode_change_type_t mode_change_type)
{
int ret;
frescan_server_params_t server_params;
- frescan_sa_vres_t *vres;
- frescan_request_data_t tmp_req_data;
+ frescan_bwres_vres_t *vres;
struct timespec start_timestamp, next_activation;
- struct list_head *the_mode_change_list;
- frescan_node_t me = the_networks[req_data->net].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)) /
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;
#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_
**/
struct request_t {
- frescan_request_data_t request_data;
+ frescan_bwres_request_data_t request_data;
struct list_head request_list;
int pool_pos;
};
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;
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);
}
/**
- * 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;
}
/**
- * 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;
}
/**
- * 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));
}
/**
- * 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;
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);
*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));
#ifndef _FRESCAN_BWRES_REQUESTS_H_
#define _FRESCAN_BWRES_REQUESTS_H_
-#include <stdint.h>
-#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
* 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_
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;
/**
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;
*
**/
-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;
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;
*
**/
-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;
*
**/
-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;
*
**/
-int frescan_bwres_robjs_wait(frescan_robj_id_t id)
+int frescan_bwres_robjs_wait(frescan_bwres_robj_id_t id)
{
int err;
*
**/
-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;
#ifndef _FRESCAN_BWRES_ROBJS_H_
#define _FRESCAN_BWRES_ROBJS_H_
-#include <time.h> /* 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_
#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"
#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()
*
* 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;
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);
* 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;
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);
* 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);
}
}
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);
}
}
/**
- * 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; i<req_data->contracts_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; i<req_data->contracts_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; i<req_data->ss_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; i<req_data->contracts_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; i<req_data->contracts_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; i<req_data->ss_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);
}
#ifndef _FRESCAN_BWRES_THREADS_H_
#define _FRESCAN_BWRES_THREADS_H_
-#include "frescan.h"
+#include "frescan_types.h"
/**
* frescan_manager_thread_create()
* 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);
#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)
*/
#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)
{
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; id<FRESCAN_MX_IDS; id++) {
for(src=0; src<FRESCAN_MX_NODES; src++) {
- the_networks[params->net].id_queues[src][id] = NULL;
+ frescan_data[params->net].id_queues[src][id] = NULL;
}
}
for(prio=0; prio<FRESCAN_MX_PRIOS; prio++) {
for(src=0; src<FRESCAN_MX_NODES; src++) {
- the_networks[params->net].id_fp_queues[src][prio] = NULL;
+ frescan_data[params->net].id_fp_queues[src][prio] = NULL;
}
}
#ifndef _MARTE_FRESCAN_DATA_H_
#define _MARTE_FRESCAN_DATA_H_
-#include <stdint.h> // uint32_t
-#include <semaphore.h> // sem_t
-#include <time.h> // struct timespec, timer_t
-#include "fosa_threads_and_signals.h" // fosa_thread_id_t
-
-#include <misc/linux_list.h> // struct list_head
-#include <misc/freelist.h> // 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);
#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_
#include <string.h> // 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
{
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;
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;
}
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) {
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",
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));
#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);
*
*/
-#ifndef _MARTE_FRESCAN_PACKETS_H_
-#define _MARTE_FRESCAN_PACKETS_H_
+#ifndef _FRESCAN_PACKETS_H_
+#define _FRESCAN_PACKETS_H_
-#include <time.h> // struct timespec
-#include <stdint.h> // uint8_t ...
-#include "frescan.h" // frescan_flags_t
-#include <misc/linux_list.h> // struct list_head
-#include <drivers/can.h> // 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_
#include "frescan_packets.h"
#include "frescan_debug.h"
#include "frescan_id.h"
+#include "frescan_data.h"
/**
* frescan_pqueue_create() - creates a priority queue
// 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)) {
}
}
- 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;
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);
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;
}
// 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;
}
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);
#ifndef _MARTE_FRESCAN_QUEUES_H_
#define _MARTE_FRESCAN_QUEUES_H_
-#include <stdint.h> // uint8_t
-#include <stdbool.h> // 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
#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 <signal.h>
#include <time.h>
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; i<FRESCAN_MX_NETWORKS; i++) {
- INIT_LIST_HEAD(&the_active_servers[net].servers_list);
+ INIT_LIST_HEAD(&frescan_data[net].ss_active_head.servers_list);
}
ret = frescan_replenishments_init(net);
{
int i, ret, pos;
struct sigevent evp;
- frescan_server_data_t *server;
+ frescan_ss_data_t *server;
frescan_repl_op_t *repl;
- FRESCAN_ACQUIRE_LOCK(&the_networks[net].lock);
- pos = freelist_alloc(&the_servers_pool_freelist[net]);
- FRESCAN_RELEASE_LOCK(&the_networks[net].lock);
+ FRESCAN_ACQUIRE_LOCK(&frescan_data[net].lock);
+ pos = freelist_alloc(&frescan_data[net].ss_id_freelist);
+ FRESCAN_RELEASE_LOCK(&frescan_data[net].lock);
if (pos == -1) {
FRESCAN_ERROR("could not allocate servers\n");
*id = (frescan_ss_t)pos;
- server = &the_servers_pool[net][*id];
+ server = &frescan_data[net].ss_data[*id];
server->net = 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);
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;
}
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;
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) {
}
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");
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;
}
{
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);
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;
{
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)) {
#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
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;
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);
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);
*/
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;
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) {
#ifndef _MARTE_FRESCAN_SERVERS_REPLENISHMENTS_H_
#define _MARTE_FRESCAN_SERVERS_REPLENISHMENTS_H_
-#include <time.h>
-#include "frescan.h" // frescan_network_t
-#include "frescan_data.h"
+#include "frescan_types.h"
/**
* frescan_replenishments_init - init the replenishment structures and thread
*
* @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_
--- /dev/null
+/*!
+ * @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 <stdint.h> // uint8_t, uint32_t..
+#include <stdbool.h> // bool
+#include <unistd.h> // size_t
+#include <time.h> // struct timespec, timer_t
+#include <semaphore.h> // 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 <misc/linux_list.h> // struct list_head
+#include <drivers/can.h> // can_frame_t
+#include <misc/freelist.h> // 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_