2 * @file frescan_bwres_analysis.h
4 * @brief FRESCAN bandwith reservation layer: mode change protocol
10 * @author Daniel Sangorrin <daniel.sangorrin@unican.es>
14 * This module contains the mode change protocol
18 * -----------------------------------------------------------------------
19 * Copyright (C) 2006 - 2008 FRESCOR consortium partners:
21 * Universidad de Cantabria, SPAIN
22 * University of York, UK
23 * Scuola Superiore Sant'Anna, ITALY
24 * Kaiserslautern University, GERMANY
25 * Univ. Politécnica Valencia, SPAIN
26 * Czech Technical University in Prague, CZECH REPUBLIC
28 * Thales Communication S.A. FRANCE
29 * Visual Tools S.A. SPAIN
30 * Rapita Systems Ltd UK
33 * See http://www.frescor.org for a link to partners' websites
35 * FRESCOR project (FP6/2005/IST/5-034026) is funded
36 * in part by the European Union Sixth Framework Programme
37 * The European Union is not liable of any use that may be
40 * This file is part of FRESCAN
42 * FRESCAN is free software; you can redistribute it and/or modify
43 * it under the terms of the GNU General Public License as published by
44 * the Free Software Foundation; either version 2, or (at your option)
47 * FRESCAN is distributed in the hope that it will be useful, but
48 * WITHOUT ANY WARRANTY; without even the implied warranty of
49 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
50 * General Public License for more details.
52 * You should have received a copy of the GNU General Public License
53 * distributed with FRESCAN; see file COPYING. If not, write to the
54 * Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
57 * As a special exception, including FRESCAN header files in a file,
58 * instantiating FRESCAN generics or templates, or linking other files
59 * with FRESCAN objects to produce an executable application, does not
60 * by itself cause the resulting executable application to be covered
61 * by the GNU General Public License. This exception does not
62 * however invalidate any other reasons why the executable file might be
63 * covered by the GNU Public License.
64 * -----------------------------------------------------------------------
68 #include <misc/linux_list.h>
71 #include "frescan_data.h"
72 #include "frescan_servers.h"
73 #include "frescan_bwres_messages.h"
74 #include "frescan_bwres_mode_change.h"
75 #include "frescan_debug.h"
76 #include "frescan_config.h"
78 static int frescan_bwres_send_mc_messages
79 (frescan_network_t net,
80 frescan_bwres_mode_change_type_t mode_change_type);
83 * frescan_bwres_mode_change_protocol() - performs the mode change protocol
86 int frescan_bwres_mode_change_protocol(frescan_bwres_request_data_t *req_data)
90 frescan_bwres_vres_t *vres;
91 frsh_sa_vres_data_t *sa_vres_data;
92 frsh_sa_time_t max_period_in_budget_dec;
93 frsh_sa_time_t max_period_in_budget_inc;
94 struct timespec start_timestamp, next_activation;
96 DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG, "START MODE CHANGE PROTOCOL\n");
98 for(node=0; node<FRESCAN_MX_NODES; node++) {
99 INIT_LIST_HEAD(&frescan_data[req_data->net].
100 mode_change_list[node]);
102 frescan_data[req_data->net].mode_change_type[node] = 0;
105 max_period_in_budget_dec = (frsh_sa_time_t)0;
106 max_period_in_budget_inc = (frsh_sa_time_t)0;
108 DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG, "1.- adding vres to mc list\n");
112 &frescan_data[req_data->net].scenario.vres_head.list,
115 sa_vres_data = &frescan_data[req_data->net].
116 scenario.fsa_scenario.sa_vres_alloc
117 [vres->fsa_vres_global_id];
118 vres->mode_change_type = 0;
120 if (sa_vres_data->c > vres->old_c) {
121 vres->mode_change_type |= FRESCAN_BWRES_MC_BUDGET_INC;
122 if (sa_vres_data->t > max_period_in_budget_inc) {
123 max_period_in_budget_inc = sa_vres_data->t;
125 } else if (sa_vres_data->c < vres->old_c) {
126 vres->mode_change_type |= FRESCAN_BWRES_MC_BUDGET_DEC;
127 if (sa_vres_data->t > max_period_in_budget_dec) {
128 max_period_in_budget_dec = sa_vres_data->t;
132 if (sa_vres_data->t > vres->old_t) {
133 vres->mode_change_type |= FRESCAN_BWRES_MC_PERIOD_INC;
134 } else if (sa_vres_data->t < vres->old_t) {
135 vres->mode_change_type |= FRESCAN_BWRES_MC_PERIOD_DEC;
138 if (sa_vres_data->p > vres->old_p) {
139 vres->mode_change_type |= FRESCAN_BWRES_MC_PRIO_INC;
140 } else if (sa_vres_data->p < vres->old_p) {
141 vres->mode_change_type |= FRESCAN_BWRES_MC_PRIO_DEC;
144 if (vres->mode_change_type == 0) continue;
146 vres->old_c = sa_vres_data->c;
147 vres->old_t = sa_vres_data->t;
148 vres->old_p = sa_vres_data->p;
150 list_add_tail(&(vres->mode_change_list),
151 &(frescan_data[req_data->net].
152 mode_change_list[vres->node]));
154 frescan_data[req_data->net].mode_change_type[vres->node] |=
155 vres->mode_change_type;
157 DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG,
158 "vres:%u node:%u ss:%u mc_type:0x%X\n",
159 vres->fsa_vres_global_id, vres->node,
160 vres->ss, vres->mode_change_type);
163 DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG, "2.- Budget decrease\n");
165 ret = frescan_bwres_send_mc_messages(req_data->net,
166 FRESCAN_BWRES_MC_BUDGET_DEC);
167 if (ret != 0) return -1;
169 ret = frescan_bwres_mode_change_local(req_data->net,
170 FRESCAN_BWRES_MC_BUDGET_DEC);
171 if (ret != 0) return -1;
173 DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG, "3.- Wait max_period\n");
175 ret = clock_gettime(CLOCK_MONOTONIC, &start_timestamp);
176 if (ret != 0) return -1;
178 add_timespec(next_activation,
179 frsh_rel_time_to_timespec(frsh_sa_time_to_rel_time
180 (max_period_in_budget_inc)),
181 frsh_rel_time_to_timespec(frsh_sa_time_to_rel_time
182 (max_period_in_budget_dec)));
184 incr_timespec(next_activation, start_timestamp);
186 ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME,
187 &next_activation, NULL);
188 if (ret != 0) return -1;
190 DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG, "4.- Budget increase\n");
192 ret = frescan_bwres_send_mc_messages(req_data->net,
193 FRESCAN_BWRES_MC_BUDGET_INC);
194 if (ret != 0) return -1;
196 ret = frescan_bwres_mode_change_local(req_data->net,
197 FRESCAN_BWRES_MC_BUDGET_INC);
198 if (ret != 0) return -1;
204 * frescan_bwres_send_mc_messages()
206 * This function is executed at the master node to send mode change
207 * messages to the slaves
210 static int frescan_bwres_send_mc_messages
211 (frescan_network_t net,
212 frescan_bwres_mode_change_type_t mode_change_type)
216 frescan_bwres_request_data_t tmp_req_data;
218 tmp_req_data.net = net;
219 tmp_req_data.type = FRESCAN_BWRES_REQ_MC;
220 tmp_req_data.mode_change_type = mode_change_type;
222 for(node=0; node<FRESCAN_MX_NODES; node++) {
223 if (node == FRESCAN_BWRES_MASTER_NODE) continue;
225 if ((frescan_data[net].mode_change_type[node] &
226 mode_change_type) != mode_change_type) continue;
228 DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG,
229 "send MC message to node:%u\n", node);
231 tmp_req_data.request_node = node;
233 ret = frescan_messages_send_request(&tmp_req_data);
234 if (ret != 0) return -1;
241 * frescan_bwres_mode_change_local()
243 * This function updates local vres. When a slave receives a change mode
244 * message to change the values of any vres this function is called.
247 int frescan_bwres_mode_change_local
248 (frescan_network_t net,
249 frescan_bwres_mode_change_type_t mode_change_type)
252 frescan_server_params_t server_params;
253 frescan_bwres_vres_t *vres;
254 struct timespec start_timestamp, next_activation;
255 frescan_node_t me = frescan_data[net].local_node;
257 list_for_each_entry(vres,
258 &frescan_data[net].mode_change_list[me],
261 if ((vres->mode_change_type & mode_change_type) !=
262 mode_change_type) continue;
264 server_params.budget = frsh_rel_time_to_usec(
265 frsh_sa_time_to_rel_time(vres->old_c)) /
266 FRESCAN_FRAME_TX_TIME_US;
267 server_params.period = frsh_sa_time_to_rel_time(vres->old_t);
268 server_params.prio = vres->old_p;
270 if (mode_change_type == FRESCAN_BWRES_MC_BUDGET_INC) {
271 DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG,
272 "commit ss:%u\n", vres->ss);
273 ret = frescan_servers_update(net,
276 if (ret != 0) return ret;
278 DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG,
279 "set perceived ss:%u\n", vres->ss);
280 ret = frescan_servers_set_perceived(net,
283 if (ret != 0) return ret;
287 if (mode_change_type == FRESCAN_BWRES_MC_BUDGET_INC) return 0;
289 ret = clock_gettime(CLOCK_MONOTONIC, &start_timestamp);
290 if (ret != 0) return -1;
292 list_for_each_entry(vres,
293 &frescan_data[net].mode_change_list[me],
296 if ((vres->mode_change_type & mode_change_type) !=
297 mode_change_type) continue;
299 DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG,
300 "wait ss:%u period\n", vres->ss);
302 add_timespec(next_activation, start_timestamp,
303 frsh_rel_time_to_timespec(
304 frsh_sa_time_to_rel_time(vres->old_t)));
306 ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME,
307 &next_activation, NULL);
308 if (ret != 0) return -1;
310 DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG,
311 "commit ss:%u\n", vres->ss);
313 ret = frescan_servers_commit_perceived(net, vres->ss);
314 if (ret != 0) return ret;