summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--openbsc/include/openbsc/signal.h1
-rw-r--r--openbsc/src/libabis/e1_input.c1
-rw-r--r--openbsc/src/libabis/input/dahdi.c20
-rw-r--r--openbsc/src/libabis/input/lapd.c14
-rw-r--r--openbsc/src/libabis/input/lapd.h16
5 files changed, 44 insertions, 8 deletions
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);