]> rtime.felk.cvut.cz Git - frescor/fna.git/blob - src_frescan/frescan_bwres_mode_change.c
0bfb7e989c9052c45689269e798521ee9d7b2930
[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
77 int frescan_bwres_budget_change(frescan_request_data_t *req_data,
78                                 frescan_node_t node,
79                                 frescan_sa_mode_change_type_t mode_change_type);
80
81 /**
82  * frescan_bwres_mode_change_protocol() - performs the mode change
83  *
84  * Follow the mode change protocol described in the paper.
85  *
86  */
87
88 int frescan_bwres_mode_change_protocol(frescan_request_data_t *req_data)
89 {
90         int ret, i;
91         frescan_node_t node;
92         frescan_sa_vres_t *vres;
93         frsh_sa_vres_data_t *sa_vres_data;
94         frsh_sa_time_t max_period_in_budget_dec;
95         frsh_sa_time_t max_period_in_budget_inc;
96         struct timespec start_timestamp, next_activation;
97
98         DEBUG(FRESCAN_MODECHANGE_ENABLE_DEBUG, "starting mode change\n");
99
100         for(node=0; node<FRESCAN_MX_NODES; node++) {
101                 INIT_LIST_HEAD(&the_networks[req_data->net].
102                                 mode_change_budget_inc_list_head[node]);
103
104                 INIT_LIST_HEAD(&the_networks[req_data->net].
105                                 mode_change_budget_dec_list_head[node]);
106         }
107
108         max_period_in_budget_dec = (frsh_sa_time_t)0;
109         max_period_in_budget_inc = (frsh_sa_time_t)0;
110
111         list_for_each_entry
112                         (vres,
113                          &the_networks[req_data->net].scenario.vres_head.list,
114                          list)
115         {
116                 sa_vres_data = &the_networks[req_data->net].
117                                 scenario.fsa_scenario.sa_vres_alloc
118                                                 [vres->fsa_vres_global_id];
119
120                 vres->mode_change_type = 0;
121
122                 if (sa_vres_data->c > vres->old_c) {
123                         vres->mode_change_type |= FRESCAN_SA_BUDGET_INC;
124
125                         if (sa_vres_data->t > max_period_in_budget_inc) {
126                                 max_period_in_budget_inc = sa_vres_data->t;
127                         }
128
129                         list_add_tail
130                             (&(vres->mode_change_list),
131                              &(the_networks[req_data->net].
132                                mode_change_budget_inc_list_head[vres->node]));
133                 } else if (sa_vres_data->c < vres->old_c) {
134                         vres->mode_change_type |= FRESCAN_SA_BUDGET_DEC;
135
136                         if (sa_vres_data->t > max_period_in_budget_dec) {
137                                 max_period_in_budget_dec = sa_vres_data->t;
138                         }
139
140                         list_add_tail
141                             (&(vres->mode_change_list),
142                              &(the_networks[req_data->net].
143                                mode_change_budget_dec_list_head[vres->node]));
144                 }
145
146                 if (sa_vres_data->t > vres->old_t) {
147                         vres->mode_change_type |= FRESCAN_SA_PERIOD_INC;
148                 } else if (sa_vres_data->t < vres->old_t) {
149                         vres->mode_change_type |= FRESCAN_SA_PERIOD_DEC;
150                 }
151
152                 if (sa_vres_data->p > vres->old_p) {
153                         vres->mode_change_type |= FRESCAN_SA_PRIO_INC;
154                 } else if (sa_vres_data->p < vres->old_p) {
155                         vres->mode_change_type |= FRESCAN_SA_PRIO_DEC;
156                 }
157
158                 vres->old_c = sa_vres_data->c;
159                 vres->old_t = sa_vres_data->t;
160                 vres->old_p = sa_vres_data->p;
161
162                 DEBUG(FRESCAN_MODECHANGE_ENABLE_DEBUG,
163                       "vres: %u type: %X budget_change: %s\n",
164                       vres->fsa_vres_global_id,
165                       vres->mode_change_type,
166                       ((vres->mode_change_type & FRESCAN_SA_BUDGET_INC) ==
167                        FRESCAN_SA_BUDGET_INC) ? "inc" : "dec");
168         }
169
170         // 1.- mode change for B- members
171         for(i=(FRESCAN_MX_NODES-1); i>=0; i--) {
172                 ret = frescan_bwres_budget_change(req_data,
173                                                   (frescan_node_t)i,
174                                                   FRESCAN_SA_BUDGET_DEC);
175                 if (ret != 0) return -1;
176         }
177
178         // 2.- wait the time needed to keep schedulability
179         ret = clock_gettime(CLOCK_MONOTONIC,
180                             &start_timestamp);
181         if (ret != 0) return -1;
182
183         add_timespec(next_activation,
184                      frsh_rel_time_to_timespec(frsh_sa_time_to_rel_time
185                                                 (max_period_in_budget_inc)),
186                      frsh_rel_time_to_timespec(frsh_sa_time_to_rel_time
187                                                 (max_period_in_budget_dec)));
188
189         incr_timespec(next_activation, start_timestamp);
190
191         ret = clock_nanosleep(CLOCK_MONOTONIC,
192                               TIMER_ABSTIME,
193                               &next_activation,
194                               NULL);
195         if (ret != 0) return -1;
196
197         // 3-. mode change for B+ members
198         for(i=(FRESCAN_MX_NODES-1); i>=0; i--) {
199                 ret = frescan_bwres_budget_change(req_data,
200                                                   (frescan_node_t)i,
201                                                   FRESCAN_SA_BUDGET_INC);
202                 if (ret != 0) return -1;
203         }
204
205         return 0;
206 }
207
208 int frescan_bwres_budget_change
209                 (frescan_request_data_t *req_data,
210                  frescan_node_t node,
211                  frescan_sa_mode_change_type_t mode_change_type)
212 {
213         int ret;
214         frescan_server_params_t server_params;
215         frescan_sa_vres_t *vres;
216         frescan_request_data_t tmp_req_data;
217         struct timespec start_timestamp, next_activation;
218         struct list_head *the_mode_change_list;
219         frescan_node_t me = the_networks[req_data->net].local_node;
220         bool is_increase;
221
222         is_increase = (mode_change_type & FRESCAN_SA_BUDGET_INC) ==
223                        FRESCAN_SA_BUDGET_INC;
224
225         DEBUG(FRESCAN_MODECHANGE_ENABLE_DEBUG,
226               "budget change node: %u (me: %u) type: '%s'\n",
227                node, me, is_increase ? "inc" : "dec");
228
229         if (is_increase) {
230                 the_mode_change_list = &the_networks[req_data->net].
231                                 mode_change_budget_inc_list_head[node];
232         } else {
233                 the_mode_change_list = &the_networks[req_data->net].
234                                 mode_change_budget_dec_list_head[node];
235         }
236
237         list_for_each_entry(vres, the_mode_change_list, mode_change_list)
238         {
239                 DEBUG(FRESCAN_MODECHANGE_ENABLE_DEBUG,
240                       "vres %u\n", vres->fsa_vres_global_id);
241
242                 server_params.budget = frsh_rel_time_to_usec(
243                                 frsh_sa_time_to_rel_time(vres->old_c)) /
244                                 FRESCAN_FRAME_TX_TIME_US;
245                 server_params.period = frsh_sa_time_to_rel_time(vres->old_t);
246                 server_params.prio   = vres->old_p;
247
248                 if (node == me) {
249                         if (is_increase) {
250                                 DEBUG(FRESCAN_MODECHANGE_ENABLE_DEBUG,
251                                       "Local: update server\n");
252                                 ret = frescan_servers_update(req_data->net,
253                                                              &server_params,
254                                                              vres->ss);
255                                 if (ret != 0) return ret;
256                         } else {
257                                 DEBUG(FRESCAN_MODECHANGE_ENABLE_DEBUG,
258                                       "Local: set perceived\n");
259                                 ret = frescan_servers_set_perceived
260                                      (req_data->net, &server_params, vres->ss);
261                                 if (ret != 0) return ret;
262                         }
263                 } else {
264                         if ((node == req_data->request_node) &&
265                             (vres->ss == req_data->ss)) {
266                                 DEBUG(FRESCAN_MODECHANGE_ENABLE_DEBUG,
267                                       "External: send reply to reneg\n");
268                                 req_data->type = FRESCAN_REP_NEG;
269                                 req_data->final_values = server_params;
270
271                                 ret = frescan_messages_send_request(req_data);
272                                 if (ret != 0) return -1;
273                         } else {
274                                 DEBUG(FRESCAN_MODECHANGE_ENABLE_DEBUG,
275                                       "External: send SC change update\n");
276                                 tmp_req_data.net  = req_data->net;
277                                 tmp_req_data.request_node = node;
278
279                                 if (is_increase) {
280                                         tmp_req_data.type =
281                                                         FRESCAN_REP_INC_BUDGET;
282                                 } else {
283                                         tmp_req_data.type =
284                                                         FRESCAN_REP_DEC_BUDGET;
285                                 }
286
287                                 ret = frescan_messages_send_request
288                                                                (&tmp_req_data);
289                                 if (ret != 0) return -1;
290                         }
291                 }
292         }
293
294         if (is_increase) return 0;
295
296         if (node == me) {
297                 ret = clock_gettime(CLOCK_MONOTONIC, &start_timestamp);
298                 if (ret != 0) return -1;
299
300                 list_for_each_entry
301                         (vres, the_mode_change_list, mode_change_list)
302                 {
303                         add_timespec(next_activation,
304                                      start_timestamp,
305                                      frsh_rel_time_to_timespec
306                                                 (frsh_sa_time_to_rel_time
307                                                         (vres->old_t)));
308
309                         ret = clock_nanosleep(CLOCK_MONOTONIC,
310                                               TIMER_ABSTIME,
311                                               &next_activation,
312                                               NULL);
313                         if (ret != 0) return -1;
314
315                         ret = frescan_servers_commit_perceived(req_data->net,
316                                                                vres->ss);
317                         if (ret != 0) return ret;
318                 }
319         }
320
321         return 0;
322 }