]> rtime.felk.cvut.cz Git - frescor/fwp.git/blob - fwp/mngr/fwp_admctrl.c
Added utilization based admission test - needed to be modified.
[frescor/fwp.git] / fwp / mngr / fwp_admctrl.c
1 #include <fres_sa_scenario.h>
2
3 /* TODO: Find out the real value and determine what influences it (MTU
4  *       of the interface minus header sizes?).  */
5 #define MTU 1472
6 #define UDP_HEADER_SIZE 8
7 #define IP_HEADER_SIZE 20
8 #define LLC_HEADER_SIZE 2       /* ??? */
9 #define MAC_HEADER_SIZE 26      /* With QoS field added */
10 #define MAC_FCS_SIZE 4
11
12 #define RTS_FRAME_SIZE 20
13 #define CTS_FRAME_SIZE 14
14 #define ACK_FRAME_SIZE 14
15
16 #define BITRATE_BPS (1000*1000)
17 #define ASLOTTIME_USEC 20       /* 802.11g-2003 p. 46 */
18 #define ASIFSTIME_USEC 10
19 #define ADIFSTIME_USEC (ASIFSTIME_USEC + 2*ASLOTTIME_USEC)
20 #define AAIFSTIME_USEC(n) (ASIFSTIME_USEC + (n)*ASLOTTIME_USEC)
21
22 #define TXTIME_USEC(bytes) ((int64_t)(bytes) * 8 * SEC_TO_USEC / BITRATE_BPS)
23
24
25 /* Default values from 802.11e */
26 const int aifsn[FWP_AC_NUM] = { 2, 2, 3, 7 };
27 const int cwmin[FWP_AC_NUM] = { 3, 7, 15, 15 };
28
29 /* Experimental konstants - weight of backoff */
30 const int pisvejc[FWP_AC_NUM] = { 6, 5, 2, 2 };
31
32 int fwp_reserved_utilization;
33
34 /**
35  * Calucaltes frame duration in microseconds. If the real duration is
36  * represented by a fractional number, the value is rounded up.
37  *
38  * @param length Number of bytes in PSDU.
39  * @param rate_bps Transmit rate of PSDU. The rate should correspond
40  *            to other parameters accoring to 19.3.2 (802.11g)
41  * @param erp_ofdm Whether Extended Rate PHY (part of 802.11g) and ERP-OFDM
42  *            modulation is used.
43  * @param short_preamble Whether short preamble (HR/DSSS/short) is
44  *            used (802.11b)
45  *
46  * @return The number of microseconds or a negative number in case of error.
47  */
48 static int frame_duration(uint16_t length, int rate_bps, bool erp_ofdm, bool short_preamble)
49 {
50         uint32_t duration_usec;
51
52         if (!erp_ofdm) {
53                 duration_usec = ((int64_t)(length) * 8 * SEC_TO_USEC / rate_bps);
54                 if (short_preamble) {
55                         /* For HR/DSSS/short (2, 5.5 and 11 Mbit,
56                          * 802.11b-1999), also for DSSS-OFDM rates and
57                          * ERP-PBCC rates.
58                          * Preamble sent at 1 MBit, header at 2 Mbit */
59                         duration_usec += 72/*bits*/+48/*bits*//2;
60                 } else {
61                         /* For DSSS PHY (1 and 2 Mbit rates,
62                          * 802.11-1999) and for DSS-OFDM and ERP-PBCC
63                          * rates. Always sent at 1 MBit */
64                         duration_usec += 144/*bits*/+48/*bits*/;
65                 }
66         } else {
67 #define MBIT_TO_INDEX(rate_Mbps)  ((rate_Mbps)/3 - 2)
68                 const int N_dbps[] = {
69                         [MBIT_TO_INDEX(6)] = 24,
70                         [MBIT_TO_INDEX(9)] = 36,
71                         [MBIT_TO_INDEX(12)] = 48,
72                         [MBIT_TO_INDEX(18)] = 72,
73                         [MBIT_TO_INDEX(24)] = 96,
74                         [MBIT_TO_INDEX(36)] = 144,
75                         [MBIT_TO_INDEX(48)] = 192,
76                         [MBIT_TO_INDEX(54)] = 216
77                 };
78                 int rate_idx = MBIT_TO_INDEX(rate_bps/1000/1000);
79 #undef MBIT_TO_INDEX
80                 if (rate_idx < 0 ||
81                     rate_idx >= sizeof(N_dbps)/sizeof(*N_dbps) ||
82                     N_dbps[rate_idx] == 0)
83                         return -1;
84
85                 duration_usec += 16 + 4; /* Preamble, SIGNAL */
86                 int bits =
87                         16 +        /* SERVICE */
88                         length * 8 +
89                         6;          /* tail bits */
90                 int Nsym = (bits + N_dbps[rate_idx] - 1)/N_dbps[rate_idx];
91
92                 duration_usec += Nsym * 4;
93
94                 duration_usec += 6; /* signal extension */
95         }
96         return duration_usec;
97 }
98
99 int fwp_admctrl_utilization(struct fres_sa_scenario *scenario, void *priv,
100                                 bool *schedulable)
101 {
102         int utilization = 0;
103
104         const int rate = 1*1000*1000;
105         const bool erp_ofdm = false;
106         const bool short_preamble = false;
107
108         int bytes, duration_usec, tmp_usec, fragments;
109         int ac = FWP_AC_VO; /* FIXME: assign to AC before this
110                              * loop based on deadlines */
111         
112         fres_sa_scenario_for_each_contract(scenario, c) {
113                 fres_block_basic *basic;
114                 char id[40];
115                 fres_contract_id_to_string(id, &c->contract->id, sizeof(id));
116                 basic = fres_contract_get_basic(c->contract);
117
118                 printf("  processing: id=%s, period=%ld ms, budget=%ld ms\n",
119                        id,
120                        fosa_rel_time_to_msec(basic->period),
121                        fosa_rel_time_to_msec(basic->budget));
122
123                 /* Calculate protocol overhead */
124                 bytes = fwp_fna_network_budget_to_bytes(basic->budget);
125                 fragments = (bytes + MTU - 1) / MTU;
126
127                 if (fragments == 0)
128                         continue;
129
130                 const int data_overhead = UDP_HEADER_SIZE + IP_HEADER_SIZE +
131                         LLC_HEADER_SIZE + MAC_FCS_SIZE;
132
133                 duration_usec = frame_duration(data_overhead + bytes%MTU, rate, 
134                                                 erp_ofdm, short_preamble);
135                 tmp_usec = frame_duration(data_overhead + MTU, rate, erp_ofdm, 
136                                                 short_preamble);
137                 duration_usec += tmp_usec*(fragments-1);
138                 /* Add average backoff - assume there is no collision */
139                 tmp_usec = ASLOTTIME_USEC*fragments*pisvejc[ac];
140                 duration_usec += (aifsn[ac] + cwmin[ac]/2)*tmp_usec;
141                 /* We use ACK and ignore burst */
142                 tmp_usec = frame_duration(ACK_FRAME_SIZE, rate, erp_ofdm, 
143                                         short_preamble) + ASIFSTIME_USEC; 
144                 duration_usec += fragments * tmp_usec; 
145
146                 /* TODO: If STA-to-STA, multiply it by two. Note that
147                  * AP may use different values for backoff. */
148                 duration_usec *= 2; /* For demo, we have always STA-to-STA */
149                 if (contract->period_usec == 0) {
150                         if (contdata == contdata_new) {
151                                 contdata->status = FWP_CONT_NOTNEGOTIATED;
152                                 return;
153                         }
154                 }
155                 utilization += (long long)(duration_usec * 10000) / contract->period_usec;
156         }
157
158         if (contdata_new) {
159                 if (utilization >= 10000 * 96/100) {
160                         contdata_new->status = FWP_CONT_NOTNEGOTIATED;
161                 } else {
162                         struct fwp_contract *c = &contdata_new->contract;
163                         int d = c->deadline_usec;
164                         if (d <= 0) d = 100*1000*1000;
165                         if (d < 50000) {
166                                 contdata_new->status = FWP_CONT_NOTNEGOTIATED;
167                         } else {
168                                 contdata_new->status = FWP_CONT_RESERVED;
169                         }
170
171                         contdata_new->vres_params.ac_id =
172                                 d <  100*1000 ? FWP_AC_VO :
173                                 d <  500*1000 ? FWP_AC_VI :
174                                 d < 1000*1000 ? FWP_AC_BE :
175                                 FWP_AC_BK;
176                         contdata_new->vres_params.budget = c->budget;
177                         contdata_new->vres_params.period_usec = c->period_usec; 
178                 }
179         }
180
181         /* Update utilization for GUI */
182         if (contdata_new == NULL || contdata_new->status == FWP_CONT_RESERVED) {
183                 fwp_reserved_utilization = utilization;
184         }
185 }