[PATCH 1/3] LAPD: Propagate lapd_receive() errors to the E1 driver

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/OpenBSC@lists.osmocom.org/.

pablo at gnumonks.org pablo at gnumonks.org
Tue Aug 9 23:35:50 UTC 2011


From: Pablo Neira Ayuso <pablo at 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);
-- 
1.7.1





More information about the OpenBSC mailing list