dyn TS: if PCU is not connected, allow operation as TCH

Before this patch, Osmocom style TCH/F_TCH/H_PDCH dyn TS were paralyzed if no
PCU was running. The state of the dyn TS would lock up in the PDCH activation
phase since the PCU never completed the process.

Make more robust, i.e. don't concern the BSC with PDCH activation failures.
This matches the way plain PDCH TS work: besides declaring the TS as PDCH, the
BSC is not involved and is not told about errors.

During PDCH deactivation, still wait for the PCU to tear down the PDTCH SAPIs,
but in case no PCU is connected, send a rel ack right away.

Thus, the BSC will happily switch Osmocom style dynamic timeslots to and from
PDCH mode, using the dyn TS as voice channels as needed, and not caring about
possible PDCH failures. GPRS starts working right away as soon as a PCU
connects, regardless of dyn TS having been used for voice any number of times,
and without another switchover needed.

In detail:

In rsl_rx_chan_activ(), upon receiving a PDCH activation, send an RSL chan act
ack right away, unconditionally (with an explaining comment). Do not concern
the Abis link with PDCH activation failures.

Since we're acking right away now, drop the chan act ack that would follow
after the PCU activation: as before dyn TS, only send acks and nacks for
rel_act_kind == LCHAN_REL_ACT_RSL (PDCH runs as LCHAN_REL_ACT_PCU).

In dyn_ts_pdch_release, indicate that the PCU is not connected by means of
returning 1. In rsl_rx_rf_chan_rel(), use this indicator to send a rel ack
right away if the PCU is not connected.

Change-Id: I2a0b9730197786b99ff3bc1f08c75f7d279cb1f7
This commit is contained in:
Neels Hofmeyr 2016-08-22 23:07:09 +02:00 committed by Harald Welte
parent 3cc91746a3
commit d44f0772f9
1 changed files with 34 additions and 11 deletions

View File

@ -606,14 +606,7 @@ static int rsl_tx_chan_act_nack(struct gsm_lchan *lchan, uint8_t cause)
/* Send an RSL Channel Activation Ack if cause is zero, a Nack otherwise. */
int rsl_tx_chan_act_acknack(struct gsm_lchan *lchan, uint8_t cause)
{
/*
* Normally, PDCH activation via PCU does not ack back to the BSC.
* But for GSM_PCHAN_TCH_F_TCH_H_PDCH, send a non-standard act ack for
* LCHAN_REL_ACT_PCU, since the act req came from RSL initially.
*/
if (lchan->rel_act_kind != LCHAN_REL_ACT_RSL
&& !(lchan->ts->pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH
&& lchan->rel_act_kind == LCHAN_REL_ACT_PCU)) {
if (lchan->rel_act_kind != LCHAN_REL_ACT_RSL) {
LOGP(DRSL, LOGL_NOTICE, "%s not sending CHAN ACT %s\n",
gsm_lchan_name(lchan), cause ? "NACK" : "ACK");
return 0;
@ -930,6 +923,29 @@ static int rsl_rx_chan_activ(struct msgb *msg)
/* Connecting PDCH on dyn TS goes via PCU instead. */
if (ts->pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH
&& ts->dyn.pchan_want == GSM_PCHAN_PDCH) {
/*
* We ack the activation to the BSC right away, regardless of
* the PCU succeeding or not; if a dynamic timeslot fails to go
* to PDCH mode for any reason, the BSC should still be able to
* switch it back to TCH modes and should not put the time slot
* in an error state. So for operating dynamic TS, the BSC
* would not take any action if the PDCH mode failed, e.g.
* because the PCU is not yet running. Even if alerting the
* core network of broken GPRS service is desired, this only
* makes sense when the PCU has not shown up for some time.
* It's easiest to not forward activation delays to the BSC: if
* the BSC tells us to do PDCH, we do our best, and keep the
* details on the BTS and PCU level. This is kind of analogous
* to how plain PDCH TS operate. Directly call
* rsl_tx_chan_act_ack() instead of rsl_tx_chan_act_acknack()
* because we don't want/need to decide whether to drop due to
* lchan->rel_act_kind.
*/
rc = rsl_tx_chan_act_ack(lchan);
if (rc < 0)
LOGP(DRSL, LOGL_ERROR, "%s Cannot send act ack: %d\n",
gsm_ts_and_pchan_name(ts), rc);
/*
* pcu_tx_info_ind() will pick up the ts->dyn.pchan_want. If
* the PCU is not connected yet, ignore for now; the PCU will
@ -981,7 +997,7 @@ static int dyn_ts_pdch_release(struct gsm_lchan *lchan)
/* PCU not connected yet. Just record the new type and done,
* the PCU will pick it up once connected. */
ts->dyn.pchan_is = GSM_PCHAN_NONE;
return 0;
return 1;
}
return pcu_tx_info_ind();
@ -990,6 +1006,8 @@ static int dyn_ts_pdch_release(struct gsm_lchan *lchan)
/* 8.4.14 RF CHANnel RELease is received */
static int rsl_rx_rf_chan_rel(struct gsm_lchan *lchan, uint8_t chan_nr)
{
int rc;
if (lchan->abis_ip.rtp_socket) {
rsl_tx_ipac_dlcx_ind(lchan, RSL_ERR_NORMAL_UNSPEC);
osmo_rtp_socket_free(lchan->abis_ip.rtp_socket);
@ -1004,8 +1022,13 @@ static int rsl_rx_rf_chan_rel(struct gsm_lchan *lchan, uint8_t chan_nr)
/* Dynamic channel in PDCH mode is released via PCU */
if (lchan->ts->pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH
&& lchan->ts->dyn.pchan_is == GSM_PCHAN_PDCH)
return dyn_ts_pdch_release(lchan);
&& lchan->ts->dyn.pchan_is == GSM_PCHAN_PDCH) {
rc = dyn_ts_pdch_release(lchan);
if (rc != 1)
return rc;
/* If the PCU is not connected, continue right away. */
return rsl_tx_rf_rel_ack(lchan);
}
l1sap_chan_rel(lchan->ts->trx, chan_nr);