aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--openbsc/include/openbsc/gsm_data.h6
-rw-r--r--openbsc/src/abis_rsl.c36
-rw-r--r--openbsc/src/chan_alloc.c9
-rw-r--r--openbsc/src/gsm_04_08.c4
-rw-r--r--openbsc/src/gsm_data.c13
5 files changed, 47 insertions, 21 deletions
diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h
index 012481a5f..b21f8aa05 100644
--- a/openbsc/include/openbsc/gsm_data.h
+++ b/openbsc/include/openbsc/gsm_data.h
@@ -194,6 +194,10 @@ struct gsm_lchan {
/* use count. how many users use this channel */
unsigned int use_count;
+ /* cache of last measurement reports on this lchan */
+ struct gsm_meas_rep meas_rep[6];
+ int meas_rep_idx;
+
struct {
u_int32_t bound_ip;
u_int16_t bound_port;
@@ -564,4 +568,6 @@ const char *rrlp_mode_name(enum rrlp_mode mode);
void gsm_trx_lock_rf(struct gsm_bts_trx *trx, int locked);
+struct gsm_meas_rep *lchan_next_meas_rep(struct gsm_lchan *lchan);
+
#endif
diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c
index c6675c840..51d524459 100644
--- a/openbsc/src/abis_rsl.c
+++ b/openbsc/src/abis_rsl.c
@@ -998,14 +998,12 @@ static int rsl_rx_meas_res(struct msgb *msg)
{
struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
struct tlv_parsed tp;
- struct gsm_meas_rep mr;
+ struct gsm_meas_rep *mr = lchan_next_meas_rep(msg->lchan);
u_int8_t len;
const u_int8_t *val;
int rc;
- memset(&mr, 0, sizeof(mr));
-
- mr.lchan = msg->lchan;
+ memset(mr, 0, sizeof(*mr));
rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
@@ -1015,44 +1013,44 @@ static int rsl_rx_meas_res(struct msgb *msg)
return -EIO;
/* Mandatory Parts */
- mr.nr = *TLVP_VAL(&tp, RSL_IE_MEAS_RES_NR);
+ mr->nr = *TLVP_VAL(&tp, RSL_IE_MEAS_RES_NR);
len = TLVP_LEN(&tp, RSL_IE_UPLINK_MEAS);
val = TLVP_VAL(&tp, RSL_IE_UPLINK_MEAS);
if (len >= 3) {
if (val[0] & 0x40)
- mr.flags |= MEAS_REP_F_DL_DTX;
- mr.ul.full.rx_lev = val[0] & 0x3f;
- mr.ul.sub.rx_lev = val[1] & 0x3f;
- mr.ul.full.rx_qual = val[2]>>3 & 0x7;
- mr.ul.sub.rx_qual = val[2] & 0x7;
+ mr->flags |= MEAS_REP_F_DL_DTX;
+ mr->ul.full.rx_lev = val[0] & 0x3f;
+ mr->ul.sub.rx_lev = val[1] & 0x3f;
+ mr->ul.full.rx_qual = val[2]>>3 & 0x7;
+ mr->ul.sub.rx_qual = val[2] & 0x7;
}
- mr.bs_power = *TLVP_VAL(&tp, RSL_IE_BS_POWER);
+ mr->bs_power = *TLVP_VAL(&tp, RSL_IE_BS_POWER);
/* Optional Parts */
if (TLVP_PRESENT(&tp, RSL_IE_MS_TIMING_OFFSET))
- mr.ms_timing_offset =
+ mr->ms_timing_offset =
*TLVP_VAL(&tp, RSL_IE_MS_TIMING_OFFSET);
if (TLVP_PRESENT(&tp, RSL_IE_L1_INFO)) {
val = TLVP_VAL(&tp, RSL_IE_L1_INFO);
- mr.flags |= MEAS_REP_F_MS_L1;
- mr.ms_l1.pwr = ms_pwr_dbm(msg->trx->bts->band, val[0] >> 3);
+ mr->flags |= MEAS_REP_F_MS_L1;
+ mr->ms_l1.pwr = ms_pwr_dbm(msg->trx->bts->band, val[0] >> 3);
if (val[0] & 0x04)
- mr.flags |= MEAS_REP_F_FPC;
- mr.ms_l1.ta = val[1];
+ mr->flags |= MEAS_REP_F_FPC;
+ mr->ms_l1.ta = val[1];
}
if (TLVP_PRESENT(&tp, RSL_IE_L3_INFO)) {
msg->l3h = (u_int8_t *) TLVP_VAL(&tp, RSL_IE_L3_INFO);
- rc = gsm48_parse_meas_rep(&mr, msg);
+ rc = gsm48_parse_meas_rep(mr, msg);
if (rc < 0)
return rc;
}
- print_meas_rep(&mr);
+ print_meas_rep(mr);
- dispatch_signal(SS_LCHAN, S_LCHAN_MEAS_REP, &mr);
+ dispatch_signal(SS_LCHAN, S_LCHAN_MEAS_REP, mr);
return 0;
}
diff --git a/openbsc/src/chan_alloc.c b/openbsc/src/chan_alloc.c
index 2f0d7b93f..0a2984773 100644
--- a/openbsc/src/chan_alloc.c
+++ b/openbsc/src/chan_alloc.c
@@ -235,6 +235,8 @@ struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type)
/* Free a logical channel */
void lchan_free(struct gsm_lchan *lchan)
{
+ int i;
+
lchan->type = GSM_LCHAN_NONE;
if (lchan->subscr) {
subscr_put(lchan->subscr);
@@ -250,6 +252,13 @@ void lchan_free(struct gsm_lchan *lchan)
/* stop the timer */
bsc_del_timer(&lchan->release_timer);
+ /* clear cached measuement reports */
+ lchan->meas_rep_idx = 0;
+ for (i = 0; i < ARRAY_SIZE(lchan->meas_rep); i++) {
+ lchan->meas_rep[i].flags = 0;
+ lchan->meas_rep[i].nr = 0;
+ }
+
/* FIXME: ts_free() the timeslot, if we're the last logical
* channel using it */
}
diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c
index 6d05a20ad..ef29b29cc 100644
--- a/openbsc/src/gsm_04_08.c
+++ b/openbsc/src/gsm_04_08.c
@@ -1558,13 +1558,13 @@ static int gsm48_rx_rr_status(struct msgb *msg)
static int gsm48_rx_rr_meas_rep(struct msgb *msg)
{
- static struct gsm_meas_rep meas_rep;
+ struct gsm_meas_rep *meas_rep = lchan_next_meas_rep(msg->lchan);
/* This shouldn't actually end up here, as RSL treats
* L3 Info of 08.58 MEASUREMENT REPORT different by calling
* directly into gsm48_parse_meas_rep */
DEBUGP(DMEAS, "DIRECT GSM48 MEASUREMENT REPORT ?!? ");
- gsm48_parse_meas_rep(&meas_rep, msg);
+ gsm48_parse_meas_rep(meas_rep, msg);
return 0;
}
diff --git a/openbsc/src/gsm_data.c b/openbsc/src/gsm_data.c
index 91a854f46..94ed91ba5 100644
--- a/openbsc/src/gsm_data.c
+++ b/openbsc/src/gsm_data.c
@@ -415,3 +415,16 @@ const char *rrlp_mode_name(enum rrlp_mode mode)
return "none";
return rrlp_mode_names[mode];
}
+
+struct gsm_meas_rep *lchan_next_meas_rep(struct gsm_lchan *lchan)
+{
+ struct gsm_meas_rep *meas_rep;
+
+ meas_rep = &lchan->meas_rep[lchan->meas_rep_idx];
+ memset(meas_rep, 0, sizeof(*meas_rep));
+ meas_rep->lchan = lchan;
+ lchan->meas_rep_idx = (lchan->meas_rep_idx + 1)
+ % ARRAY_SIZE(lchan->meas_rep);
+
+ return meas_rep;
+}