/* Measurements * * Copyright (C) 2012 Andreas Eversberg * * 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 #include #include #include #include #include /* * 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, " \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; }