aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2013-03-16 16:22:02 +0100
committerHarald Welte <laforge@gnumonks.org>2013-03-17 17:16:44 +0100
commit050ace2fb47fc6b490a09512efbad4c902044dea (patch)
treed2465e155dda5db6589dc7f6aa8efdd402ccdbbb
parent570b44b29bf1186448e2838a537e1c2e250585fe (diff)
Introduce new file for various measurements
The measurements include: - DL bandwidth usage - DL packet loss rate - DL measurements by mobile - UL measurements by BTS In order to receive DL measurements from mobile, it must be enabled via system information message at BSC.
-rw-r--r--src/Makefile.am1
-rw-r--r--src/gprs_bssgp_pcu.cpp3
-rw-r--r--src/gprs_debug.cpp2
-rw-r--r--src/gprs_debug.h2
-rw-r--r--src/gprs_rlcmac.cpp8
-rw-r--r--src/gprs_rlcmac.h30
-rw-r--r--src/gprs_rlcmac_data.cpp84
-rw-r--r--src/gprs_rlcmac_meas.cpp190
8 files changed, 271 insertions, 49 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index b4dcfed9..b20b0a98 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -36,6 +36,7 @@ libgprs_la_SOURCES = \
gprs_rlcmac.cpp \
gprs_rlcmac_data.cpp \
gprs_rlcmac_sched.cpp \
+ gprs_rlcmac_meas.cpp \
gsm_timer.cpp \
bitvector.cpp \
pcu_l1_if.cpp \
diff --git a/src/gprs_bssgp_pcu.cpp b/src/gprs_bssgp_pcu.cpp
index 17c3fe45..5dbfb2c1 100644
--- a/src/gprs_bssgp_pcu.cpp
+++ b/src/gprs_bssgp_pcu.cpp
@@ -244,6 +244,9 @@ int gprs_bssgp_pcu_rx_dl_ud(struct msgb *msg, struct tlv_parsed *tp)
gprs_rlcmac_trigger_downlink_assignment(tbf, old_tbf, imsi);
}
+ /* store IMSI for debugging purpose */
+ strncpy(tbf->meas.imsi, imsi, sizeof(tbf->meas.imsi) - 1);
+
return 0;
}
diff --git a/src/gprs_debug.cpp b/src/gprs_debug.cpp
index 6da0d516..6f9e310a 100644
--- a/src/gprs_debug.cpp
+++ b/src/gprs_debug.cpp
@@ -40,7 +40,7 @@ static const struct log_info_cat default_categories[] = {
{"DRLCMACDL", "\033[1;33m", "GPRS RLC/MAC layer Downlink (RLCMAC)", LOGL_NOTICE, 1},
{"DRLCMACUL", "\033[1;36m", "GPRS RLC/MAC layer Uplink (RLCMAC)", LOGL_NOTICE, 1},
{"DRLCMACSCHED", "\033[0;36m", "GPRS RLC/MAC layer Scheduling (RLCMAC)", LOGL_NOTICE, 1},
- {"DRLCMACBW", "\033[1;31m", "GPRS RLC/MAC layer Bandwidth (RLCMAC)", LOGL_INFO, 1},
+ {"DRLCMACMEAS", "\033[1;31m", "GPRS RLC/MAC layer Measurements (RLCMAC)", LOGL_INFO, 1},
{"DBSSGP","\033[1;34m", "GPRS BSS Gateway Protocol (BSSGP)", LOGL_INFO , 1},
{"DPCU", "\033[1;35m", "GPRS Packet Control Unit (PCU)", LOGL_NOTICE, 1},
};
diff --git a/src/gprs_debug.h b/src/gprs_debug.h
index abd5d95a..8b113a1b 100644
--- a/src/gprs_debug.h
+++ b/src/gprs_debug.h
@@ -38,7 +38,7 @@ enum {
DRLCMACDL,
DRLCMACUL,
DRLCMACSCHED,
- DRLCMACBW,
+ DRLCMACMEAS,
DBSSGP,
DPCU,
aDebug_LastEntry
diff --git a/src/gprs_rlcmac.cpp b/src/gprs_rlcmac.cpp
index ff4cbddb..2c873172 100644
--- a/src/gprs_rlcmac.cpp
+++ b/src/gprs_rlcmac.cpp
@@ -384,7 +384,9 @@ next_diagram:
}
/* set timestamp */
- gettimeofday(&tbf->bw_tv, NULL);
+ gettimeofday(&tbf->meas.dl_bw_tv, NULL);
+ gettimeofday(&tbf->meas.rssi_tv, NULL);
+ gettimeofday(&tbf->meas.dl_loss_tv, NULL);
INIT_LLIST_HEAD(&tbf->llc_queue);
if (dir == GPRS_RLCMAC_UL_TBF)
@@ -914,6 +916,10 @@ void tbf_free(struct gprs_rlcmac_tbf *tbf)
{
struct msgb *msg;
+ /* Give final measurement report */
+ gprs_rlcmac_rssi_rep(tbf);
+ gprs_rlcmac_lost_rep(tbf);
+
debug_diagram(tbf->diag, "+---------------+");
debug_diagram(tbf->diag, "| THE END |");
debug_diagram(tbf->diag, "+---------------+");
diff --git a/src/gprs_rlcmac.h b/src/gprs_rlcmac.h
index 67edca1a..5badb120 100644
--- a/src/gprs_rlcmac.h
+++ b/src/gprs_rlcmac.h
@@ -226,8 +226,21 @@ struct gprs_rlcmac_tbf {
unsigned int fT; /* fTxxxx number */
unsigned int num_fT_exp; /* number of consecutive fT expirations */
- struct timeval bw_tv; /* timestamp for bandwidth calculation */
- uint32_t bw_octets; /* number of octets transmitted since bw_tv */
+ struct {
+ char imsi[16];
+
+ struct timeval dl_bw_tv; /* timestamp for dl bw calculation */
+ uint32_t dl_bw_octets; /* number of octets since bw_tv */
+
+ struct timeval rssi_tv; /* timestamp for rssi calculation */
+ int32_t rssi_sum; /* sum of rssi values */
+ int rssi_num; /* number of rssi values added since rssi_tv */
+
+ struct timeval dl_loss_tv; /* timestamp for loss calculation */
+ uint16_t dl_loss_lost; /* sum of lost packets */
+ uint16_t dl_loss_received; /* sum of received packets */
+
+ } meas;
uint8_t cs; /* current coding scheme */
@@ -278,6 +291,19 @@ void debug_diagram(int diag, const char *format, ...);
#define debug_diagram(a, b, args...) ;
#endif
+int gprs_rlcmac_received_lost(struct gprs_rlcmac_tbf *tbf, uint16_t received,
+ uint16_t lost);
+
+int gprs_rlcmac_lost_rep(struct gprs_rlcmac_tbf *tbf);
+
+int gprs_rlcmac_meas_rep(Packet_Measurement_Report_t *pmr);
+
+int gprs_rlcmac_rssi(struct gprs_rlcmac_tbf *tbf, int8_t rssi);
+
+int gprs_rlcmac_rssi_rep(struct gprs_rlcmac_tbf *tbf);
+
+int gprs_rlcmac_dl_bw(struct gprs_rlcmac_tbf *tbf, uint16_t octets);
+
int sba_alloc(uint8_t *_trx, uint8_t *_ts, uint32_t *_fn, uint8_t ta);
struct gprs_rlcmac_sba *sba_find(uint8_t trx, uint8_t ts, uint32_t fn);
diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp
index e7b29723..1109451e 100644
--- a/src/gprs_rlcmac_data.cpp
+++ b/src/gprs_rlcmac_data.cpp
@@ -468,6 +468,9 @@ int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint8_t trx, uint8_t ts,
}
LOGP(DRLCMAC, LOGL_ERROR, "RX: [PCU <- BTS] %s TFI: %u TLLI: 0x%08x FIXME: Packet ressource request\n", (tbf->direction == GPRS_RLCMAC_UL_TBF) ? "UL" : "DL", tbf->tfi, tbf->tlli);
break;
+ case MT_PACKET_MEASUREMENT_REPORT:
+ gprs_rlcmac_meas_rep(&ul_control_block->u.Packet_Measurement_Report);
+ break;
default:
LOGP(DRLCMAC, LOGL_NOTICE, "RX: [PCU <- BTS] unknown control block received\n");
}
@@ -846,6 +849,9 @@ int gprs_rlcmac_rcv_data_block_acknowledged(uint8_t trx, uint8_t ts,
LOGP(DRLCMACUL, LOGL_DEBUG, "UL DATA TBF=%d received (V(Q)=%d .. "
"V(R)=%d)\n", rh->tfi, tbf->dir.ul.v_q, tbf->dir.ul.v_r);
+ /* process RSSI */
+ gprs_rlcmac_rssi(tbf, rssi);
+
/* get TLLI */
if (!tbf->tlli_valid) {
struct gprs_rlcmac_tbf *dl_tbf, *ul_tbf;
@@ -1213,29 +1219,6 @@ static struct msgb *llc_dequeue(struct gprs_rlcmac_tbf *tbf)
return msg;
}
-static int gprs_rlcmac_debug_bw(struct gprs_rlcmac_tbf *tbf, uint16_t octets)
-{
- struct timeval now_tv, *bw_tv = &tbf->bw_tv;
- uint32_t elapsed;
-
- tbf->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(DRLCMACBW, LOGL_DEBUG, "DL Bandwitdh of TLLI=0x%08x: %d KBits/s\n",
- tbf->tlli, tbf->bw_octets / elapsed);
-
- /* reset bandwidth values timestamp */
- memcpy(bw_tv, &now_tv, sizeof(struct timeval));
- tbf->bw_octets = 0;
-
- return 0;
-}
-
/* send DL data block
*
* The messages are fragmented and forwarded as data blocks.
@@ -1380,7 +1363,7 @@ do_resend:
LOGP(DRLCMACDL, LOGL_INFO, "Complete DL frame for "
"TBF=%d that fits precisely in last block: "
"len=%d\n", tbf->tfi, tbf->llc_length);
- gprs_rlcmac_debug_bw(tbf, tbf->llc_length);
+ gprs_rlcmac_dl_bw(tbf, tbf->llc_length);
/* block is filled, so there is no extension */
*e_pointer |= 0x01;
/* fill space */
@@ -1440,7 +1423,7 @@ do_resend:
space -= chunk;
LOGP(DRLCMACDL, LOGL_INFO, "Complete DL frame for TBF=%d: "
"len=%d\n", tbf->tfi, tbf->llc_length);
- gprs_rlcmac_debug_bw(tbf, tbf->llc_length);
+ gprs_rlcmac_dl_bw(tbf, tbf->llc_length);
/* reset LLC frame */
tbf->llc_index = tbf->llc_length = 0;
/* dequeue next LLC frame, if any */
@@ -1568,6 +1551,7 @@ int gprs_rlcmac_downlink_ack(struct gprs_rlcmac_tbf *tbf, uint8_t final,
uint8_t bit;
uint16_t bsn;
struct msgb *msg;
+ uint16_t lost = 0, received = 0;
LOGP(DRLCMACDL, LOGL_DEBUG, "TBF=%d downlink acknowledge\n",
tbf->tfi);
@@ -1587,25 +1571,7 @@ int gprs_rlcmac_downlink_ack(struct gprs_rlcmac_tbf *tbf, uint8_t final,
/* calculate distance of ssn from V(S) */
dist = (tbf->dir.dl.v_s - ssn) & mod_sns;
/* check if distance is less than distance V(A)..V(S) */
- if (dist < ((tbf->dir.dl.v_s - tbf->dir.dl.v_a) & mod_sns)) {
- /* SSN - 1 is in range V(A)..V(S)-1 */
- for (i = 63, bsn = (ssn - 1) & mod_sns;
- i >= 0 && bsn != ((tbf->dir.dl.v_a - 1) & mod_sns);
- i--, bsn = (bsn - 1) & mod_sns) {
- bit = (rbb[i >> 3] >> (7 - (i&7))) & 1;
- if (bit) {
- LOGP(DRLCMACDL, LOGL_DEBUG, "- got "
- "ack for BSN=%d\n", bsn);
- tbf->dir.dl.v_b[bsn & mod_sns_half]
- = 'A';
- } else {
- LOGP(DRLCMACDL, LOGL_DEBUG, "- got "
- "NACK for BSN=%d\n", bsn);
- tbf->dir.dl.v_b[bsn & mod_sns_half]
- = 'N';
- }
- }
- } else {
+ if (dist >= ((tbf->dir.dl.v_s - tbf->dir.dl.v_a) & mod_sns)) {
/* this might happpen, if the downlink assignment
* was not received by ms and the ack refers
* to previous TBF
@@ -1616,6 +1582,27 @@ int gprs_rlcmac_downlink_ack(struct gprs_rlcmac_tbf *tbf, uint8_t final,
tbf->tfi);
return 1; /* indicate to free TBF */
}
+ /* SSN - 1 is in range V(A)..V(S)-1 */
+ for (i = 63, bsn = (ssn - 1) & mod_sns;
+ i >= 0 && bsn != ((tbf->dir.dl.v_a - 1) & mod_sns);
+ i--, bsn = (bsn - 1) & mod_sns) {
+ bit = (rbb[i >> 3] >> (7 - (i&7))) & 1;
+ if (bit) {
+ LOGP(DRLCMACDL, LOGL_DEBUG, "- got "
+ "ack for BSN=%d\n", bsn);
+ if (tbf->dir.dl.v_b[bsn & mod_sns_half]
+ != 'A')
+ received++;
+ tbf->dir.dl.v_b[bsn & mod_sns_half] = 'A';
+ } else {
+ LOGP(DRLCMACDL, LOGL_DEBUG, "- got "
+ "NACK for BSN=%d\n", bsn);
+ tbf->dir.dl.v_b[bsn & mod_sns_half] = 'N';
+ lost++;
+ }
+ }
+ /* report lost and received packets */
+ gprs_rlcmac_received_lost(tbf, received, lost);
/* raise V(A), if possible */
for (i = 0, bsn = tbf->dir.dl.v_a; bsn != tbf->dir.dl.v_s;
@@ -1653,6 +1640,15 @@ int gprs_rlcmac_downlink_ack(struct gprs_rlcmac_tbf *tbf, uint8_t final,
LOGP(DRLCMACDL, LOGL_DEBUG, "- Final ACK received.\n");
debug_diagram(tbf->diag, "got Final ACK");
+ /* range V(A)..V(S)-1 */
+ for (bsn = tbf->dir.dl.v_a; bsn != tbf->dir.dl.v_s;
+ bsn = (bsn + 1) & mod_sns) {
+ if (tbf->dir.dl.v_b[bsn & mod_sns_half] != 'A')
+ received++;
+ }
+
+ /* report all outstanding packets as received */
+ gprs_rlcmac_received_lost(tbf, received, lost);
/* check for LLC PDU in the LLC Queue */
msg = llc_dequeue(tbf);
diff --git a/src/gprs_rlcmac_meas.cpp b/src/gprs_rlcmac_meas.cpp
new file mode 100644
index 00000000..75da835a
--- /dev/null
+++ b/src/gprs_rlcmac_meas.cpp
@@ -0,0 +1,190 @@
+/* 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 <string.h>
+#include <errno.h>
+
+/*
+ * downlink measurement
+ */
+
+/* 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_tbf *tbf, uint16_t received,
+ uint16_t lost)
+{
+ struct timeval now_tv, *loss_tv = &tbf->meas.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->meas.dl_loss_received += received;
+ tbf->meas.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->meas.dl_loss_received = 0;
+ tbf->meas.dl_loss_lost = 0;
+
+ return 0;
+}
+
+/* Give Lost report */
+int gprs_rlcmac_lost_rep(struct gprs_rlcmac_tbf *tbf)
+{
+ uint16_t sum = tbf->meas.dl_loss_lost + tbf->meas.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->meas.imsi, tbf->tlli,
+ tbf->meas.dl_loss_lost * 100 / sum);
+
+ return 0;
+}
+
+
+/*
+ * downlink bandwidth
+ */
+
+int gprs_rlcmac_dl_bw(struct gprs_rlcmac_tbf *tbf, uint16_t octets)
+{
+ struct timeval now_tv, *bw_tv = &tbf->meas.dl_bw_tv;
+ uint32_t elapsed;
+
+ tbf->meas.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->meas.imsi, tbf->tlli,
+ tbf->meas.dl_bw_octets / elapsed);
+
+ /* reset bandwidth values timestamp */
+ memcpy(bw_tv, &now_tv, sizeof(struct timeval));
+ tbf->meas.dl_bw_octets = 0;
+
+ return 0;
+}
+