blob: 9ff06db9bc6a1f1eee9711182fa4cc87024b6a6d [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
Stefan Sperling78ab6242018-05-31 12:28:55 +020020#include <osmocom/core/timer_compat.h>
21
Andreas Eversberg050ace22013-03-16 16:22:02 +010022#include <gprs_rlcmac.h>
23#include <gprs_debug.h>
24#include <pcu_l1_if.h>
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +020025#include <tbf.h>
Andreas Eversberg050ace22013-03-16 16:22:02 +010026
27#include <string.h>
28#include <errno.h>
29
30/*
31 * downlink measurement
32 */
Max5a6bcfb2017-09-01 14:36:44 +020033/* TODO: trigger the measurement report from the pollcontroller and use it for flow control */
Andreas Eversberg050ace22013-03-16 16:22:02 +010034
35/* received Measurement Report */
36int gprs_rlcmac_meas_rep(Packet_Measurement_Report_t *pmr)
37{
38 NC_Measurement_Report_t *ncr;
39 NC_Measurements_t *nc;
40 int i;
41
42 LOGP(DRLCMACMEAS, LOGL_INFO, "Measuement Report of TLLI=0x%08x:",
43 pmr->TLLI);
44
45 switch (pmr->UnionType) {
46 case 0:
47 ncr = &pmr->u.NC_Measurement_Report;
48 LOGPC(DRLCMACMEAS, LOGL_INFO, " NC%u Serv %d dbm",
49 ncr->NC_MODE + 1,
50 ncr->Serving_Cell_Data.RXLEV_SERVING_CELL - 110);
51 for (i = 0; i < ncr->NUMBER_OF_NC_MEASUREMENTS; i++) {
52 nc = &ncr->NC_Measurements[i];
53 LOGPC(DRLCMACMEAS, LOGL_DEBUG, ", Neigh %u %d dbm",
54 nc->FREQUENCY_N, nc->RXLEV_N - 110);
55 }
56 LOGPC(DRLCMACMEAS, LOGL_INFO, "\n");
57
58 break;
59 case 1:
60 LOGPC(DRLCMACMEAS, LOGL_INFO,
61 " <EXT Reporting not supported!>\n");
62 break;
63 }
64
65 return 0;
66}
67
68
69/*
70 * uplink measurement
71 */
72
73/* RSSI values received from MS */
74int gprs_rlcmac_rssi(struct gprs_rlcmac_tbf *tbf, int8_t rssi)
75{
Stefan Sperlingf0f7df12018-05-25 15:12:30 +020076 struct timespec now_tv, *rssi_tv = &tbf->meas.rssi_tv;
Stefan Sperling78ab6242018-05-31 12:28:55 +020077 struct timespec elapsed;
Andreas Eversberg050ace22013-03-16 16:22:02 +010078
79 tbf->meas.rssi_sum += rssi;
80 tbf->meas.rssi_num++;
81
Stefan Sperlingf0f7df12018-05-25 15:12:30 +020082 osmo_clock_gettime(CLOCK_MONOTONIC, &now_tv);
Stefan Sperling78ab6242018-05-31 12:28:55 +020083
84 timespecsub(&now_tv, rssi_tv, &elapsed);
85 if (elapsed.tv_sec < 1)
Andreas Eversberg050ace22013-03-16 16:22:02 +010086 return 0;
87
88 gprs_rlcmac_rssi_rep(tbf);
89
90 /* reset rssi values and timestamp */
Stefan Sperlingf0f7df12018-05-25 15:12:30 +020091 memcpy(rssi_tv, &now_tv, sizeof(*rssi_tv));
Andreas Eversberg050ace22013-03-16 16:22:02 +010092 tbf->meas.rssi_sum = 0;
93 tbf->meas.rssi_num = 0;
94
95 return 0;
96}
97
98/* Give RSSI report */
99int gprs_rlcmac_rssi_rep(struct gprs_rlcmac_tbf *tbf)
100{
101 /* No measurement values */
102 if (!tbf->meas.rssi_num)
103 return -EINVAL;
104
105 LOGP(DRLCMACMEAS, LOGL_INFO, "UL RSSI of TLLI=0x%08x: %d dBm\n",
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100106 tbf->tlli(), tbf->meas.rssi_sum / tbf->meas.rssi_num);
Andreas Eversberg050ace22013-03-16 16:22:02 +0100107
108 return 0;
109}
110
111
112/*
113 * lost frames
114 */
115
116/* Lost frames reported from RLCMAC layer */
Daniel Willmann418a4232014-08-08 11:21:04 +0200117int gprs_rlcmac_received_lost(struct gprs_rlcmac_dl_tbf *tbf, uint16_t received,
Andreas Eversberg050ace22013-03-16 16:22:02 +0100118 uint16_t lost)
119{
Stefan Sperlingf0f7df12018-05-25 15:12:30 +0200120 struct timespec now_tv, *loss_tv = &tbf->m_bw.dl_loss_tv;
Stefan Sperling78ab6242018-05-31 12:28:55 +0200121 struct timespec elapsed;
Andreas Eversberg050ace22013-03-16 16:22:02 +0100122 uint16_t sum = received + lost;
123
124 /* No measurement values */
125 if (!sum)
126 return -EINVAL;
127
128 LOGP(DRLCMACMEAS, LOGL_DEBUG, "DL Loss of TLLI 0x%08x: Received: %4d "
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100129 "Lost: %4d Sum: %4d\n", tbf->tlli(), received, lost, sum);
Andreas Eversberg050ace22013-03-16 16:22:02 +0100130
Daniel Willmann418a4232014-08-08 11:21:04 +0200131 tbf->m_bw.dl_loss_received += received;
132 tbf->m_bw.dl_loss_lost += lost;
Andreas Eversberg050ace22013-03-16 16:22:02 +0100133
Harald Welte099f4f22018-10-21 11:50:10 +0200134 osmo_clock_gettime(CLOCK_MONOTONIC, &now_tv);
Stefan Sperling78ab6242018-05-31 12:28:55 +0200135 timespecsub(&now_tv, loss_tv, &elapsed);
136 if (elapsed.tv_sec < 1)
Andreas Eversberg050ace22013-03-16 16:22:02 +0100137 return 0;
138
139 gprs_rlcmac_lost_rep(tbf);
140
141 /* reset lost values and timestamp */
Stefan Sperlingf0f7df12018-05-25 15:12:30 +0200142 memcpy(loss_tv, &now_tv, sizeof(*loss_tv));
Daniel Willmann418a4232014-08-08 11:21:04 +0200143 tbf->m_bw.dl_loss_received = 0;
144 tbf->m_bw.dl_loss_lost = 0;
Andreas Eversberg050ace22013-03-16 16:22:02 +0100145
146 return 0;
147}
148
149/* Give Lost report */
Daniel Willmann418a4232014-08-08 11:21:04 +0200150int gprs_rlcmac_lost_rep(struct gprs_rlcmac_dl_tbf *tbf)
Andreas Eversberg050ace22013-03-16 16:22:02 +0100151{
Daniel Willmann418a4232014-08-08 11:21:04 +0200152 uint16_t sum = tbf->m_bw.dl_loss_lost + tbf->m_bw.dl_loss_received;
Andreas Eversberg050ace22013-03-16 16:22:02 +0100153
154 /* No measurement values */
155 if (!sum)
156 return -EINVAL;
157
Stefan Sperling082443d2018-06-05 11:37:00 +0200158 LOGP(DRLCMACMEAS, LOGL_DEBUG, "DL packet loss of IMSI=%s / TLLI=0x%08x: "
Holger Hans Peter Freyther5464c9b2013-10-27 20:57:35 +0100159 "%d%%\n", tbf->imsi(), tbf->tlli(),
Daniel Willmann418a4232014-08-08 11:21:04 +0200160 tbf->m_bw.dl_loss_lost * 100 / sum);
Andreas Eversberg050ace22013-03-16 16:22:02 +0100161
162 return 0;
163}
164
165
166/*
167 * downlink bandwidth
168 */
169
Daniel Willmann418a4232014-08-08 11:21:04 +0200170int gprs_rlcmac_dl_bw(struct gprs_rlcmac_dl_tbf *tbf, uint16_t octets)
Andreas Eversberg050ace22013-03-16 16:22:02 +0100171{
Stefan Sperlingf0f7df12018-05-25 15:12:30 +0200172 struct timespec now_tv, *bw_tv = &tbf->m_bw.dl_bw_tv;
Stefan Sperling78ab6242018-05-31 12:28:55 +0200173 struct timespec elapsed;
Andreas Eversberg050ace22013-03-16 16:22:02 +0100174
Daniel Willmann418a4232014-08-08 11:21:04 +0200175 tbf->m_bw.dl_bw_octets += octets;
Andreas Eversberg050ace22013-03-16 16:22:02 +0100176
Stefan Sperlingf0f7df12018-05-25 15:12:30 +0200177 osmo_clock_gettime(CLOCK_MONOTONIC, &now_tv);
Stefan Sperling78ab6242018-05-31 12:28:55 +0200178 timespecsub(&now_tv, bw_tv, &elapsed);
179 if (elapsed.tv_sec < 1)
Andreas Eversberg050ace22013-03-16 16:22:02 +0100180 return 0;
181
Stefan Sperling78ab6242018-05-31 12:28:55 +0200182 tbf->m_bw.dl_throughput = (tbf->m_bw.dl_bw_octets << 10) / ((elapsed.tv_sec << 10) + (elapsed.tv_nsec >> 20));
Andreas Eversberg050ace22013-03-16 16:22:02 +0100183 LOGP(DRLCMACMEAS, LOGL_INFO, "DL Bandwitdh of IMSI=%s / TLLI=0x%08x: "
Stefan Sperling78ab6242018-05-31 12:28:55 +0200184 "%d KBits/s\n", tbf->imsi(), tbf->tlli(), tbf->m_bw.dl_throughput);
Andreas Eversberg050ace22013-03-16 16:22:02 +0100185
186 /* reset bandwidth values timestamp */
Stefan Sperlingf0f7df12018-05-25 15:12:30 +0200187 memcpy(bw_tv, &now_tv, sizeof(*bw_tv));
Daniel Willmann418a4232014-08-08 11:21:04 +0200188 tbf->m_bw.dl_bw_octets = 0;
Andreas Eversberg050ace22013-03-16 16:22:02 +0100189
190 return 0;
191}
192