aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@sysmocom.de>2023-07-21 15:53:47 +0200
committerPau Espin Pedrol <pespin@sysmocom.de>2023-07-21 17:59:45 +0200
commit49535bec37caddcea5718ed4e526c477c71f1b3a (patch)
treed7e779c504f824e64907a0e109b9f0eb8d2ed476
parent1d41688c56397f4cdab077050f648df6be9a7e5e (diff)
rlcmac: Mark received BSNs falling out of the V(N)/RBB when V(R) is raised
Problem this patch is fixing: The current RLCMAC window code ported from osmo-pcu is never invalidating the BSNs which have been received after they are not needed. As a result, when the DL TBF keeps sending data for a long time, and finally BSN wraps around 127->0, when this implementation receives the BSN=0, it will find it is already received and hence will discard it, and then keep asking for BSN=0 nevertheless in PKT DL ACK, causing an endless loop where PCU stays submitting the same block forever. Explanation of the solution: The V(N) array contains the status of the previous WS (64 in GPRS) data blocks. This array is used to construct the RRB signaled to the peer during PKT DL ACK/NACK messages together with the SSN (start sequence number), which in our case is mainly V(R), aka one block higher than the highest received block in the rx window. Hence, whenever PKT DL ACK/NACK is transmitted, it contains an RRB ranging [V(R)-1,...V(R)-WS)] mod SNS (SNS=128 in GPRS). The receive window is basically [V(Q) <= BSN < V(R)] mod SNS, as is of size 64. The V(R) is increased whenever a highest new block arrives which is in the receive window (guaranteeing it will be increased to at most V(Q)+64. Since we are only announcing state of blocks from V(R)..V(R)-WS, and blocks received which are before that BSN are dropped since don't fall inside the rx window, we can securely mark as invalid those blocks falling behind V(R)-WS whenever we increase V(R). Related: OS#6102 Change-Id: I962111995e741a7e9c230b2dd4904c2fa9a828e9
-rw-r--r--include/osmocom/gprs/rlcmac/rlc_window_dl.h1
-rw-r--r--src/rlcmac/rlc_window_dl.c23
-rw-r--r--tests/rlcmac/rlcmac_prim_test.err2
3 files changed, 15 insertions, 11 deletions
diff --git a/include/osmocom/gprs/rlcmac/rlc_window_dl.h b/include/osmocom/gprs/rlcmac/rlc_window_dl.h
index 58faaa4..93ccbe4 100644
--- a/include/osmocom/gprs/rlcmac/rlc_window_dl.h
+++ b/include/osmocom/gprs/rlcmac/rlc_window_dl.h
@@ -62,7 +62,6 @@ void gprs_rlcmac_rlc_dl_window_raise_v_r(struct gprs_rlcmac_rlc_dl_window *dlw,
uint16_t gprs_rlcmac_rlc_dl_window_raise_v_q(struct gprs_rlcmac_rlc_dl_window *dlw);
void gprs_rlcmac_rlc_dl_window_receive_bsn(struct gprs_rlcmac_rlc_dl_window *dlw, uint16_t bsn);
-bool gprs_rlcmac_rlc_dl_window_invalidate_bsn(struct gprs_rlcmac_rlc_dl_window *dlw, uint16_t bsn);
static inline uint16_t gprs_rlcmac_rlc_dl_window_ssn(const struct gprs_rlcmac_rlc_dl_window *dlw)
{
diff --git a/src/rlcmac/rlc_window_dl.c b/src/rlcmac/rlc_window_dl.c
index 77153b6..eab01cd 100644
--- a/src/rlcmac/rlc_window_dl.c
+++ b/src/rlcmac/rlc_window_dl.c
@@ -69,6 +69,11 @@ void gprs_rlcmac_rlc_v_n_mark_missing(struct gprs_rlcmac_rlc_v_n *v_n, int bsn)
return gprs_rlcmac_rlc_v_n_mark(v_n, bsn, GPRS_RLCMAC_RLC_DL_BSN_MISSING);
}
+void gprs_rlcmac_rlc_v_n_mark_invalid(struct gprs_rlcmac_rlc_v_n *v_n, int bsn)
+{
+ return gprs_rlcmac_rlc_v_n_mark(v_n, bsn, GPRS_RLCMAC_RLC_DL_BSN_INVALID);
+}
+
/*************
* UL WINDOW
*************/
@@ -220,8 +225,14 @@ void gprs_rlcmac_rlc_dl_window_raise_v_r(struct gprs_rlcmac_rlc_dl_window *dlw,
/* Positive offset, so raise. */
if (offset_v_r < (gprs_rlcmac_rlc_window_sns(w) >> 1)) {
while (offset_v_r--) {
- if (offset_v_r) /* all except the received block */
- gprs_rlcmac_rlc_v_n_mark_missing(&dlw->v_n, gprs_rlcmac_rlc_dl_window_v_r(dlw));
+ const uint16_t v_r = gprs_rlcmac_rlc_dl_window_v_r(dlw);
+ const uint16_t bsn_no_longer_in_ws = gprs_rlcmac_rlc_window_mod_sns_bsn(w, v_r - gprs_rlcmac_rlc_window_ws(w));
+ LOGRLCMAC(LOGL_DEBUG, "- Mark BSN %u as INVALID\n", bsn_no_longer_in_ws);
+ gprs_rlcmac_rlc_v_n_mark_invalid(&dlw->v_n, bsn_no_longer_in_ws);
+ if (offset_v_r) {/* all except the received block */
+ LOGRLCMAC(LOGL_DEBUG, "- Mark BSN %u as MISSING\n", v_r);
+ gprs_rlcmac_rlc_v_n_mark_missing(&dlw->v_n, v_r);
+ }
gprs_rlcmac_rlc_dl_window_raise_v_r_to(dlw, 1);
}
LOGRLCMAC(LOGL_DEBUG, "- Raising V(R) to %d\n", gprs_rlcmac_rlc_dl_window_v_r(dlw));
@@ -255,11 +266,3 @@ void gprs_rlcmac_rlc_dl_window_receive_bsn(struct gprs_rlcmac_rlc_dl_window *dlw
gprs_rlcmac_rlc_v_n_mark_received(&dlw->v_n, bsn);
gprs_rlcmac_rlc_dl_window_raise_v_r(dlw, bsn);
}
-
-bool gprs_rlcmac_rlc_dl_window_invalidate_bsn(struct gprs_rlcmac_rlc_dl_window *dlw, uint16_t bsn)
-{
- bool was_valid = gprs_rlcmac_rlc_v_n_is_received(&dlw->v_n, bsn);
- gprs_rlcmac_rlc_v_n_mark_missing(&dlw->v_n, bsn);
-
- return was_valid;
-}
diff --git a/tests/rlcmac/rlcmac_prim_test.err b/tests/rlcmac/rlcmac_prim_test.err
index ec707d2..006efc3 100644
--- a/tests/rlcmac/rlcmac_prim_test.err
+++ b/tests/rlcmac/rlcmac_prim_test.err
@@ -885,6 +885,7 @@ DLGLOBAL DEBUG TBF(DL:NR-0:TLLI-00000001) DL DATA TFI=0 received (V(Q)=0 .. V(R)
DLGLOBAL DEBUG TBF(DL:NR-0:TLLI-00000001) Got CS-1 RLC data block: FBI=1, BSN=0, SPB=0, S/P=1 RRBP=1, E=0, bitoffs=24
DLGLOBAL DEBUG TBF(DL:NR-0:TLLI-00000001) BSN 0 storing in window (0..63)
DLGLOBAL DEBUG TBF(DL:NR-0:TLLI-00000001) data_length=20, data=19 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+DLGLOBAL DEBUG - Mark BSN 64 as INVALID
DLGLOBAL DEBUG - Raising V(R) to 1
DLGLOBAL DEBUG - Taking block 0 out, raising V(Q) to 1
DLGLOBAL DEBUG TBF(DL:NR-0:TLLI-00000001) Assembling frames: (len=20)
@@ -923,6 +924,7 @@ DLGLOBAL DEBUG TBF(DL:NR-0:TLLI-00000001) DL DATA TFI=0 received (V(Q)=0 .. V(R)
DLGLOBAL DEBUG TBF(DL:NR-0:TLLI-00000001) Got CS-1 RLC data block: FBI=1, BSN=0, SPB=0, S/P=1 RRBP=1, E=0, bitoffs=24
DLGLOBAL DEBUG TBF(DL:NR-0:TLLI-00000001) BSN 0 storing in window (0..63)
DLGLOBAL DEBUG TBF(DL:NR-0:TLLI-00000001) data_length=20, data=19 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+DLGLOBAL DEBUG - Mark BSN 64 as INVALID
DLGLOBAL DEBUG - Raising V(R) to 1
DLGLOBAL DEBUG - Taking block 0 out, raising V(Q) to 1
DLGLOBAL DEBUG TBF(DL:NR-0:TLLI-00000001) Assembling frames: (len=20)