]> rtime.felk.cvut.cz Git - frescor/fna.git/blob - src_frescan/frescan_bwres_mode_change.c
add group negotiations to frescan and change all the requests and messages to map...
[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
82 /**
83  * frescan_bwres_mode_change_protocol() - performs the mode change protocol
84  */
85
86 int frescan_bwres_mode_change_protocol(frescan_bwres_request_data_t *req_data)
87 {
88         int ret;
89         frescan_node_t node;
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;
95
96         DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG, "START MODE CHANGE PROTOCOL\n");
97
98         for(node=0; node<FRESCAN_MX_NODES; node++) {
99                 INIT_LIST_HEAD(&frescan_data[req_data->net].
100                                                 mode_change_list[node]);
101
102                 frescan_data[req_data->net].mode_change_type[node] = 0;
103         }
104
105         max_period_in_budget_dec = (frsh_sa_time_t)0;
106         max_period_in_budget_inc = (frsh_sa_time_t)0;
107
108         DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG, "1.- adding vres to mc list\n");
109
110         list_for_each_entry
111                         (vres,
112                          &frescan_data[req_data->net].scenario.vres_head.list,
113                          list)
114         {
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;
119
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;
124                         }
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;
129                         }
130                 }
131
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;
136                 }
137
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;
142                 }
143
144                 if (vres->mode_change_type == 0) continue;
145
146                 vres->old_c = sa_vres_data->c;
147                 vres->old_t = sa_vres_data->t;
148                 vres->old_p = sa_vres_data->p;
149
150                 list_add_tail(&(vres->mode_change_list),
151                               &(frescan_data[req_data->net].
152                                         mode_change_list[vres->node]));
153
154                 frescan_data[req_data->net].mode_change_type[vres->node] |=
155                                 vres->mode_change_type;
156
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);
161         }
162
163         DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG, "2.- Budget decrease\n");
164
165         ret = frescan_bwres_send_mc_messages(req_data->net,
166                                              FRESCAN_BWRES_MC_BUDGET_DEC);
167         if (ret != 0) return -1;
168
169         ret = frescan_bwres_mode_change_local(req_data->net,
170                                               FRESCAN_BWRES_MC_BUDGET_DEC);
171         if (ret != 0) return -1;
172
173         DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG, "3.- Wait max_period\n");
174
175         ret = clock_gettime(CLOCK_MONOTONIC, &start_timestamp);
176         if (ret != 0) return -1;
177
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)));
183
184         incr_timespec(next_activation, start_timestamp);
185
186         ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME,
187                               &next_activation, NULL);
188         if (ret != 0) return -1;
189
190         DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG, "4.- Budget increase\n");
191
192         ret = frescan_bwres_send_mc_messages(req_data->net,
193                                              FRESCAN_BWRES_MC_BUDGET_INC);
194         if (ret != 0) return -1;
195
196         ret = frescan_bwres_mode_change_local(req_data->net,
197                                               FRESCAN_BWRES_MC_BUDGET_INC);
198         if (ret != 0) return -1;
199
200         return 0;
201 }
202
203 /**
204  * frescan_bwres_send_mc_messages()
205  *
206  * This function is executed at the master node to send mode change
207  * messages to the slaves
208  */
209
210 static int frescan_bwres_send_mc_messages
211                         (frescan_network_t net,
212                          frescan_bwres_mode_change_type_t mode_change_type)
213 {
214         int ret;
215         frescan_node_t node;
216         frescan_bwres_request_data_t tmp_req_data;
217
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;
221
222         for(node=0; node<FRESCAN_MX_NODES; node++) {
223                 if (node == FRESCAN_BWRES_MASTER_NODE) continue;
224
225                 if ((frescan_data[net].mode_change_type[node] &
226                      mode_change_type) != mode_change_type) continue;
227
228                 DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG,
229                       "send MC message to node:%u\n", node);
230
231                 tmp_req_data.request_node = node;
232
233                 ret = frescan_messages_send_request(&tmp_req_data);
234                 if (ret != 0) return -1;
235         }
236
237         return 0;
238 }
239
240 /**
241  * frescan_bwres_mode_change_local()
242  *
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.
245  */
246
247 int frescan_bwres_mode_change_local
248                 (frescan_network_t net,
249                  frescan_bwres_mode_change_type_t mode_change_type)
250 {
251         int ret;
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;
256
257         list_for_each_entry(vres,
258                             &frescan_data[net].mode_change_list[me],
259                             mode_change_list)
260         {
261                 if ((vres->mode_change_type & mode_change_type) !=
262                      mode_change_type) continue;
263
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;
269
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,
274                                                      &server_params,
275                                                      vres->ss);
276                         if (ret != 0) return ret;
277                 } else {
278                         DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG,
279                               "set perceived ss:%u\n", vres->ss);
280                         ret = frescan_servers_set_perceived(net,
281                                                             &server_params,
282                                                             vres->ss);
283                         if (ret != 0) return ret;
284                 }
285         }
286
287         if (mode_change_type == FRESCAN_BWRES_MC_BUDGET_INC) return 0;
288
289         ret = clock_gettime(CLOCK_MONOTONIC, &start_timestamp);
290         if (ret != 0) return -1;
291
292         list_for_each_entry(vres,
293                             &frescan_data[net].mode_change_list[me],
294                             mode_change_list)
295         {
296                 if ((vres->mode_change_type & mode_change_type) !=
297                      mode_change_type) continue;
298
299                 DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG,
300                       "wait ss:%u period\n", vres->ss);
301
302                 add_timespec(next_activation, start_timestamp,
303                                 frsh_rel_time_to_timespec(
304                                        frsh_sa_time_to_rel_time(vres->old_t)));
305
306                 ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME,
307                                       &next_activation, NULL);
308                 if (ret != 0) return -1;
309
310                 DEBUG(FRESCAN_BWRES_MC_ENABLE_DEBUG,
311                       "commit ss:%u\n", vres->ss);
312
313                 ret = frescan_servers_commit_perceived(net, vres->ss);
314                 if (ret != 0) return ret;
315         }
316
317         return 0;
318 }