channels: Mark channels as broken that time out on activation/release

A channel that fails to send an ACK/NACK/REL within the four second
timeout is now marked as broken. In case the release comes in late
it will be ignored. The lchan should already been freed and for now
we don't want to trust the channel.

In the future we might want to send a "release" for a channel that
got activated ack late and just set the state to none on a channel
that is released acked late.

The late ACK and REL has been tested with two manual tests using the
fakebts. The channels remained blocked even after having received
the ACK message here. The NACK case has not been manually tested.
diff --git a/openbsc/src/libbsc/abis_rsl.c b/openbsc/src/libbsc/abis_rsl.c
index 644706f..7aae590 100644
--- a/openbsc/src/libbsc/abis_rsl.c
+++ b/openbsc/src/libbsc/abis_rsl.c
@@ -196,10 +196,11 @@
 {
 	struct gsm_lchan *lchan = data;
 
-	LOGP(DRSL, LOGL_ERROR, "%s Timeout during activation!\n",
+	LOGP(DRSL, LOGL_ERROR,
+		"%s Timeout during activation. Marked as broken.\n",
 		gsm_lchan_name(lchan));
 
-	rsl_lchan_set_state(lchan, LCHAN_S_NONE);
+	rsl_lchan_set_state(lchan, LCHAN_S_BROKEN);
 	lchan_free(lchan);
 }
 
@@ -207,10 +208,12 @@
 {
 	struct gsm_lchan *lchan = data;
 
-	LOGP(DRSL, LOGL_ERROR, "%s Timeout during deactivation!\n",
+	LOGP(DRSL, LOGL_ERROR,
+		"%s Timeout during deactivation! Marked as broken.\n",
 		gsm_lchan_name(lchan));
 
-	do_lchan_free(lchan);
+	rsl_lchan_set_state(lchan, LCHAN_S_BROKEN);
+	lchan_free(lchan);
 }
 
 
@@ -737,6 +740,13 @@
 	osmo_timer_del(&lchan->act_timer);
 	osmo_timer_del(&lchan->T3111);
 
+	if (lchan->state == LCHAN_S_BROKEN) {
+		/* we are leaving this channel broken for now */
+		LOGP(DRSL, LOGL_NOTICE, "%s CHAN REL ACK for broken channel.\n",
+			gsm_lchan_name(lchan));
+		return 0;
+	}
+
 	if (lchan->state != LCHAN_S_REL_REQ && lchan->state != LCHAN_S_REL_ERR)
 		LOGP(DRSL, LOGL_NOTICE, "%s CHAN REL ACK but state %s\n",
 			gsm_lchan_name(lchan),
@@ -907,6 +917,12 @@
 
 	osmo_timer_del(&msg->lchan->act_timer);
 
+	if (msg->lchan->state == LCHAN_S_BROKEN) {
+		LOGP(DRSL, LOGL_NOTICE, "%s CHAN ACT ACK for broken channel.\n",
+			gsm_lchan_name(msg->lchan));
+		return 0;
+	}
+
 	if (msg->lchan->state != LCHAN_S_ACT_REQ)
 		LOGP(DRSL, LOGL_NOTICE, "%s CHAN ACT ACK, but state %s\n",
 			gsm_lchan_name(msg->lchan),
@@ -933,6 +949,13 @@
 
 	osmo_timer_del(&msg->lchan->act_timer);
 
+	if (msg->lchan->state == LCHAN_S_BROKEN) {
+		LOGP(DRSL, LOGL_ERROR,
+			"%s CHANNEL ACTIVATE NACK for broken channel.\n",
+			gsm_lchan_name(msg->lchan));
+		return -1;
+	}
+
 	LOGP(DRSL, LOGL_ERROR, "%s CHANNEL ACTIVATE NACK ",
 		gsm_lchan_name(msg->lchan));