]> rtime.felk.cvut.cz Git - frescor/frsh-forb.git/blob - fwp/mngr/admtest_utilization.c
Merge branch 'master' of rtime.felk.cvut.cz:/var/git/frescor
[frescor/frsh-forb.git] / fwp / mngr / admtest_utilization.c
1 #include "admtest.h"
2 #include <fwp_util.h>
3 #include <stdint.h>
4 #include <fwp_ac.h>
5 #include <fwp_conf.h>
6 #include <stdbool.h>
7
8 /* TODO: Find out the real value and determine what influences it (MTU
9  *       of the interface minus header sizes?).  */
10 #define MTU 1472
11 #define UDP_HEADER_SIZE 8
12 #define IP_HEADER_SIZE 20
13 #define LLC_HEADER_SIZE 2       /* ??? */
14 #define MAC_HEADER_SIZE 26      /* With QoS field added */
15 #define MAC_FCS_SIZE 4
16
17 #define RTS_FRAME_SIZE 20
18 #define CTS_FRAME_SIZE 14
19 #define ACK_FRAME_SIZE 14
20
21 #define BITRATE_BPS (1000*1000)
22 #define ASLOTTIME_USEC 20       /* 802.11g-2003 p. 46 */
23 #define ASIFSTIME_USEC 10
24 #define ADIFSTIME_USEC (ASIFSTIME_USEC + 2*ASLOTTIME_USEC)
25 #define AAIFSTIME_USEC(n) (ASIFSTIME_USEC + (n)*ASLOTTIME_USEC)
26
27 #define TXTIME_USEC(bytes) ((int64_t)(bytes) * 8 * SEC_TO_USEC / BITRATE_BPS)
28
29
30 /* Default values from 802.11e */
31 const int aifsn[FWP_AC_NUM] = { 2, 2, 3, 7 };
32 const int cwmin[FWP_AC_NUM] = { 3, 7, 15, 15 };
33
34 /* Experimental konstants - weight of backoff */
35 const int pisvejc[FWP_AC_NUM] = { 6, 5, 2, 2 };
36
37
38 /**
39  * Calucaltes frame duration in microseconds. If the real duration is
40  * represented by a fractional number, the value is rounded up.
41  *
42  * @param length Number of bytes in PSDU.
43  * @param rate_bps Transmit rate of PSDU. The rate should correspond
44  *            to other parameters accoring to 19.3.2 (802.11g)
45  * @param erp_ofdm Whether Extended Rate PHY (part of 802.11g) and ERP-OFDM
46  *            modulation is used.
47  * @param short_preamble Whether short preamble (HR/DSSS/short) is
48  *            used (802.11b)
49  *
50  * @return The number of microseconds or a negative number in case of error.
51  */
52 static int frame_duration(uint16_t length, int rate_bps, bool erp_ofdm, bool short_preamble)
53 {
54         uint32_t duration_usec;
55
56         if (!erp_ofdm) {
57                 duration_usec = ((int64_t)(length) * 8 * SEC_TO_USEC / rate_bps);
58                 if (short_preamble) {
59                         /* For HR/DSSS/short (2, 5.5 and 11 Mbit,
60                          * 802.11b-1999), also for DSSS-OFDM rates and
61                          * ERP-PBCC rates.
62                          * Preamble sent at 1 MBit, header at 2 Mbit */
63                         duration_usec += 72/*bits*/+48/*bits*//2;
64                 } else {
65                         /* For DSSS PHY (1 and 2 Mbit rates,
66                          * 802.11-1999) and for DSS-OFDM and ERP-PBCC
67                          * rates. Always sent at 1 MBit */
68                         duration_usec += 144/*bits*/+48/*bits*/;
69                 }
70         } else {
71 #define MBIT_TO_INDEX(rate_Mbps)  ((rate_Mbps)/3 - 2)
72                 const int N_dbps[] = {
73                         [MBIT_TO_INDEX(6)] = 24,
74                         [MBIT_TO_INDEX(9)] = 36,
75                         [MBIT_TO_INDEX(12)] = 48,
76                         [MBIT_TO_INDEX(18)] = 72,
77                         [MBIT_TO_INDEX(24)] = 96,
78                         [MBIT_TO_INDEX(36)] = 144,
79                         [MBIT_TO_INDEX(48)] = 192,
80                         [MBIT_TO_INDEX(54)] = 216
81                 };
82                 int rate_idx = MBIT_TO_INDEX(rate_bps/1000/1000);
83 #undef MBIT_TO_INDEX
84                 if (rate_idx < 0 ||
85                     rate_idx >= sizeof(N_dbps)/sizeof(*N_dbps) ||
86                     N_dbps[rate_idx] == 0)
87                         return -1;
88
89                 duration_usec += 16 + 4; /* Preamble, SIGNAL */
90                 int bits =
91                         16 +        /* SERVICE */
92                         length * 8 +
93                         6;          /* tail bits */
94                 int Nsym = (bits + N_dbps[rate_idx] - 1)/N_dbps[rate_idx];
95
96                 duration_usec += Nsym * 4;
97
98                 duration_usec += 6; /* signal extension */
99         }
100         return duration_usec;
101 }
102
103 int fwp_adm_test(struct fwp_ctable *ct)
104 {
105         int i;
106         int utilization = 0;
107
108         const int rate = 1*1000*1000;
109         const bool erp_ofdm = false;
110         const bool short_preamble = false;
111
112         for (i = 0; i < ct->nr_contract; i++) {
113                 int bytes, duration_usec, fragments;
114                 struct fwp_contract *contract = &ct->entry[i].contract;
115                 int ac = FWP_AC_VO; /* FIXME: assign to AC before this
116                                      * loop based on deadlines */
117                 ac = contract->ac_id;
118
119                 /* Calculate protocol overhead */
120
121                 bytes = contract->budget;
122                 fragments = (bytes + MTU - 1) / MTU;
123
124                 if (fragments == 0)
125                         continue;
126
127                 const int data_overhead = UDP_HEADER_SIZE + IP_HEADER_SIZE +
128                         LLC_HEADER_SIZE + MAC_FCS_SIZE;
129
130                 duration_usec = frame_duration(data_overhead + bytes%MTU, rate, erp_ofdm, short_preamble);
131                 duration_usec += frame_duration(data_overhead + MTU, rate, erp_ofdm, short_preamble)*(fragments-1);
132
133                 /* Add average backoff - assume there is no collision */
134                 duration_usec += (aifsn[ac] + cwmin[ac]/2)*ASLOTTIME_USEC*fragments*pisvejc[ac];
135                 /* We use ACK and ignore burst */
136                 duration_usec += fragments * (ASIFSTIME_USEC +
137                                   frame_duration(ACK_FRAME_SIZE, rate, erp_ofdm, short_preamble));
138
139                 /* TODO: If STA-to-STA, multiply it by two. Note that
140                  * AP may use different values for backoff. */
141                 if (contract->period_usec == 0) return FWP_CNT_REJECTED;
142                 utilization += (long long)(duration_usec * 10000) / contract->period_usec;
143         }
144         if (utilization >= 10000 * 96/100) {
145                 return FWP_CNT_REJECTED;
146         } else {
147                 return FWP_CNT_NEGOTIATED;
148         }
149 }