diff --git a/openbsc/include/openbsc/signal.h b/openbsc/include/openbsc/signal.h index 2991cfac1..71e1deef9 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 97dcd3364..293175e5f 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 a7b45a1af..eb66fa018 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 66ff05e09..2934b58ca 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 fb980d104..dd22028ab 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);