forked from cellular-infrastructure/osmo-pcu
edge: Handle EGPRS PACKET DOWNLINK ACK NACK
Currently this message is ignored. Support decoding and handling of this message. Use a bitvec for the decoder that just represents a BSN sequence without any encoding details (first bit -> first BSN). Return the corresponding BSN range (snsmod(bsn_begin + bits_in_bitvec) = bsn_end), so snsmod(bsn_end-1) is the last BSN if there is at least 1. If bsn_begin == bsn_end, no BSNs has been added. Note that this bitvec is not yet used for RBB handling. It just calls the old rcvd_dl_ack with a faked (all bits are 1) RBB map. Sponsored-by: On-Waves ehf
This commit is contained in:
parent
c2141c6064
commit
ae9c575d2c
120
src/bts.cpp
120
src/bts.cpp
|
@ -946,6 +946,123 @@ void gprs_rlcmac_pdch::rcv_control_dl_ack_nack(Packet_Downlink_Ack_Nack_t *ack_n
|
|||
}
|
||||
}
|
||||
|
||||
void gprs_rlcmac_pdch::rcv_control_egprs_dl_ack_nack(EGPRS_PD_AckNack_t *ack_nack, uint32_t fn)
|
||||
{
|
||||
int8_t tfi = 0; /* must be signed */
|
||||
struct gprs_rlcmac_dl_tbf *tbf;
|
||||
struct pcu_l1_meas meas;
|
||||
int rc;
|
||||
int num_blocks;
|
||||
uint8_t bits_data[RLC_EGPRS_MAX_WS/8];
|
||||
char show_bits[RLC_EGPRS_MAX_WS + 1];
|
||||
bitvec bits;
|
||||
int bsn_begin, bsn_end;
|
||||
|
||||
tfi = ack_nack->DOWNLINK_TFI;
|
||||
tbf = bts()->dl_tbf_by_poll_fn(fn, trx_no(), ts_no);
|
||||
if (!tbf) {
|
||||
LOGP(DRLCMAC, LOGL_NOTICE, "EGPRS PACKET DOWNLINK ACK with "
|
||||
"unknown FN=%u TFI=%d (TRX %d TS %d)\n",
|
||||
fn, tfi, trx_no(), ts_no);
|
||||
return;
|
||||
}
|
||||
if (tbf->tfi() != tfi) {
|
||||
LOGP(DRLCMAC, LOGL_NOTICE, "EGPRS PACKET DOWNLINK ACK with "
|
||||
"wrong TFI=%d, ignoring!\n", tfi);
|
||||
return;
|
||||
}
|
||||
tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_DL_ACK);
|
||||
if ((tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_TO_DL_ACK))) {
|
||||
tbf->state_flags &= ~(1 << GPRS_RLCMAC_FLAG_TO_DL_ACK);
|
||||
LOGP(DRLCMAC, LOGL_NOTICE, "Recovered EGPRS downlink ack "
|
||||
"for %s\n", tbf_name(tbf));
|
||||
}
|
||||
/* reset N3105 */
|
||||
tbf->n3105 = 0;
|
||||
tbf->stop_t3191();
|
||||
LOGP(DRLCMAC, LOGL_DEBUG,
|
||||
"RX: [PCU <- BTS] %s EGPRS Packet Downlink Ack/Nack\n",
|
||||
tbf_name(tbf));
|
||||
tbf->poll_state = GPRS_RLCMAC_POLL_NONE;
|
||||
|
||||
LOGP(DRLCMAC, LOGL_DEBUG, "EGPRS ACK/NACK: "
|
||||
"ut: %d, final: %d, bow: %d, eow: %d, ssn: %d, have_crbb: %d, "
|
||||
"urbb_len:%d, %p, %p, %d, %d, win: %d-%d, urbb: %s\n",
|
||||
(int)ack_nack->EGPRS_AckNack.UnionType,
|
||||
(int)ack_nack->EGPRS_AckNack.Desc.FINAL_ACK_INDICATION,
|
||||
(int)ack_nack->EGPRS_AckNack.Desc.BEGINNING_OF_WINDOW,
|
||||
(int)ack_nack->EGPRS_AckNack.Desc.END_OF_WINDOW,
|
||||
(int)ack_nack->EGPRS_AckNack.Desc.STARTING_SEQUENCE_NUMBER,
|
||||
(int)ack_nack->EGPRS_AckNack.Desc.Exist_CRBB,
|
||||
(int)ack_nack->EGPRS_AckNack.Desc.URBB_LENGTH,
|
||||
(void *)&ack_nack->EGPRS_AckNack.UnionType,
|
||||
(void *)&ack_nack->EGPRS_AckNack.Desc,
|
||||
(int)offsetof(EGPRS_AckNack_t, Desc),
|
||||
(int)offsetof(EGPRS_AckNack_w_len_t, Desc),
|
||||
tbf->m_window.v_a(),
|
||||
tbf->m_window.v_s(),
|
||||
osmo_hexdump((const uint8_t *)&ack_nack->EGPRS_AckNack.Desc.URBB,
|
||||
sizeof(ack_nack->EGPRS_AckNack.Desc.URBB)));
|
||||
|
||||
bits.data = bits_data;
|
||||
bits.data_len = sizeof(bits_data);
|
||||
bits.cur_bit = 0;
|
||||
|
||||
num_blocks = Decoding::decode_egprs_acknack_bits(
|
||||
&ack_nack->EGPRS_AckNack.Desc, &bits,
|
||||
&bsn_begin, &bsn_end, &tbf->m_window);
|
||||
|
||||
for (int i = 0; i < num_blocks; i++) {
|
||||
show_bits[i] = bitvec_get_bit_pos(&bits, i) ? 'R' : 'I';
|
||||
}
|
||||
show_bits[num_blocks] = 0;
|
||||
|
||||
LOGP(DRLCMAC, LOGL_DEBUG,
|
||||
"EGPRS DL ACK bitmap: BSN %d to %d - 1 (%d blocks): %s\n",
|
||||
bsn_begin, bsn_end, num_blocks, show_bits);
|
||||
|
||||
if (ack_nack->EGPRS_AckNack.Desc.URBB_LENGTH == 0 &&
|
||||
!ack_nack->EGPRS_AckNack.Desc.Exist_CRBB)
|
||||
{
|
||||
/* Everything has been received successfully */
|
||||
/* Fake a GPRS type ack */
|
||||
uint64_t fake_map = -1;
|
||||
|
||||
rc = tbf->rcvd_dl_ack(
|
||||
ack_nack->EGPRS_AckNack.Desc.FINAL_ACK_INDICATION,
|
||||
tbf->m_window.mod_sns(ack_nack->EGPRS_AckNack.Desc.STARTING_SEQUENCE_NUMBER-1),
|
||||
(uint8_t *)&fake_map);
|
||||
|
||||
if (rc == 1) {
|
||||
tbf_free(tbf);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* check for channel request */
|
||||
if (ack_nack->Exist_ChannelRequestDescription) {
|
||||
LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF in ack "
|
||||
"message, so we provide one:\n");
|
||||
|
||||
/* This call will register the new TBF with the MS on success */
|
||||
tbf_alloc_ul(bts_data(), tbf->trx->trx_no,
|
||||
tbf->ms_class(), tbf->ms()->egprs_ms_class(),
|
||||
tbf->tlli(), tbf->ta(), tbf->ms());
|
||||
|
||||
/* schedule uplink assignment */
|
||||
tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_SEND_ASS;
|
||||
}
|
||||
|
||||
/* get measurements */
|
||||
if (tbf->ms()) {
|
||||
/* TODO: Implement Measurements parsing for EGPRS */
|
||||
/*
|
||||
get_meas(&meas, &ack_nack->Channel_Quality_Report);
|
||||
tbf->ms()->update_l1_meas(&meas);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
void gprs_rlcmac_pdch::rcv_resource_request(Packet_Resource_Request_t *request, uint32_t fn)
|
||||
{
|
||||
struct gprs_rlcmac_sba *sba;
|
||||
|
@ -1105,6 +1222,9 @@ int gprs_rlcmac_pdch::rcv_control_block(
|
|||
case MT_PACKET_DOWNLINK_ACK_NACK:
|
||||
rcv_control_dl_ack_nack(&ul_control_block->u.Packet_Downlink_Ack_Nack, fn);
|
||||
break;
|
||||
case MT_EGPRS_PACKET_DOWNLINK_ACK_NACK:
|
||||
rcv_control_egprs_dl_ack_nack(&ul_control_block->u.Egprs_Packet_Downlink_Ack_Nack, fn);
|
||||
break;
|
||||
case MT_PACKET_RESOURCE_REQUEST:
|
||||
rcv_resource_request(&ul_control_block->u.Packet_Resource_Request, fn);
|
||||
break;
|
||||
|
|
|
@ -107,6 +107,7 @@ private:
|
|||
|
||||
void rcv_control_ack(Packet_Control_Acknowledgement_t *, uint32_t fn);
|
||||
void rcv_control_dl_ack_nack(Packet_Downlink_Ack_Nack_t *, uint32_t fn);
|
||||
void rcv_control_egprs_dl_ack_nack(EGPRS_PD_AckNack_t *, uint32_t fn);
|
||||
void rcv_resource_request(Packet_Resource_Request_t *t, uint32_t fn);
|
||||
void rcv_measurement_report(Packet_Measurement_Report_t *t, uint32_t fn);
|
||||
gprs_rlcmac_tbf *tbf_from_list_by_tfi(
|
||||
|
|
|
@ -549,6 +549,7 @@ csnStreamDecoder(csnStream_t* ar, const CSN_DESCR* pDescr, bitvec *vector, unsig
|
|||
|
||||
csnStreamInit(&arT, bit_offset, length);
|
||||
arT.direction = 1;
|
||||
LOGPC(DCSN1, LOGL_NOTICE, "ptr = %p | offset = %d | ", (void *)data, (int)pDescr->offset);
|
||||
Status = serialize(&arT, vector, readIndex, pvDATA(data, pDescr->offset));
|
||||
|
||||
if (Status >= 0)
|
||||
|
|
|
@ -493,3 +493,94 @@ const uint8_t *Decoding::rlc_get_data_aligned(
|
|||
Decoding::rlc_copy_to_aligned_buffer(rlc, data_block_idx, src, buffer);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static int handle_final_ack(bitvec *bits, int *bsn_begin, int *bsn_end,
|
||||
gprs_rlc_dl_window *window)
|
||||
{
|
||||
int num_blocks, i;
|
||||
|
||||
num_blocks = window->mod_sns(window->v_s() - window->v_a());
|
||||
for (i = 0; i < num_blocks; i++)
|
||||
bitvec_set_bit(bits, ONE);
|
||||
|
||||
*bsn_begin = window->v_a();
|
||||
*bsn_end = window->mod_sns(*bsn_begin + num_blocks);
|
||||
return num_blocks;
|
||||
}
|
||||
|
||||
int Decoding::decode_egprs_acknack_bits(const EGPRS_AckNack_Desc_t *desc,
|
||||
bitvec *bits, int *bsn_begin, int *bsn_end, gprs_rlc_dl_window *window)
|
||||
{
|
||||
int urbb_len = desc->URBB_LENGTH;
|
||||
int crbb_len = 0;
|
||||
int num_blocks = 0;
|
||||
struct bitvec urbb;
|
||||
int i;
|
||||
bool have_bitmap;
|
||||
int implicitly_acked_blocks;
|
||||
int ssn = desc->STARTING_SEQUENCE_NUMBER;
|
||||
|
||||
if (desc->FINAL_ACK_INDICATION)
|
||||
return handle_final_ack(bits, bsn_begin, bsn_end, window);
|
||||
|
||||
if (desc->Exist_CRBB)
|
||||
crbb_len = desc->CRBB_LENGTH;
|
||||
|
||||
have_bitmap = (urbb_len + crbb_len) > 0;
|
||||
|
||||
/*
|
||||
* bow & bitmap present:
|
||||
* V(A)-> [ 11111...11111 0 SSN-> BBBBB...BBBBB ] (SSN+Nbits) .... V(S)
|
||||
* bow & not bitmap present:
|
||||
* V(A)-> [ 11111...11111 ] . SSN .... V(S)
|
||||
* not bow & bitmap present:
|
||||
* V(A)-> ... [ 0 SSN-> BBBBB...BBBBB ](SSN+N) .... V(S)
|
||||
* not bow & not bitmap present:
|
||||
* V(A)-> ... [] . SSN .... V(S)
|
||||
*/
|
||||
|
||||
if (desc->BEGINNING_OF_WINDOW) {
|
||||
implicitly_acked_blocks = window->mod_sns(ssn - 1 - window->v_a());
|
||||
|
||||
for (i = 0; i < implicitly_acked_blocks; i++)
|
||||
bitvec_set_bit(bits, ONE);
|
||||
|
||||
num_blocks += implicitly_acked_blocks;
|
||||
}
|
||||
|
||||
if (have_bitmap) {
|
||||
/* next bit refers to V(Q) and thus is always zero (and not
|
||||
* transmitted) */
|
||||
bitvec_set_bit(bits, ZERO);
|
||||
num_blocks += 1;
|
||||
|
||||
if (crbb_len > 0) {
|
||||
int old_len = bits->cur_bit;
|
||||
/*
|
||||
decode_t4_rle(bits, desc->CRBB, desc->CRBB_LENGTH,
|
||||
desc->CRBB_STARTING_COLOR_CODE);
|
||||
*/
|
||||
|
||||
num_blocks += (bits->cur_bit - old_len);
|
||||
}
|
||||
|
||||
urbb.cur_bit = 0;
|
||||
urbb.data = (uint8_t *)desc->URBB;
|
||||
urbb.data_len = sizeof(desc->URBB);
|
||||
|
||||
for (i = urbb_len; i > 0; i--) {
|
||||
/*
|
||||
* Set bit at the appropriate position (see 3GPP TS
|
||||
* 44.060 12.3.1)
|
||||
*/
|
||||
int is_ack = bitvec_get_bit_pos(&urbb, i-1);
|
||||
bitvec_set_bit(bits, is_ack == 1 ? ONE : ZERO);
|
||||
}
|
||||
num_blocks += urbb_len;
|
||||
}
|
||||
|
||||
*bsn_begin = window->v_a();
|
||||
*bsn_end = window->mod_sns(*bsn_begin + num_blocks);
|
||||
|
||||
return num_blocks;
|
||||
}
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
struct bitvec;
|
||||
|
||||
class Decoding {
|
||||
public:
|
||||
struct RlcData {
|
||||
|
@ -51,4 +53,8 @@ public:
|
|||
const struct gprs_rlc_data_info *rlc,
|
||||
unsigned int data_block_idx,
|
||||
const uint8_t *src, uint8_t *buffer);
|
||||
static int decode_egprs_acknack_bits(
|
||||
const EGPRS_AckNack_Desc_t *desc,
|
||||
struct bitvec *bits, int *bsn_begin, int *bsn_end,
|
||||
struct gprs_rlc_dl_window *window);
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue