introduce cache of 6 last recently received measurement reports for each lchan
This commit is contained in:
parent
0b12103965
commit
d12b0fdf51
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue