rlcmac: Implement Rx of UL ACK/NACK
Related: OS#5500 Change-Id: I5e3d8e77042d3ad1618e6b62bc1a377a93239580
This commit is contained in:
parent
61c0f7f158
commit
8c2734fa43
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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__);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue