aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--openbsc/include/openbsc/gprs_llc.h4
-rw-r--r--openbsc/src/gprs/gprs_llc.c18
2 files changed, 21 insertions, 1 deletions
diff --git a/openbsc/include/openbsc/gprs_llc.h b/openbsc/include/openbsc/gprs_llc.h
index e3fc82ef9..4be7b1f18 100644
--- a/openbsc/include/openbsc/gprs_llc.h
+++ b/openbsc/include/openbsc/gprs_llc.h
@@ -126,6 +126,10 @@ struct gprs_llc_lle {
uint16_t vu_send;
uint16_t vu_recv;
+ /* non-standard LLC state */
+ uint16_t vu_recv_last;
+ uint16_t vu_recv_duplicates;
+
/* Overflow Counter for ABM */
uint32_t oc_i_send;
uint32_t oc_i_recv;
diff --git a/openbsc/src/gprs/gprs_llc.c b/openbsc/src/gprs/gprs_llc.c
index 6244d186f..a4bff654b 100644
--- a/openbsc/src/gprs/gprs_llc.c
+++ b/openbsc/src/gprs/gprs_llc.c
@@ -547,7 +547,23 @@ static int gprs_llc_hdr_rx(struct gprs_llc_hdr_parsed *gph,
"TLLI=%08x dropping UI, N(U=%d) not in window V(URV(UR:%d).\n",
lle->llme ? lle->llme->tlli : -1,
gph->seq_tx, lle->vu_recv);
- return -EIO;
+
+ /* HACK: non-standard recovery handling. If remote LLE
+ * is re-transmitting the same sequence number for
+ * threee times, don't discard the frame but pass it on
+ * and 'learn' the new sequence number */
+ if (gph->seq_tx != lle->vu_recv_last) {
+ lle->vu_recv_last = gph->seq_tx;
+ lle->vu_recv_duplicates = 0;
+ } else {
+ lle->vu_recv_duplicates++;
+ if (lle->vu_recv_duplicates < 3)
+ return -EIO;
+ LOGP(DLLC, LOGL_NOTICE, "TLLI=%08x recovering "
+ "N(U=%d) after receiving %u duplicates\n",
+ lle->llme ? lle->llme->tlli : -1,
+ gph->seq_tx, lle->vu_recv_duplicates);
+ }
}
/* Increment the sequence number that we expect in the next frame */
lle->vu_recv = (gph->seq_tx + 1) % 512;