diff options
author | Vadim Yanitskiy <axilirator@gmail.com> | 2018-01-04 01:26:34 +0100 |
---|---|---|
committer | Vadim Yanitskiy <axilirator@gmail.com> | 2018-01-05 14:35:29 +0700 |
commit | 5c70e48077352d35b86aec733dda59d05aab1e01 (patch) | |
tree | 5196621d4007dd1ac953242e4709a423a174056c | |
parent | 96da00d45766d43c919d059fb94e9106cff33f2b (diff) |
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
-rw-r--r-- | src/host/trxcon/sched_trx.c | 58 |
1 files 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; } } |