From 5c70e48077352d35b86aec733dda59d05aab1e01 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Thu, 4 Jan 2018 01:26:34 +0100 Subject: trxcon/scheduler: reset lchan state after deactivation Let's assume that a logical channel, which was already in use, is activated again for a new connection. As we don't reset the state variables, such as burst masks or ciphering data, it may cause an unexpected behaviour. In order to avoid this, let's always reset the logical channel state after deactivation. Change-Id: I91e736a97cb05b167614cb488a00d847a9a859e0 --- src/host/trxcon/sched_trx.c | 58 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 13 deletions(-) diff --git a/src/host/trxcon/sched_trx.c b/src/host/trxcon/sched_trx.c index 120098bd..2142119f 100644 --- a/src/host/trxcon/sched_trx.c +++ b/src/host/trxcon/sched_trx.c @@ -406,6 +406,42 @@ int sched_trx_activate_lchan(struct trx_ts *ts, enum trx_lchan_type chan) return 0; } +static void sched_trx_reset_lchan(struct trx_lchan_state *lchan) +{ + /* Prevent NULL-pointer deference */ + OSMO_ASSERT(lchan != NULL); + + /* Reset internal state variables */ + lchan->rx_burst_mask = 0x00; + lchan->tx_burst_mask = 0x00; + lchan->rx_first_fn = 0; + + /* Free burst memory */ + talloc_free(lchan->rx_bursts); + talloc_free(lchan->tx_bursts); + + lchan->rx_bursts = NULL; + lchan->tx_bursts = NULL; + + /* Forget the current prim */ + sched_prim_drop(lchan); + + /* TCH specific variables */ + if (CHAN_IS_TCH(lchan->type)) { + lchan->dl_ongoing_facch = 0; + lchan->ul_ongoing_facch = 0; + + lchan->rsl_cmode = 0x00; + lchan->tch_mode = 0x00; + + /* Reset AMR state */ + memset(&lchan->amr, 0x00, sizeof(lchan->amr)); + } + + /* Reset ciphering state */ + memset(&lchan->a5, 0x00, sizeof(lchan->a5)); +} + int sched_trx_deactivate_lchan(struct trx_ts *ts, enum trx_lchan_type chan) { struct trx_lchan_state *lchan; @@ -424,16 +460,10 @@ int sched_trx_deactivate_lchan(struct trx_ts *ts, enum trx_lchan_type chan) LOGP(DSCH, LOGL_DEBUG, "Deactivating lchan=%s " "on ts=%d\n", trx_lchan_desc[chan].name, ts->index); - /* Free memory */ - talloc_free(lchan->rx_bursts); - talloc_free(lchan->tx_bursts); - - /* Reset ciphering state */ - memset(&lchan->a5, 0x00, sizeof(lchan->a5)); - - /* Forget the current prim */ - sched_prim_drop(lchan); + /* Reset internal state, free memory */ + sched_trx_reset_lchan(lchan); + /* Update activation flag */ lchan->active = 0; return 0; @@ -451,12 +481,14 @@ void sched_trx_deactivate_all_lchans(struct trx_ts *ts) for (i = 0; i < len; i++) { lchan = ts->lchans + i; - talloc_free(lchan->rx_bursts); - talloc_free(lchan->tx_bursts); + /* Omit inactive channels */ + if (!lchan->active) + continue; - /* Forget the current prim */ - sched_prim_drop(lchan); + /* Reset internal state, free memory */ + sched_trx_reset_lchan(lchan); + /* Update activation flag */ lchan->active = 0; } } -- cgit v1.2.3