aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <holger@moiji-mobile.com>2013-10-26 21:38:30 +0200
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2013-10-30 21:24:12 +0100
commit3dc56a3b341ffd22a7a5951a5ec6f78163fdc800 (patch)
treea44ced0e030c014f118b608faed953696e92cc99
parentae03f22199fb93b104411f113e93134cf11d1bb2 (diff)
tbf: Move gprs_rlcmac_send_packet_uplink_assignment into the tbf
-rw-r--r--TODO2
-rw-r--r--src/bts.cpp2
-rw-r--r--src/gprs_rlcmac.h4
-rw-r--r--src/gprs_rlcmac_data.cpp144
-rw-r--r--src/tbf.cpp140
-rw-r--r--src/tbf.h1
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 <encoding.h>
#include <gprs_rlcmac.h>
#include <gprs_debug.h>
+#include <gprs_bssgp_pcu.h>
extern "C" {
#include <osmocom/core/msgb.h>
@@ -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();