Changes includes uplink PAN handling for Downlink tbf and
bitmap handling to update Tentative ack or nacked
---
src/decoding.cpp | 40 +++++++++++++++++++++
src/tbf.cpp | 2 ++
src/tbf.h | 1 +
src/tbf_ul.cpp | 92 +++++++++++++++++++++++++++++++++++++++++++++--
tests/edge/EdgeTest.cpp | 68 +++++++++++++++++++++++++++++++++++
5 files changed, 201 insertions(+), 2 deletions(-)
diff --git a/src/decoding.cpp b/src/decoding.cpp
index 649f68d..d3d0d89 100644
--- a/src/decoding.cpp
+++ b/src/decoding.cpp
@@ -423,6 +423,19 @@ int Decoding::decode_ul_data_fanr_type1(struct
gprs_rlc_ul_header_generic *rlc,
rlc->block_info[1].data_len = data_len;
rlc->data_offs_bytes[0] = 7;
rlc->data_offs_bytes[1] = 7 + data_len + 1;
+ if ( rlc->pani == 1) {
+ const struct egprs_ssn_based_pan_header *egprs1_fanr;
+ egprs1_fanr = static_cast<struct egprs_ssn_based_pan_header*>
+ ((void *)&data[rlc->block_info[1].data_len + rlc->data_offs_bytes[1]]);
+ rlc->pan_info.bow = egprs1_fanr->bow;
+
+ rlc->pan_info.short_ssn_a = egprs1_fanr->short_ssn_a;
+ rlc->pan_info.short_ssn_rb = egprs1_fanr->short_ssn_rb;
+
+ rlc->pan_info.rb_a = egprs1_fanr->rb_a;
+ rlc->pan_info.rb_b = egprs1_fanr->rb_b;
+ rlc->pan_info.tfi = (egprs1_fanr->tfi_a << 0) | (egprs1_fanr->tfi_b
<< 4);
+ }
return 0;
}
@@ -502,6 +515,19 @@ int Decoding::decode_ul_data_fanr_type2(struct
gprs_rlc_ul_header_generic *rlc,
rlc->block_info[0].data_len = data_len;
rlc->data_offs_bytes[0] = 6;
+ if ( rlc->pani == 1) {
+ const struct egprs_ssn_based_pan_header *egprs2_fanr;
+ egprs2_fanr = static_cast<struct egprs_ssn_based_pan_header*>
+ ((void *)&data[rlc->block_info[0].data_len + rlc->data_offs_bytes[0]]);
+ rlc->pan_info.bow = egprs2_fanr->bow;
+
+ rlc->pan_info.short_ssn_a = egprs2_fanr->short_ssn_a;
+ rlc->pan_info.short_ssn_rb = egprs2_fanr->short_ssn_rb;
+
+ rlc->pan_info.rb_a = egprs2_fanr->rb_a;
+ rlc->pan_info.rb_b = egprs2_fanr->rb_b;
+ rlc->pan_info.tfi = (egprs2_fanr->tfi_a << 0) | (egprs2_fanr->tfi_b
<< 4);
+ }
if(*cs == GprsCodingScheme::MCS6){
if(rlc->cps == 2 || rlc->cps == 3 ){
rlc->block_info[0].data_len -= pad_bytes;
@@ -588,6 +614,20 @@ int Decoding::decode_ul_data_fanr_type3(struct
gprs_rlc_ul_header_generic *rlc,
rlc->block_info[0].data_len = data_len;
rlc->data_offs_bytes[0] = 5;
+ if ( rlc->pani == 1) {
+ const struct egprs_ssn_based_pan_header *egprs3_fanr;
+ egprs3_fanr = static_cast<struct egprs_ssn_based_pan_header*>
+ ((void *)&data[rlc->block_info[0].data_len + rlc->data_offs_bytes[0]]);
+
+ rlc->pan_info.bow = egprs3_fanr->bow;
+
+ rlc->pan_info.short_ssn_a = egprs3_fanr->short_ssn_a;
+ rlc->pan_info.short_ssn_rb = egprs3_fanr->short_ssn_rb;
+
+ rlc->pan_info.rb_a = egprs3_fanr->rb_a;
+ rlc->pan_info.rb_b = egprs3_fanr->rb_b;
+ rlc->pan_info.tfi = (egprs3_fanr->tfi_a << 0) | (egprs3_fanr->tfi_b
<< 4);
+ }
if(rlc->block_info[0].spb == 2){
if(*cs == GprsCodingScheme::MCS3){
if(rlc->cps == 6 || rlc->cps == 7 || rlc->cps == 8){
diff --git a/src/tbf.cpp b/src/tbf.cpp
index 05f5c82..559e565 100644
--- a/src/tbf.cpp
+++ b/src/tbf.cpp
@@ -53,6 +53,8 @@ uint16_t windowsizebyTS[9] = {
1024 // 8 TS
};
+uint16_t log2ws[9] = {6,7,8,8,9,9,9,9,10};
+
gprs_rlcmac_tbf::Meas::Meas() :
rssi_sum(0),
rssi_num(0)
diff --git a/src/tbf.h b/src/tbf.h
index a6878d7..ba0dce1 100644
--- a/src/tbf.h
+++ b/src/tbf.h
@@ -504,6 +504,7 @@ struct gprs_rlcmac_ul_tbf : public gprs_rlcmac_tbf {
uint8_t m_usf[8]; /* list USFs per PDCH (timeslot) */
uint8_t m_contention_resolution_done; /* set after done */
uint8_t m_final_ack_sent; /* set if we sent final ack */
+ int uplink_pan_handling(const gprs_rlc_ul_header_generic *rlc);
protected:
void maybe_schedule_uplink_acknack(const gprs_rlc_ul_header_generic *rlc);
diff --git a/src/tbf_ul.cpp b/src/tbf_ul.cpp
index e89ac14..e56dccf 100644
--- a/src/tbf_ul.cpp
+++ b/src/tbf_ul.cpp
@@ -41,7 +41,8 @@ extern "C" {
#define SEND_ACK_AFTER_FRAMES 20
extern void *tall_pcu_ctx;
-
+extern uint16_t log2ws[];
+extern uint16_t windowsizebyTS[];
/*
* Store received block data in LLC message(s) and forward to SGSN
@@ -392,9 +393,96 @@ int gprs_rlcmac_ul_tbf::rcv_data_block_acknowledged(
/* If TLLI is included or if we received half of the window, we send
* an ack/nack */
maybe_schedule_uplink_acknack(rlc);
-
+ /*Uplink PAN info handling for downlink data, Need to update Ack/Nack
+ based on recieved bitmap */
+ if (rlc->pani == 1) {
+ uplink_pan_handling(rlc);
+ } else {
+ LOGP(DRLCMACUL, LOGL_ERROR, "No PAN info present \n");
+ }
return 0;
+}
+int gprs_rlcmac_ul_tbf::uplink_pan_handling(
+ const gprs_rlc_ul_header_generic *rlc)
+{
+ bool bit;
+ uint16_t bsn;
+ int i = 0, j;
+ int8_t rb_length, bits_left, shortSSNsize, mask, rb_mask;
+ int ssn = 0, ssn_base_va, ssn_base_vs;
+
+ gprs_rlcmac_dl_tbf *tbf;
+ tbf = gprs_rlcmac_ul_tbf::ms()->dl_tbf();
+ if (!tbf) {
+ LOGP(DRLCMACUL, LOGL_ERROR, "DL DATA unknown TFI=%d\n",
+ rlc->pan_info.tfi);
+ return 0;
+ }
+ if (tbf->tfi() != rlc->pan_info.tfi) {
+ LOGP(DRLCMACUL, LOGL_ERROR, "Received TFI %d and DL TBF Tfi %d are not\n"
+ "matching \n", tbf->tfi(), rlc->pan_info.tfi);
+ return 0;
+ }
+ for (j = 0; j < 9; j++) {
+ if (tbf->m_window.ws() == windowsizebyTS[j]) {
+ break;
+ }
+ }
+ shortSSNsize = log2ws[j] + 1;
+ mask = (1 << (shortSSNsize -7)) -1 ;
+ //Short SSN
+ int16_t short_ssn = ((rlc->pan_info.short_ssn_a) |
+ ((rlc->pan_info.short_ssn_rb << 8) & mask ));
+ //RB
+ rb_mask = (1 << (4 - (shortSSNsize -7))) -1 ;
+
+ int16_t rb = ((rlc->pan_info.rb_b << (8 - (shortSSNsize -7))) |
+ (rlc->pan_info.rb_a << (4 - (shortSSNsize -7))) |
+ ((rlc->pan_info.short_ssn_rb >> (shortSSNsize -7)) & rb_mask ));
+
+ //Get SSN from short SSN
+ ssn_base_va = (tbf->m_window.v_a() & (((1 << (11-shortSSNsize))-1) <<
shortSSNsize)) ;
+ ssn_base_vs = (tbf->m_window.v_s() & (((1 << (11-shortSSNsize))-1) <<
shortSSNsize)) ;
+
+ if ( ssn_base_va == ssn_base_vs ) {
+ ssn = MOD2048((ssn_base_va|short_ssn));
+ }
+ else {
+ /*Algorithm to be modified for the case V(A) is less than 2048 and V(S) is greater
than
+ 2048 and RB comes in between these two */
+ //TODO different cases to be handled
+ return 0;
+ }
+ /* if Beginning of window is set 1, Mark Acked between SSN-2 ( V(Q)-1) to V(A)*/
+ if (rlc->pan_info.bow) {
+ for (int i = tbf->m_window.v_a(); i <= (ssn -2); i++ ) {
+ uint16_t bsn = tbf->m_window.mod_sns(i);
+ tbf->m_window.m_v_b.mark_tentative_acked(bsn);
+ }
+ }
+
+ rb_length = 8 + (4 - (shortSSNsize -7));
+
+ //Mark TENTATIVE_ACK
+ rb = rb << (16 - rb_length);
+ bits_left = rb_length;
+
+ while (bits_left != 0) {
+ bsn = tbf->m_window.mod_sns(ssn + i);
+ if (tbf->m_window.mod_sns(tbf->m_window.v_s() - bsn) >=
tbf->m_window.distance())
+ break;
+ bit = !!(rb & 0x8000);
+ if (bit) {
+ tbf->m_window.m_v_b.mark_tentative_acked(bsn);
+ } else {
+ tbf->m_window.m_v_b.mark_nacked(bsn);
+ }
+ rb = rb << 1;
+ bits_left--;
+ i++;
+ }
+ return 1;
}
void gprs_rlcmac_ul_tbf::maybe_schedule_uplink_acknack(
diff --git a/tests/edge/EdgeTest.cpp b/tests/edge/EdgeTest.cpp
index 7177832..924728f 100644
--- a/tests/edge/EdgeTest.cpp
+++ b/tests/edge/EdgeTest.cpp
@@ -1641,7 +1641,74 @@ static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase_cv0(BTS
*the_bts,
return ul_tbf;
}
+void fanr_handling(gprs_rlcmac_ul_tbf *ul_tbf, BTS *the_bts, uint32_t *fn, uint8_t
ts_no,
+ GprsMs *ms , uint32_t tlli, uint16_t qta)
+{
+ uint8_t data_msg[200] = {0};
+ int tfi = 0;
+ struct gprs_rlcmac_pdch *pdch;
+ uint32_t rach_fn = *fn - 51;
+ uint32_t sba_fn = *fn + 52;
+ uint8_t trx_no = 0;
+
+ tfi = ul_tbf->tfi();
+ struct pcu_l1_meas meas;
+ meas.set_rssi(31);
+
+ ul_tbf->enable_fanr();
+ /* send fake data */
+ data_msg[0] = 0x00 | 0xf << 2;
+ data_msg[1] = uint8_t(0 | (tfi << 1));
+ data_msg[2] = uint8_t(0);/* BSN:7, E:1 */
+ data_msg[3] =uint8_t(1 << 6); /* BSN:7, E:1 */
+ data_msg[4] = 0x2b; /* E: 1 */
+ data_msg[5] = 0x2b; /* E: 1 */
+ data_msg[6] = 0x2b; /* E: 1 */
+ data_msg[7] = 0x2b; /* E: 1 */
+ data_msg[8] = 0x2b; /* E: 1 */
+ data_msg[9] = 0x2b; /* E: 1 */
+ data_msg[10] = 0x2b; /* E: 1 */
+ data_msg[11] = 0x2b; /* E: 1 */
+ data_msg[12] = 0x2b; /* E: 1 */
+ data_msg[13] = 0x2b; /* E: 1 */
+ data_msg[14] = 0x2b; /* E: 1 */
+ data_msg[15] = 0x2b; /* E: 1 */
+ data_msg[16] = 0x2b; /* E: 1 */
+ data_msg[17] = 0x2b; /* E: 1 */
+ data_msg[18] = 0x2b; /* E: 1 */
+ data_msg[19] = 0x2b; /* E: 1 */
+ data_msg[20] = 0x2b; /* E: 1 */
+ data_msg[21] = 0x2b; /* E: 1 */
+ data_msg[22] = 0x2b; /* E: 1 */
+ data_msg[23] = 0x2b; /* E: 1 */
+ data_msg[24] = 0x2b; /* E: 1 */
+ data_msg[25] = 0x2b; /* E: 1 */
+ data_msg[26] = 0x2b;
+ data_msg[27] = 0x02; /* Fanr SSN & BOW */
+ data_msg[28] = 0xff; /* RB & SSN */
+ data_msg[29] = 0x0f; /* TFI & RB */
+ data_msg[30] = 0x00; /* TFI */
+ data_msg[31] = 0x00;
+
+ pdch = &the_bts->bts_data()->trx[trx_no].pdch[ts_no];
+ pdch->rcv_block(&data_msg[0], 31, *fn, &meas);
+
+ ms = the_bts->ms_by_tlli(tlli);
+ OSMO_ASSERT(ms != NULL);
+ OSMO_ASSERT(ms->ta() == qta/4);
+ OSMO_ASSERT(ms->ul_tbf() == ul_tbf);
+
+
+ /* send fake data */
+ data_msg[0] = 0x00 | 0xf << 2;
+ data_msg[1] = uint8_t(0 | (tfi << 1));
+ data_msg[2] = uint8_t(0);/* BSN:7, E:1 */
+ data_msg[3] =uint8_t(1 << 6); /* BSN:7, E:1 */
+ data_msg[4] = uint8_t(1); /* E: 1 */
+ pdch = &the_bts->bts_data()->trx[trx_no].pdch[ts_no];
+ pdch->rcv_block(&data_msg[0], 37, *fn, &meas);
+}
void test_tbf_two_phase()
{
BTS the_bts;
@@ -1669,6 +1736,7 @@ void test_tbf_two_phase()
/* Send Packet Downlink Assignment to MS */
request_dl_rlc_block(ul_tbf, &fn);
+ fanr_handling (ul_tbf, &the_bts, &fn, ts_no, ms, tlli, qta);
printf("=== end %s ===\n", __func__);
}
--
1.7.9.5