blob: 75da835ae3419b55262bdb340d58d592a7a2216a [file] [log] [blame]
Andreas Eversberg050ace22013-03-16 16:22:02 +01001/* Measurements
2 *
3 * Copyright (C) 2012 Andreas Eversberg <jolly@eversberg.eu>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20#include <gprs_rlcmac.h>
21#include <gprs_debug.h>
22#include <pcu_l1_if.h>
23
24#include <string.h>
25#include <errno.h>
26
27/*
28 * downlink measurement
29 */
30
31/* received Measurement Report */
32int gprs_rlcmac_meas_rep(Packet_Measurement_Report_t *pmr)
33{
34 NC_Measurement_Report_t *ncr;
35 NC_Measurements_t *nc;
36 int i;
37
38 LOGP(DRLCMACMEAS, LOGL_INFO, "Measuement Report of TLLI=0x%08x:",
39 pmr->TLLI);
40
41 switch (pmr->UnionType) {
42 case 0:
43 ncr = &pmr->u.NC_Measurement_Report;
44 LOGPC(DRLCMACMEAS, LOGL_INFO, " NC%u Serv %d dbm",
45 ncr->NC_MODE + 1,
46 ncr->Serving_Cell_Data.RXLEV_SERVING_CELL - 110);
47 for (i = 0; i < ncr->NUMBER_OF_NC_MEASUREMENTS; i++) {
48 nc = &ncr->NC_Measurements[i];
49 LOGPC(DRLCMACMEAS, LOGL_DEBUG, ", Neigh %u %d dbm",
50 nc->FREQUENCY_N, nc->RXLEV_N - 110);
51 }
52 LOGPC(DRLCMACMEAS, LOGL_INFO, "\n");
53
54 break;
55 case 1:
56 LOGPC(DRLCMACMEAS, LOGL_INFO,
57 " <EXT Reporting not supported!>\n");
58 break;
59 }
60
61 return 0;
62}
63
64
65/*
66 * uplink measurement
67 */
68
69/* RSSI values received from MS */
70int gprs_rlcmac_rssi(struct gprs_rlcmac_tbf *tbf, int8_t rssi)
71{
72 struct timeval now_tv, *rssi_tv = &tbf->meas.rssi_tv;
73 uint32_t elapsed;
74
75 tbf->meas.rssi_sum += rssi;
76 tbf->meas.rssi_num++;
77
78 gettimeofday(&now_tv, NULL);
79 elapsed = ((now_tv.tv_sec - rssi_tv->tv_sec) << 7)
80 + ((now_tv.tv_usec - rssi_tv->tv_usec) << 7) / 1000000;
81 if (elapsed < 128)
82 return 0;
83
84 gprs_rlcmac_rssi_rep(tbf);
85
86 /* reset rssi values and timestamp */
87 memcpy(rssi_tv, &now_tv, sizeof(struct timeval));
88 tbf->meas.rssi_sum = 0;
89 tbf->meas.rssi_num = 0;
90
91 return 0;
92}
93
94/* Give RSSI report */
95int gprs_rlcmac_rssi_rep(struct gprs_rlcmac_tbf *tbf)
96{
97 /* No measurement values */
98 if (!tbf->meas.rssi_num)
99 return -EINVAL;
100
101 LOGP(DRLCMACMEAS, LOGL_INFO, "UL RSSI of TLLI=0x%08x: %d dBm\n",
102 tbf->tlli, tbf->meas.rssi_sum / tbf->meas.rssi_num);
103
104 return 0;
105}
106
107
108/*
109 * lost frames
110 */
111
112/* Lost frames reported from RLCMAC layer */
113int gprs_rlcmac_received_lost(struct gprs_rlcmac_tbf *tbf, uint16_t received,
114 uint16_t lost)
115{
116 struct timeval now_tv, *loss_tv = &tbf->meas.dl_loss_tv;
117 uint32_t elapsed;
118 uint16_t sum = received + lost;
119
120 /* No measurement values */
121 if (!sum)
122 return -EINVAL;
123
124 LOGP(DRLCMACMEAS, LOGL_DEBUG, "DL Loss of TLLI 0x%08x: Received: %4d "
125 "Lost: %4d Sum: %4d\n", tbf->tlli, received, lost, sum);
126
127 tbf->meas.dl_loss_received += received;
128 tbf->meas.dl_loss_lost += lost;
129
130 gettimeofday(&now_tv, NULL);
131 elapsed = ((now_tv.tv_sec - loss_tv->tv_sec) << 7)
132 + ((now_tv.tv_usec - loss_tv->tv_usec) << 7) / 1000000;
133 if (elapsed < 128)
134 return 0;
135
136 gprs_rlcmac_lost_rep(tbf);
137
138 /* reset lost values and timestamp */
139 memcpy(loss_tv, &now_tv, sizeof(struct timeval));
140 tbf->meas.dl_loss_received = 0;
141 tbf->meas.dl_loss_lost = 0;
142
143 return 0;
144}
145
146/* Give Lost report */
147int gprs_rlcmac_lost_rep(struct gprs_rlcmac_tbf *tbf)
148{
149 uint16_t sum = tbf->meas.dl_loss_lost + tbf->meas.dl_loss_received;
150
151 /* No measurement values */
152 if (!sum)
153 return -EINVAL;
154
155 LOGP(DRLCMACMEAS, LOGL_INFO, "DL packet loss of IMSI=%s / TLLI=0x%08x: "
156 "%d%%\n", tbf->meas.imsi, tbf->tlli,
157 tbf->meas.dl_loss_lost * 100 / sum);
158
159 return 0;
160}
161
162
163/*
164 * downlink bandwidth
165 */
166
167int gprs_rlcmac_dl_bw(struct gprs_rlcmac_tbf *tbf, uint16_t octets)
168{
169 struct timeval now_tv, *bw_tv = &tbf->meas.dl_bw_tv;
170 uint32_t elapsed;
171
172 tbf->meas.dl_bw_octets += octets;
173
174 gettimeofday(&now_tv, NULL);
175 elapsed = ((now_tv.tv_sec - bw_tv->tv_sec) << 7)
176 + ((now_tv.tv_usec - bw_tv->tv_usec) << 7) / 1000000;
177 if (elapsed < 128)
178 return 0;
179
180 LOGP(DRLCMACMEAS, LOGL_INFO, "DL Bandwitdh of IMSI=%s / TLLI=0x%08x: "
181 "%d KBits/s\n", tbf->meas.imsi, tbf->tlli,
182 tbf->meas.dl_bw_octets / elapsed);
183
184 /* reset bandwidth values timestamp */
185 memcpy(bw_tv, &now_tv, sizeof(struct timeval));
186 tbf->meas.dl_bw_octets = 0;
187
188 return 0;
189}
190