rlcmac: Implement Rx of UL ACK/NACK

Related: OS#5500
Change-Id: I5e3d8e77042d3ad1618e6b62bc1a377a93239580
This commit is contained in:
Pau Espin 2023-02-15 12:15:11 +01:00
parent 61c0f7f158
commit 8c2734fa43
13 changed files with 331 additions and 11 deletions

View File

@ -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;

View File

@ -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 @@ unsigned int gprs_rlcmac_rlc_copy_to_aligned_buffer(const struct gprs_rlcmac_rlc
/****************
* 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);

View File

@ -80,6 +80,7 @@ extern struct gprs_rlcmac_ctx *g_ctx;
/* 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);

View File

@ -49,6 +49,8 @@ bool gprs_rlcmac_ul_tbf_dummy_rts(const struct gprs_rlcmac_ul_tbf *ul_tbf, const
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)
{

View File

@ -26,7 +26,7 @@ enum tbf_ul_fsm_event {
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);

View File

@ -46,3 +46,11 @@ enum gprs_rlcmac_llc_pdu_type {
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,
};

View File

@ -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)

View File

@ -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 @@ struct gprs_rlcmac_dl_tbf *gprs_rlcmac_find_dl_tbf_by_tfi(uint8_t dl_tfi)
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 @@ int gprs_rlcmac_handle_ccch_imm_ass(const struct gsm48_imm_ass *ia)
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 @@ static int gprs_rlcmac_handle_gprs_dl_ctrl_block(const struct osmo_gprs_rlcmac_p
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);

View File

@ -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 @@ unsigned int gprs_rlcmac_rlc_copy_to_aligned_buffer(
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;
}

View File

@ -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 @@ bool gprs_rlcmac_ul_tbf_data_rts(const struct gprs_rlcmac_ul_tbf *ul_tbf, const
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;

View File

@ -33,7 +33,7 @@ static const struct value_string tbf_ul_fsm_event_names[] = {
{ 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 @@ static void st_finished(struct osmo_fsm_inst *fi, uint32_t event, void *data)
{
//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 @@ static struct osmo_fsm_state tbf_ul_fsm_states[] = {
},
[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",

View File

@ -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 @@ static inline unsigned fn_next_block(unsigned fn)
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 @@ static void test_ul_tbf_attach(void)
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 @@ static void test_ul_tbf_attach(void)
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__);

View File

@ -37,6 +37,15 @@ DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) need_padding 0 spb_status 0 spb 0 (BSN
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