aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <holger@moiji-mobile.com>2013-10-26 17:38:37 +0200
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2013-10-30 21:24:11 +0100
commitfcbc70211208323b22ab9805cdf19769cce72d23 (patch)
tree4d3b54833789ff6b60b93e657dd9c9097386f7b8
parentd11290b90bb5f32a7d57affbe11bdadb24e42db0 (diff)
pdch: Move the giant switch/case of gprs_rlcmac_rcv_control_block
Move the dispatch into the PDCH. This needs to be split up further into understandable blocks.
-rw-r--r--src/bts.cpp254
-rw-r--r--src/bts.h3
-rw-r--r--src/decoding.cpp15
-rw-r--r--src/decoding.h3
-rw-r--r--src/gprs_rlcmac.h4
-rw-r--r--src/gprs_rlcmac_data.cpp267
6 files changed, 274 insertions, 272 deletions
diff --git a/src/bts.cpp b/src/bts.cpp
index 95672143..3c7ce407 100644
--- a/src/bts.cpp
+++ b/src/bts.cpp
@@ -571,6 +571,258 @@ int gprs_rlcmac_pdch::rcv_data_block_acknowledged(struct gprs_rlcmac_bts *bts,
return 0;
}
+/* Received Uplink RLC control block. */
+int gprs_rlcmac_pdch::rcv_control_block(struct gprs_rlcmac_bts *bts,
+ bitvec *rlc_block, uint8_t trx, uint8_t ts,
+ uint32_t fn)
+{
+ int8_t tfi = 0; /* must be signed */
+ uint32_t tlli = 0;
+ struct gprs_rlcmac_tbf *tbf;
+ struct gprs_rlcmac_sba *sba;
+ int rc;
+
+ RlcMacUplink_t * ul_control_block = (RlcMacUplink_t *)talloc_zero(tall_pcu_ctx, RlcMacUplink_t);
+ LOGP(DRLCMAC, LOGL_DEBUG, "+++++++++++++++++++++++++ RX : Uplink Control Block +++++++++++++++++++++++++\n");
+ decode_gsm_rlcmac_uplink(rlc_block, ul_control_block);
+ LOGPC(DCSN1, LOGL_NOTICE, "\n");
+ LOGP(DRLCMAC, LOGL_DEBUG, "------------------------- RX : Uplink Control Block -------------------------\n");
+ switch (ul_control_block->u.MESSAGE_TYPE) {
+ case MT_PACKET_CONTROL_ACK:
+ tlli = ul_control_block->u.Packet_Control_Acknowledgement.TLLI;
+ tbf = bts->bts->tbf_by_poll_fn(fn, trx, ts);
+ if (!tbf) {
+ LOGP(DRLCMAC, LOGL_NOTICE, "PACKET CONTROL ACK with "
+ "unknown FN=%u TLL=0x%08x (TRX %d TS %d)\n",
+ fn, tlli, trx, ts);
+ break;
+ }
+ tfi = tbf->tfi;
+ if (tlli != tbf->tlli) {
+ LOGP(DRLCMAC, LOGL_INFO, "Phone changed TLLI to "
+ "0x%08x\n", tlli);
+ tbf->tlli = tlli;
+ }
+ LOGP(DRLCMAC, LOGL_DEBUG, "RX: [PCU <- BTS] TFI: %u TLLI: 0x%08x Packet Control Ack\n", tbf->tfi, tbf->tlli);
+ tbf->poll_state = GPRS_RLCMAC_POLL_NONE;
+
+ /* check if this control ack belongs to packet uplink ack */
+ if (tbf->ul_ack_state == GPRS_RLCMAC_UL_ACK_WAIT_ACK) {
+ LOGP(DRLCMAC, LOGL_DEBUG, "TBF: [UPLINK] END TFI: %u TLLI: 0x%08x \n", tbf->tfi, tbf->tlli);
+ tbf->ul_ack_state = GPRS_RLCMAC_UL_ACK_NONE;
+ debug_diagram(bts->bts, tbf->diag, "got CTL-ACK (fin)");
+ if ((tbf->state_flags &
+ (1 << GPRS_RLCMAC_FLAG_TO_UL_ACK))) {
+ tbf->state_flags &=
+ ~(1 << GPRS_RLCMAC_FLAG_TO_UL_ACK);
+ LOGP(DRLCMAC, LOGL_NOTICE, "Recovered uplink "
+ "ack for UL TBF=%d\n", tbf->tfi);
+ }
+ tbf_free(tbf);
+ break;
+ }
+ if (tbf->dl_ass_state == GPRS_RLCMAC_DL_ASS_WAIT_ACK) {
+ LOGP(DRLCMAC, LOGL_DEBUG, "TBF: [UPLINK] DOWNLINK ASSIGNED TFI: %u TLLI: 0x%08x \n", tbf->tfi, tbf->tlli);
+ /* reset N3105 */
+ tbf->n3105 = 0;
+ tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_NONE;
+ debug_diagram(bts->bts, tbf->diag, "got CTL-ACK DL-ASS");
+ if (tbf->direction == GPRS_RLCMAC_UL_TBF)
+ tbf = bts->bts->tbf_by_tlli(tbf->tlli,
+ GPRS_RLCMAC_DL_TBF);
+ if (!tbf) {
+ LOGP(DRLCMAC, LOGL_ERROR, "Got ACK, but DL "
+ "TBF is gone\n");
+ break;
+ }
+ tbf_new_state(tbf, GPRS_RLCMAC_FLOW);
+ /* stop pending assignment timer */
+ tbf_timer_stop(tbf);
+ if ((tbf->state_flags &
+ (1 << GPRS_RLCMAC_FLAG_TO_DL_ASS))) {
+ tbf->state_flags &=
+ ~(1 << GPRS_RLCMAC_FLAG_TO_DL_ASS);
+ LOGP(DRLCMAC, LOGL_NOTICE, "Recovered downlink "
+ "assignment for DL TBF=%d\n", tbf->tfi);
+ }
+ tbf_assign_control_ts(tbf);
+ break;
+ }
+ if (tbf->ul_ass_state == GPRS_RLCMAC_UL_ASS_WAIT_ACK) {
+ LOGP(DRLCMAC, LOGL_DEBUG, "TBF: [DOWNLINK] UPLINK ASSIGNED TFI: %u TLLI: 0x%08x \n", tbf->tfi, tbf->tlli);
+ /* reset N3105 */
+ tbf->n3105 = 0;
+ tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_NONE;
+ debug_diagram(bts->bts, tbf->diag, "got CTL-AC UL-ASS");
+ if (tbf->direction == GPRS_RLCMAC_DL_TBF)
+ tbf = bts->bts->tbf_by_tlli(tbf->tlli,
+ GPRS_RLCMAC_UL_TBF);
+ if (!tbf) {
+ LOGP(DRLCMAC, LOGL_ERROR, "Got ACK, but UL "
+ "TBF is gone\n");
+ break;
+ }
+ tbf_new_state(tbf, GPRS_RLCMAC_FLOW);
+ if ((tbf->state_flags &
+ (1 << GPRS_RLCMAC_FLAG_TO_UL_ASS))) {
+ tbf->state_flags &=
+ ~(1 << GPRS_RLCMAC_FLAG_TO_UL_ASS);
+ LOGP(DRLCMAC, LOGL_NOTICE, "Recovered uplink "
+ "assignment for UL TBF=%d\n", tbf->tfi);
+ }
+ tbf_assign_control_ts(tbf);
+ break;
+ }
+ LOGP(DRLCMAC, LOGL_ERROR, "Error: received PACET CONTROL ACK "
+ "at no request\n");
+ break;
+ case MT_PACKET_DOWNLINK_ACK_NACK:
+ tfi = ul_control_block->u.Packet_Downlink_Ack_Nack.DOWNLINK_TFI;
+ tbf = bts->bts->tbf_by_poll_fn(fn, trx, ts);
+ if (!tbf) {
+ LOGP(DRLCMAC, LOGL_NOTICE, "PACKET DOWNLINK ACK with "
+ "unknown FN=%u TFI=%d (TRX %d TS %d)\n",
+ fn, tfi, trx, ts);
+ break;
+ }
+ if (tbf->tfi != tfi) {
+ LOGP(DRLCMAC, LOGL_NOTICE, "PACKET DOWNLINK ACK with "
+ "wrong TFI=%d, ignoring!\n", tfi);
+ break;
+ }
+ 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 downlink ack "
+ "for DL TBF=%d\n", tbf->tfi);
+ }
+ /* reset N3105 */
+ tbf->n3105 = 0;
+ /* stop timer T3191 */
+ tbf_timer_stop(tbf);
+ tlli = tbf->tlli;
+ LOGP(DRLCMAC, LOGL_DEBUG, "RX: [PCU <- BTS] TFI: %u TLLI: 0x%08x Packet Downlink Ack/Nack\n", tbf->tfi, tbf->tlli);
+ tbf->poll_state = GPRS_RLCMAC_POLL_NONE;
+ debug_diagram(bts->bts, tbf->diag, "got DL-ACK");
+
+ rc = gprs_rlcmac_downlink_ack(tbf,
+ 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);
+ if (rc == 1) {
+ tbf_free(tbf);
+ break;
+ }
+ /* check for channel request */
+ if (ul_control_block->u.Packet_Downlink_Ack_Nack.Exist_Channel_Request_Description) {
+ LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF in ack "
+ "message, so we provide one:\n");
+ tbf_alloc_ul(bts, tbf->trx_no, tbf->ms_class, tbf->tlli, tbf->ta, tbf);
+ /* schedule uplink assignment */
+ tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_SEND_ASS;
+ }
+ break;
+ case MT_PACKET_RESOURCE_REQUEST:
+ if (ul_control_block->u.Packet_Resource_Request.ID.UnionType) {
+ tlli = ul_control_block->u.Packet_Resource_Request.ID.u.TLLI;
+ tbf = bts->bts->tbf_by_tlli(tlli, GPRS_RLCMAC_UL_TBF);
+ if (tbf) {
+ LOGP(DRLCMACUL, LOGL_NOTICE, "Got RACH from "
+ "TLLI=0x%08x while UL TBF=%d still "
+ "exists. Killing pending DL TBF\n",
+ tlli, tbf->tfi);
+ tbf_free(tbf);
+ tbf = NULL;
+ }
+ if (!tbf) {
+ uint8_t ms_class = 0;
+ struct gprs_rlcmac_tbf *dl_tbf;
+ uint8_t ta;
+
+ if ((dl_tbf = bts->bts->tbf_by_tlli(tlli, GPRS_RLCMAC_DL_TBF))) {
+ LOGP(DRLCMACUL, LOGL_NOTICE, "Got RACH from "
+ "TLLI=0x%08x while DL TBF=%d still exists. "
+ "Killing pending DL TBF\n", tlli,
+ dl_tbf->tfi);
+ tbf_free(dl_tbf);
+ }
+ LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF "
+ "in packet ressource request of single "
+ "block, so we provide one:\n");
+ sba = bts->bts->sba()->find(trx, ts, fn);
+ if (!sba) {
+ LOGP(DRLCMAC, LOGL_NOTICE, "MS requests UL TBF "
+ "in packet ressource request of single "
+ "block, but there is no resource request "
+ "scheduled!\n");
+ rc = bts->bts->timing_advance()->recall(tlli);
+ if (rc >= 0)
+ ta = rc;
+ else
+ ta = 0;
+ } else {
+ ta = sba->ta;
+ bts->bts->timing_advance()->remember(tlli, ta);
+ llist_del(&sba->list);
+ talloc_free(sba);
+ }
+ if (ul_control_block->u.Packet_Resource_Request.Exist_MS_Radio_Access_capability)
+ ms_class = Decoding::get_ms_class_by_capability(&ul_control_block->u.Packet_Resource_Request.MS_Radio_Access_capability);
+ if (!ms_class)
+ LOGP(DRLCMAC, LOGL_NOTICE, "MS does not give us a class.\n");
+ tbf = tbf_alloc_ul(bts, trx, ms_class, tlli, ta, NULL);
+ if (!tbf)
+ break;
+ /* set control ts to current MS's TS, until assignment complete */
+ LOGP(DRLCMAC, LOGL_DEBUG, "Change control TS to %d until assinment is complete.\n", ts);
+ tbf->control_ts = ts;
+ /* schedule uplink assignment */
+ tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_SEND_ASS;
+ debug_diagram(bts->bts, tbf->diag, "Res. REQ");
+ break;
+ }
+ tfi = tbf->tfi;
+ } else {
+ if (ul_control_block->u.Packet_Resource_Request.ID.u.Global_TFI.UnionType) {
+ tfi = ul_control_block->u.Packet_Resource_Request.ID.u.Global_TFI.u.DOWNLINK_TFI;
+ tbf = tbf_by_tfi(bts, tfi, trx, GPRS_RLCMAC_DL_TBF);
+ if (!tbf) {
+ LOGP(DRLCMAC, LOGL_NOTICE, "PACKET RESSOURCE REQ unknown downlink TBF=%d\n", tlli);
+ break;
+ }
+ } else {
+ tfi = ul_control_block->u.Packet_Resource_Request.ID.u.Global_TFI.u.UPLINK_TFI;
+ tbf = tbf_by_tfi(bts, tfi, trx, GPRS_RLCMAC_UL_TBF);
+ if (!tbf) {
+ LOGP(DRLCMAC, LOGL_NOTICE, "PACKET RESSOURCE REQ unknown uplink TBF=%d\n", tlli);
+ break;
+ }
+ }
+ tlli = tbf->tlli;
+ }
+ 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:
+ sba = bts->bts->sba()->find(trx, ts, fn);
+ if (!sba) {
+ LOGP(DRLCMAC, LOGL_NOTICE, "MS send measurement "
+ "in packet ressource request of single "
+ "block, but there is no resource request "
+ "scheduled!\n");
+ } else {
+ bts->bts->timing_advance()->remember(ul_control_block->u.Packet_Measurement_Report.TLLI, sba->ta);
+ llist_del(&sba->list);
+ talloc_free(sba);
+ }
+ 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");
+ }
+ talloc_free(ul_control_block);
+ return 1;
+}
+
/* received RLC/MAC block from L1 */
int gprs_rlcmac_pdch::rcv_block(uint8_t *data, uint8_t len, uint32_t fn, int8_t rssi)
@@ -590,7 +842,7 @@ int gprs_rlcmac_pdch::rcv_block(uint8_t *data, uint8_t len, uint32_t fn, int8_t
if (!block)
return -ENOMEM;
bitvec_unpack(block, data);
- rc = gprs_rlcmac_rcv_control_block(bts, block, trx_no, ts_no, fn);
+ rc = rcv_control_block(bts, block, trx_no, ts_no, fn);
bitvec_free(block);
break;
case GPRS_RLCMAC_CONTROL_BLOCK_OPT:
diff --git a/src/bts.h b/src/bts.h
index 7eabfbc8..541b9b20 100644
--- a/src/bts.h
+++ b/src/bts.h
@@ -76,6 +76,9 @@ private:
int rcv_data_block_acknowledged(struct gprs_rlcmac_bts *bts,
uint8_t trx, uint8_t ts,
uint8_t *data, uint8_t len, int8_t rssi);
+ int rcv_control_block(struct gprs_rlcmac_bts *bts,
+ bitvec *rlc_block, uint8_t trx, uint8_t ts,
+ uint32_t fn);
#endif
};
diff --git a/src/decoding.cpp b/src/decoding.cpp
index 596b66eb..e7ec99ab 100644
--- a/src/decoding.cpp
+++ b/src/decoding.cpp
@@ -68,3 +68,18 @@ int Decoding::tlli_from_ul_data(const uint8_t *data, uint8_t len,
return 0;
}
+uint8_t Decoding::get_ms_class_by_capability(MS_Radio_Access_capability_t *cap)
+{
+ int i;
+
+ for (i = 0; i < cap->Count_MS_RA_capability_value; i++) {
+ if (!cap->MS_RA_capability_value[i].u.Content.Exist_Multislot_capability)
+ continue;
+ if (!cap->MS_RA_capability_value[i].u.Content.Multislot_capability.Exist_GPRS_multislot_class)
+ continue;
+ return cap->MS_RA_capability_value[i].u.Content.Multislot_capability.GPRS_multislot_class;
+ }
+
+ return 0;
+}
+
diff --git a/src/decoding.h b/src/decoding.h
index 47983a2a..0590eb40 100644
--- a/src/decoding.h
+++ b/src/decoding.h
@@ -19,10 +19,13 @@
*/
#pragma once
+#include <gsm_rlcmac.h>
+
#include <stdint.h>
class Decoding {
public:
static int tlli_from_ul_data(const uint8_t *data, uint8_t len,
uint32_t *tlli);
+ static uint8_t get_ms_class_by_capability(MS_Radio_Access_capability_t *cap);
};
diff --git a/src/gprs_rlcmac.h b/src/gprs_rlcmac.h
index af15e77a..4fe5067a 100644
--- a/src/gprs_rlcmac.h
+++ b/src/gprs_rlcmac.h
@@ -98,10 +98,6 @@ int gprs_rlcmac_poll_timeout(struct gprs_rlcmac_bts *bts, struct gprs_rlcmac_tbf
int gprs_rlcmac_rcv_rach(struct gprs_rlcmac_bts *bts, uint8_t ra, uint32_t Fn, int16_t qta);
-int gprs_rlcmac_rcv_control_block(struct gprs_rlcmac_bts *bts,
- bitvec *rlc_block, uint8_t trx, uint8_t ts,
- uint32_t fn);
-
struct msgb *gprs_rlcmac_send_packet_uplink_assignment(
struct gprs_rlcmac_tbf *tbf, uint32_t fn);
diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp
index f2887b2a..1f81201b 100644
--- a/src/gprs_rlcmac_data.cpp
+++ b/src/gprs_rlcmac_data.cpp
@@ -159,273 +159,6 @@ int gprs_rlcmac_poll_timeout(struct gprs_rlcmac_bts *bts, struct gprs_rlcmac_tbf
return 0;
}
-static uint8_t get_ms_class_by_capability(MS_Radio_Access_capability_t *cap)
-{
- int i;
-
- for (i = 0; i < cap->Count_MS_RA_capability_value; i++) {
- if (!cap->MS_RA_capability_value[i].u.Content.Exist_Multislot_capability)
- continue;
- if (!cap->MS_RA_capability_value[i].u.Content.Multislot_capability.Exist_GPRS_multislot_class)
- continue;
- return cap->MS_RA_capability_value[i].u.Content.Multislot_capability.GPRS_multislot_class;
- }
-
- return 0;
-}
-
-/* Received Uplink RLC control block. */
-int gprs_rlcmac_rcv_control_block(struct gprs_rlcmac_bts *bts,
- bitvec *rlc_block, uint8_t trx, uint8_t ts,
- uint32_t fn)
-{
- int8_t tfi = 0; /* must be signed */
- uint32_t tlli = 0;
- struct gprs_rlcmac_tbf *tbf;
- struct gprs_rlcmac_sba *sba;
- int rc;
-
- RlcMacUplink_t * ul_control_block = (RlcMacUplink_t *)talloc_zero(tall_pcu_ctx, RlcMacUplink_t);
- LOGP(DRLCMAC, LOGL_DEBUG, "+++++++++++++++++++++++++ RX : Uplink Control Block +++++++++++++++++++++++++\n");
- decode_gsm_rlcmac_uplink(rlc_block, ul_control_block);
- LOGPC(DCSN1, LOGL_NOTICE, "\n");
- LOGP(DRLCMAC, LOGL_DEBUG, "------------------------- RX : Uplink Control Block -------------------------\n");
- switch (ul_control_block->u.MESSAGE_TYPE) {
- case MT_PACKET_CONTROL_ACK:
- tlli = ul_control_block->u.Packet_Control_Acknowledgement.TLLI;
- tbf = bts->bts->tbf_by_poll_fn(fn, trx, ts);
- if (!tbf) {
- LOGP(DRLCMAC, LOGL_NOTICE, "PACKET CONTROL ACK with "
- "unknown FN=%u TLL=0x%08x (TRX %d TS %d)\n",
- fn, tlli, trx, ts);
- break;
- }
- tfi = tbf->tfi;
- if (tlli != tbf->tlli) {
- LOGP(DRLCMAC, LOGL_INFO, "Phone changed TLLI to "
- "0x%08x\n", tlli);
- tbf->tlli = tlli;
- }
- LOGP(DRLCMAC, LOGL_DEBUG, "RX: [PCU <- BTS] TFI: %u TLLI: 0x%08x Packet Control Ack\n", tbf->tfi, tbf->tlli);
- tbf->poll_state = GPRS_RLCMAC_POLL_NONE;
-
- /* check if this control ack belongs to packet uplink ack */
- if (tbf->ul_ack_state == GPRS_RLCMAC_UL_ACK_WAIT_ACK) {
- LOGP(DRLCMAC, LOGL_DEBUG, "TBF: [UPLINK] END TFI: %u TLLI: 0x%08x \n", tbf->tfi, tbf->tlli);
- tbf->ul_ack_state = GPRS_RLCMAC_UL_ACK_NONE;
- debug_diagram(bts->bts, tbf->diag, "got CTL-ACK (fin)");
- if ((tbf->state_flags &
- (1 << GPRS_RLCMAC_FLAG_TO_UL_ACK))) {
- tbf->state_flags &=
- ~(1 << GPRS_RLCMAC_FLAG_TO_UL_ACK);
- LOGP(DRLCMAC, LOGL_NOTICE, "Recovered uplink "
- "ack for UL TBF=%d\n", tbf->tfi);
- }
- tbf_free(tbf);
- break;
- }
- if (tbf->dl_ass_state == GPRS_RLCMAC_DL_ASS_WAIT_ACK) {
- LOGP(DRLCMAC, LOGL_DEBUG, "TBF: [UPLINK] DOWNLINK ASSIGNED TFI: %u TLLI: 0x%08x \n", tbf->tfi, tbf->tlli);
- /* reset N3105 */
- tbf->n3105 = 0;
- tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_NONE;
- debug_diagram(bts->bts, tbf->diag, "got CTL-ACK DL-ASS");
- if (tbf->direction == GPRS_RLCMAC_UL_TBF)
- tbf = bts->bts->tbf_by_tlli(tbf->tlli,
- GPRS_RLCMAC_DL_TBF);
- if (!tbf) {
- LOGP(DRLCMAC, LOGL_ERROR, "Got ACK, but DL "
- "TBF is gone\n");
- break;
- }
- tbf_new_state(tbf, GPRS_RLCMAC_FLOW);
- /* stop pending assignment timer */
- tbf_timer_stop(tbf);
- if ((tbf->state_flags &
- (1 << GPRS_RLCMAC_FLAG_TO_DL_ASS))) {
- tbf->state_flags &=
- ~(1 << GPRS_RLCMAC_FLAG_TO_DL_ASS);
- LOGP(DRLCMAC, LOGL_NOTICE, "Recovered downlink "
- "assignment for DL TBF=%d\n", tbf->tfi);
- }
- tbf_assign_control_ts(tbf);
- break;
- }
- if (tbf->ul_ass_state == GPRS_RLCMAC_UL_ASS_WAIT_ACK) {
- LOGP(DRLCMAC, LOGL_DEBUG, "TBF: [DOWNLINK] UPLINK ASSIGNED TFI: %u TLLI: 0x%08x \n", tbf->tfi, tbf->tlli);
- /* reset N3105 */
- tbf->n3105 = 0;
- tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_NONE;
- debug_diagram(bts->bts, tbf->diag, "got CTL-AC UL-ASS");
- if (tbf->direction == GPRS_RLCMAC_DL_TBF)
- tbf = bts->bts->tbf_by_tlli(tbf->tlli,
- GPRS_RLCMAC_UL_TBF);
- if (!tbf) {
- LOGP(DRLCMAC, LOGL_ERROR, "Got ACK, but UL "
- "TBF is gone\n");
- break;
- }
- tbf_new_state(tbf, GPRS_RLCMAC_FLOW);
- if ((tbf->state_flags &
- (1 << GPRS_RLCMAC_FLAG_TO_UL_ASS))) {
- tbf->state_flags &=
- ~(1 << GPRS_RLCMAC_FLAG_TO_UL_ASS);
- LOGP(DRLCMAC, LOGL_NOTICE, "Recovered uplink "
- "assignment for UL TBF=%d\n", tbf->tfi);
- }
- tbf_assign_control_ts(tbf);
- break;
- }
- LOGP(DRLCMAC, LOGL_ERROR, "Error: received PACET CONTROL ACK "
- "at no request\n");
- break;
- case MT_PACKET_DOWNLINK_ACK_NACK:
- tfi = ul_control_block->u.Packet_Downlink_Ack_Nack.DOWNLINK_TFI;
- tbf = bts->bts->tbf_by_poll_fn(fn, trx, ts);
- if (!tbf) {
- LOGP(DRLCMAC, LOGL_NOTICE, "PACKET DOWNLINK ACK with "
- "unknown FN=%u TFI=%d (TRX %d TS %d)\n",
- fn, tfi, trx, ts);
- break;
- }
- if (tbf->tfi != tfi) {
- LOGP(DRLCMAC, LOGL_NOTICE, "PACKET DOWNLINK ACK with "
- "wrong TFI=%d, ignoring!\n", tfi);
- break;
- }
- 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 downlink ack "
- "for DL TBF=%d\n", tbf->tfi);
- }
- /* reset N3105 */
- tbf->n3105 = 0;
- /* stop timer T3191 */
- tbf_timer_stop(tbf);
- tlli = tbf->tlli;
- LOGP(DRLCMAC, LOGL_DEBUG, "RX: [PCU <- BTS] TFI: %u TLLI: 0x%08x Packet Downlink Ack/Nack\n", tbf->tfi, tbf->tlli);
- tbf->poll_state = GPRS_RLCMAC_POLL_NONE;
- debug_diagram(bts->bts, tbf->diag, "got DL-ACK");
-
- rc = gprs_rlcmac_downlink_ack(tbf,
- 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);
- if (rc == 1) {
- tbf_free(tbf);
- break;
- }
- /* check for channel request */
- if (ul_control_block->u.Packet_Downlink_Ack_Nack.Exist_Channel_Request_Description) {
- LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF in ack "
- "message, so we provide one:\n");
- tbf_alloc_ul(bts, tbf->trx_no, tbf->ms_class, tbf->tlli, tbf->ta, tbf);
- /* schedule uplink assignment */
- tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_SEND_ASS;
- }
- break;
- case MT_PACKET_RESOURCE_REQUEST:
- if (ul_control_block->u.Packet_Resource_Request.ID.UnionType) {
- tlli = ul_control_block->u.Packet_Resource_Request.ID.u.TLLI;
- tbf = bts->bts->tbf_by_tlli(tlli, GPRS_RLCMAC_UL_TBF);
- if (tbf) {
- LOGP(DRLCMACUL, LOGL_NOTICE, "Got RACH from "
- "TLLI=0x%08x while UL TBF=%d still "
- "exists. Killing pending DL TBF\n",
- tlli, tbf->tfi);
- tbf_free(tbf);
- tbf = NULL;
- }
- if (!tbf) {
- uint8_t ms_class = 0;
- struct gprs_rlcmac_tbf *dl_tbf;
- uint8_t ta;
-
- if ((dl_tbf = bts->bts->tbf_by_tlli(tlli, GPRS_RLCMAC_DL_TBF))) {
- LOGP(DRLCMACUL, LOGL_NOTICE, "Got RACH from "
- "TLLI=0x%08x while DL TBF=%d still exists. "
- "Killing pending DL TBF\n", tlli,
- dl_tbf->tfi);
- tbf_free(dl_tbf);
- }
- LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF "
- "in packet ressource request of single "
- "block, so we provide one:\n");
- sba = bts->bts->sba()->find(trx, ts, fn);
- if (!sba) {
- LOGP(DRLCMAC, LOGL_NOTICE, "MS requests UL TBF "
- "in packet ressource request of single "
- "block, but there is no resource request "
- "scheduled!\n");
- rc = bts->bts->timing_advance()->recall(tlli);
- if (rc >= 0)
- ta = rc;
- else
- ta = 0;
- } else {
- ta = sba->ta;
- bts->bts->timing_advance()->remember(tlli, ta);
- llist_del(&sba->list);
- talloc_free(sba);
- }
- if (ul_control_block->u.Packet_Resource_Request.Exist_MS_Radio_Access_capability)
- ms_class = get_ms_class_by_capability(&ul_control_block->u.Packet_Resource_Request.MS_Radio_Access_capability);
- if (!ms_class)
- LOGP(DRLCMAC, LOGL_NOTICE, "MS does not give us a class.\n");
- tbf = tbf_alloc_ul(bts, trx, ms_class, tlli, ta, NULL);
- if (!tbf)
- break;
- /* set control ts to current MS's TS, until assignment complete */
- LOGP(DRLCMAC, LOGL_DEBUG, "Change control TS to %d until assinment is complete.\n", ts);
- tbf->control_ts = ts;
- /* schedule uplink assignment */
- tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_SEND_ASS;
- debug_diagram(bts->bts, tbf->diag, "Res. REQ");
- break;
- }
- tfi = tbf->tfi;
- } else {
- if (ul_control_block->u.Packet_Resource_Request.ID.u.Global_TFI.UnionType) {
- tfi = ul_control_block->u.Packet_Resource_Request.ID.u.Global_TFI.u.DOWNLINK_TFI;
- tbf = tbf_by_tfi(bts, tfi, trx, GPRS_RLCMAC_DL_TBF);
- if (!tbf) {
- LOGP(DRLCMAC, LOGL_NOTICE, "PACKET RESSOURCE REQ unknown downlink TBF=%d\n", tlli);
- break;
- }
- } else {
- tfi = ul_control_block->u.Packet_Resource_Request.ID.u.Global_TFI.u.UPLINK_TFI;
- tbf = tbf_by_tfi(bts, tfi, trx, GPRS_RLCMAC_UL_TBF);
- if (!tbf) {
- LOGP(DRLCMAC, LOGL_NOTICE, "PACKET RESSOURCE REQ unknown uplink TBF=%d\n", tlli);
- break;
- }
- }
- tlli = tbf->tlli;
- }
- 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:
- sba = bts->bts->sba()->find(trx, ts, fn);
- if (!sba) {
- LOGP(DRLCMAC, LOGL_NOTICE, "MS send measurement "
- "in packet ressource request of single "
- "block, but there is no resource request "
- "scheduled!\n");
- } else {
- bts->bts->timing_advance()->remember(ul_control_block->u.Packet_Measurement_Report.TLLI, sba->ta);
- llist_del(&sba->list);
- talloc_free(sba);
- }
- 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");
- }
- talloc_free(ul_control_block);
- return 1;
-}
-
#ifdef DEBUG_DL_ASS_IDLE
char debug_imsi[16];
#endif