pespin has submitted this change. (
https://gerrit.osmocom.org/c/libosmo-gprs/+/31344 )
Change subject: rlcmac: Implement Rx of UL ACK/NACK
......................................................................
rlcmac: Implement Rx of UL ACK/NACK
Related: OS#5500
Change-Id: I5e3d8e77042d3ad1618e6b62bc1a377a93239580
---
M include/osmocom/gprs/rlcmac/rlc_window.h
M include/osmocom/gprs/rlcmac/rlcmac_dec.h
M include/osmocom/gprs/rlcmac/rlcmac_private.h
M include/osmocom/gprs/rlcmac/tbf_ul.h
M include/osmocom/gprs/rlcmac/tbf_ul_fsm.h
M include/osmocom/gprs/rlcmac/types_private.h
M src/rlcmac/rlc_window.c
M src/rlcmac/rlcmac.c
M src/rlcmac/rlcmac_dec.c
M src/rlcmac/tbf_ul.c
M src/rlcmac/tbf_ul_fsm.c
M tests/rlcmac/rlcmac_prim_test.c
M tests/rlcmac/rlcmac_prim_test.err
13 files changed, 341 insertions(+), 11 deletions(-)
Approvals:
laforge: Looks good to me, but someone else must approve
Jenkins Builder: Verified
pespin: Looks good to me, approved
diff --git a/include/osmocom/gprs/rlcmac/rlc_window.h
b/include/osmocom/gprs/rlcmac/rlc_window.h
index a5d89ab..09a2739 100644
--- a/include/osmocom/gprs/rlcmac/rlc_window.h
+++ b/include/osmocom/gprs/rlcmac/rlc_window.h
@@ -3,6 +3,12 @@
#include <stdint.h>
+#define GPRS_RLCMAC_GPRS_WS 64 /* max window size */
+#define GPRS_RLCMAC_EGPRS_MIN_WS 64 /* min window size */
+#define GPRS_RLCMAC_EGPRS_MAX_WS 1024 /* min window size */
+#define GPRS_RLCMAC_EGPRS_MAX_BSN_DELTA 512
+#define GPRS_RLCMAC_MAX_WS RLC_EGPRS_MAX_WS
+
struct gprs_rlcmac_rlc_window {
uint16_t sns;
uint16_t ws;
diff --git a/include/osmocom/gprs/rlcmac/rlcmac_dec.h
b/include/osmocom/gprs/rlcmac/rlcmac_dec.h
index c973917..ea92a0f 100644
--- a/include/osmocom/gprs/rlcmac/rlcmac_dec.h
+++ b/include/osmocom/gprs/rlcmac/rlcmac_dec.h
@@ -4,10 +4,13 @@
#include <stdint.h>
#include <osmocom/core/msgb.h>
+#include <osmocom/core/bitvec.h>
+#include <osmocom/gprs/rlcmac/csn1_defs.h>
#include <osmocom/gprs/rlcmac/rlc.h>
#include <osmocom/gprs/rlcmac/coding_scheme.h>
+struct gprs_rlcmac_rlc_ul_window;
/****************
* DATA BLOCKS:
@@ -38,3 +41,8 @@
/****************
* CONTROL BLOCKS:
****************/
+
+void gprs_rlcmac_extract_rbb(const struct bitvec *rbb, char *show_rbb);
+int gprs_rlcmac_decode_gprs_acknack_bits(const Ack_Nack_Description_t *desc,
+ struct bitvec *bits, int *bsn_begin, int *bsn_end,
+ struct gprs_rlcmac_rlc_ul_window *ulw);
diff --git a/include/osmocom/gprs/rlcmac/rlcmac_private.h
b/include/osmocom/gprs/rlcmac/rlcmac_private.h
index f5bbfb0..80461da 100644
--- a/include/osmocom/gprs/rlcmac/rlcmac_private.h
+++ b/include/osmocom/gprs/rlcmac/rlcmac_private.h
@@ -80,6 +80,7 @@
/* rlcmac.c */
struct gprs_rlcmac_entity *gprs_rlcmac_find_entity_by_tlli(uint32_t tlli);
struct gprs_rlcmac_dl_tbf *gprs_rlcmac_find_dl_tbf_by_tfi(uint8_t dl_tfi);
+struct gprs_rlcmac_ul_tbf *gprs_rlcmac_find_ul_tbf_by_tfi(uint8_t ul_tfi);
int gprs_rlcmac_handle_ccch_imm_ass(const struct gsm48_imm_ass *ia);
int gprs_rlcmac_handle_gprs_dl_block(const struct osmo_gprs_rlcmac_prim *rlcmac_prim,
enum gprs_rlcmac_coding_scheme cs);
diff --git a/include/osmocom/gprs/rlcmac/tbf_ul.h b/include/osmocom/gprs/rlcmac/tbf_ul.h
index efe03b4..f9c5a7f 100644
--- a/include/osmocom/gprs/rlcmac/tbf_ul.h
+++ b/include/osmocom/gprs/rlcmac/tbf_ul.h
@@ -49,6 +49,8 @@
struct msgb *gprs_rlcmac_ul_tbf_data_create(struct gprs_rlcmac_ul_tbf *ul_tbf, const
struct gprs_rlcmac_rts_block_ind *bi);
struct msgb *gprs_rlcmac_ul_tbf_dummy_create(const struct gprs_rlcmac_ul_tbf *ul_tbf);
+int gprs_rlcmac_ul_tbf_handle_pkt_ul_ack_nack(struct gprs_rlcmac_ul_tbf *ul_tbf, bool
final_ack,
+ unsigned first_bsn, struct bitvec *rbb);
static inline struct gprs_rlcmac_tbf *ul_tbf_as_tbf(struct gprs_rlcmac_ul_tbf *ul_tbf)
{
diff --git a/include/osmocom/gprs/rlcmac/tbf_ul_fsm.h
b/include/osmocom/gprs/rlcmac/tbf_ul_fsm.h
index dc50a66..1d7ff88 100644
--- a/include/osmocom/gprs/rlcmac/tbf_ul_fsm.h
+++ b/include/osmocom/gprs/rlcmac/tbf_ul_fsm.h
@@ -26,7 +26,7 @@
GPRS_RLCMAC_TBF_UL_EV_UL_ASS_START,
GPRS_RLCMAC_TBF_UL_EV_UL_ASS_COMPL,
GPRS_RLCMAC_TBF_UL_EV_LAST_UL_DATA_SENT,
- GPRS_RLCMAC_TBF_UL_EV_FOOBAR,
+ GPRS_RLCMAC_TBF_UL_EV_FINAL_ACK_RECVD,
};
int gprs_rlcmac_tbf_ul_fsm_init(void);
diff --git a/include/osmocom/gprs/rlcmac/types_private.h
b/include/osmocom/gprs/rlcmac/types_private.h
index 77a0504..8f985ba 100644
--- a/include/osmocom/gprs/rlcmac/types_private.h
+++ b/include/osmocom/gprs/rlcmac/types_private.h
@@ -46,3 +46,11 @@
GPRS_RLCMAC_LLC_PDU_TYPE_ACKNOWLEDGED = 0,
GPRS_RLCMAC_LLC_PDU_TYPE_UNACKNOWLEDGED = 1,
};
+
+/* TS 44.060 12.20 "PAGE_MODE" */
+enum gprs_rlcmac_page_mode {
+ GPRS_RLCMAC_PAGE_MODE_NORMAL = 0,
+ GPRS_RLCMAC_PAGE_MODE_EXTENDED = 1,
+ GPRS_RLCMAC_PAGE_MODE_REORGANIZATION = 2,
+ GPRS_RLCMAC_PAGE_MODE_SAME_BEFORE = 3,
+};
diff --git a/src/rlcmac/rlc_window.c b/src/rlcmac/rlc_window.c
index d17307b..2a37e97 100644
--- a/src/rlcmac/rlc_window.c
+++ b/src/rlcmac/rlc_window.c
@@ -22,16 +22,10 @@
#include <osmocom/gprs/rlcmac/rlc.h>
#include <osmocom/gprs/rlcmac/rlc_window.h>
-#define RLC_GPRS_WS 64 /* max window size */
-#define RLC_EGPRS_MIN_WS 64 /* min window size */
-#define RLC_EGPRS_MAX_WS 1024 /* min window size */
-#define RLC_EGPRS_MAX_BSN_DELTA 512
-#define RLC_MAX_WS RLC_EGPRS_MAX_WS
-
void gprs_rlcmac_rlc_window_constructor(struct gprs_rlcmac_rlc_window *w)
{
w->sns = RLC_GPRS_SNS;
- w->ws = RLC_GPRS_WS;
+ w->ws = GPRS_RLCMAC_GPRS_WS;
}
void gprs_rlcmac_rlc_window_destructor(struct gprs_rlcmac_rlc_window *w)
diff --git a/src/rlcmac/rlcmac.c b/src/rlcmac/rlcmac.c
index 1e28bac..c6c23e6 100644
--- a/src/rlcmac/rlcmac.c
+++ b/src/rlcmac/rlcmac.c
@@ -36,6 +36,7 @@
#include <osmocom/gprs/rlcmac/csn1_defs.h>
#include <osmocom/gprs/rlcmac/rlc.h>
#include <osmocom/gprs/rlcmac/types_private.h>
+#include <osmocom/gprs/rlcmac/rlc_window.h>
#define GPRS_CODEL_SLOW_INTERVAL_MS 4000
@@ -144,6 +145,20 @@
return NULL;
}
+struct gprs_rlcmac_ul_tbf *gprs_rlcmac_find_ul_tbf_by_tfi(uint8_t ul_tfi)
+{
+ struct gprs_rlcmac_entity *gre;
+
+ llist_for_each_entry(gre, &g_ctx->gre_list, entry) {
+ if (!gre->ul_tbf)
+ continue;
+ if (gre->ul_tbf->cur_alloc.ul_tfi != ul_tfi)
+ continue;
+ return gre->ul_tbf;
+ }
+ return NULL;
+}
+
static int gprs_rlcmac_handle_ccch_imm_ass_ul_tbf(uint8_t ts_nr, const struct
gsm48_imm_ass *ia, const IA_RestOctets_t *iaro)
{
int rc = -ENOENT;
@@ -281,6 +296,45 @@
return rc;
}
+static int gprs_rlcmac_handle_pkt_ul_ack_nack(const struct osmo_gprs_rlcmac_prim
*rlcmac_prim, const RlcMacDownlink_t *dl_block)
+{
+ const Packet_Uplink_Ack_Nack_t *ack = &dl_block->u.Packet_Uplink_Ack_Nack;
+ const PU_AckNack_GPRS_t *gprs = &ack->u.PU_AckNack_GPRS_Struct;
+ const Ack_Nack_Description_t *ack_desc = &gprs->Ack_Nack_Description;
+ struct gprs_rlcmac_ul_tbf *ul_tbf;
+ int bsn_begin, bsn_end;
+ int num_blocks;
+ uint8_t bits_data[GPRS_RLCMAC_GPRS_WS/8];
+ char show_bits[GPRS_RLCMAC_GPRS_WS + 1];
+ struct bitvec bits = {
+ .data = bits_data,
+ .data_len = sizeof(bits_data),
+ .cur_bit = 0,
+ };
+ int rc;
+
+ ul_tbf = gprs_rlcmac_find_ul_tbf_by_tfi(dl_block->TFI);
+ if (!ul_tbf) {
+ LOGRLCMAC(LOGL_INFO, "TS=%u FN=%u Rx Pkt UL ACK/NACK: UL_TBF TFI=%u not
found\n",
+ rlcmac_prim->l1ctl.pdch_data_ind.ts_nr,
+ rlcmac_prim->l1ctl.pdch_data_ind.fn,
+ dl_block->TFI);
+ return -ENOENT;
+ }
+
+ num_blocks = gprs_rlcmac_decode_gprs_acknack_bits(
+ ack_desc, &bits, &bsn_begin, &bsn_end, ul_tbf->ulw);
+
+ LOGPTBFUL(ul_tbf, LOGL_DEBUG,
+ "Got GPRS UL ACK bitmap: SSN: %d, BSN %d to %d - 1 (%d blocks),
\"%s\"\n",
+ ack_desc->STARTING_SEQUENCE_NUMBER,
+ bsn_begin, bsn_end, num_blocks,
+ (gprs_rlcmac_extract_rbb(&bits, show_bits), show_bits));
+
+ rc = gprs_rlcmac_ul_tbf_handle_pkt_ul_ack_nack(ul_tbf,
ack_desc->FINAL_ACK_INDICATION, bsn_begin, &bits);
+ return rc;
+}
+
static int gprs_rlcmac_handle_gprs_dl_ctrl_block(const struct osmo_gprs_rlcmac_prim
*rlcmac_prim)
{
struct bitvec *bv;
@@ -302,7 +356,21 @@
goto free_ret;
}
- LOGRLCMAC(LOGL_NOTICE, "TODO: handle decoded dl ctrl block!\n");
+ LOGRLCMAC(LOGL_INFO, "TS=%u FN=%u Rx %s\n",
+ rlcmac_prim->l1ctl.pdch_data_ind.ts_nr,
+ rlcmac_prim->l1ctl.pdch_data_ind.fn,
+ get_value_string(osmo_gprs_rlcmac_dl_msg_type_names,
dl_ctrl_block->u.MESSAGE_TYPE));
+
+ switch (dl_ctrl_block->u.MESSAGE_TYPE) {
+ case OSMO_GPRS_RLCMAC_DL_MSGT_PACKET_UPLINK_ACK_NACK:
+ rc = gprs_rlcmac_handle_pkt_ul_ack_nack(rlcmac_prim, dl_ctrl_block);
+ break;
+ default:
+ LOGRLCMAC(LOGL_ERROR, "TS=%u FN=%u Rx %s NOT SUPPORTED! ignoring\n",
+ rlcmac_prim->l1ctl.pdch_data_ind.ts_nr,
+ rlcmac_prim->l1ctl.pdch_data_ind.fn,
+ get_value_string(osmo_gprs_rlcmac_dl_msg_type_names,
dl_ctrl_block->u.MESSAGE_TYPE));
+ }
free_ret:
talloc_free(dl_ctrl_block);
diff --git a/src/rlcmac/rlcmac_dec.c b/src/rlcmac/rlcmac_dec.c
index cd44fc8..fa88c26 100644
--- a/src/rlcmac/rlcmac_dec.c
+++ b/src/rlcmac/rlcmac_dec.c
@@ -26,6 +26,7 @@
#include <osmocom/gprs/rlcmac/rlcmac_private.h>
#include <osmocom/gprs/rlcmac/rlcmac_dec.h>
#include <osmocom/gprs/rlcmac/rlc.h>
+#include <osmocom/gprs/rlcmac/rlc_window_ul.h>
#define LENGTH_TO_END 255
/*!
@@ -341,3 +342,83 @@
return rdbi->data_len;
}
+
+/**
+ * show_rbb needs to be an array with 65 elements
+ * The index of the array is the bit position in the rbb
+ * (show_rbb[63] relates to BSN ssn-1)
+ */
+void gprs_rlcmac_extract_rbb(const struct bitvec *rbb, char *show_rbb)
+{
+ unsigned int i;
+ for (i = 0; i < rbb->cur_bit; i++) {
+ uint8_t bit;
+ bit = bitvec_get_bit_pos(rbb, i);
+ show_rbb[i] = bit == 1 ? 'R' : 'I';
+ }
+
+ show_rbb[i] = '\0';
+}
+
+static int handle_final_ack(struct bitvec *bits, int *bsn_begin, int *bsn_end,
+ struct gprs_rlcmac_rlc_ul_window *ulw)
+{
+ int num_blocks, i;
+ uint16_t v_a = gprs_rlcmac_rlc_ul_window_v_a(ulw);
+
+ num_blocks = gprs_rlcmac_rlc_window_mod_sns_bsn(rlc_ulw_as_w(ulw),
+ gprs_rlcmac_rlc_ul_window_v_s(ulw) - v_a);
+ for (i = 0; i < num_blocks; i++)
+ bitvec_set_bit(bits, ONE);
+
+ *bsn_begin = v_a;
+ *bsn_end = gprs_rlcmac_rlc_window_mod_sns_bsn(rlc_ulw_as_w(ulw), *bsn_begin +
num_blocks);
+ return num_blocks;
+}
+
+int gprs_rlcmac_decode_gprs_acknack_bits(const Ack_Nack_Description_t *desc,
+ struct bitvec *bits, int *bsn_begin, int *bsn_end,
+ struct gprs_rlcmac_rlc_ul_window *ulw)
+{
+ int urbb_len = GPRS_RLCMAC_GPRS_WS;
+ int num_blocks;
+ struct bitvec urbb;
+
+ if (desc->FINAL_ACK_INDICATION)
+ return handle_final_ack(bits, bsn_begin, bsn_end, ulw);
+
+ *bsn_begin = gprs_rlcmac_rlc_ul_window_v_a(ulw);
+ *bsn_end = desc->STARTING_SEQUENCE_NUMBER;
+
+ num_blocks = gprs_rlcmac_rlc_window_mod_sns_bsn(rlc_ulw_as_w(ulw), *bsn_end -
*bsn_begin);
+
+ if (num_blocks < 0 || num_blocks > urbb_len) {
+ *bsn_end = *bsn_begin;
+ LOGRLCMAC(LOGL_NOTICE, "Invalid GPRS Ack/Nack window %d:%d (length %d)\n",
+ *bsn_begin, *bsn_end, num_blocks);
+ return -EINVAL;
+ }
+
+ urbb.cur_bit = 0;
+ urbb.data = (uint8_t *)desc->RECEIVED_BLOCK_BITMAP;
+ urbb.data_len = sizeof(desc->RECEIVED_BLOCK_BITMAP);
+
+ /*
+ * TS 44.060, 12.3:
+ * BSN = (SSN - bit_number) modulo 128, for bit_number = 1 to 64.
+ * The BSN values represented range from (SSN - 1) mod 128 to (SSN - 64) mod 128.
+ *
+ * We are only interested in the range from V(A) to SSN-1 which is
+ * num_blocks large. The RBB is laid out as
+ * [SSN-1] [SSN-2] ... [V(A)] ... [SSN-64]
+ * so we want to start with [V(A)] and go backwards until we reach
+ * [SSN-1] to get the needed BSNs in an increasing order. Note that
+ * the bit numbers are counted from the end of the buffer.
+ */
+ for (int i = num_blocks; i > 0; i--) {
+ int is_ack = bitvec_get_bit_pos(&urbb, urbb_len - i);
+ bitvec_set_bit(bits, is_ack == 1 ? ONE : ZERO);
+ }
+
+ return num_blocks;
+}
diff --git a/src/rlcmac/tbf_ul.c b/src/rlcmac/tbf_ul.c
index 906efbe..ae6b156 100644
--- a/src/rlcmac/tbf_ul.c
+++ b/src/rlcmac/tbf_ul.c
@@ -22,6 +22,7 @@
#include <osmocom/core/bitvec.h>
#include <osmocom/gprs/rlcmac/tbf_ul.h>
+#include <osmocom/gprs/rlcmac/rlcmac_dec.h>
#include <osmocom/gprs/rlcmac/rlcmac_enc.h>
#include <osmocom/gprs/rlcmac/gre.h>
#include <osmocom/gprs/rlcmac/coding_scheme.h>
@@ -110,6 +111,74 @@
return (st == GPRS_RLCMAC_TBF_UL_ST_FLOW);
}
+static int gprs_rlcmac_ul_tbf_update_window(struct gprs_rlcmac_ul_tbf *ul_tbf,
+ unsigned first_bsn, struct bitvec *rbb)
+{
+ unsigned dist;
+ uint16_t lost = 0, received = 0;
+ char show_v_b[RLC_MAX_SNS + 1];
+ char show_rbb[RLC_MAX_SNS + 1];
+ dist = gprs_rlcmac_rlc_ul_window_distance(ul_tbf->ulw);
+ unsigned num_blocks = rbb->cur_bit > dist
+ ? dist : rbb->cur_bit;
+ unsigned behind_last_bsn = gprs_rlcmac_rlc_window_mod_sns_bsn(ul_tbf->w, first_bsn +
num_blocks);
+
+ gprs_rlcmac_extract_rbb(rbb, show_rbb);
+ /* show received array in debug */
+ LOGPTBFUL(ul_tbf, LOGL_DEBUG,
+ "ack: (BSN=%d)\"%s\"(BSN=%d) R=ACK I=NACK\n",
+ first_bsn, show_rbb,
+ gprs_rlcmac_rlc_window_mod_sns_bsn(ul_tbf->w, behind_last_bsn - 1));
+
+ gprs_rlcmac_rlc_ul_window_update(ul_tbf->ulw, rbb, first_bsn, &lost,
&received);
+
+ /* raise V(A), if possible */
+ gprs_rlcmac_rlc_ul_window_raise(ul_tbf->ulw,
+ gprs_rlcmac_rlc_ul_window_move_window(ul_tbf->ulw));
+
+ /* show receive state array in debug (V(A)..V(S)-1) */
+ gprs_rlcmac_rlc_ul_window_show_state(ul_tbf->ulw, show_v_b);
+ LOGPTBFUL(ul_tbf, LOGL_DEBUG,
+ "V(B): (V(A)=%d)\"%s\"(V(S)-1=%d) A=Acked N=Nacked U=Unacked
X=Resend-Unacked I=Invalid\n",
+ gprs_rlcmac_rlc_ul_window_v_a(ul_tbf->ulw), show_v_b,
+ gprs_rlcmac_rlc_ul_window_v_s_mod(ul_tbf->ulw, -1));
+ return 0;
+}
+
+int gprs_rlcmac_ul_tbf_handle_final_ack(struct gprs_rlcmac_ul_tbf *ul_tbf)
+{
+ int rc = 0;
+
+ osmo_fsm_inst_dispatch(ul_tbf->state_fsm.fi, GPRS_RLCMAC_TBF_UL_EV_FINAL_ACK_RECVD,
NULL);
+
+ /* range V(A)..V(S)-1 */
+ //received = gprs_rlcmac_rlc_ul_window_count_unacked(ul_tbf->ulw);
+ /* report all outstanding packets as received */
+ //gprs_rlcmac_received_lost(this, received, 0);
+ gprs_rlcmac_rlc_ul_window_reset(ul_tbf->ulw);
+
+ /* TODO: check for RRBP and attempt to create a new UL TBF if
+ * gprs_rlcmac_ul_tbf_have_data(ul_tbf) */
+ return rc;
+}
+
+int gprs_rlcmac_ul_tbf_handle_pkt_ul_ack_nack(struct gprs_rlcmac_ul_tbf *ul_tbf, bool
final_ack,
+ unsigned first_bsn, struct bitvec *rbb)
+{
+ int rc;
+ rc = gprs_rlcmac_ul_tbf_update_window(ul_tbf, first_bsn, rbb);
+
+ if (final_ack) {
+ LOGPTBFUL(ul_tbf, LOGL_DEBUG, "Final ACK received.\n");
+ rc = gprs_rlcmac_ul_tbf_handle_final_ack(ul_tbf);
+ } else if (gprs_rlcmac_tbf_ul_state(ul_tbf) &&
+ gprs_rlcmac_rlc_ul_window_window_empty(ul_tbf->ulw)) {
+ LOGPTBFUL(ul_tbf, LOGL_NOTICE,
+ "Received acknowledge of all blocks, but without final ack indication
(don't worry)\n");
+ }
+ return rc;
+}
+
struct msgb *gprs_rlcmac_ul_tbf_dummy_create(const struct gprs_rlcmac_ul_tbf *ul_tbf)
{
struct msgb *msg;
diff --git a/src/rlcmac/tbf_ul_fsm.c b/src/rlcmac/tbf_ul_fsm.c
index 5095605..3cff899 100644
--- a/src/rlcmac/tbf_ul_fsm.c
+++ b/src/rlcmac/tbf_ul_fsm.c
@@ -33,7 +33,7 @@
{ GPRS_RLCMAC_TBF_UL_EV_UL_ASS_START, "UL_ASS_START" },
{ GPRS_RLCMAC_TBF_UL_EV_UL_ASS_COMPL, "UL_ASS_COMPL" },
{ GPRS_RLCMAC_TBF_UL_EV_LAST_UL_DATA_SENT, "LAST_UL_DATA_SENT" },
- { GPRS_RLCMAC_TBF_UL_EV_FOOBAR, "FOOBAR" },
+ { GPRS_RLCMAC_TBF_UL_EV_FINAL_ACK_RECVD, "FINAL_ACK_RECVD" },
{ 0, NULL }
};
@@ -118,6 +118,8 @@
{
//struct gprs_rlcmac_tbf_ul_fsm_ctx *ctx = (struct gprs_rlcmac_tbf_ul_fsm_ctx
*)fi->priv;
switch (event) {
+ case GPRS_RLCMAC_TBF_UL_EV_FINAL_ACK_RECVD:
+ break;
default:
OSMO_ASSERT(0);
}
@@ -151,7 +153,7 @@
},
[GPRS_RLCMAC_TBF_UL_ST_FINISHED] = {
.in_event_mask =
- X(GPRS_RLCMAC_TBF_UL_EV_FOOBAR),
+ X(GPRS_RLCMAC_TBF_UL_EV_FINAL_ACK_RECVD),
.out_state_mask =
X(GPRS_RLCMAC_TBF_UL_ST_WAIT_ASSIGN),
.name = "FINISHED",
diff --git a/tests/rlcmac/rlcmac_prim_test.c b/tests/rlcmac/rlcmac_prim_test.c
index 2711889..658ddb3 100644
--- a/tests/rlcmac/rlcmac_prim_test.c
+++ b/tests/rlcmac/rlcmac_prim_test.c
@@ -23,8 +23,10 @@
#include <osmocom/core/fsm.h>
#include <osmocom/gprs/rlcmac/rlcmac.h>
+#include <osmocom/gprs/rlcmac/csn1_defs.h>
#include <osmocom/gprs/rlcmac/gre.h>
#include <osmocom/gprs/rlcmac/rlc.h>
+#include <osmocom/gprs/rlcmac/rlc_window.h>
#include <osmocom/gprs/rlcmac/types_private.h>
#include <osmocom/gprs/rlcmac/sched.h>
@@ -192,6 +194,64 @@
return fn % GSM_MAX_FN;
}
+static struct osmo_gprs_rlcmac_prim *create_dl_ctrl_block_buf(uint8_t *buf, int
num_bytes, uint8_t tn, uint32_t fn)
+{
+ struct osmo_gprs_rlcmac_prim *rlcmac_prim;
+
+
+ rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_pdch_data_ind(tn, fn, 0, 0, 0,
+ NULL, num_bytes);
+ rlcmac_prim->l1ctl.pdch_data_ind.data = msgb_put(rlcmac_prim->oph.msg,
num_bytes);
+ memcpy(rlcmac_prim->l1ctl.pdch_data_ind.data, buf, num_bytes);
+ return rlcmac_prim;
+}
+
+static struct osmo_gprs_rlcmac_prim *create_dl_ctrl_block(RlcMacDownlink_t *dl_block,
uint8_t tn, uint32_t fn)
+{
+ struct bitvec *rlc_block;
+ uint8_t buf[64];
+ int num_bytes;
+
+ rlc_block = bitvec_alloc(23, tall_ctx);
+
+ OSMO_ASSERT(osmo_gprs_rlcmac_encode_downlink(rlc_block, dl_block) == 0);
+ num_bytes = bitvec_pack(rlc_block, &buf[0]);
+ OSMO_ASSERT((size_t)num_bytes < sizeof(buf));
+ bitvec_free(rlc_block);
+
+ return create_dl_ctrl_block_buf(&buf[0], num_bytes, tn, fn);
+}
+
+static void ul_ack_nack_init(RlcMacDownlink_t *dl_block, uint8_t ul_tfi, enum
gprs_rlcmac_coding_scheme cs)
+{
+ Packet_Uplink_Ack_Nack_t *ack = &dl_block->u.Packet_Uplink_Ack_Nack;
+ PU_AckNack_GPRS_t *gprs = &ack->u.PU_AckNack_GPRS_Struct;
+
+ memset(dl_block, 0, sizeof(*dl_block));
+ dl_block->PAYLOAD_TYPE = GPRS_RLCMAC_PT_CONTROL_BLOCK;
+ dl_block->RRBP = 0;
+ dl_block->SP = 0;
+ dl_block->USF = 0x00;
+ dl_block->u.MESSAGE_TYPE = OSMO_GPRS_RLCMAC_DL_MSGT_PACKET_UPLINK_ACK_NACK;
+
+ ack->MESSAGE_TYPE = OSMO_GPRS_RLCMAC_DL_MSGT_PACKET_UPLINK_ACK_NACK;
+ ack->PAGE_MODE = GPRS_RLCMAC_PAGE_MODE_NORMAL;
+ ack->UPLINK_TFI = ul_tfi;
+ ack->UnionType = 0; /* GPRS */
+
+ gprs->CHANNEL_CODING_COMMAND = cs;
+}
+
+static void ul_ack_nack_mark(Ack_Nack_Description_t *ack_desc, unsigned int idx, bool
received)
+{
+ //ack_desc->RECEIVED_BLOCK_BITMAP[sizeof(ack_desc->RECEIVED_BLOCK_BITMAP) - 1] =
0xff;
+ //memset(ack_desc->RECEIVED_BLOCK_BITMAP, 0xff,
sizeof(ack_desc->RECEIVED_BLOCK_BITMAP));
+ if (received)
+ ack_desc->RECEIVED_BLOCK_BITMAP[sizeof(ack_desc->RECEIVED_BLOCK_BITMAP) - idx/8 -
1] |= (1 << (idx & 0x03));
+ else
+ ack_desc->RECEIVED_BLOCK_BITMAP[sizeof(ack_desc->RECEIVED_BLOCK_BITMAP) - idx/8 -
1] &= ~(1 << (idx & 0x03));
+}
+
static int test_rlcmac_prim_up_cb(struct osmo_gprs_rlcmac_prim *rlcmac_prim, void
*user_data)
{
const char *pdu_name = osmo_gprs_rlcmac_prim_name(rlcmac_prim);
@@ -306,7 +366,10 @@
printf("=== %s start ===\n", __func__);
prepare_test();
+ RlcMacDownlink_t dl_block;
+ Ack_Nack_Description_t *ack_desc =
&dl_block.u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.Ack_Nack_Description;
uint32_t tlli = 0x2342;
+ uint8_t ul_tfi = 0;
uint8_t ts_nr = 7;
uint8_t usf = 0;
uint32_t rts_fn = 4;
@@ -330,7 +393,16 @@
rts_fn = fn_next_block(rts_fn);
rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_pdch_rts_ind(ts_nr, rts_fn, usf);
rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
+ OSMO_ASSERT(rc == 0);
+ /* PCU acks it: */
+ ul_ack_nack_init(&dl_block, ul_tfi, GPRS_RLCMAC_CS_2);
+ ack_desc->STARTING_SEQUENCE_NUMBER = 1;
+ ack_desc->FINAL_ACK_INDICATION = 1;
+ ul_ack_nack_mark(ack_desc, 0, true);
+ ul_ack_nack_mark(ack_desc, 1, true);
+ rlcmac_prim = create_dl_ctrl_block(&dl_block, ts_nr, rts_fn);
+ rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
OSMO_ASSERT(rc == 0);
printf("=== %s end ===\n", __func__);
diff --git a/tests/rlcmac/rlcmac_prim_test.err b/tests/rlcmac/rlcmac_prim_test.err
index 2e82b2e..8f7283d 100644
--- a/tests/rlcmac/rlcmac_prim_test.err
+++ b/tests/rlcmac/rlcmac_prim_test.err
@@ -37,6 +37,15 @@
DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) Copying 1 RLC blocks, 1 BSNs
DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) Copying data unit 0 (BSN 1)
DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) msg block (BSN 1, CS-2): 00 00 02 0d e2 18 f2
2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 00
+DLGLOBAL INFO Rx from lower layers: L1CTL-PDCH_DATA.indication
+DLGLOBAL INFO TS=7 FN=8 Rx Pkt UL ACK/NACK
+DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) Got GPRS UL ACK bitmap: SSN: 1, BSN 0 to 2 - 1
(2 blocks), "RR"
+DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) ack: (BSN=0)"RR"(BSN=1) R=ACK
I=NACK
+DLGLOBAL DEBUG - got ack for BSN=0
+DLGLOBAL DEBUG - got ack for BSN=1
+DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) V(B): (V(A)=2)""(V(S)-1=1) A=Acked
N=Nacked U=Unacked X=Resend-Unacked I=Invalid
+DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) Final ACK received.
+DLGLOBAL INFO UL_TBF{FINISHED}: Received Event FINAL_ACK_RECVD
DLGLOBAL INFO UL_TBF_ASS{IDLE}: Deallocated
DLGLOBAL INFO UL_TBF{FINISHED}: Deallocated
DLGLOBAL INFO Rx from upper layers: GMMRR-ASSIGN.request
--
To view, visit
https://gerrit.osmocom.org/c/libosmo-gprs/+/31344
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings
Gerrit-Project: libosmo-gprs
Gerrit-Branch: master
Gerrit-Change-Id: I5e3d8e77042d3ad1618e6b62bc1a377a93239580
Gerrit-Change-Number: 31344
Gerrit-PatchSet: 2
Gerrit-Owner: pespin <pespin(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-Reviewer: pespin <pespin(a)sysmocom.de>
Gerrit-MessageType: merged