From: Pablo Neira Ayuso pablo@gnumonks.org
Hi Harald,
This patchset contains two updates for the Nokia support in the following scenario: the BSC stops after having configured the BTS, then the BTS is launched again but LAPD reports unknown TEI. To fix this, we report to the E1 driver about unknown TEI so it can resend the SABM message.
... and one patch from Daniel who thinks that we have to promote some logs messages from debugging to error.
You can find them in the nokia-pablo branch.
We are using them in the camp.
Please, merge them.
Daniel Willmann (1): mncc: promote log level from debug to errors
Pablo Neira Ayuso (2): LAPD: Propagate lapd_receive() errors to the E1 driver NOKIA: Resend SABM on unknown TEI from LAPD
openbsc/include/openbsc/signal.h | 1 + openbsc/src/libabis/e1_input.c | 1 + openbsc/src/libabis/input/dahdi.c | 20 ++++++++++++++++---- openbsc/src/libabis/input/lapd.c | 14 ++++++++++++-- openbsc/src/libabis/input/lapd.h | 16 ++++++++++++++-- openbsc/src/libbsc/bts_nokia_site.c | 9 ++++++++- openbsc/src/libmsc/gsm_04_08.c | 10 +++++----- 7 files changed, 57 insertions(+), 14 deletions(-)
From: Pablo Neira Ayuso pablo@gnumonks.org
Scenario: BTS are configured and working, then the BSC stops working for some reason (crash or administrative stop).
If the BSC comes back to life, LAPD among other things does not know about the previous existing TEIs. Instead of ignoring these frames, we notify the driver that we are seeing frames with unknown TEIs, so it can try to recover, e.g. by resending the SABM message. --- openbsc/include/openbsc/signal.h | 1 + openbsc/src/libabis/e1_input.c | 1 + openbsc/src/libabis/input/dahdi.c | 20 ++++++++++++++++---- openbsc/src/libabis/input/lapd.c | 14 ++++++++++++-- openbsc/src/libabis/input/lapd.h | 16 ++++++++++++++-- 5 files changed, 44 insertions(+), 8 deletions(-)
diff --git a/openbsc/include/openbsc/signal.h b/openbsc/include/openbsc/signal.h index 2991cfa..71e1dee 100644 --- a/openbsc/include/openbsc/signal.h +++ b/openbsc/include/openbsc/signal.h @@ -145,6 +145,7 @@ enum signal_input { S_INP_NONE, S_INP_TEI_UP, S_INP_TEI_DN, + S_INP_TEI_UNKNOWN, S_INP_LINE_INIT, S_INP_LINE_ALARM, S_INP_LINE_NOALARM, diff --git a/openbsc/src/libabis/e1_input.c b/openbsc/src/libabis/e1_input.c index 97dcd33..293175e 100644 --- a/openbsc/src/libabis/e1_input.c +++ b/openbsc/src/libabis/e1_input.c @@ -570,6 +570,7 @@ int e1inp_event(struct e1inp_ts *ts, int evt, uint8_t tei, uint8_t sapi) if (!link) return -EINVAL;
+ isd.line = ts->line; isd.link_type = link->type; isd.trx = link->trx; isd.tei = tei; diff --git a/openbsc/src/libabis/input/dahdi.c b/openbsc/src/libabis/input/dahdi.c index a7b45a1..eb66fa0 100644 --- a/openbsc/src/libabis/input/dahdi.c +++ b/openbsc/src/libabis/input/dahdi.c @@ -100,7 +100,7 @@ static int handle_ts1_read(struct osmo_fd *bfd) struct msgb *msg = msgb_alloc(TS1_ALLOC_SIZE, "DAHDI TS1"); lapd_mph_type prim; unsigned int sapi, tei; - int ilen, ret; + int ilen, ret, error = 0; uint8_t *idata;
if (!msg) @@ -122,9 +122,21 @@ static int handle_ts1_read(struct osmo_fd *bfd)
DEBUGP(DMI, "<= len = %d, sapi(%d) tei(%d)", ret, sapi, tei);
- idata = lapd_receive(e1i_ts->driver.dahdi.lapd, msg->data, msg->len, &ilen, &prim); - if (!idata && prim == 0) - return -EIO; + idata = lapd_receive(e1i_ts->driver.dahdi.lapd, msg->data, msg->len, &ilen, &prim, &error); + if (!idata) { + switch(error) { + case LAPD_ERR_UNKNOWN_TEI: + /* We don't know about this TEI, probably the BSC + * lost local states (it crashed or it was stopped), + * notify the driver to see if it can do anything to + * recover the existing signalling links with the BTS. + */ + e1inp_event(e1i_ts, S_INP_TEI_UNKNOWN, tei, sapi); + return -EIO; + } + if (prim == 0) + return -EIO; + }
msgb_pull(msg, 2);
diff --git a/openbsc/src/libabis/input/lapd.c b/openbsc/src/libabis/input/lapd.c index 66ff05e..2934b58 100644 --- a/openbsc/src/libabis/input/lapd.c +++ b/openbsc/src/libabis/input/lapd.c @@ -310,8 +310,9 @@ static void lapd_tei_receive(struct lapd_instance *li, uint8_t *data, int len) };
/* General input function for any data received for this LAPD instance */ -uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len, - int *ilen, lapd_mph_type *prim) +uint8_t * +lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len, + int *ilen, lapd_mph_type *prim, int *error) { uint8_t sapi, cr, tei, command; int pf, ns, nr; @@ -327,12 +328,14 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len
if (len < 2) { LOGP(DMI, LOGL_ERROR, "LAPD receive len %d < 2, ignoring\n", len); + *error = LAPD_ERR_BAD_LEN; return NULL; };
if ((data[0] & 1) != 0 || (data[1] & 1) != 1) { LOGP(DMI, LOGL_ERROR, "LAPD address field %x/%x not well formed\n", data[0], data[1]); + *error = LAPD_ERR_BAD_ADDR; return NULL; };
@@ -344,6 +347,7 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len
if (len < 3) { LOGP(DMI, LOGL_ERROR, "LAPD receive len %d < 3, ignoring\n", len); + *error = LAPD_ERR_BAD_LEN; return NULL; };
@@ -356,6 +360,7 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len typ = LAPD_TYPE_I; if (len < 4) { LOGP(DMI, LOGL_ERROR, "LAPD I frame, len %d < 4\n", len); + *error = LAPD_ERR_BAD_LEN; return NULL; } ns = data[2] >> 1; @@ -366,6 +371,7 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len typ = LAPD_TYPE_S; if (len < 4) { LOGP(DMI, LOGL_ERROR, "LAPD S frame, len %d < 4\n", len); + *error = LAPD_ERR_BAD_LEN; return NULL; } nr = data[3] >> 1; @@ -382,6 +388,7 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len break; default: LOGP(DMI, LOGL_ERROR, "LAPD unknown S cmd %x\n", data[2]); + *error = LAPD_ERR_UNKNOWN_S_CMD; return NULL; }; } else if ((data[2] & 3) == 3) { @@ -414,6 +421,7 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len default: LOGP(DMI, LOGL_ERROR, "LAPD unknown U cmd %x " "(pf %x data %x)\n", val, pf, data[2]); + *error = LAPD_ERR_UNKNOWN_U_CMD; return NULL; }; }; @@ -429,6 +437,7 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len teip = teip_from_tei(li, tei); if (!teip) { LOGP(DMI, LOGL_NOTICE, "LAPD Unknown TEI %u\n", tei); + *error = LAPD_ERR_UNKNOWN_TEI; return NULL; }
@@ -587,6 +596,7 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len return contents; }
+ *error = LAPD_ERR_BAD_CMD; return NULL; };
diff --git a/openbsc/src/libabis/input/lapd.h b/openbsc/src/libabis/input/lapd.h index fb980d1..dd22028 100644 --- a/openbsc/src/libabis/input/lapd.h +++ b/openbsc/src/libabis/input/lapd.h @@ -26,8 +26,20 @@ struct lapd_instance { struct llist_head tei_list; /* list of TEI in this LAPD instance */ };
-extern uint8_t *lapd_receive(struct lapd_instance *li, uint8_t *data, unsigned int len, - int *ilen, lapd_mph_type *prim); +enum lapd_recv_errors { + LAPD_ERR_NONE = 0, + LAPD_ERR_BAD_LEN, + LAPD_ERR_BAD_ADDR, + LAPD_ERR_UNKNOWN_S_CMD, + LAPD_ERR_UNKNOWN_U_CMD, + LAPD_ERR_UNKNOWN_TEI, + LAPD_ERR_BAD_CMD, + __LAPD_ERR_MAX +}; + +extern uint8_t *lapd_receive(struct lapd_instance *li, uint8_t *data, + unsigned int len, int *ilen, lapd_mph_type *prim, + int *error);
extern void lapd_transmit(struct lapd_instance *li, uint8_t tei, uint8_t sapi, uint8_t *data, unsigned int len);
From: Pablo Neira Ayuso pablo@gnumonks.org
--- openbsc/src/libbsc/bts_nokia_site.c | 9 ++++++++- 1 files changed, 8 insertions(+), 1 deletions(-)
diff --git a/openbsc/src/libbsc/bts_nokia_site.c b/openbsc/src/libbsc/bts_nokia_site.c index 6d14bdd..b5bc2fe 100644 --- a/openbsc/src/libbsc/bts_nokia_site.c +++ b/openbsc/src/libbsc/bts_nokia_site.c @@ -84,7 +84,7 @@ static int shutdown_om(struct gsm_bts *bts) Attention: this has to be adapted for mISDN */
-static void start_sabm_in_line(struct e1inp_line *line, int start, int sapi) +void start_sabm_in_line(struct e1inp_line *line, int start, int sapi) { struct e1inp_sign_link *link; int i; @@ -162,6 +162,13 @@ static int inp_sig_cb(unsigned int subsys, unsigned int signal, break; } break; + case S_INP_TEI_UNKNOWN: + /* We are receiving LAPD frames with one TEI that we do not + * seem to know, likely that we (the BSC) stopped working + * and lost our local states. However, the BTS is already + * configured, we try to take over the RSL links. */ + start_sabm_in_line(isd->line, 1, SAPI_RSL); + break; }
return 0;
From: Daniel Willmann daniel@totalueberwachung.de
These should not be debug messages, instead they should be error messages. --- openbsc/src/libmsc/gsm_04_08.c | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c index e710f83..bd452ed 100644 --- a/openbsc/src/libmsc/gsm_04_08.c +++ b/openbsc/src/libmsc/gsm_04_08.c @@ -1602,7 +1602,7 @@ static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan) remote_bts->nr, remote_lchan->ts->trx->nr, remote_lchan->ts->nr);
if (bts->type != remote_bts->type) { - DEBUGP(DCC, "Cannot switch calls between different BTS types yet\n"); + LOGP(DCC, LOGL_ERROR, "Cannot switch calls between different BTS types yet\n"); return -EINVAL; }
@@ -1638,7 +1638,7 @@ static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan) trau_mux_map_lchan(lchan, remote_lchan); break; default: - DEBUGP(DCC, "Unknown BTS type %u\n", bts->type); + LOGP(DCC, LOGL_ERROR, "Unknown BTS type %u\n", bts->type); return -EINVAL; }
@@ -1681,7 +1681,7 @@ static int tch_recv_mncc(struct gsm_network *net, uint32_t callref, int enable) switch (bts->type) { case GSM_BTS_TYPE_NANOBTS: if (ipacc_rtp_direct) { - DEBUGP(DCC, "Error: RTP proxy is disabled\n"); + LOGP(DCC, LOGL_ERROR, "Error: RTP proxy is disabled\n"); return -EINVAL; } /* in case, we don't have a RTP socket yet, we note this @@ -1711,7 +1711,7 @@ static int tch_recv_mncc(struct gsm_network *net, uint32_t callref, int enable) return trau_mux_unmap(NULL, callref); break; default: - DEBUGP(DCC, "Unknown BTS type %u\n", bts->type); + LOGP(DCC, LOGL_ERROR, "Unknown BTS type %u\n", bts->type); return -EINVAL; }
@@ -2994,7 +2994,7 @@ int mncc_tx_to_cc(struct gsm_network *net, int msg_type, void *arg) case GSM_BTS_TYPE_NOKIA_SITE: return trau_send_frame(trans->conn->lchan, arg); default: - DEBUGP(DCC, "Unknown BTS type %u\n", bts->type); + LOGP(DCC, LOGL_ERROR, "Unknown BTS type %u\n", bts->type); } return -EINVAL; }
Hi pablo,
On Wed, Aug 10, 2011 at 01:35:49AM +0200, pablo@gnumonks.org wrote:
This patchset contains two updates for the Nokia support in the following scenario: the BSC stops after having configured the BTS, then the BTS is launched again but LAPD reports unknown TEI. To fix this, we report to the E1 driver about unknown TEI so it can resend the SABM message.
I've applied it on top of spaar/nokia, and merged everything to master.
This means the 'spaar/nokia' branch is now gone and everything is in master.