summaryrefslogtreecommitdiffstats
path: root/src/input
diff options
context:
space:
mode:
authorPablo Neira Ayuso2011-08-09 23:15:38 +0200
committerPablo Neira Ayuso2011-08-16 14:12:33 +0200
commit31fe5f2ef8391b7f61b7dd1cb2632f27c7843534 (patch)
tree27a0897c837222864cca709a67b8b416fff60722 /src/input
parentLAPD: Use proper log levels and prefix all messages with LAPD (diff)
downloadlibosmo-abis-31fe5f2ef8391b7f61b7dd1cb2632f27c7843534.tar.gz
libosmo-abis-31fe5f2ef8391b7f61b7dd1cb2632f27c7843534.tar.xz
libosmo-abis-31fe5f2ef8391b7f61b7dd1cb2632f27c7843534.zip
LAPD: Propagate lapd_receive() errors to the E1 driver
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.
Diffstat (limited to 'src/input')
-rw-r--r--src/input/dahdi.c20
-rw-r--r--src/input/lapd.c14
2 files changed, 28 insertions, 6 deletions
diff --git a/src/input/dahdi.c b/src/input/dahdi.c
index 3adfa18..0eac0ab 100644
--- a/src/input/dahdi.c
+++ b/src/input/dahdi.c
@@ -93,7 +93,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)
@@ -115,9 +115,21 @@ static int handle_ts1_read(struct osmo_fd *bfd)
DEBUGP(DLMI, "<= 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/src/input/lapd.c b/src/input/lapd.c
index ddcce5a..0287e14 100644
--- a/src/input/lapd.c
+++ b/src/input/lapd.c
@@ -312,8 +312,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;
@@ -329,12 +330,14 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len
if (len < 2) {
LOGP(DLMI, 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(DLMI, LOGL_ERROR, "LAPD address field %x/%x not well formed\n",
data[0], data[1]);
+ *error = LAPD_ERR_BAD_ADDR;
return NULL;
};
@@ -346,6 +349,7 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len
if (len < 3) {
LOGP(DLMI, LOGL_ERROR, "LAPD receive len %d < 3, ignoring\n", len);
+ *error = LAPD_ERR_BAD_LEN;
return NULL;
};
@@ -358,6 +362,7 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len
typ = LAPD_TYPE_I;
if (len < 4) {
LOGP(DLMI, LOGL_ERROR, "LAPD I frame, len %d < 4\n", len);
+ *error = LAPD_ERR_BAD_LEN;
return NULL;
}
ns = data[2] >> 1;
@@ -368,6 +373,7 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len
typ = LAPD_TYPE_S;
if (len < 4) {
LOGP(DLMI, LOGL_ERROR, "LAPD S frame, len %d < 4\n", len);
+ *error = LAPD_ERR_BAD_LEN;
return NULL;
}
nr = data[3] >> 1;
@@ -384,6 +390,7 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len
break;
default:
LOGP(DLMI, LOGL_ERROR, "LAPD unknown S cmd %x\n", data[2]);
+ *error = LAPD_ERR_UNKNOWN_S_CMD;
return NULL;
};
} else if ((data[2] & 3) == 3) {
@@ -416,6 +423,7 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len
default:
LOGP(DLMI, LOGL_ERROR, "LAPD unknown U cmd %x "
"(pf %x data %x)\n", val, pf, data[2]);
+ *error = LAPD_ERR_UNKNOWN_U_CMD;
return NULL;
};
};
@@ -431,6 +439,7 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len
teip = teip_from_tei(li, tei);
if (!teip) {
LOGP(DLMI, LOGL_NOTICE, "LAPD Unknown TEI %u\n", tei);
+ *error = LAPD_ERR_UNKNOWN_TEI;
return NULL;
}
@@ -589,6 +598,7 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len
return contents;
}
+ *error = LAPD_ERR_BAD_CMD;
return NULL;
};