From 3dc56a3b341ffd22a7a5951a5ec6f78163fdc800 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Sat, 26 Oct 2013 21:38:30 +0200 Subject: [PATCH] tbf: Move gprs_rlcmac_send_packet_uplink_assignment into the tbf --- TODO | 2 + src/bts.cpp | 2 +- src/gprs_rlcmac.h | 4 -- src/gprs_rlcmac_data.cpp | 144 --------------------------------------- src/tbf.cpp | 140 +++++++++++++++++++++++++++++++++++++ src/tbf.h | 1 + 6 files changed, 144 insertions(+), 149 deletions(-) diff --git a/TODO b/TODO index 1568b360..8646243b 100644 --- a/TODO +++ b/TODO @@ -8,3 +8,5 @@ it is on... then we can omit trx, ts and parameters and just pass the pdch. * On global free/reset... also flush the timing advance.. +* tbf/llc window code appears to be duplicated and nested in other + methods. This needs to be cleaned. diff --git a/src/bts.cpp b/src/bts.cpp index 1fc0c32a..32d26770 100644 --- a/src/bts.cpp +++ b/src/bts.cpp @@ -956,7 +956,7 @@ int gprs_rlcmac_pdch::rcv_control_block( tbf->poll_state = GPRS_RLCMAC_POLL_NONE; debug_diagram(bts(), tbf->diag, "got DL-ACK"); - rc = gprs_rlcmac_downlink_ack(tbf, + rc = tbf->snd_dl_ack( ul_control_block->u.Packet_Downlink_Ack_Nack.Ack_Nack_Description.FINAL_ACK_INDICATION, ul_control_block->u.Packet_Downlink_Ack_Nack.Ack_Nack_Description.STARTING_SEQUENCE_NUMBER, ul_control_block->u.Packet_Downlink_Ack_Nack.Ack_Nack_Description.RECEIVED_BLOCK_BITMAP); diff --git a/src/gprs_rlcmac.h b/src/gprs_rlcmac.h index 0e09f3f3..0f05b167 100644 --- a/src/gprs_rlcmac.h +++ b/src/gprs_rlcmac.h @@ -94,10 +94,6 @@ enum gprs_rlcmac_block_type { int gprs_rlcmac_tx_ul_ud(gprs_rlcmac_tbf *tbf); -int gprs_rlcmac_downlink_ack( - struct gprs_rlcmac_tbf *tbf, uint8_t final, - uint8_t ssn, uint8_t *rbb); - int gprs_rlcmac_paging_request(uint8_t *ptmsi, uint16_t ptmsi_len, const char *imsi); diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp index aa5bfda7..18a037ad 100644 --- a/src/gprs_rlcmac_data.cpp +++ b/src/gprs_rlcmac_data.cpp @@ -368,147 +368,3 @@ tx_block: return dl_msg; } -int gprs_rlcmac_downlink_ack( - struct gprs_rlcmac_tbf *tbf, uint8_t final, - uint8_t ssn, uint8_t *rbb) -{ - char show_rbb[65], show_v_b[RLC_MAX_SNS + 1]; - uint16_t mod_sns = tbf->sns - 1; - uint16_t mod_sns_half = (tbf->sns >> 1) - 1; - int i; /* must be signed */ - int16_t dist; /* must be signed */ - uint8_t bit; - uint16_t bsn; - struct msgb *msg; - uint16_t lost = 0, received = 0; - - LOGP(DRLCMACDL, LOGL_DEBUG, "TBF=%d downlink acknowledge\n", - tbf->tfi); - - if (!final) { - /* show received array in debug (bit 64..1) */ - for (i = 63; i >= 0; i--) { - bit = (rbb[i >> 3] >> (7 - (i&7))) & 1; - show_rbb[i] = (bit) ? '1' : 'o'; - } - show_rbb[64] = '\0'; - LOGP(DRLCMACDL, LOGL_DEBUG, "- ack: (BSN=%d)\"%s\"" - "(BSN=%d) 1=ACK o=NACK\n", (ssn - 64) & mod_sns, - show_rbb, (ssn - 1) & mod_sns); - - /* apply received array to receive state (SSN-64..SSN-1) */ - /* calculate distance of ssn from V(S) */ - dist = (tbf->dir.dl.v_s - ssn) & mod_sns; - /* check if distance is less than distance V(A)..V(S) */ - if (dist >= ((tbf->dir.dl.v_s - tbf->dir.dl.v_a) & mod_sns)) { - /* this might happpen, if the downlink assignment - * was not received by ms and the ack refers - * to previous TBF - * FIXME: we should implement polling for - * control ack!*/ - LOGP(DRLCMACDL, LOGL_NOTICE, "- ack range is out of " - "V(A)..V(S) range (DL TBF=%d) Free TFB!\n", - tbf->tfi); - return 1; /* indicate to free TBF */ - } - /* SSN - 1 is in range V(A)..V(S)-1 */ - for (i = 63, bsn = (ssn - 1) & mod_sns; - i >= 0 && bsn != ((tbf->dir.dl.v_a - 1) & mod_sns); - i--, bsn = (bsn - 1) & mod_sns) { - bit = (rbb[i >> 3] >> (7 - (i&7))) & 1; - if (bit) { - LOGP(DRLCMACDL, LOGL_DEBUG, "- got " - "ack for BSN=%d\n", bsn); - if (tbf->dir.dl.v_b[bsn & mod_sns_half] - != 'A') - received++; - tbf->dir.dl.v_b[bsn & mod_sns_half] = 'A'; - } else { - LOGP(DRLCMACDL, LOGL_DEBUG, "- got " - "NACK for BSN=%d\n", bsn); - tbf->dir.dl.v_b[bsn & mod_sns_half] = 'N'; - lost++; - } - } - /* report lost and received packets */ - gprs_rlcmac_received_lost(tbf, received, lost); - - /* raise V(A), if possible */ - for (i = 0, bsn = tbf->dir.dl.v_a; bsn != tbf->dir.dl.v_s; - i++, bsn = (bsn + 1) & mod_sns) { - if (tbf->dir.dl.v_b[bsn & mod_sns_half] == 'A') { - tbf->dir.dl.v_b[bsn & mod_sns_half] = 'I'; - /* mark invalid */ - tbf->dir.dl.v_a = (tbf->dir.dl.v_a + 1) - & mod_sns; - } else - break; - } - - /* show receive state array in debug (V(A)..V(S)-1) */ - for (i = 0, bsn = tbf->dir.dl.v_a; bsn != tbf->dir.dl.v_s; - i++, bsn = (bsn + 1) & mod_sns) { - show_v_b[i] = tbf->dir.dl.v_b[bsn & mod_sns_half]; - if (show_v_b[i] == 0) - show_v_b[i] = ' '; - } - show_v_b[i] = '\0'; - LOGP(DRLCMACDL, LOGL_DEBUG, "- V(B): (V(A)=%d)\"%s\"" - "(V(S)-1=%d) A=Acked N=Nacked U=Unacked " - "X=Resend-Unacked\n", tbf->dir.dl.v_a, show_v_b, - (tbf->dir.dl.v_s - 1) & mod_sns); - - if (tbf->state_is(GPRS_RLCMAC_FINISHED) - && tbf->dir.dl.v_s == tbf->dir.dl.v_a) { - LOGP(DRLCMACDL, LOGL_NOTICE, "Received acknowledge of " - "all blocks, but without final ack " - "inidcation (don't worry)\n"); - } - return 0; - } - - LOGP(DRLCMACDL, LOGL_DEBUG, "- Final ACK received.\n"); - debug_diagram(tbf->bts, tbf->diag, "got Final ACK"); - /* range V(A)..V(S)-1 */ - for (bsn = tbf->dir.dl.v_a; bsn != tbf->dir.dl.v_s; - bsn = (bsn + 1) & mod_sns) { - if (tbf->dir.dl.v_b[bsn & mod_sns_half] != 'A') - received++; - } - - /* report all outstanding packets as received */ - gprs_rlcmac_received_lost(tbf, received, lost); - - /* check for LLC PDU in the LLC Queue */ - msg = tbf->llc_dequeue(gprs_bssgp_pcu_current_bctx()); - if (!msg) { - /* no message, start T3193, change state to RELEASE */ - LOGP(DRLCMACDL, LOGL_DEBUG, "- No new message, so we " - "release.\n"); - /* start T3193 */ - debug_diagram(bts->bts, tbf->diag, "start T3193"); - tbf_timer_start(tbf, 3193, - tbf->bts->bts_data()->t3193_msec / 1000, - (tbf->bts->bts_data()->t3193_msec % 1000) * 1000); - tbf_new_state(tbf, GPRS_RLCMAC_WAIT_RELEASE); - - return 0; - } - #warning "Copy and paste on the sender path" - tbf->update_llc_frame(msg); - msgb_free(msg); - - /* we have a message, so we trigger downlink assignment, and there - * set the state to ASSIGN. also we set old_downlink, because we - * re-use this tbf. */ - LOGP(DRLCMAC, LOGL_DEBUG, "Trigger dowlink assignment on PACCH, " - "because another LLC PDU has arrived in between\n"); - memset(&tbf->dir.dl, 0, sizeof(tbf->dir.dl)); /* reset RLC states */ - tbf->state_flags &= GPRS_RLCMAC_FLAG_TO_MASK; /* keep TO flags */ - tbf->state_flags &= ~(1 << GPRS_RLCMAC_FLAG_CCCH); - tbf->update(); - tbf->bts->trigger_dl_ass(tbf, tbf, NULL); - return 0; -} - - diff --git a/src/tbf.cpp b/src/tbf.cpp index c640c8d2..08f6cf38 100644 --- a/src/tbf.cpp +++ b/src/tbf.cpp @@ -25,6 +25,7 @@ #include #include #include +#include extern "C" { #include @@ -1099,6 +1100,145 @@ struct msgb *gprs_rlcmac_tbf::create_ul_ack(uint32_t fn) return msg; } +int gprs_rlcmac_tbf::snd_dl_ack(uint8_t final, uint8_t ssn, uint8_t *rbb) +{ + char show_rbb[65], show_v_b[RLC_MAX_SNS + 1]; + uint16_t mod_sns = sns - 1; + uint16_t mod_sns_half = (sns >> 1) - 1; + int i; /* must be signed */ + int16_t dist; /* must be signed */ + uint8_t bit; + uint16_t bsn; + struct msgb *msg; + uint16_t lost = 0, received = 0; + + LOGP(DRLCMACDL, LOGL_DEBUG, "TBF=%d downlink acknowledge\n", tfi); + + if (!final) { + /* show received array in debug (bit 64..1) */ + for (i = 63; i >= 0; i--) { + bit = (rbb[i >> 3] >> (7 - (i&7))) & 1; + show_rbb[i] = (bit) ? '1' : 'o'; + } + show_rbb[64] = '\0'; + LOGP(DRLCMACDL, LOGL_DEBUG, "- ack: (BSN=%d)\"%s\"" + "(BSN=%d) 1=ACK o=NACK\n", (ssn - 64) & mod_sns, + show_rbb, (ssn - 1) & mod_sns); + + /* apply received array to receive state (SSN-64..SSN-1) */ + /* calculate distance of ssn from V(S) */ + dist = (dir.dl.v_s - ssn) & mod_sns; + /* check if distance is less than distance V(A)..V(S) */ + if (dist >= ((dir.dl.v_s - dir.dl.v_a) & mod_sns)) { + /* this might happpen, if the downlink assignment + * was not received by ms and the ack refers + * to previous TBF + * FIXME: we should implement polling for + * control ack!*/ + LOGP(DRLCMACDL, LOGL_NOTICE, "- ack range is out of " + "V(A)..V(S) range (DL TBF=%d) Free TFB!\n", tfi); + return 1; /* indicate to free TBF */ + } + /* SSN - 1 is in range V(A)..V(S)-1 */ + for (i = 63, bsn = (ssn - 1) & mod_sns; + i >= 0 && bsn != ((dir.dl.v_a - 1) & mod_sns); + i--, bsn = (bsn - 1) & mod_sns) { + bit = (rbb[i >> 3] >> (7 - (i&7))) & 1; + if (bit) { + LOGP(DRLCMACDL, LOGL_DEBUG, "- got " + "ack for BSN=%d\n", bsn); + if (dir.dl.v_b[bsn & mod_sns_half] + != 'A') + received++; + dir.dl.v_b[bsn & mod_sns_half] = 'A'; + } else { + LOGP(DRLCMACDL, LOGL_DEBUG, "- got " + "NACK for BSN=%d\n", bsn); + dir.dl.v_b[bsn & mod_sns_half] = 'N'; + lost++; + } + } + /* report lost and received packets */ + gprs_rlcmac_received_lost(this, received, lost); + + /* raise V(A), if possible */ + for (i = 0, bsn = dir.dl.v_a; bsn != dir.dl.v_s; + i++, bsn = (bsn + 1) & mod_sns) { + if (dir.dl.v_b[bsn & mod_sns_half] == 'A') { + dir.dl.v_b[bsn & mod_sns_half] = 'I'; + /* mark invalid */ + dir.dl.v_a = (dir.dl.v_a + 1) + & mod_sns; + } else + break; + } + + /* show receive state array in debug (V(A)..V(S)-1) */ + for (i = 0, bsn = dir.dl.v_a; bsn != dir.dl.v_s; + i++, bsn = (bsn + 1) & mod_sns) { + show_v_b[i] = dir.dl.v_b[bsn & mod_sns_half]; + if (show_v_b[i] == 0) + show_v_b[i] = ' '; + } + show_v_b[i] = '\0'; + LOGP(DRLCMACDL, LOGL_DEBUG, "- V(B): (V(A)=%d)\"%s\"" + "(V(S)-1=%d) A=Acked N=Nacked U=Unacked " + "X=Resend-Unacked\n", dir.dl.v_a, show_v_b, + (dir.dl.v_s - 1) & mod_sns); + + if (state_is(GPRS_RLCMAC_FINISHED) + && dir.dl.v_s == dir.dl.v_a) { + LOGP(DRLCMACDL, LOGL_NOTICE, "Received acknowledge of " + "all blocks, but without final ack " + "inidcation (don't worry)\n"); + } + return 0; + } + + LOGP(DRLCMACDL, LOGL_DEBUG, "- Final ACK received.\n"); + debug_diagram(ts, diag, "got Final ACK"); + /* range V(A)..V(S)-1 */ + for (bsn = dir.dl.v_a; bsn != dir.dl.v_s; + bsn = (bsn + 1) & mod_sns) { + if (dir.dl.v_b[bsn & mod_sns_half] != 'A') + received++; + } + + /* report all outstanding packets as received */ + gprs_rlcmac_received_lost(this, received, lost); + + /* check for LLC PDU in the LLC Queue */ + msg = llc_dequeue(gprs_bssgp_pcu_current_bctx()); + if (!msg) { + /* no message, start T3193, change state to RELEASE */ + LOGP(DRLCMACDL, LOGL_DEBUG, "- No new message, so we " + "release.\n"); + /* start T3193 */ + debug_diagram(bts, diag, "start T3193"); + tbf_timer_start(this, 3193, + bts_data()->t3193_msec / 1000, + (bts_data()->t3193_msec % 1000) * 1000); + tbf_new_state(this, GPRS_RLCMAC_WAIT_RELEASE); + + return 0; + } + #warning "Copy and paste on the sender path" + update_llc_frame(msg); + msgb_free(msg); + + /* we have a message, so we trigger downlink assignment, and there + * set the state to ASSIGN. also we set old_downlink, because we + * re-use this tbf. */ + LOGP(DRLCMAC, LOGL_DEBUG, "Trigger dowlink assignment on PACCH, " + "because another LLC PDU has arrived in between\n"); + memset(&dir.dl, 0, sizeof(dir.dl)); /* reset RLC states */ + state_flags &= GPRS_RLCMAC_FLAG_TO_MASK; /* keep TO flags */ + state_flags &= ~(1 << GPRS_RLCMAC_FLAG_CCCH); + update(); + bts->trigger_dl_ass(this, this, NULL); + return 0; +} + void gprs_rlcmac_tbf::free_all(struct gprs_rlcmac_trx *trx) { for (uint8_t tfi = 0; tfi < 32; tfi++) { diff --git a/src/tbf.h b/src/tbf.h index 57fe3b9d..a1a7986d 100644 --- a/src/tbf.h +++ b/src/tbf.h @@ -102,6 +102,7 @@ struct gprs_rlcmac_tbf { struct msgb *create_dl_ass(uint32_t fn); struct msgb *create_ul_ass(uint32_t fn); struct msgb *create_ul_ack(uint32_t fn); + int snd_dl_ack(uint8_t final, uint8_t ssn, uint8_t *rbb); int rlcmac_diag();