aboutsummaryrefslogtreecommitdiffstats
path: root/src/gprs_rlcmac_data.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gprs_rlcmac_data.cpp')
-rw-r--r--src/gprs_rlcmac_data.cpp84
1 files changed, 40 insertions, 44 deletions
diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp
index e7b29723..1109451e 100644
--- a/src/gprs_rlcmac_data.cpp
+++ b/src/gprs_rlcmac_data.cpp
@@ -468,6 +468,9 @@ int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint8_t trx, uint8_t ts,
}
LOGP(DRLCMAC, LOGL_ERROR, "RX: [PCU <- BTS] %s TFI: %u TLLI: 0x%08x FIXME: Packet ressource request\n", (tbf->direction == GPRS_RLCMAC_UL_TBF) ? "UL" : "DL", tbf->tfi, tbf->tlli);
break;
+ case MT_PACKET_MEASUREMENT_REPORT:
+ gprs_rlcmac_meas_rep(&ul_control_block->u.Packet_Measurement_Report);
+ break;
default:
LOGP(DRLCMAC, LOGL_NOTICE, "RX: [PCU <- BTS] unknown control block received\n");
}
@@ -846,6 +849,9 @@ int gprs_rlcmac_rcv_data_block_acknowledged(uint8_t trx, uint8_t ts,
LOGP(DRLCMACUL, LOGL_DEBUG, "UL DATA TBF=%d received (V(Q)=%d .. "
"V(R)=%d)\n", rh->tfi, tbf->dir.ul.v_q, tbf->dir.ul.v_r);
+ /* process RSSI */
+ gprs_rlcmac_rssi(tbf, rssi);
+
/* get TLLI */
if (!tbf->tlli_valid) {
struct gprs_rlcmac_tbf *dl_tbf, *ul_tbf;
@@ -1213,29 +1219,6 @@ static struct msgb *llc_dequeue(struct gprs_rlcmac_tbf *tbf)
return msg;
}
-static int gprs_rlcmac_debug_bw(struct gprs_rlcmac_tbf *tbf, uint16_t octets)
-{
- struct timeval now_tv, *bw_tv = &tbf->bw_tv;
- uint32_t elapsed;
-
- tbf->bw_octets += octets;
-
- gettimeofday(&now_tv, NULL);
- elapsed = ((now_tv.tv_sec - bw_tv->tv_sec) << 7)
- + ((now_tv.tv_usec - bw_tv->tv_usec) << 7) / 1000000;
- if (elapsed < 128)
- return 0;
-
- LOGP(DRLCMACBW, LOGL_DEBUG, "DL Bandwitdh of TLLI=0x%08x: %d KBits/s\n",
- tbf->tlli, tbf->bw_octets / elapsed);
-
- /* reset bandwidth values timestamp */
- memcpy(bw_tv, &now_tv, sizeof(struct timeval));
- tbf->bw_octets = 0;
-
- return 0;
-}
-
/* send DL data block
*
* The messages are fragmented and forwarded as data blocks.
@@ -1380,7 +1363,7 @@ do_resend:
LOGP(DRLCMACDL, LOGL_INFO, "Complete DL frame for "
"TBF=%d that fits precisely in last block: "
"len=%d\n", tbf->tfi, tbf->llc_length);
- gprs_rlcmac_debug_bw(tbf, tbf->llc_length);
+ gprs_rlcmac_dl_bw(tbf, tbf->llc_length);
/* block is filled, so there is no extension */
*e_pointer |= 0x01;
/* fill space */
@@ -1440,7 +1423,7 @@ do_resend:
space -= chunk;
LOGP(DRLCMACDL, LOGL_INFO, "Complete DL frame for TBF=%d: "
"len=%d\n", tbf->tfi, tbf->llc_length);
- gprs_rlcmac_debug_bw(tbf, tbf->llc_length);
+ gprs_rlcmac_dl_bw(tbf, tbf->llc_length);
/* reset LLC frame */
tbf->llc_index = tbf->llc_length = 0;
/* dequeue next LLC frame, if any */
@@ -1568,6 +1551,7 @@ int gprs_rlcmac_downlink_ack(struct gprs_rlcmac_tbf *tbf, uint8_t final,
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);
@@ -1587,25 +1571,7 @@ int gprs_rlcmac_downlink_ack(struct gprs_rlcmac_tbf *tbf, uint8_t final,
/* 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)) {
- /* 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);
- 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';
- }
- }
- } else {
+ 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
@@ -1616,6 +1582,27 @@ int gprs_rlcmac_downlink_ack(struct gprs_rlcmac_tbf *tbf, uint8_t final,
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;
@@ -1653,6 +1640,15 @@ int gprs_rlcmac_downlink_ack(struct gprs_rlcmac_tbf *tbf, uint8_t final,
LOGP(DRLCMACDL, LOGL_DEBUG, "- Final ACK received.\n");
debug_diagram(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 = llc_dequeue(tbf);