LAPD: Indicate sequence error after indicating received data

First indicated the received data in an I frame, if possible. Then
indicate the sequence error using MDL-ERROR-INDICATION. This way the
data is delivered before the error is handled by BSC.

Also there is no reason to indicate sequence error on supervisory
frames.

See ยง8.7.4 of 3GPP TS 44.006.

Related: OS#5968
Change-Id: I535c18018bf0df4124a5e9618238028fa31be289
diff --git a/src/isdn/lapd_core.c b/src/isdn/lapd_core.c
index d98edae..b32ed26 100644
--- a/src/isdn/lapd_core.c
+++ b/src/isdn/lapd_core.c
@@ -796,8 +796,9 @@
 	lapd_start_t200(dl);
 }
 
-/* 5.5.3.1: Common function to acknowlege frames up to the given N(R) value */
-static void lapd_acknowledge(struct lapd_msg_ctx *lctx)
+/* 5.5.3.1: Common function to acknowlege frames up to the given N(R) value
+ * In case of a sequence error, the cause is returned with negative sign. */
+static int lapd_acknowledge(struct lapd_msg_ctx *lctx)
 {
 	struct lapd_datalink *dl = lctx->dl;
 	uint8_t nr = lctx->n_recv;
@@ -838,7 +839,7 @@
 		 */
 		if (sub_mod(nr, dl->v_ack, dl->v_range) > sub_mod(dl->v_send, dl->v_ack, dl->v_range)) {
 			LOGDL(dl, LOGL_NOTICE, "N(R) sequence error\n");
-			mdl_error(MDL_CAUSE_SEQ_ERR, lctx);
+			return -MDL_CAUSE_SEQ_ERR;
 		}
 	}
 
@@ -861,6 +862,8 @@
 	/* Start T203, if T200 is not running in MF EST state, if enabled */
 	if (!lapd_is_t200_started(dl) && (dl->t203_sec || dl->t203_usec) && (dl->state == LAPD_STATE_MF_EST))
 		lapd_start_t203(dl);
+
+	return 0;
 }
 
 /* L1 -> L2 */
@@ -1576,6 +1579,7 @@
 	int length = lctx->length;
 	int rc;
 	bool i_frame_in_queue = false;
+	int mdl_cause = 0;
 
 	LOGDL(dl, LOGL_INFO, "I received in state %s on SAPI(%u)\n",
 	      lapd_state_name(dl->state), lctx->sapi);
@@ -1652,7 +1656,9 @@
 		}
 		/* Even if N(s) sequence error, acknowledge to N(R)-1 */
 		/* 5.5.3.1: Acknowlege all transmitted frames up the N(R)-1 */
-		lapd_acknowledge(lctx); /* V(A) is also set here */
+		mdl_cause = lapd_acknowledge(lctx); /* V(A) is also set here */
+		if (mdl_cause < 0)
+			mdl_error(-mdl_cause, lctx);
 
 		/* Send message, if possible due to acknowledged data */
 		lapd_send_i(dl, __LINE__, false);
@@ -1673,7 +1679,7 @@
 	}
 
 	/* 5.5.3.1: Acknowlege all transmitted frames up the the N(R)-1 */
-	lapd_acknowledge(lctx); /* V(A) is also set here */
+	mdl_cause = lapd_acknowledge(lctx); /* V(A) is also set here */
 
 	/* Only if we are not in own receiver busy condition */
 	if (!dl->own_busy) {
@@ -1718,6 +1724,10 @@
 	} else
 		LOGDL(dl, LOGL_INFO, "I frame ignored during own receiver busy condition\n");
 
+	/* Indicate sequence error, if exists. */
+	if (mdl_cause < 0)
+		mdl_error(-mdl_cause, lctx);
+
 	/* Check for P bit */
 	if (lctx->p_f) {
 		/* 5.5.2.1 */