]> rtime.felk.cvut.cz Git - frescor/fwp.git/blob - fwp/mngr/fwp_admctrl.c
3ab53c200dd17a5c3564a2817db36cc23ba5f0a9
[frescor/fwp.git] / fwp / mngr / fwp_admctrl.c
1 /**************************************************************************/
2 /* ---------------------------------------------------------------------- */
3 /* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                 */
4 /*                                                                        */
5 /*   Universidad de Cantabria,              SPAIN                         */
6 /*   University of York,                    UK                            */
7 /*   Scuola Superiore Sant'Anna,            ITALY                         */
8 /*   Kaiserslautern University,             GERMANY                       */
9 /*   Univ. Politécnica  Valencia,           SPAIN                        */
10 /*   Czech Technical University in Prague,  CZECH REPUBLIC                */
11 /*   ENEA                                   SWEDEN                        */
12 /*   Thales Communication S.A.              FRANCE                        */
13 /*   Visual Tools S.A.                      SPAIN                         */
14 /*   Rapita Systems Ltd                     UK                            */
15 /*   Evidence                               ITALY                         */
16 /*                                                                        */
17 /*   See http://www.frescor.org for a link to partners' websites          */
18 /*                                                                        */
19 /*          FRESCOR project (FP6/2005/IST/5-034026) is funded             */
20 /*       in part by the European Union Sixth Framework Programme          */
21 /*       The European Union is not liable of any use that may be          */
22 /*       made of this code.                                               */
23 /*                                                                        */
24 /*                                                                        */
25 /*  This file is part of FWP (Frescor WLAN Protocol)                      */
26 /*                                                                        */
27 /* FWP is free software; you can redistribute it and/or modify it         */
28 /* under terms of the GNU General Public License as published by the      */
29 /* Free Software Foundation; either version 2, or (at your option) any    */
30 /* later version.  FWP is distributed in the hope that it will be         */
31 /* useful, but WITHOUT ANY WARRANTY; without even the implied warranty    */
32 /* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU    */
33 /* General Public License for more details. You should have received a    */
34 /* copy of the GNU General Public License along with FWP; see file        */
35 /* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
36 /* Cambridge, MA 02139, USA.                                              */
37 /*                                                                        */
38 /* As a special exception, including FWP header files in a file,          */
39 /* instantiating FWP generics or templates, or linking other files        */
40 /* with FWP objects to produce an executable application, does not        */
41 /* by itself cause the resulting executable application to be covered     */
42 /* by the GNU General Public License. This exception does not             */
43 /* however invalidate any other reasons why the executable file might be  */
44 /* covered by the GNU Public License.                                     */
45 /**************************************************************************/
46 #include <fres_sa_scenario.h>
47 #include <fwp.h>
48 #include "fwp_idl.h"
49 #include "fwp_admctrl.h"
50 #include <ul_log.h>
51
52 UL_LOG_CUST(ulogd_fwp_admctrl);
53 ul_log_domain_t ulogd_frm_aqcpu = {UL_LOGL_MSG, "fwp_admctrl"};
54
55 /* TODO: Find out the real value and determine what influences it (MTU
56  *       of the interface minus header sizes?).  */
57 #define MTU 1472
58 #define UDP_HEADER_SIZE 8
59 #define IP_HEADER_SIZE 20
60 #define LLC_HEADER_SIZE 2       /* ??? */
61 #define MAC_HEADER_SIZE 26      /* With QoS field added */
62 #define MAC_FCS_SIZE 4
63
64 #define RTS_FRAME_SIZE 20
65 #define CTS_FRAME_SIZE 14
66 #define ACK_FRAME_SIZE 14
67
68 #define ASLOTTIME_USEC 20       /* 802.11g-2003 p. 46 */
69 #define ASIFSTIME_USEC 10
70 #define ADIFSTIME_USEC (ASIFSTIME_USEC + 2*ASLOTTIME_USEC)
71 #define AAIFSTIME_USEC(n) (ASIFSTIME_USEC + (n)*ASLOTTIME_USEC)
72
73 /* Default values from 802.11e */
74 const int aifsn[FWP_AC_NUM] = { 2, 2, 3, 7 };
75 const int cwmin[FWP_AC_NUM] = { 3, 7, 15, 15 };
76
77 /* Experimental konstants - weight of backoff */
78 const int pisvejc[FWP_AC_NUM] = { 6, 5, 2, 2 };
79
80 int fwp_reserved_utilization;
81
82 /**
83  * Calucaltes frame duration in microseconds. If the real duration is
84  * represented by a fractional number, the value is rounded up.
85  *
86  * @param length Number of bytes in PSDU.
87  * @param rate_bps Transmit rate of PSDU. The rate should correspond
88  *            to other parameters accoring to 19.3.2 (802.11g)
89  * @param erp_ofdm Whether Extended Rate PHY (part of 802.11g) and ERP-OFDM
90  *            modulation is used.
91  * @param short_preamble Whether short preamble (HR/DSSS/short) is
92  *            used (802.11b)
93  *
94  * @return The number of microseconds or a negative number in case of error.
95  */
96 static int frame_duration(uint16_t length, int rate_bps, bool erp_ofdm, bool short_preamble)
97 {
98         uint32_t duration_usec = 0;
99
100         if (!erp_ofdm) {
101                 duration_usec = ((int64_t)(length) * 8 * SEC_TO_USEC / rate_bps);
102                 if (short_preamble) {
103                         /* For HR/DSSS/short (2, 5.5 and 11 Mbit,
104                          * 802.11b-1999), also for DSSS-OFDM rates and
105                          * ERP-PBCC rates.
106                          * Preamble sent at 1 MBit, header at 2 Mbit */
107                         duration_usec += 72/*bits*/+48/*bits*//2;
108                 } else {
109                         /* For DSSS PHY (1 and 2 Mbit rates,
110                          * 802.11-1999) and for DSS-OFDM and ERP-PBCC
111                          * rates. Always sent at 1 MBit */
112                         duration_usec += 144/*bits*/+48/*bits*/;
113                 }
114         } else {
115 #define MBIT_TO_INDEX(rate_Mbps)  ((rate_Mbps)/3 - 2)
116                 const int N_dbps[] = {
117                         [MBIT_TO_INDEX(6)] = 24,
118                         [MBIT_TO_INDEX(9)] = 36,
119                         [MBIT_TO_INDEX(12)] = 48,
120                         [MBIT_TO_INDEX(18)] = 72,
121                         [MBIT_TO_INDEX(24)] = 96,
122                         [MBIT_TO_INDEX(36)] = 144,
123                         [MBIT_TO_INDEX(48)] = 192,
124                         [MBIT_TO_INDEX(54)] = 216
125                 };
126                 int rate_idx = MBIT_TO_INDEX(rate_bps/1000/1000);
127 #undef MBIT_TO_INDEX
128                 if (rate_idx < 0 ||
129                     rate_idx >= sizeof(N_dbps)/sizeof(*N_dbps) ||
130                     N_dbps[rate_idx] == 0)
131                         return -1;
132
133                 duration_usec += 16 + 4; /* Preamble, SIGNAL */
134                 int bits =
135                         16 +        /* SERVICE */
136                         length * 8 +
137                         6;          /* tail bits */
138                 int Nsym = (bits + N_dbps[rate_idx] - 1)/N_dbps[rate_idx];
139
140                 duration_usec += Nsym * 4;
141
142                 duration_usec += 6; /* signal extension */
143         }
144         return duration_usec;
145 }
146
147 int fwp_admctrl_utilization(struct fres_sa_scenario *scenario, void *priv,
148                                 bool *schedulable)
149 {
150         int utilization = 0;
151
152         const int rate = 54*1000*1000;
153         const bool erp_ofdm = true;
154         const bool short_preamble = true;
155         struct fres_sa_contract *c;
156         long int period_usec;
157         fres_block_fwp_sched *fwp_sched;
158
159         size_t bytes; 
160         long int duration_usec, tmp_usec;
161         int fragments;
162         int ac = FWP_AC_VO; 
163         
164         fres_sa_scenario_for_each_no_cancel_contract(scenario, c) {
165                 fres_block_basic *basic;
166                 char id[40];
167                 fres_contract_id_to_string(id, &c->contract->id, sizeof(id));
168                 basic = fres_contract_get_basic(c->contract);
169
170                 frsh_network_budget_to_bytes(FRSH_NETPF_FWP,&basic->budget,&bytes);
171                 printf("  processing: id=%s, period=%ld ms, budget=%lu bytes\n",
172                        id,
173                        fosa_rel_time_to_msec(basic->period),
174                        (long unsigned int)bytes);
175
176                 /* Calculate protocol overhead */
177                 fragments = (bytes + MTU - 1) / MTU;
178
179                 if (fragments == 0)
180                         continue;
181
182                 const int data_overhead = UDP_HEADER_SIZE + IP_HEADER_SIZE +
183                         LLC_HEADER_SIZE + MAC_FCS_SIZE;
184
185                 duration_usec = frame_duration(data_overhead + bytes%MTU, rate, 
186                                                 erp_ofdm, short_preamble);
187                 tmp_usec = frame_duration(data_overhead + MTU, rate, erp_ofdm, 
188                                                 short_preamble);
189                 duration_usec += tmp_usec*(fragments-1);
190                 /* Add average backoff - assume there is no collision */
191                 tmp_usec = ASLOTTIME_USEC*fragments*pisvejc[ac];
192                 duration_usec += (aifsn[ac] + cwmin[ac]/2)*tmp_usec;
193                 /* We use ACK and ignore burst */
194                 tmp_usec = frame_duration(ACK_FRAME_SIZE, rate, erp_ofdm, 
195                                         short_preamble) + ASIFSTIME_USEC; 
196                 duration_usec += fragments * tmp_usec; 
197                 //printf("duration: %ld ms\n", duration_usec/1000);
198
199                 /* TODO: If STA-to-STA, multiply it by two. Note that
200                  * AP may use different values for backoff. */
201                 //duration_usec *= 2; /* For demo, we have always STA-to-STA */
202
203                 basic = fres_contract_get_basic(c->contract);
204                 period_usec = basic ? fosa_rel_time_to_msec(basic->period)*1000 : 0;
205
206                 if (c->contract == c->new) {
207                         if (period_usec == 0) {
208                                 ul_logmsg("Period is zero!\n");
209                                 goto not_schedulable;
210                         }
211
212                         frsh_rel_time_t deadline;
213                         long int d;
214                         if (fres_contract_get_deadline(&c->contract, &deadline)) {
215                                 d = fosa_rel_time_to_msec(deadline)*1000;
216                         } else {
217                                 d = 100/*sec*/*1000*1000;
218                         }
219                         if (d < 30/*msec*/*1000) {
220                                 ul_logmsg("Deadline shorter than 30 ms!\n");
221                                 goto not_schedulable;
222                         };
223                         
224                         fwp_sched = malloc(sizeof(*fwp_sched));
225                         fwp_sched->ac_id =
226                                 d <  100*1000 ? FWP_AC_VO :
227                                 d <  500*1000 ? FWP_AC_VI :
228                                 d < 1000*1000 ? FWP_AC_BE :
229                                 FWP_AC_BK;
230                         fres_contract_add_block(c->contract, FRES_BLOCK_FWP_SCHED, fwp_sched);  
231                 }
232
233                 utilization += (long long)(duration_usec * 10000) / period_usec;
234         }
235         
236         if (utilization >= 10000 * 96/100) {
237                 goto not_schedulable;
238         }
239         scenario->utilization = utilization/100; /* For GUI */
240         
241         *schedulable = true;
242         return 0;
243
244 not_schedulable:
245         *schedulable = false;
246         return 0;
247 }