diff options
-rw-r--r-- | openbsc/include/openbsc/gprs_llc.h | 4 | ||||
-rw-r--r-- | openbsc/src/gprs/gprs_llc.c | 18 |
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; |