193 lines
4.6 KiB
C++
193 lines
4.6 KiB
C++
/* Measurements
|
|
*
|
|
* Copyright (C) 2012 Andreas Eversberg <jolly@eversberg.eu>
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include <gprs_rlcmac.h>
|
|
#include <gprs_debug.h>
|
|
#include <pcu_l1_if.h>
|
|
#include <tbf.h>
|
|
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
|
|
/*
|
|
* downlink measurement
|
|
*/
|
|
#warning "TODO: trigger the measurement report from the pollcontroller and use it for flow control"
|
|
|
|
/* received Measurement Report */
|
|
int gprs_rlcmac_meas_rep(Packet_Measurement_Report_t *pmr)
|
|
{
|
|
NC_Measurement_Report_t *ncr;
|
|
NC_Measurements_t *nc;
|
|
int i;
|
|
|
|
LOGP(DRLCMACMEAS, LOGL_INFO, "Measuement Report of TLLI=0x%08x:",
|
|
pmr->TLLI);
|
|
|
|
switch (pmr->UnionType) {
|
|
case 0:
|
|
ncr = &pmr->u.NC_Measurement_Report;
|
|
LOGPC(DRLCMACMEAS, LOGL_INFO, " NC%u Serv %d dbm",
|
|
ncr->NC_MODE + 1,
|
|
ncr->Serving_Cell_Data.RXLEV_SERVING_CELL - 110);
|
|
for (i = 0; i < ncr->NUMBER_OF_NC_MEASUREMENTS; i++) {
|
|
nc = &ncr->NC_Measurements[i];
|
|
LOGPC(DRLCMACMEAS, LOGL_DEBUG, ", Neigh %u %d dbm",
|
|
nc->FREQUENCY_N, nc->RXLEV_N - 110);
|
|
}
|
|
LOGPC(DRLCMACMEAS, LOGL_INFO, "\n");
|
|
|
|
break;
|
|
case 1:
|
|
LOGPC(DRLCMACMEAS, LOGL_INFO,
|
|
" <EXT Reporting not supported!>\n");
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* uplink measurement
|
|
*/
|
|
|
|
/* RSSI values received from MS */
|
|
int gprs_rlcmac_rssi(struct gprs_rlcmac_tbf *tbf, int8_t rssi)
|
|
{
|
|
struct timeval now_tv, *rssi_tv = &tbf->meas.rssi_tv;
|
|
uint32_t elapsed;
|
|
|
|
tbf->meas.rssi_sum += rssi;
|
|
tbf->meas.rssi_num++;
|
|
|
|
gettimeofday(&now_tv, NULL);
|
|
elapsed = ((now_tv.tv_sec - rssi_tv->tv_sec) << 7)
|
|
+ ((now_tv.tv_usec - rssi_tv->tv_usec) << 7) / 1000000;
|
|
if (elapsed < 128)
|
|
return 0;
|
|
|
|
gprs_rlcmac_rssi_rep(tbf);
|
|
|
|
/* reset rssi values and timestamp */
|
|
memcpy(rssi_tv, &now_tv, sizeof(struct timeval));
|
|
tbf->meas.rssi_sum = 0;
|
|
tbf->meas.rssi_num = 0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Give RSSI report */
|
|
int gprs_rlcmac_rssi_rep(struct gprs_rlcmac_tbf *tbf)
|
|
{
|
|
/* No measurement values */
|
|
if (!tbf->meas.rssi_num)
|
|
return -EINVAL;
|
|
|
|
LOGP(DRLCMACMEAS, LOGL_INFO, "UL RSSI of TLLI=0x%08x: %d dBm\n",
|
|
tbf->tlli(), tbf->meas.rssi_sum / tbf->meas.rssi_num);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* lost frames
|
|
*/
|
|
|
|
/* Lost frames reported from RLCMAC layer */
|
|
int gprs_rlcmac_received_lost(struct gprs_rlcmac_dl_tbf *tbf, uint16_t received,
|
|
uint16_t lost)
|
|
{
|
|
struct timeval now_tv, *loss_tv = &tbf->m_bw.dl_loss_tv;
|
|
uint32_t elapsed;
|
|
uint16_t sum = received + lost;
|
|
|
|
/* No measurement values */
|
|
if (!sum)
|
|
return -EINVAL;
|
|
|
|
LOGP(DRLCMACMEAS, LOGL_DEBUG, "DL Loss of TLLI 0x%08x: Received: %4d "
|
|
"Lost: %4d Sum: %4d\n", tbf->tlli(), received, lost, sum);
|
|
|
|
tbf->m_bw.dl_loss_received += received;
|
|
tbf->m_bw.dl_loss_lost += lost;
|
|
|
|
gettimeofday(&now_tv, NULL);
|
|
elapsed = ((now_tv.tv_sec - loss_tv->tv_sec) << 7)
|
|
+ ((now_tv.tv_usec - loss_tv->tv_usec) << 7) / 1000000;
|
|
if (elapsed < 128)
|
|
return 0;
|
|
|
|
gprs_rlcmac_lost_rep(tbf);
|
|
|
|
/* reset lost values and timestamp */
|
|
memcpy(loss_tv, &now_tv, sizeof(struct timeval));
|
|
tbf->m_bw.dl_loss_received = 0;
|
|
tbf->m_bw.dl_loss_lost = 0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Give Lost report */
|
|
int gprs_rlcmac_lost_rep(struct gprs_rlcmac_dl_tbf *tbf)
|
|
{
|
|
uint16_t sum = tbf->m_bw.dl_loss_lost + tbf->m_bw.dl_loss_received;
|
|
|
|
/* No measurement values */
|
|
if (!sum)
|
|
return -EINVAL;
|
|
|
|
LOGP(DRLCMACMEAS, LOGL_INFO, "DL packet loss of IMSI=%s / TLLI=0x%08x: "
|
|
"%d%%\n", tbf->imsi(), tbf->tlli(),
|
|
tbf->m_bw.dl_loss_lost * 100 / sum);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* downlink bandwidth
|
|
*/
|
|
|
|
int gprs_rlcmac_dl_bw(struct gprs_rlcmac_dl_tbf *tbf, uint16_t octets)
|
|
{
|
|
struct timeval now_tv, *bw_tv = &tbf->m_bw.dl_bw_tv;
|
|
uint32_t elapsed;
|
|
|
|
tbf->m_bw.dl_bw_octets += octets;
|
|
|
|
gettimeofday(&now_tv, NULL);
|
|
elapsed = ((now_tv.tv_sec - bw_tv->tv_sec) << 7)
|
|
+ ((now_tv.tv_usec - bw_tv->tv_usec) << 7) / 1000000;
|
|
if (elapsed < 128)
|
|
return 0;
|
|
|
|
LOGP(DRLCMACMEAS, LOGL_INFO, "DL Bandwitdh of IMSI=%s / TLLI=0x%08x: "
|
|
"%d KBits/s\n", tbf->imsi(), tbf->tlli(),
|
|
tbf->m_bw.dl_bw_octets / elapsed);
|
|
|
|
/* reset bandwidth values timestamp */
|
|
memcpy(bw_tv, &now_tv, sizeof(struct timeval));
|
|
tbf->m_bw.dl_bw_octets = 0;
|
|
|
|
return 0;
|
|
}
|
|
|