]> rtime.felk.cvut.cz Git - frescor/fna.git/blob - src_frescan/frescan_bwres_mode_change.c
changes until i get bwres_negotiate_in_slave and in_master work... TODO: test more...
[frescor/fna.git] / src_frescan / frescan_bwres_mode_change.c
1 /*!
2  * @file frescan_bwres_analysis.h
3  *
4  * @brief FRESCAN bandwith reservation layer: mode change protocol
5  *
6  * @version 0.02
7  *
8  * @date 19-Jul-2008
9  *
10  * @author Daniel Sangorrin <daniel.sangorrin@unican.es>
11  *
12  * @comments
13  *
14  * This module contains the mode change protocol
15  *
16  * @license
17  *
18  * -----------------------------------------------------------------------
19  *  Copyright (C) 2006 - 2008 FRESCOR consortium partners:
20  *
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
27  *    ENEA                                   SWEDEN
28  *    Thales Communication S.A.              FRANCE
29  *    Visual Tools S.A.                      SPAIN
30  *    Rapita Systems Ltd                     UK
31  *    Evidence                               ITALY
32  *
33  *    See http://www.frescor.org for a link to partners' websites
34  *
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
38  *        made of this code.
39  *
40  *  This file is part of FRESCAN
41  *
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)
45  *  any later version.
46  *
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.
51  *
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
55  *  02111-1307, USA.
56  *
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  * -----------------------------------------------------------------------
65  *
66  */
67
68 #include <misc/linux_list.h>
69 #include <stdbool.h>
70
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"
77
78 static int frescan_bwres_send_mc_messages
79                         (frescan_network_t net,
80                          frescan_bwres_mode_change_type_t mode_change_type,
81                          frescan_ss_group_t *ss_to_cancel);
82
83 /**
84  * frescan_bwres_mode_change_protocol() - performs the mode change protocol
85  */
86
87 int frescan_bwres_mode_change_protocol(frescan_bwres_request_data_t *req_data)
88 {
89         int ret;
90         frescan_node_t node;
91         frescan_bwres_vres_t *vres;
92         frsh_sa_vres_data_t *sa_vres_data;
93         frsh_sa_time_t max_period_in_budget_dec;
94         frsh_sa_time_t max_period_in_budget_inc;
95         struct timespec start_timestamp, next_activation;
96
97         DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG, "START MODE CHANGE PROTOCOL\n");
98
99         for(node=0; node<FRESCAN_MX_NODES; node++) {
100                 INIT_LIST_HEAD(&frescan_data[req_data->net].
101                                                 mode_change_list[node]);
102
103                 frescan_data[req_data->net].mode_change_type[node] = 0;
104         }
105
106         max_period_in_budget_dec = (frsh_sa_time_t)0;
107         max_period_in_budget_inc = (frsh_sa_time_t)0;
108
109         DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG, "1.- adding vres to mc list\n");
110
111         list_for_each_entry
112                         (vres,
113                          &frescan_data[req_data->net].scenario.vres_head.list,
114                          list)
115         {
116                 sa_vres_data = &frescan_data[req_data->net].
117                                 scenario.fsa_scenario.sa_vres_alloc
118                                                 [vres->fsa_vres_global_id];
119                 vres->mode_change_type = 0;
120
121                 if ((vres->old_c == 0) &&
122                     (vres->old_t == 0) &&
123                     (vres->old_p == 0)) {
124                         //new vres (transmitted in the reply message)
125                         vres->old_c = sa_vres_data->c;
126                         vres->old_t = sa_vres_data->t;
127                         vres->old_p = sa_vres_data->p;
128                         continue;
129                 }
130
131                 if (sa_vres_data->c > vres->old_c) {
132                         vres->mode_change_type |= FRESCAN_BWRES_MC_BUDGET_INC;
133                         if (sa_vres_data->t > max_period_in_budget_inc) {
134                                 max_period_in_budget_inc = sa_vres_data->t;
135                         }
136                 } else if (sa_vres_data->c < vres->old_c) {
137                         vres->mode_change_type |= FRESCAN_BWRES_MC_BUDGET_DEC;
138                         if (sa_vres_data->t > max_period_in_budget_dec) {
139                                 max_period_in_budget_dec = sa_vres_data->t;
140                         }
141                 }
142
143                 if (sa_vres_data->t > vres->old_t) {
144                         vres->mode_change_type |= FRESCAN_BWRES_MC_PERIOD_INC;
145                 } else if (sa_vres_data->t < vres->old_t) {
146                         vres->mode_change_type |= FRESCAN_BWRES_MC_PERIOD_DEC;
147                 }
148
149                 if (sa_vres_data->p > vres->old_p) {
150                         vres->mode_change_type |= FRESCAN_BWRES_MC_PRIO_INC;
151                 } else if (sa_vres_data->p < vres->old_p) {
152                         vres->mode_change_type |= FRESCAN_BWRES_MC_PRIO_DEC;
153                 }
154
155                 if (vres->mode_change_type == 0) continue;
156
157                 vres->old_c = sa_vres_data->c;
158                 vres->old_t = sa_vres_data->t;
159                 vres->old_p = sa_vres_data->p;
160
161                 list_add_tail(&(vres->mode_change_list),
162                               &(frescan_data[req_data->net].
163                                         mode_change_list[vres->node]));
164
165                 frescan_data[req_data->net].mode_change_type[vres->node] |=
166                                 vres->mode_change_type;
167
168                 DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG,
169                       "vres:%u node:%u ss:%u mc_type:0x%X\n",
170                       vres->fsa_vres_global_id, vres->node,
171                       vres->ss, vres->mode_change_type);
172         }
173
174         DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG, "2.- Budget decrease\n");
175
176         ret = frescan_bwres_send_mc_messages(req_data->net,
177                                              FRESCAN_BWRES_MC_BUDGET_DEC,
178                                              req_data->ss_to_cancel);
179         if (ret != 0) return -1;
180
181         ret = frescan_bwres_mode_change_local(req_data->net,
182                                               FRESCAN_BWRES_MC_BUDGET_DEC,
183                                               req_data->ss_to_cancel);
184         if (ret != 0) return -1;
185
186         DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG, "3.- Wait max_period\n");
187
188         ret = clock_gettime(CLOCK_MONOTONIC, &start_timestamp);
189         if (ret != 0) return -1;
190
191         add_timespec(next_activation,
192                      frsh_rel_time_to_timespec(frsh_sa_time_to_rel_time
193                                                 (max_period_in_budget_inc)),
194                      frsh_rel_time_to_timespec(frsh_sa_time_to_rel_time
195                                                 (max_period_in_budget_dec)));
196
197         incr_timespec(next_activation, start_timestamp);
198
199         ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME,
200                               &next_activation, NULL);
201         if (ret != 0) return -1;
202
203         DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG, "4.- Budget increase\n");
204
205         ret = frescan_bwres_send_mc_messages(req_data->net,
206                                              FRESCAN_BWRES_MC_BUDGET_INC,
207                                              NULL);
208         if (ret != 0) return -1;
209
210         ret = frescan_bwres_mode_change_local(req_data->net,
211                                               FRESCAN_BWRES_MC_BUDGET_INC,
212                                               NULL);
213         if (ret != 0) return -1;
214
215         return 0;
216 }
217
218 /**
219  * frescan_bwres_send_mc_messages()
220  *
221  * This function is executed at the master node to send mode change
222  * messages to the slaves
223  */
224
225 static int frescan_bwres_send_mc_messages
226                         (frescan_network_t net,
227                          frescan_bwres_mode_change_type_t mode_change_type,
228                          frescan_ss_group_t *ss_to_cancel)
229 {
230         int ret;
231         frescan_node_t node;
232         frescan_bwres_request_data_t tmp_req_data;
233
234         tmp_req_data.net              = net;
235         tmp_req_data.type             = FRESCAN_BWRES_REQ_MC;
236         tmp_req_data.mode_change_type = mode_change_type;
237
238         for(node=0; node<FRESCAN_MX_NODES; node++) {
239                 if (node == FRESCAN_BWRES_MASTER_NODE) continue;
240
241                 if ((frescan_data[net].mode_change_type[node] &
242                      mode_change_type) != mode_change_type) continue;
243
244                 DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG,
245                       "send MC message to node:%u\n", node);
246
247                 tmp_req_data.request_node = node;
248                 tmp_req_data.ss_to_cancel = ss_to_cancel;
249
250                 ret = frescan_messages_send_request(&tmp_req_data);
251                 if (ret != 0) return -1;
252         }
253
254         return 0;
255 }
256
257 /**
258  * frescan_bwres_mode_change_local()
259  *
260  * This function updates local vres. When a slave receives a change mode
261  * message to change the values of any vres this function is called.
262  */
263
264 int frescan_bwres_mode_change_local
265                 (frescan_network_t net,
266                  frescan_bwres_mode_change_type_t mode_change_type,
267                  frescan_ss_group_t *ss_to_cancel)
268 {
269         int ret, i;
270         frescan_server_params_t server_params;
271         frescan_bwres_vres_t *vres;
272         struct timespec start_timestamp, next_activation;
273         frescan_node_t me = frescan_data[net].local_node;
274
275         list_for_each_entry(vres,
276                             &frescan_data[net].mode_change_list[me],
277                             mode_change_list)
278         {
279                 if ((vres->mode_change_type & mode_change_type) !=
280                      mode_change_type) continue;
281
282                 server_params.budget = frsh_rel_time_to_usec(
283                                 frsh_sa_time_to_rel_time(vres->old_c)) /
284                                 FRESCAN_FRAME_TX_TIME_US;
285                 server_params.period = frsh_sa_time_to_rel_time(vres->old_t);
286                 server_params.prio   = vres->old_p;
287
288                 if (mode_change_type == FRESCAN_BWRES_MC_BUDGET_INC) {
289                         DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG,
290                               "commit ss:%u\n", vres->ss);
291                         ret = frescan_servers_update(net,
292                                                      &server_params,
293                                                      vres->ss);
294                         if (ret != 0) return ret;
295                 } else {
296                         DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG,
297                               "set perceived ss:%u\n", vres->ss);
298                         ret = frescan_servers_set_perceived(net,
299                                                             &server_params,
300                                                             vres->ss);
301                         if (ret != 0) return ret;
302                 }
303         }
304
305         if (mode_change_type == FRESCAN_BWRES_MC_BUDGET_INC) return 0;
306
307         // for ss cancelled set the perceived capacity to cero
308         if (ss_to_cancel != NULL) {
309                 for(i=0; i<ss_to_cancel->size; i++) {
310                         server_params.budget = 0;
311                         server_params.period = frsh_usec_to_rel_time(0);
312                         server_params.prio   = 0;
313                         ret = frescan_servers_set_perceived
314                                                         (net,
315                                                         &server_params,
316                                                         ss_to_cancel->ss[i]);
317                         if (ret != 0) return ret;
318                 }
319         }
320
321         ret = clock_gettime(CLOCK_MONOTONIC, &start_timestamp);
322         if (ret != 0) return -1;
323
324         list_for_each_entry(vres,
325                             &frescan_data[net].mode_change_list[me],
326                             mode_change_list)
327         {
328                 if ((vres->mode_change_type & mode_change_type) !=
329                      mode_change_type) continue;
330
331                 DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG,
332                       "wait ss:%u period\n", vres->ss);
333
334                 add_timespec(next_activation, start_timestamp,
335                                 frsh_rel_time_to_timespec(
336                                        frsh_sa_time_to_rel_time(vres->old_t)));
337
338                 ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME,
339                                       &next_activation, NULL);
340                 if (ret != 0) return -1;
341
342                 DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG,
343                       "commit ss:%u\n", vres->ss);
344
345                 ret = frescan_servers_commit_perceived(net, vres->ss);
346                 if (ret != 0) return ret;
347         }
348
349         if (ss_to_cancel != NULL) {
350                 for(i=0; i<ss_to_cancel->size; i++) {
351                         ret = frescan_servers_destroy
352                                         (net, ss_to_cancel->ss[i]);
353                         if (ret != 0) return ret;
354                 }
355         }
356
357         return 0;
358 }