#endif
fna_operations_t *fna_operations[FNA_MAX_NETWORKS] = {
-#ifdef UNIX_FNA_ENABLED
+#ifdef FRESCAN_FNA_ENABLED
&frescan_fna_operations,
#endif
#ifdef RTEP_FNA_ENABLED
* return value to say if the contract is admited or not, and the final
* values if it was admited
*
- * +----------------------------------------------+
- * | 'REPNEG' | REQ | RETURN_VALUE | FINAL_VALUES |
- * +----------------------------------------------+
+ * +-------------------------------------------+
+ * | 'REPNEG' | REQ | RET_VALUE | FINAL_VALUES | + FRESCAN_REP_INC/DEC_BUDGET
+ * +-------------------------------------------+
*
*/
repneg_msg->type = FRESCAN_REP_NEG;
repneg_msg->req = data->req;
repneg_msg->return_value = data->return_value;
- // TODO: use final values only if it was accepted!
repneg_msg->final_values = data->final_values;
+ if (data->return_value == FRESCAN_REQ_ACCEPTED) {
+ }
+
+
DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "type:%d req:%d ret:%d\n",
repneg_msg->type, repneg_msg->req, repneg_msg->return_value);
#include <misc/linux_list.h>
-static int frescan_bwres_budget_change(frescan_request_data_t *req_data,
+int frescan_bwres_budget_change(frescan_request_data_t *req_data,
frescan_node_t node,
frescan_sa_mode_change_type_t mode_change_type);
return 0;
}
-static int frescan_bwres_budget_change
+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_request_data_t tmp_req_data;
struct timespec start_timestamp, next_activation;
struct list_head *the_mode_change_list;
-
+ frescan_node_t me = the_networks[req_data->net].local_node;
if (mode_change_type == FRESCAN_SA_BUDGET_INC) {
the_mode_change_list = &the_networks[req_data->net].
server_params.period = frsh_sa_time_to_rel_time(vres->old_t);
server_params.prio = vres->old_p;
- if (node == FRESCAN_NEG_MASTER_NODE) {
+ if (node == me) {
if (mode_change_type == FRESCAN_SA_BUDGET_INC) {
- // Local: Update server
ret = frescan_servers_update(req_data->net,
&server_params,
vres->ss);
if (ret != 0) return ret;
} else {
- // Local: Change perceived allocation
ret = frescan_servers_set_perceived
- (req_data->net,
- &server_params,
- vres->ss);
+ (req_data->net, &server_params, vres->ss);
if (ret != 0) return ret;
}
} else {
} else {
// External: send SC change update
tmp_req_data.net = req_data->net;
- tmp_req_data.type = mode_change_type;
tmp_req_data.request_node = node;
+ if (mode_change_type == FRESCAN_SA_BUDGET_INC) {
+ 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;
if (mode_change_type == FRESCAN_SA_BUDGET_INC) return 0;
- if (node == FRESCAN_NEG_MASTER_NODE) {
+ if (node == me) {
ret = clock_gettime(CLOCK_MONOTONIC, &start_timestamp);
if (ret != 0) return -1;
#include "frescan_data.h"
#include "frescan_bwres_requests.h"
+/**
+ * frescan_bwres_budget_change() - performs the budget change
+ */
+
+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);
+
/**
* frescan_bwres_mode_change_protocol() - performs the mode change
- *
- * @net: the network (in)
*/
extern int frescan_bwres_mode_change_protocol(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)
{
case FRESCAN_REQ_CANCEL:
frescan_manager_cancel(req_data);
break;
+ case FRESCAN_REP_DEC_BUDGET:
+ case FRESCAN_REP_INC_BUDGET:
+ frescan_manager_budget_change(req_data);
+ break;
case FRESCAN_REP_NEG:
frescan_manager_repneg(req_data);
break;
}
/**
- * frescan_manager_repneg
+ * frescan_manager_budget_change
*/
-static void frescan_manager_repneg(frescan_request_data_t *req_data)
+static void frescan_manager_budget_change(frescan_request_data_t *req_data)
{
int ret;
- frescan_request_data_t *neg_req_data;
+ frescan_sa_mode_change_type_t mode_change_type;
+ frescan_node_t me = the_networks[req_data->net].local_node;
- DEBUG(FRESCAN_MANAGER_ENABLE_DEBUG, "reply to neg request\n");
+ DEBUG(FRESCAN_MANAGER_ENABLE_DEBUG, "budget change request\n");
- ret = frescan_requests_get_data(req_data->req, &neg_req_data);
+ if (req_data->type == FRESCAN_REP_INC_BUDGET) {
+ mode_change_type = FRESCAN_SA_BUDGET_INC;
+ } else {
+ mode_change_type = FRESCAN_SA_BUDGET_DEC;
+ }
+
+ ret = frescan_bwres_budget_change(req_data,
+ me,
+ mode_change_type);
assert(ret == 0);
+}
- neg_req_data->return_value = req_data->return_value;
- neg_req_data->final_values = req_data->final_values;
+/**
+ * frescan_manager_repneg
+ */
+
+static void frescan_manager_repneg(frescan_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);
- ret = frescan_bwres_robjs_signal(neg_req_data->robj);
- assert(ret == 0);
}
* frescan_repl_op_t - a replenishment operation
*
* @when: when the replenishment operation is programmed at
- * @amount: number of frames to add to the current_budget
+ * @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
*/
* frescan_server_data_t - server data
*
* @params: the fixed parameters (budget, period and priority)
- * @current_budget: the current available capacity
+ * @old_params: a copy of old params for the perceived-commit process
* @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
typedef struct {
frescan_server_params_t params;
+ frescan_server_params_t old_params;
frescan_network_t net;
frescan_ss_t id;
- frescan_budget_t current_budget;
frescan_prio_t current_priority;
frescan_budget_t pending_packets;
frescan_repl_op_t replenishments;
server->net = net;
server->id = *id;
server->params = *params;
- server->current_budget = params->budget;
server->current_priority = params->prio;
server->pending_packets = 0;
const frescan_server_params_t *params,
frescan_ss_t id)
{
- the_servers_pool[net][id].params = *params;
+ frescan_server_data_t *server;
+
+ server = &the_servers_pool[net][id];
+
+ server->old_params = server->params;
+ server->params = *params;
+
return 0;
}
/**
* frescan_servers_commit_perceived() - commit sporadic server perceived data
*
+ * Add or remove repl operations according to the budget change
+ *
* @net: the network instance
- * @params: the parameters for the server
* @id: the identificator for the server
*
*/
int frescan_servers_commit_perceived(frescan_network_t net,
frescan_ss_t id)
{
+ int i, ret;
+ frescan_server_data_t *server;
+ int budget_variation;
+ frescan_repl_op_t *repl;
+ struct list_head *pos;
-// typedef struct {
-// frescan_server_params_t params;
-// frescan_network_t net;
-// frescan_ss_t id;
-// frescan_budget_t current_budget;
-// 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;
-
- // TODO: remove or add replenishment operations
- ...
- return -1;
+ server = &the_servers_pool[net][id];
+ budget_variation = server->params.budget - server->old_params.budget;
+
+ if (budget_variation > 0) {
+ // we have more budget: add repl ops to the tail
+ for (i=0; i < budget_variation; i++) {
+ repl = frescan_repl_op_alloc();
+ repl->when = server->act_time; // TODO: check when!
+ repl->amount = 1;
+ list_add_tail(&repl->repl_list,
+ &server->replenishments.repl_list);
+ }
+ } else {
+ // we have less budget: remove repl ops from the tail
+ for (i=0; i > budget_variation; i--) {
+ list_for_each_prev(pos,
+ &server->replenishments.repl_list) {
+ repl = list_entry(pos,
+ frescan_repl_op_t,
+ repl_list);
+ break;
+ }
+ list_del(&repl->repl_list);
+
+ ret = frescan_repl_op_free(repl);
+ if (ret != 0) return ret;
+ }
+ }
+
+ return 0;
}
/**
int frescan_servers_destroy(frescan_network_t net, frescan_ss_t id)
{
int ret;
+ frescan_repl_op_t *repl;
+ frescan_packet_t *packet;
+ frescan_server_data_t *server;
- // TODO: free the replenishment operations and the packets for the
- // server.
+ server = &the_servers_pool[net][id];
- ret = timer_delete (the_servers_pool[net][id].repl_timer);
+ ret = timer_delete (server->repl_timer);
if (ret != 0) {
FRESCAN_ERROR("could not delete timer\n");
return ret;
}
- FRESCAN_ACQUIRE_LOCK(&the_networks[net].lock);
- list_del(&the_servers_pool[net][id].servers_list);
+ // remove packets associated to the server
+ if (!list_empty(&server->packet_list.fifo_list)) {
+ FRESCAN_WARNING("destroying a server with packets enqueued\n");
+ list_for_each_entry(packet,
+ &server->packet_list.fifo_list,
+ fifo_list) {
+ ret = frescan_packets_free(packet);
+ if (ret != 0) return ret;
+ }
+ INIT_LIST_HEAD(&server->packet_list.fifo_list);
+ }
+
+ // remove the servers replenishment capacity queue
+ list_for_each_entry(repl,
+ &server->replenishments.repl_list,
+ repl_list) {
+ ret = frescan_repl_op_free(repl);
+ if (ret != 0) return ret;
+ }
+ INIT_LIST_HEAD(&server->replenishments.repl_list);
+ FRESCAN_ACQUIRE_LOCK(&the_networks[net].lock);
+ list_del(&server->servers_list);
ret = freelist_free(&the_servers_pool_freelist[net], id);
FRESCAN_RELEASE_LOCK(&the_networks[net].lock);
+
if (ret != 0) {
FRESCAN_ERROR("could not free server data from pool\n");
return ret;
}
/**
- * frescan_servers_get_current_budget() - get the current sporadic server budget
+ * frescan_servers_get_current_budget() - get the current ss budget
*
* @net: the network instance
* @id: the identificator for the server
* @current_budget: the current budget of the server
*
+ * Traverse the capacity queue until we find a replenishment operation
+ * that was programmed for a time later than now.
+ *
*/
int frescan_servers_get_current_budget(frescan_network_t net,
frescan_ss_t id,
frescan_budget_t *current_budget)
{
- *current_budget = the_servers_pool[net][id].current_budget;
+ struct timespec now;
+ frescan_repl_op_t *repl;
+ frescan_server_data_t *server;
+
+ server = &the_servers_pool[net][id];
+
+ clock_gettime (CLOCK_MONOTONIC, &now);
+
+ *current_budget = 0;
+
+ list_for_each_entry(repl,
+ &server->replenishments.repl_list,
+ repl_list) {
+ if (smaller_timespec(now, repl->when)) break;
+ *current_budget = *current_budget + 1;
+ }
+
return 0;
}
} else {
repl_time = &packet->timestamp;
}
+
ret = frescan_replenishment_program(net, id, repl_time);
if (ret != 0) return -1;
}
#define NETWORK 0
-#define SENDER
+// #define SENDER
// #define ENABLE_LOGGING
#ifdef SENDER
--- /dev/null
+// mgcc test_frescan_servers_send_basic.c -L. -lfrescan -o mprogram_wifi2
+// mgcc test_frescan_servers_send_basic.c -DSENDER -L. -lfrescan -o mprogram_wifi1
+
+#include <stdio.h> // perror
+#include <stdlib.h> // exit
+#include <unistd.h> // sleep
+
+#include "frescan.h"
+#include "frescan_servers.h"
+
+#define PUT_ERROR(s) {perror (s); exit (-1);}
+
+#define NETWORK 0
+
+#define SENDER
+// #define ENABLE_LOGGING
+
+#ifdef SENDER
+
+#define LOCAL_NODE 0
+
+#ifdef ENABLE_LOGGING
+
+#include <drivers/console_switcher.h>
+#include <misc/logger.h>
+#include <assert.h>
+#define LOG_DEVICE LOG_ETHERNET
+
+#endif
+
+static void pause(){
+ char key;
+ printf(" press Enter...");
+ key = getchar();
+}
+
+int main ()
+{
+ int i, ret;
+ frescan_send_params_t params;
+ char msg[200];
+ int written;
+ frescan_init_params_t init_params;
+ frescan_server_params_t server_params, server_params_read;
+ frescan_budget_t current_budget;
+
+#ifdef ENABLE_LOGGING
+ ret = logger_init(LOG_DEVICE);
+ assert(ret == 0);
+ printf("Changing to membuffer console\n");
+ MEMBUFFER_CONSOLE_INIT();
+#endif
+
+ printf(">> Initializing FRESCAN\n");
+
+ init_params.net = NETWORK;
+ init_params.node = LOCAL_NODE;
+ init_params.tx_fp_max_prio = 10;
+ init_params.rx_num_of_channels = 5;
+ init_params.rx_channel_max_prio = NULL;
+
+ ret = frescan_init(&init_params);
+ if (ret != 0) PUT_ERROR ("could not init FRESCAN");
+
+ printf(">> Creating a Server\n");
+
+ server_params.budget = 3;
+ server_params.period.tv_sec = 3;
+ server_params.period.tv_nsec = 0;
+ server_params.prio = 4;
+
+ ret = frescan_servers_create(NETWORK,
+ &server_params,
+ ¶ms.ss);
+ if (ret != 0) PUT_ERROR ("could not create server");
+
+ printf(">> Getting data from Server\n");
+
+ ret = frescan_servers_get_data(NETWORK,
+ &server_params_read,
+ params.ss);
+ if (ret != 0) PUT_ERROR ("could not get data from server");
+
+ printf("params: C = %d\n T = (%d, %d) P = %d\n",
+ server_params_read.budget,
+ server_params_read.period.tv_sec,
+ server_params_read.period.tv_nsec,
+ server_params_read.prio);
+
+ printf(">> Getting current_budget from Server\n");
+
+ ret = frescan_servers_get_current_budget(NETWORK,
+ params.ss,
+ ¤t_budget);
+ if (ret != 0) PUT_ERROR ("could not get current_budget");
+
+ printf("current_budget = %d\n", current_budget);
+
+ printf(">> Enter in loop for sending packets\n");
+
+ params.net = NETWORK;
+ params.to = 1;
+ params.channel = 0;
+ params.flags = FRESCAN_SS | FRESCAN_ASYNC;
+
+ while(1) {
+ pause();
+ for (i=0; i<=2; i++) {
+ written = snprintf(msg, sizeof(msg),
+ "his number is: %d", i);
+
+ ret = frescan_send(¶ms, (uint8_t *)msg, written);
+ if (ret != 0) PUT_ERROR ("could not send message\n");
+ printf("SENT: %d\n", i);
+
+ ret = frescan_servers_get_current_budget
+ (NETWORK, params.ss, ¤t_budget);
+ if (ret != 0) PUT_ERROR ("could not get current_budget");
+ printf("current_budget = %d\n", current_budget);
+ }
+ pause();
+ ret = frescan_servers_get_current_budget
+ (NETWORK, params.ss, ¤t_budget);
+ if (ret != 0) PUT_ERROR ("could not get current_budget");
+ printf("current_budget = %d\n", current_budget);
+
+#ifdef ENABLE_LOGGING
+ while (logger_manual_call() > 0);
+#endif
+}
+
+ return 0;
+}
+
+#else
+
+#define LOCAL_NODE 1
+
+int main ()
+{
+ int ret;
+ frescan_recv_params_t params;
+ uint8_t msg[3000];
+ size_t recv_bytes;
+ frescan_node_t from;
+ frescan_init_params_t init_params;
+ frescan_prio_t prio;
+
+ init_params.net = NETWORK;
+ init_params.node = LOCAL_NODE;
+ init_params.tx_fp_max_prio = 10;
+ init_params.rx_num_of_channels = 5;
+ init_params.rx_channel_max_prio = NULL;
+
+ ret = frescan_init(&init_params);
+ if (ret != 0) PUT_ERROR ("could not init FRESCAN");
+
+ printf("FRESCAN initialized\n");
+
+ params.net = NETWORK;
+ params.channel = 0;
+ params.flags = FRESCAN_SYNC;
+
+ while (1) {
+ printf("RECEIVING...\n");
+ ret = frescan_recv(¶ms, (uint8_t *)msg, sizeof(msg),
+ &recv_bytes, &from, &prio);
+ if (ret != 0) PUT_ERROR ("could not send message");
+
+ msg[recv_bytes] = '\0';
+ printf("RECEIVED: %s with prio:%u\n", msg, prio);
+
+// for (i=0; i<recv_bytes; i++) {
+// printf("msg[%d] = 0x%X;\n", i, msg[i]);
+// }
+ }
+
+ return 0;
+}
+
+#endif
--- /dev/null
+// mgcc test_frescan_servers_send_basic.c -L. -lfrescan -o mprogram_wifi2
+// mgcc test_frescan_servers_send_basic.c -DSENDER -L. -lfrescan -o mprogram_wifi1
+
+#include <stdio.h> // perror
+#include <stdlib.h> // exit
+#include <unistd.h> // sleep
+
+#include "frescan.h"
+#include "frescan_servers.h"
+
+#define PUT_ERROR(s) {perror (s); exit (-1);}
+
+#define NETWORK 0
+
+#define SENDER
+// #define ENABLE_LOGGING
+
+#ifdef SENDER
+
+#define LOCAL_NODE 0
+
+#ifdef ENABLE_LOGGING
+
+#include <drivers/console_switcher.h>
+#include <misc/logger.h>
+#include <assert.h>
+#define LOG_DEVICE LOG_ETHERNET
+
+#endif
+
+static void pause(){
+ char key;
+ printf(" press Enter...");
+ key = getchar();
+}
+
+int main ()
+{
+ int i, ret;
+ frescan_send_params_t params;
+ char msg[200];
+ int written;
+ frescan_init_params_t init_params;
+ frescan_server_params_t server_params;
+
+#ifdef ENABLE_LOGGING
+ ret = logger_init(LOG_DEVICE);
+ assert(ret == 0);
+ printf("Changing to membuffer console\n");
+ MEMBUFFER_CONSOLE_INIT();
+#endif
+
+ printf(">> Initializing FRESCAN\n");
+
+ init_params.net = NETWORK;
+ init_params.node = LOCAL_NODE;
+ init_params.tx_fp_max_prio = 10;
+ init_params.rx_num_of_channels = 5;
+ init_params.rx_channel_max_prio = NULL;
+
+ ret = frescan_init(&init_params);
+ if (ret != 0) PUT_ERROR ("could not init FRESCAN");
+
+ printf(">> Creating a Server\n");
+
+ server_params.budget = 3;
+ server_params.period.tv_sec = 3;
+ server_params.period.tv_nsec = 0;
+ server_params.prio = 4;
+
+ ret = frescan_servers_create(NETWORK,
+ &server_params,
+ ¶ms.ss);
+ if (ret != 0) PUT_ERROR ("could not create server");
+
+ printf(">> Destroy the Server\n");
+
+ ret = frescan_servers_destroy(NETWORK, params.ss);
+ if (ret != 0) PUT_ERROR ("could not destroy server");
+
+ printf(">> Creating a Server\n");
+
+ server_params.budget = 3;
+ server_params.period.tv_sec = 3;
+ server_params.period.tv_nsec = 0;
+ server_params.prio = 7;
+
+ ret = frescan_servers_create(NETWORK,
+ &server_params,
+ ¶ms.ss);
+ if (ret != 0) PUT_ERROR ("could not create server");
+
+ printf(">> Enter in loop for sending packets\n");
+
+ params.net = NETWORK;
+ params.to = 1;
+ params.channel = 0;
+ params.flags = FRESCAN_SS | FRESCAN_ASYNC;
+
+ while(1) {
+ pause();
+ for (i=0; i<=2; i++) {
+ written = snprintf(msg, sizeof(msg), "his number is: %d", i);
+ ret = frescan_send(¶ms, (uint8_t *)msg, written);
+ if (ret != 0) PUT_ERROR ("could not send message\n");
+ printf("SENT: %d\n", i);
+ }
+#ifdef ENABLE_LOGGING
+ while (logger_manual_call() > 0);
+#endif
+ }
+
+ return 0;
+}
+
+#else
+
+#define LOCAL_NODE 1
+
+int main ()
+{
+ int ret;
+ frescan_recv_params_t params;
+ uint8_t msg[3000];
+ size_t recv_bytes;
+ frescan_node_t from;
+ frescan_init_params_t init_params;
+ frescan_prio_t prio;
+
+ init_params.net = NETWORK;
+ init_params.node = LOCAL_NODE;
+ init_params.tx_fp_max_prio = 10;
+ init_params.rx_num_of_channels = 5;
+ init_params.rx_channel_max_prio = NULL;
+
+ ret = frescan_init(&init_params);
+ if (ret != 0) PUT_ERROR ("could not init FRESCAN");
+
+ printf("FRESCAN initialized\n");
+
+ params.net = NETWORK;
+ params.channel = 0;
+ params.flags = FRESCAN_SYNC;
+
+ while (1) {
+ printf("RECEIVING...\n");
+ ret = frescan_recv(¶ms, (uint8_t *)msg, sizeof(msg),
+ &recv_bytes, &from, &prio);
+ if (ret != 0) PUT_ERROR ("could not send message");
+
+ msg[recv_bytes] = '\0';
+ printf("RECEIVED: %s with prio:%u\n", msg, prio);
+
+// for (i=0; i<recv_bytes; i++) {
+// printf("msg[%d] = 0x%X;\n", i, msg[i]);
+// }
+ }
+
+ return 0;
+}
+
+#endif
#define NETWORK 0
-// #define SENDER
+#define SENDER
// #define ENABLE_LOGGING
#ifdef SENDER