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