aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJacob Erlbeck <jerlbeck@sysmocom.de>2015-06-08 11:05:45 +0200
committerJacob Erlbeck <jerlbeck@sysmocom.de>2015-06-22 10:39:06 +0200
commit20f6fd1b63355b9a3ab1423cb24b73ca27f57243 (patch)
tree2c2c07032358dd63a34c045ac04bc3da9eecb52d
parentb4584ff6c433551f9b633d3e0c6d00380119fa89 (diff)
l1: Pass all L1 measurements upwards
Currently only the RSSI value is passed to the upper layers. Other values like TA and BER which are needed for TA update respectively CS selection are not propagated. This commit introduces and passes a struct that contains a set of measurement values. Sponsored-by: On-Waves ehf
-rw-r--r--src/bts.cpp10
-rw-r--r--src/bts.h6
-rw-r--r--src/pcu_l1_if.cpp8
-rw-r--r--src/pcu_l1_if.h34
-rw-r--r--src/sysmo_l1_if.c18
-rw-r--r--src/tbf.h4
-rw-r--r--src/tbf_ul.cpp5
-rw-r--r--tests/tbf/TbfTest.cpp9
8 files changed, 76 insertions, 18 deletions
diff --git a/src/bts.cpp b/src/bts.cpp
index 608bd0e..f94799b 100644
--- a/src/bts.cpp
+++ b/src/bts.cpp
@@ -657,7 +657,8 @@ void gprs_rlcmac_pdch::add_paging(struct gprs_rlcmac_paging *pag)
*
* The blocks are defragmented and forwarded as LLC frames, if complete.
*/
-int gprs_rlcmac_pdch::rcv_data_block_acknowledged(uint8_t *data, uint8_t len, int8_t rssi)
+int gprs_rlcmac_pdch::rcv_data_block_acknowledged(uint8_t *data, uint8_t len,
+ struct pcu_l1_meas *meas)
{
struct gprs_rlcmac_ul_tbf *tbf;
struct rlc_ul_header *rh = (struct rlc_ul_header *)data;
@@ -692,7 +693,7 @@ int gprs_rlcmac_pdch::rcv_data_block_acknowledged(uint8_t *data, uint8_t len, in
return 0;
}
- return tbf->rcv_data_block_acknowledged(data, len, rssi);
+ return tbf->rcv_data_block_acknowledged(data, len, meas);
}
void gprs_rlcmac_pdch::rcv_control_ack(Packet_Control_Acknowledgement_t *packet, uint32_t fn)
@@ -995,7 +996,8 @@ int gprs_rlcmac_pdch::rcv_control_block(
/* received RLC/MAC block from L1 */
-int gprs_rlcmac_pdch::rcv_block(uint8_t *data, uint8_t len, uint32_t fn, int8_t rssi)
+int gprs_rlcmac_pdch::rcv_block(uint8_t *data, uint8_t len, uint32_t fn,
+ struct pcu_l1_meas *meas)
{
unsigned payload = data[0] >> 6;
bitvec *block;
@@ -1003,7 +1005,7 @@ int gprs_rlcmac_pdch::rcv_block(uint8_t *data, uint8_t len, uint32_t fn, int8_t
switch (payload) {
case GPRS_RLCMAC_DATA_BLOCK:
- rc = rcv_data_block_acknowledged(data, len, rssi);
+ rc = rcv_data_block_acknowledged(data, len, meas);
break;
case GPRS_RLCMAC_CONTROL_BLOCK:
block = bitvec_alloc(len);
diff --git a/src/bts.h b/src/bts.h
index e52875e..8233b63 100644
--- a/src/bts.h
+++ b/src/bts.h
@@ -56,7 +56,8 @@ struct gprs_rlcmac_pdch {
void disable();
/* dispatching of messages */
- int rcv_block(uint8_t *data, uint8_t len, uint32_t fn, int8_t rssi);
+ int rcv_block(uint8_t *data, uint8_t len, uint32_t fn,
+ struct pcu_l1_meas *meas);
gprs_rlcmac_bts *bts_data() const;
BTS *bts() const;
@@ -80,7 +81,8 @@ struct gprs_rlcmac_pdch {
#ifdef __cplusplus
private:
- int rcv_data_block_acknowledged(uint8_t *data, uint8_t len, int8_t rssi);
+ int rcv_data_block_acknowledged(uint8_t *data, uint8_t len,
+ struct pcu_l1_meas *meas);
int rcv_control_block(bitvec *rlc_block, uint32_t fn);
void rcv_control_ack(Packet_Control_Acknowledgement_t *, uint32_t fn);
diff --git a/src/pcu_l1_if.cpp b/src/pcu_l1_if.cpp
index 0cb79eb..9d7d9c4 100644
--- a/src/pcu_l1_if.cpp
+++ b/src/pcu_l1_if.cpp
@@ -181,17 +181,19 @@ void pcu_l1if_tx_pch(bitvec * block, int plen, const char *imsi)
}
extern "C" int pcu_rx_data_ind_pdtch(uint8_t trx_no, uint8_t ts_no, uint8_t *data,
- uint8_t len, uint32_t fn, int8_t rssi)
+ uint8_t len, uint32_t fn, struct pcu_l1_meas *meas)
{
struct gprs_rlcmac_pdch *pdch;
pdch = &bts_main_data()->trx[trx_no].pdch[ts_no];
- return pdch->rcv_block(data, len, fn, rssi);
+ return pdch->rcv_block(data, len, fn, meas);
}
static int pcu_rx_data_ind(struct gsm_pcu_if_data *data_ind)
{
int rc = 0;
+ pcu_l1_meas meas;
+ meas.set_rssi(data_ind->rssi);
LOGP(DL1IF, LOGL_DEBUG, "Data indication received: sapi=%d arfcn=%d "
"block=%d data=%s\n", data_ind->sapi,
@@ -202,7 +204,7 @@ static int pcu_rx_data_ind(struct gsm_pcu_if_data *data_ind)
case PCU_IF_SAPI_PDTCH:
rc = pcu_rx_data_ind_pdtch(data_ind->trx_nr, data_ind->ts_nr,
data_ind->data, data_ind->len, data_ind->fn,
- data_ind->rssi);
+ &meas);
break;
default:
LOGP(DL1IF, LOGL_ERROR, "Received PCU data indication with "
diff --git a/src/pcu_l1_if.h b/src/pcu_l1_if.h
index bd8fe94..88c8399 100644
--- a/src/pcu_l1_if.h
+++ b/src/pcu_l1_if.h
@@ -31,7 +31,39 @@ extern "C" {
#include <osmocom/gsm/gsm_utils.h>
#ifdef __cplusplus
}
+#endif
+
+/*
+ * L1 Measurement values
+ */
+
+struct pcu_l1_meas {
+ unsigned have_rssi:1;
+ unsigned have_ber:1;
+ unsigned have_bto:1;
+ unsigned have_link_qual:1;
+ int8_t rssi; /* RSSI in dBm */
+ uint8_t ber; /* Bit error rate in % */
+ int16_t bto; /* Burst timing offset in quarter bits */
+ int16_t link_qual; /* Link quality in db */
+#ifdef __cplusplus
+ pcu_l1_meas& set_rssi(int8_t v) { rssi = v; have_rssi = 1; return *this;}
+ pcu_l1_meas& set_ber(uint8_t v) { ber = v; have_ber = 1; return *this;}
+ pcu_l1_meas& set_bto(int16_t v) { bto = v; have_bto = 1; return *this;}
+ pcu_l1_meas& set_link_qual(int16_t v) {
+ link_qual = v; have_link_qual = 1; return *this;
+ }
+ pcu_l1_meas() :
+ have_rssi(0),
+ have_ber(0),
+ have_bto(0),
+ have_link_qual(0)
+ {}
+#endif
+};
+
+#ifdef __cplusplus
void pcu_l1if_tx_pdtch(msgb *msg, uint8_t trx, uint8_t ts, uint16_t arfcn,
uint32_t fn, uint8_t block_nr);
void pcu_l1if_tx_ptcch(msgb *msg, uint8_t trx, uint8_t ts, uint16_t arfcn,
@@ -57,6 +89,6 @@ int pcu_rx_rts_req_pdtch(uint8_t trx, uint8_t ts, uint16_t arfcn,
extern "C"
#endif
int pcu_rx_data_ind_pdtch(uint8_t trx, uint8_t ts, uint8_t *data,
- uint8_t len, uint32_t fn, int8_t rssi);
+ uint8_t len, uint32_t fn, struct pcu_l1_meas *meas);
#endif // PCU_L1_IF_H
diff --git a/src/sysmo_l1_if.c b/src/sysmo_l1_if.c
index 6e1e9e4..fc4b59b 100644
--- a/src/sysmo_l1_if.c
+++ b/src/sysmo_l1_if.c
@@ -166,10 +166,23 @@ static int handle_ph_readytosend_ind(struct femtol1_hdl *fl1h,
return rc;
}
+static void get_meas(struct pcu_l1_meas *meas, const GsmL1_MeasParam_t *l1_meas)
+{
+ meas->rssi = (int8_t) (l1_meas->fRssi);
+ meas->have_rssi = 1;
+ meas->ber = (uint8_t) (l1_meas->fBer * 100);
+ meas->have_ber = 1;
+ meas->bto = (int16_t) (l1_meas->i16BurstTiming);
+ meas->have_bto = 1;
+ meas->link_qual = (int16_t) (l1_meas->fLinkQuality);
+ meas->have_link_qual = 1;
+}
+
static int handle_ph_data_ind(struct femtol1_hdl *fl1h,
GsmL1_PhDataInd_t *data_ind, struct msgb *l1p_msg)
{
int rc = 0;
+ struct pcu_l1_meas meas = {0};
DEBUGP(DL1IF, "Rx PH-DATA.ind %s (hL2 %08x): %s\n",
get_value_string(femtobts_l1sapi_names, data_ind->sapi),
@@ -190,8 +203,7 @@ static int handle_ph_data_ind(struct femtol1_hdl *fl1h,
data_ind->u32Fn, 0, 0, data_ind->msgUnitParam.u8Buffer+1,
data_ind->msgUnitParam.u8Size-1);
-
-
+ get_meas(&meas, &data_ind->measParam);
switch (data_ind->sapi) {
case GsmL1_Sapi_Pdtch:
@@ -205,7 +217,7 @@ static int handle_ph_data_ind(struct femtol1_hdl *fl1h,
data_ind->msgUnitParam.u8Buffer + 1,
data_ind->msgUnitParam.u8Size - 1,
data_ind->u32Fn,
- (int8_t) (data_ind->measParam.fRssi));
+ &meas);
break;
case GsmL1_Sapi_Ptcch:
// FIXME
diff --git a/src/tbf.h b/src/tbf.h
index 8e4c3b9..c74fcc3 100644
--- a/src/tbf.h
+++ b/src/tbf.h
@@ -30,6 +30,7 @@
struct bssgp_bvc_ctx;
struct rlc_ul_header;
struct msgb;
+struct pcu_l1_meas;
class GprsMs;
/*
@@ -372,7 +373,8 @@ struct gprs_rlcmac_ul_tbf : public gprs_rlcmac_tbf {
struct msgb *create_ul_ack(uint32_t fn);
/* blocks were acked */
- int rcv_data_block_acknowledged(const uint8_t *data, size_t len, int8_t rssi);
+ int rcv_data_block_acknowledged(const uint8_t *data, size_t len,
+ struct pcu_l1_meas *meas);
/* TODO: extract LLC class? */
int assemble_forward_llc(const gprs_rlc_data *data);
diff --git a/src/tbf_ul.cpp b/src/tbf_ul.cpp
index 3ab71f0..b9ea659 100644
--- a/src/tbf_ul.cpp
+++ b/src/tbf_ul.cpp
@@ -27,6 +27,7 @@
#include <gprs_debug.h>
#include <gprs_bssgp_pcu.h>
#include <decoding.h>
+#include <pcu_l1_if.h>
extern "C" {
#include <osmocom/core/msgb.h>
@@ -261,10 +262,12 @@ struct msgb *gprs_rlcmac_ul_tbf::create_ul_ack(uint32_t fn)
return msg;
}
-int gprs_rlcmac_ul_tbf::rcv_data_block_acknowledged(const uint8_t *data, size_t len, int8_t rssi)
+int gprs_rlcmac_ul_tbf::rcv_data_block_acknowledged(const uint8_t *data,
+ size_t len, struct pcu_l1_meas *meas)
{
struct rlc_ul_header *rh = (struct rlc_ul_header *)data;
int rc;
+ int8_t rssi = meas->have_rssi ? meas->rssi : 0;
const uint16_t mod_sns = m_window.mod_sns();
const uint16_t ws = m_window.ws();
diff --git a/tests/tbf/TbfTest.cpp b/tests/tbf/TbfTest.cpp
index e5e7156..c7393f4 100644
--- a/tests/tbf/TbfTest.cpp
+++ b/tests/tbf/TbfTest.cpp
@@ -438,6 +438,7 @@ static void test_tbf_single_phase()
int tfi = 0;
gprs_rlcmac_ul_tbf *ul_tbf;
struct gprs_rlcmac_pdch *pdch;
+ struct pcu_l1_meas meas;
printf("=== start %s ===\n", __func__);
@@ -462,7 +463,7 @@ static void test_tbf_single_phase()
};
pdch = &the_bts.bts_data()->trx[trx_no].pdch[ts_no];
- pdch->rcv_block(&data_msg[0], sizeof(data_msg), fn, 0);
+ pdch->rcv_block(&data_msg[0], sizeof(data_msg), fn, &meas);
ms = the_bts.ms_by_tlli(0xf1223344);
OSMO_ASSERT(ms != NULL);
@@ -491,6 +492,8 @@ static void test_tbf_two_phase()
bitvec *rlc_block;
uint8_t buf[64];
int num_bytes;
+ struct pcu_l1_meas meas;
+ meas.set_rssi(31);
printf("=== start %s ===\n", __func__);
@@ -520,7 +523,7 @@ static void test_tbf_two_phase()
bitvec_free(rlc_block);
pdch = &the_bts.bts_data()->trx[trx_no].pdch[ts_no];
- pdch->rcv_block(&buf[0], num_bytes, 2654270, 31);
+ pdch->rcv_block(&buf[0], num_bytes, 2654270, &meas);
/* check the TBF */
ul_tbf = the_bts.ul_tbf_by_tfi(tfi, trx_no);
@@ -543,7 +546,7 @@ static void test_tbf_two_phase()
uint8_t(1), /* BSN:7, E:1 */
};
- pdch->rcv_block(&data_msg[0], sizeof(data_msg), rts_fn, 31);
+ pdch->rcv_block(&data_msg[0], sizeof(data_msg), rts_fn, &meas);
ms = the_bts.ms_by_tlli(0xf1223344);
OSMO_ASSERT(ms != NULL);