[bsc_init] When the RSL/OML connection drops, free all lchans
Free all allocated channels on the TRX that failed, go through
lchan_free to signal higher layers and then force a reset of
the channel. Make the TRX and TS unusable by setting the operational
set to 0 (not really defined) which should be reset once the
RSL is coming up again.
diff --git a/openbsc/include/openbsc/chan_alloc.h b/openbsc/include/openbsc/chan_alloc.h
index f564e9e..d4f5858 100644
--- a/openbsc/include/openbsc/chan_alloc.h
+++ b/openbsc/include/openbsc/chan_alloc.h
@@ -45,6 +45,7 @@
/* Free a logical channel (SDCCH, TCH, ...) */
void lchan_free(struct gsm_lchan *lchan);
+void lchan_reset(struct gsm_lchan *lchan);
/* Consider releasing the channel */
int lchan_auto_release(struct gsm_lchan *lchan);
diff --git a/openbsc/src/bsc_init.c b/openbsc/src/bsc_init.c
index f343662..fccdb0c 100644
--- a/openbsc/src/bsc_init.c
+++ b/openbsc/src/bsc_init.c
@@ -31,6 +31,7 @@
#include <openbsc/system_information.h>
#include <openbsc/paging.h>
#include <openbsc/signal.h>
+#include <openbsc/chan_alloc.h>
#include <osmocore/talloc.h>
/* global pointer to the gsm network data structure */
@@ -899,6 +900,8 @@
void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx)
{
+ int ts_no, lchan_no;
+
switch (event) {
case EVT_E1_TEI_UP:
switch (type) {
@@ -913,8 +916,30 @@
}
break;
case EVT_E1_TEI_DN:
- LOGP(DMI, LOGL_NOTICE, "Lost some E1 TEI link\n");
- /* FIXME: deal with TEI or L1 link loss */
+ LOGP(DMI, LOGL_ERROR, "Lost some E1 TEI link: %d %p\n", type, trx);
+
+ /*
+ * free all allocated channels. change the nm_state so the
+ * trx and trx_ts becomes unusable and chan_alloc.c can not
+ * allocate from it.
+ */
+ for (ts_no = 0; ts_no < ARRAY_SIZE(trx->ts); ++ts_no) {
+ struct gsm_bts_trx_ts *ts = &trx->ts[ts_no];
+
+ for (lchan_no = 0; lchan_no < ARRAY_SIZE(ts->lchan); ++lchan_no) {
+ if (ts->lchan[lchan_no].state != GSM_LCHAN_NONE)
+ lchan_free(&ts->lchan[lchan_no]);
+ lchan_reset(&ts->lchan[lchan_no]);
+ }
+
+ ts->nm_state.operational = 0;
+ ts->nm_state.availability = 0;
+ }
+
+ trx->nm_state.operational = 0;
+ trx->nm_state.availability = 0;
+ trx->bb_transc.nm_state.operational = 0;
+ trx->bb_transc.nm_state.availability = 0;
break;
default:
break;
diff --git a/openbsc/src/chan_alloc.c b/openbsc/src/chan_alloc.c
index 118deca..107abdc 100644
--- a/openbsc/src/chan_alloc.c
+++ b/openbsc/src/chan_alloc.c
@@ -330,6 +330,20 @@
* channel using it */
}
+/*
+ * There was an error with the TRX and we need to forget
+ * any state so that a lchan can be allocated again after
+ * the trx is fully usable.
+ */
+void lchan_reset(struct gsm_lchan *lchan)
+{
+ bsc_del_timer(&lchan->T3101);
+
+ lchan->type = GSM_LCHAN_NONE;
+ lchan->state = LCHAN_S_NONE;
+}
+
+
/* Consider releasing the channel now */
int lchan_auto_release(struct gsm_lchan *lchan)
{