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 <[email protected]>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <[email protected]>
Gerrit-Reviewer: pespin <[email protected]>
Gerrit-MessageType: merged

Reply via email to