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
This commit is contained in:
Jacob Erlbeck 2015-06-08 11:05:45 +02:00
parent b4584ff6c4
commit 20f6fd1b63
8 changed files with 76 additions and 18 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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 "

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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();

View File

@ -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);