From 285df2ec624f5c51ca5621de0524fba64226d4ed Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Mon, 13 Jun 2016 12:28:21 +0200 Subject: dyn PDCH: add lchan sanity checks in PDCH DE/ACT ACK Change-Id: I0456cfb88860823c37c14688673e9cbc8d0085d8 --- openbsc/src/libbsc/abis_rsl.c | 54 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/openbsc/src/libbsc/abis_rsl.c b/openbsc/src/libbsc/abis_rsl.c index 349b3de39..3aefd9c13 100644 --- a/openbsc/src/libbsc/abis_rsl.c +++ b/openbsc/src/libbsc/abis_rsl.c @@ -1201,8 +1201,59 @@ static int rsl_rx_hando_det(struct msgb *msg) return 0; } +static bool lchan_may_change_pdch(struct gsm_lchan *lchan, bool pdch_act) +{ + struct gsm_bts_trx_ts *ts; + bool ok; + + OSMO_ASSERT(lchan); + + ts = lchan->ts; + OSMO_ASSERT(ts); + OSMO_ASSERT(ts->trx); + OSMO_ASSERT(ts->trx->bts); + + if (lchan->ts->pchan != GSM_PCHAN_TCH_F_PDCH) { + LOGP(DRSL, LOGL_ERROR, "(bts %u, trx %u, ts %u, pchan %s)" + " Rx PDCH %s ACK for channel that is no TCH/F_PDCH\n", + ts->trx->bts->nr, ts->trx->nr, ts->nr, + gsm_pchan_name(ts->pchan), + pdch_act? "ACT" : "DEACT"); + return false; + } + + /* During BTS initialization, we expect to PDCH ACT in channel state == + * NONE. However, during dynamic channel switching, we will PDCH ACT + * while in state DEACTIVATION REQUESTED (we're deactivating TCH/F + * while activating PDCH); and we will PDCH DEACT while in state + * ACTIVATION REQUESTED (we're activating TCH/F while deactivating + * PDCH). */ + /* FIXME: rather switch PDCH while in state NONE, i.e. after + * deactivation of TCH/F and before activation of TCH/F? */ + if (pdch_act) + ok = (lchan->state == LCHAN_S_NONE + || lchan->state == LCHAN_S_REL_REQ); + else + ok = (lchan->state == LCHAN_S_NONE + || lchan->state == LCHAN_S_ACT_REQ); + + if (!ok) { + LOGP(DRSL, LOGL_ERROR, "(bts %u, trx %u, ts %u, pchan %s)" + " Rx PDCH %s ACK in unexpected state: %s\n", + ts->trx->bts->nr, ts->trx->nr, ts->nr, + gsm_pchan_name(ts->pchan), + pdch_act? "ACT" : "DEACT", + gsm_lchans_name(lchan->state)); + return false; + } + return true; +} + static int rsl_rx_pdch_act_ack(struct msgb *msg) { + if (!lchan_may_change_pdch(msg->lchan, true)) + return -EINVAL; + msg->lchan->ts->flags |= TS_F_PDCH_ACTIVE; msg->lchan->ts->flags &= ~TS_F_PDCH_ACT_PENDING; @@ -1214,6 +1265,9 @@ static int rsl_rx_pdch_act_ack(struct msgb *msg) static int rsl_rx_pdch_deact_ack(struct msgb *msg) { + if (!lchan_may_change_pdch(msg->lchan, false)) + return -EINVAL; + msg->lchan->ts->flags &= ~TS_F_PDCH_ACTIVE; msg->lchan->ts->flags &= ~TS_F_PDCH_DEACT_PENDING; -- cgit v1.2.3