aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gprs_bssgp_pcu.cpp15
-rw-r--r--src/gprs_rlcmac.cpp166
-rw-r--r--src/gprs_rlcmac.h27
-rw-r--r--src/gprs_rlcmac_data.cpp24
-rw-r--r--src/gprs_rlcmac_sched.cpp114
-rw-r--r--src/tbf.txt20
6 files changed, 236 insertions, 130 deletions
diff --git a/src/gprs_bssgp_pcu.cpp b/src/gprs_bssgp_pcu.cpp
index 5f967eef..fb298039 100644
--- a/src/gprs_bssgp_pcu.cpp
+++ b/src/gprs_bssgp_pcu.cpp
@@ -123,6 +123,9 @@ int gprs_bssgp_pcu_rx_dl_ud(struct msgb *msg, struct tlv_parsed *tp)
tbf->llc_length = len;
memset(&tbf->dir.dl, 0, sizeof(tbf->dir.dl)); /* reset
rlc states */
+ if (!tbf->ms_class && ms_class)
+ tbf->ms_class = ms_class;
+ tbf_update(tbf);
gprs_rlcmac_trigger_downlink_assignment(tbf, 1, NULL);
} else {
/* the TBF exists, so we must write it in the queue */
@@ -131,17 +134,24 @@ int gprs_bssgp_pcu_rx_dl_ud(struct msgb *msg, struct tlv_parsed *tp)
return -ENOMEM;
memcpy(msgb_put(llc_msg, len), data, len);
msgb_enqueue(&tbf->llc_queue, llc_msg);
+ /* set ms class for updating TBF */
+ if (!tbf->ms_class && ms_class)
+ tbf->ms_class = ms_class;
}
} else {
- uint8_t trx, ts, use_trx, first_ts;
+ uint8_t trx, ts, use_trx, first_ts, ta, ss;
/* check for uplink data, so we copy our informations */
if ((tbf = tbf_by_tlli(tlli, GPRS_RLCMAC_UL_TBF))) {
use_trx = tbf->trx;
first_ts = tbf->first_ts;
+ ta = tbf->ta;
+ ss = 0;
} else {
use_trx = -1;
first_ts = -1;
+ ta = 0; /* FIXME: initial TA */
+ ss = 1; /* PCH assignment only allows one timeslot */
}
// Create new TBF (any TRX)
@@ -152,7 +162,8 @@ int gprs_bssgp_pcu_rx_dl_ud(struct msgb *msg, struct tlv_parsed *tp)
return -EBUSY;
}
/* set number of downlink slots according to multislot class */
- tbf = tbf_alloc(GPRS_RLCMAC_DL_TBF, tfi, trx, ts, ms_class);
+ tbf = tbf_alloc(tbf, GPRS_RLCMAC_DL_TBF, tfi, trx, ts, ms_class,
+ ss);
if (!tbf) {
LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH ressource\n");
/* FIXME: send reject */
diff --git a/src/gprs_rlcmac.cpp b/src/gprs_rlcmac.cpp
index 3db405f2..145049eb 100644
--- a/src/gprs_rlcmac.cpp
+++ b/src/gprs_rlcmac.cpp
@@ -154,29 +154,30 @@ struct gprs_rlcmac_tbf *tbf_by_tlli(uint32_t tlli,
struct gprs_rlcmac_tbf *tbf_by_poll_fn(uint32_t fn, uint8_t trx, uint8_t ts)
{
- struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
struct gprs_rlcmac_tbf *tbf;
- uint8_t tfi;
/* only one TBF can poll on specific TS/FN, because scheduler can only
* schedule one downlink control block (with polling) at a FN per TS */
- for (tfi = 0; tfi < 32; tfi++) {
- tbf = bts->trx[trx].pdch[ts].ul_tbf[tfi];
- if (tbf && tbf->state != GPRS_RLCMAC_RELEASING
+ llist_for_each_entry(tbf, &gprs_rlcmac_ul_tbfs, list) {
+ if (tbf->state != GPRS_RLCMAC_RELEASING
&& tbf->poll_state == GPRS_RLCMAC_POLL_SCHED
- && tbf->poll_fn == fn && tbf->poll_ts == ts)
+ && tbf->poll_fn == fn && tbf->trx == trx
+ && tbf->control_ts == ts)
return tbf;
- tbf = bts->trx[trx].pdch[ts].dl_tbf[tfi];
- if (tbf && tbf->state != GPRS_RLCMAC_RELEASING
+ }
+ llist_for_each_entry(tbf, &gprs_rlcmac_dl_tbfs, list) {
+ if (tbf->state != GPRS_RLCMAC_RELEASING
&& tbf->poll_state == GPRS_RLCMAC_POLL_SCHED
- && tbf->poll_fn == fn && tbf->poll_ts == ts)
+ && tbf->poll_fn == fn && tbf->trx == trx
+ && tbf->control_ts == ts)
return tbf;
}
return NULL;
}
-struct gprs_rlcmac_tbf *tbf_alloc(enum gprs_rlcmac_tbf_direction dir,
- uint8_t tfi, uint8_t trx, uint8_t first_ts, uint8_t ms_class)
+struct gprs_rlcmac_tbf *tbf_alloc(struct gprs_rlcmac_tbf *old_tbf,
+ enum gprs_rlcmac_tbf_direction dir, uint8_t tfi, uint8_t trx,
+ uint8_t first_ts, uint8_t ms_class, uint8_t single_slot)
{
struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
struct gprs_rlcmac_tbf *tbf;
@@ -202,11 +203,21 @@ struct gprs_rlcmac_tbf *tbf_alloc(enum gprs_rlcmac_tbf_direction dir,
tbf->ms_class = ms_class;
tbf->ws = 64;
tbf->sns = 128;
- /* select algorithm according to multislot class */
- if (ms_class)
- rc = bts->alloc_algorithm(tbf);
+ /* select algorithm A in case we don't have multislot class info */
+ if (single_slot || ms_class == 0)
+ rc = alloc_algorithm_a(old_tbf, tbf,
+ bts->alloc_algorithm_curst);
else
- rc = alloc_algorithm_a(tbf);
+ rc = bts->alloc_algorithm(old_tbf, tbf,
+ bts->alloc_algorithm_curst);
+ /* if no ressource */
+ if (rc < 0) {
+ talloc_free(tbf);
+ return NULL;
+ }
+ /* assign control ts */
+ tbf->control_ts = 0xff;
+ rc = tbf_assign_control_ts(tbf);
/* if no ressource */
if (rc < 0) {
talloc_free(tbf);
@@ -222,31 +233,21 @@ struct gprs_rlcmac_tbf *tbf_alloc(enum gprs_rlcmac_tbf_direction dir,
return tbf;
}
-#if 0
-int alloc_algorithm_b(struct gprs_rlcmac_tbf *tbf)
-{
- pdch = &bts->trx[tbf->trx].pdch[ts];
- if (!pdch->enable)
- continue;
- if (tsc < 0)
- tbf->tsc = tsc = pdch->tsc;
- else if (tsc != pdch->tsc) {
- LOGP(DRLCMAC, LOGL_ERROR, "Skipping TS=%d of TRX=%d, "
- "because it has different TSC than lower TS "
- "of TRX. In order to allow multislot, all "
- "slots must be configured with the same TSC!\n",
- ts, tbf->trx);
- continue;
- }
-#endif
-
-int alloc_algorithm_a(struct gprs_rlcmac_tbf *tbf)
+/* Slot Allocation: Algorithm A
+ *
+ * Assign single slot for uplink and downlink
+ */
+int alloc_algorithm_a(struct gprs_rlcmac_tbf *old_tbf,
+ struct gprs_rlcmac_tbf *tbf, uint32_t cust)
{
struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
struct gprs_rlcmac_pdch *pdch;
uint8_t ts = tbf->first_ts;
int8_t usf; /* must be signed */
+ LOGP(DRLCMAC, LOGL_DEBUG, "Slot Allocation (Algorithm A) for class "
+ "%d\n", tbf->ms_class);
+
pdch = &bts->trx[tbf->trx].pdch[ts];
if (!pdch->enable) {
LOGP(DRLCMAC, LOGL_ERROR, "TS=%d not enabled.", ts);
@@ -259,43 +260,66 @@ int alloc_algorithm_a(struct gprs_rlcmac_tbf *tbf)
/* if USF available */
usf = find_free_usf(pdch, ts);
if (usf >= 0) {
- LOGP(DRLCMAC, LOGL_DEBUG, " Assign uplink "
+ LOGP(DRLCMAC, LOGL_DEBUG, "- Assign uplink "
"TS=%d USF=%d\n", ts, usf);
pdch->ul_tbf[tbf->tfi] = tbf;
tbf->pdch[ts] = pdch;
} else {
- LOGP(DRLCMAC, LOGL_NOTICE, " Failed allocating "
- "TS=%d, no USF available\n", ts);
+ LOGP(DRLCMAC, LOGL_NOTICE, "- Failed "
+ "allocating TS=%d, no USF available\n",
+ ts);
return -EBUSY;
}
} else {
- LOGP(DRLCMAC, LOGL_NOTICE, " Failed allocating "
+ LOGP(DRLCMAC, LOGL_NOTICE, "- Failed allocating "
"TS=%d, TFI is not available\n", ts);
return -EBUSY;
}
} else {
/* if TFI is free on TS */
if (!pdch->dl_tbf[tbf->tfi]) {
- LOGP(DRLCMAC, LOGL_DEBUG, " Assign downlink TS=%d\n",
+ LOGP(DRLCMAC, LOGL_DEBUG, "- Assign downlink TS=%d\n",
ts);
pdch->dl_tbf[tbf->tfi] = tbf;
tbf->pdch[ts] = pdch;
} else {
- LOGP(DRLCMAC, LOGL_NOTICE, " Failed allocating "
+ LOGP(DRLCMAC, LOGL_NOTICE, "- Failed allocating "
"TS=%d, TFI is not available\n", ts);
return -EBUSY;
}
}
+ /* the only one TS is the common TS */
+ tbf->first_common_ts = ts;
return 0;
}
-void tbf_free(struct gprs_rlcmac_tbf *tbf)
+static void tbf_unlink_pdch(struct gprs_rlcmac_tbf *tbf)
{
struct gprs_rlcmac_pdch *pdch;
- struct msgb *msg;
int ts;
+ if (tbf->direction == GPRS_RLCMAC_UL_TBF) {
+ for (ts = 0; ts < 8; ts++) {
+ pdch = tbf->pdch[ts];
+ if (pdch)
+ pdch->ul_tbf[tbf->tfi] = NULL;
+ tbf->pdch[ts] = NULL;
+ }
+ } else {
+ for (ts = 0; ts < 8; ts++) {
+ pdch = tbf->pdch[ts];
+ if (pdch)
+ pdch->dl_tbf[tbf->tfi] = NULL;
+ tbf->pdch[ts] = NULL;
+ }
+ }
+}
+
+void tbf_free(struct gprs_rlcmac_tbf *tbf)
+{
+ struct msgb *msg;
+
LOGP(DRLCMAC, LOGL_INFO, "Free %s TBF=%d with TLLI=0x%08x.\n",
(tbf->direction == GPRS_RLCMAC_UL_TBF) ? "UL" : "DL", tbf->tfi,
tbf->tlli);
@@ -312,24 +336,56 @@ void tbf_free(struct gprs_rlcmac_tbf *tbf)
tbf_timer_stop(tbf);
while ((msg = msgb_dequeue(&tbf->llc_queue)))
msgb_free(msg);
- if (tbf->direction == GPRS_RLCMAC_UL_TBF) {
- for (ts = 0; ts < 8; ts++) {
- pdch = tbf->pdch[ts];
- if (pdch)
- pdch->ul_tbf[tbf->tfi] = NULL;
- }
- } else {
- for (ts = 0; ts < 8; ts++) {
- pdch = tbf->pdch[ts];
- if (pdch)
- pdch->dl_tbf[tbf->tfi] = NULL;
- }
- }
+ tbf_unlink_pdch(tbf);
llist_del(&tbf->list);
LOGP(DRLCMAC, LOGL_DEBUG, "********** TBF ends here **********\n");
talloc_free(tbf);
}
+int tbf_update(struct gprs_rlcmac_tbf *tbf)
+{
+ struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
+ struct gprs_rlcmac_tbf *ul_tbf = NULL;
+ int rc;
+
+ LOGP(DRLCMAC, LOGL_DEBUG, "********** TBF update **********\n");
+
+ if (tbf->direction != GPRS_RLCMAC_DL_TBF)
+ return -EINVAL;
+
+ if (!tbf->ms_class) {
+ LOGP(DRLCMAC, LOGL_DEBUG, "- Cannot update, no class\n");
+ return -EINVAL;
+ }
+
+ if (tbf->tlli_valid)
+ ul_tbf = tbf_by_tlli(tbf->tlli, GPRS_RLCMAC_UL_TBF);
+
+ tbf_unlink_pdch(tbf);
+ rc = bts->alloc_algorithm(ul_tbf, tbf, bts->alloc_algorithm_curst);
+ /* if no ressource */
+ if (rc < 0) {
+ LOGP(DRLCMAC, LOGL_ERROR, "No ressource after update???\n");
+ return -rc;
+ }
+
+ return 0;
+}
+
+int tbf_assign_control_ts(struct gprs_rlcmac_tbf *tbf)
+{
+ if (tbf->control_ts == 0xff)
+ LOGP(DRLCMAC, LOGL_DEBUG, "- Setting Control TS %d\n",
+ tbf->control_ts);
+ else if (tbf->control_ts != tbf->first_common_ts)
+ LOGP(DRLCMAC, LOGL_DEBUG, "- Changing Control TS %d\n",
+ tbf->control_ts);
+ tbf->control_ts = tbf->first_common_ts;
+
+ return 0;
+}
+
+
const char *tbf_state_name[] = {
"NULL",
"ASSIGN",
diff --git a/src/gprs_rlcmac.h b/src/gprs_rlcmac.h
index 71edf3df..1e6bc0d2 100644
--- a/src/gprs_rlcmac.h
+++ b/src/gprs_rlcmac.h
@@ -71,7 +71,9 @@ struct gprs_rlcmac_bts {
uint8_t n3103;
uint8_t n3105;
struct gprs_rlcmac_trx trx[8];
- int (*alloc_algorithm)(struct gprs_rlcmac_tbf *tbf);
+ int (*alloc_algorithm)(struct gprs_rlcmac_tbf *old_tbf,
+ struct gprs_rlcmac_tbf *tbf, uint32_t cust);
+ uint32_t alloc_algorithm_curst; /* options to customize algorithm */
};
extern struct gprs_rlcmac_bts *gprs_rlcmac_bts;
@@ -135,7 +137,10 @@ struct gprs_rlcmac_tbf {
uint8_t trx;
uint16_t arfcn;
uint8_t tsc;
- uint8_t first_ts;
+ uint8_t first_ts; /* first TS used by TBF */
+ uint8_t first_common_ts; /* first TS that the phone can send and
+ reveive simultaniously */
+ uint8_t control_ts; /* timeslot control messages and polling */
uint8_t ms_class;
struct gprs_rlcmac_pdch *pdch[8]; /* list of PDCHs allocated to TBF */
uint16_t ta;
@@ -150,7 +155,6 @@ struct gprs_rlcmac_tbf {
enum gprs_rlcmac_tbf_poll_state poll_state;
uint32_t poll_fn; /* frame number to poll */
- uint8_t poll_ts; /* timeslot to poll */
uint16_t ws; /* window size */
uint16_t sns; /* sequence number space */
@@ -197,10 +201,15 @@ extern struct llist_head gprs_rlcmac_dl_tbfs; /* list of downlink TBFs */
int tfi_alloc(enum gprs_rlcmac_tbf_direction dir, uint8_t *_trx, uint8_t *_ts,
uint8_t use_trx, uint8_t first_ts);
-struct gprs_rlcmac_tbf *tbf_alloc(enum gprs_rlcmac_tbf_direction dir,
- uint8_t tfi, uint8_t trx, uint8_t first_ts, uint8_t ms_class);
+struct gprs_rlcmac_tbf *tbf_alloc(struct gprs_rlcmac_tbf *old_tbf,
+ enum gprs_rlcmac_tbf_direction dir, uint8_t tfi, uint8_t trx,
+ uint8_t first_ts, uint8_t ms_class, uint8_t single_slot);
-int alloc_algorithm_a(struct gprs_rlcmac_tbf *tbf);
+int alloc_algorithm_a(struct gprs_rlcmac_tbf *old_tbf,
+ struct gprs_rlcmac_tbf *tbf, uint32_t cust);
+
+int alloc_algorithm_b(struct gprs_rlcmac_tbf *old_tbf,
+ struct gprs_rlcmac_tbf *tbf, uint32_t cust);
struct gprs_rlcmac_tbf *tbf_by_tfi(uint8_t tfi, uint8_t trx, uint8_t ts,
enum gprs_rlcmac_tbf_direction dir);
@@ -212,6 +221,10 @@ struct gprs_rlcmac_tbf *tbf_by_poll_fn(uint32_t fn, uint8_t trx, uint8_t ts);
void tbf_free(struct gprs_rlcmac_tbf *tbf);
+int tbf_update(struct gprs_rlcmac_tbf *tbf);
+
+int tbf_assign_control_ts(struct gprs_rlcmac_tbf *tbf);
+
void tbf_new_state(struct gprs_rlcmac_tbf *tbf,
enum gprs_rlcmac_tbf_state state);
@@ -275,7 +288,7 @@ int gprs_rlcmac_rcv_data_block_acknowledged(uint8_t trx, uint8_t ts,
uint8_t *data, uint8_t len);
struct msgb *gprs_rlcmac_send_data_block_acknowledged(
- struct gprs_rlcmac_tbf *tbf, uint32_t fn);
+ struct gprs_rlcmac_tbf *tbf, uint32_t fn, uint8_t ts);
struct msgb *gprs_rlcmac_send_uplink_ack(struct gprs_rlcmac_tbf *tbf,
uint32_t fn);
diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp
index 1b936fc7..bbbcfd55 100644
--- a/src/gprs_rlcmac_data.cpp
+++ b/src/gprs_rlcmac_data.cpp
@@ -139,7 +139,8 @@ int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint8_t trx, uint8_t ts,
tbf = tbf_by_poll_fn(fn, trx, ts);
if (!tbf) {
LOGP(DRLCMAC, LOGL_NOTICE, "PACKET CONTROL ACK with "
- "unknown FN=%u TLL=0x%08x\n", fn, tlli);
+ "unknown FN=%u TLL=0x%08x (TRX %d TS %d)\n",
+ fn, tlli, trx, ts);
break;
}
tfi = tbf->tfi;
@@ -176,7 +177,8 @@ int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint8_t trx, uint8_t ts,
tbf = tbf_by_poll_fn(fn, trx, ts);
if (!tbf) {
LOGP(DRLCMAC, LOGL_NOTICE, "PACKET DOWNLINK ACK with "
- "unknown FN=%u TBF=%d\n", fn, tfi);
+ "unknown FN=%u TBF=%d (TRX %d TS %d)\n",
+ fn, tfi, trx, ts);
break;
}
/* reset N3105 */
@@ -208,8 +210,8 @@ uplink_request:
break;
}
/* use multislot class of downlink TBF */
- ul_tbf = tbf_alloc(GPRS_RLCMAC_UL_TBF, tfi, trx, ts,
- tbf->ms_class);
+ ul_tbf = tbf_alloc(tbf, GPRS_RLCMAC_UL_TBF, tfi, trx,
+ ts, tbf->ms_class, 0);
if (!ul_tbf) {
LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH ressource\n");
/* FIXME: send reject */
@@ -286,9 +288,10 @@ void tbf_timer_cb(void *_tbf)
#endif
case 0: /* assignment */
/* change state to FLOW, so scheduler will start transmission */
- if (tbf->state == GPRS_RLCMAC_ASSIGN)
+ if (tbf->state == GPRS_RLCMAC_ASSIGN) {
tbf_new_state(tbf, GPRS_RLCMAC_FLOW);
- else
+ tbf_assign_control_ts(tbf);
+ } else
LOGP(DRLCMAC, LOGL_ERROR, "Error: TBF is not in assign "
"state\n");
break;
@@ -550,7 +553,6 @@ struct msgb *gprs_rlcmac_send_uplink_ack(struct gprs_rlcmac_tbf *tbf,
if (final) {
tbf->poll_state = GPRS_RLCMAC_POLL_SCHED;
tbf->poll_fn = (fn + 13) % 2715648;
- tbf->poll_ts = tbf->first_ts;
/* waiting for final acknowledge */
tbf->ul_ack_state = GPRS_RLCMAC_UL_ACK_WAIT_ACK;
} else
@@ -800,7 +802,6 @@ struct msgb *gprs_rlcmac_send_packet_uplink_assignment(
FIXME process does not work, also the acknowledgement is not checked.
tbf->poll_state = GPRS_RLCMAC_POLL_SCHED;
tbf->poll_fn = (fn + 13) % 2715648;
- tbf->poll_ts = tbf->first_ts;
tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_WAIT_ACK;
#else
tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_NONE;
@@ -826,7 +827,7 @@ int gprs_rlcmac_rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta)
return -EBUSY;
}
/* set class to 0, since we don't know the multislot class yet */
- tbf = tbf_alloc(GPRS_RLCMAC_UL_TBF, tfi, trx, ts, 0);
+ tbf = tbf_alloc(NULL, GPRS_RLCMAC_UL_TBF, tfi, trx, ts, 0, 1);
if (!tbf) {
LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH ressource\n");
/* FIXME: send reject */
@@ -861,7 +862,7 @@ int gprs_rlcmac_rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta)
* The messages are fragmented and forwarded as data blocks.
*/
struct msgb *gprs_rlcmac_send_data_block_acknowledged(
- struct gprs_rlcmac_tbf *tbf, uint32_t fn)
+ struct gprs_rlcmac_tbf *tbf, uint32_t fn, uint8_t ts)
{
struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
struct rlc_dl_header *rh;
@@ -1144,7 +1145,6 @@ tx_block:
/* schedule polling */
tbf->poll_state = GPRS_RLCMAC_POLL_SCHED;
tbf->poll_fn = (fn + 13) % 2715648;
- tbf->poll_ts = tbf->first_ts;
/* set polling in header */
rh->rrbp = 0; /* N+13 */
@@ -1269,6 +1269,7 @@ int gprs_rlcmac_downlink_ack(struct gprs_rlcmac_tbf *tbf, uint8_t final,
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_update(tbf);
gprs_rlcmac_trigger_downlink_assignment(tbf, 1, NULL);
return 0;
@@ -1329,7 +1330,6 @@ struct msgb *gprs_rlcmac_send_packet_downlink_assignment(
#if POLLING_ASSIGNMENT == 1
tbf->poll_state = GPRS_RLCMAC_POLL_SCHED;
tbf->poll_fn = (fn + 13) % 2715648;
- tbf->poll_ts = tbf->first_ts;
tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_WAIT_ACK;
#else
tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_NONE;
diff --git a/src/gprs_rlcmac_sched.cpp b/src/gprs_rlcmac_sched.cpp
index 7d9a156f..f88b09b5 100644
--- a/src/gprs_rlcmac_sched.cpp
+++ b/src/gprs_rlcmac_sched.cpp
@@ -36,7 +36,8 @@ int gprs_rlcmac_rcv_rts_block(uint8_t trx, uint8_t ts, uint16_t arfcn,
{
struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
struct gprs_rlcmac_pdch *pdch;
- struct gprs_rlcmac_tbf *tbf;
+ struct gprs_rlcmac_tbf *tbf, *poll_tbf = NULL, *dl_ass_tbf = NULL,
+ *ul_ass_tbf = NULL, *ul_ack_tbf = NULL;
uint8_t usf = 0x7;
struct msgb *msg = NULL;
uint32_t poll_fn;
@@ -55,39 +56,50 @@ int gprs_rlcmac_rcv_rts_block(uint8_t trx, uint8_t ts, uint16_t arfcn,
/* store last frame number of RTS */
pdch->last_rts_fn = fn;
- /* check uplink ressource for polling */
+ /* check special TBF for events */
poll_fn = fn + 4;
if ((block_nr % 3) == 2)
poll_fn ++;
poll_fn = poll_fn % 2715648;
- for (tfi = 0; tfi < 32; tfi++) {
- tbf = pdch->ul_tbf[tfi];
- if (tbf) {
- /* no polling */
- if (tbf->poll_state != GPRS_RLCMAC_POLL_SCHED)
- continue;
- /* polling for next uplink block */
- if (tbf->poll_fn == poll_fn)
- break;
- }
- tbf = pdch->dl_tbf[tfi];
- if (tbf) {
- /* no polling */
- if (tbf->poll_state != GPRS_RLCMAC_POLL_SCHED)
- continue;
- /* polling for next uplink block */
- if (tbf->poll_fn == poll_fn)
- break;
- }
+ llist_for_each_entry(tbf, &gprs_rlcmac_ul_tbfs, list) {
+ /* this trx, this ts */
+ if (tbf->trx != trx || tbf->control_ts != ts)
+ continue;
+ /* polling for next uplink block */
+ if (tbf->poll_state == GPRS_RLCMAC_POLL_SCHED
+ && tbf->poll_fn == poll_fn)
+ poll_tbf = tbf;
+ if (tbf->dl_ass_state == GPRS_RLCMAC_DL_ASS_SEND_ASS)
+ dl_ass_tbf = tbf;
+ if (tbf->ul_ass_state == GPRS_RLCMAC_UL_ASS_SEND_ASS)
+ ul_ass_tbf = tbf;
+ if (tbf->ul_ack_state == GPRS_RLCMAC_UL_ACK_SEND_ACK)
+ ul_ack_tbf = tbf;
}
- /* found uplink where a block is polled */
- if (tfi < 32) {
+ llist_for_each_entry(tbf, &gprs_rlcmac_dl_tbfs, list) {
+ /* this trx, this ts */
+ if (tbf->trx != trx || tbf->control_ts != ts)
+ continue;
+ /* polling for next uplink block */
+ if (tbf->poll_state == GPRS_RLCMAC_POLL_SCHED
+ && tbf->poll_fn == poll_fn)
+ poll_tbf = tbf;
+ if (tbf->dl_ass_state == GPRS_RLCMAC_DL_ASS_SEND_ASS)
+ dl_ass_tbf = tbf;
+ if (tbf->ul_ass_state == GPRS_RLCMAC_UL_ASS_SEND_ASS)
+ ul_ass_tbf = tbf;
+ if (tbf->ul_ack_state == GPRS_RLCMAC_UL_ACK_SEND_ACK)
+ ul_ack_tbf = tbf;
+ }
+
+ /* check uplink ressource for polling */
+ if (poll_tbf) {
LOGP(DRLCMACSCHED, LOGL_DEBUG, "Received RTS for PDCH: TRX=%d "
"TS=%d FN=%d block_nr=%d scheduling free USF for "
"polling at FN=%d of %s TFI=%d\n", trx, ts, fn,
block_nr, poll_fn,
(tbf->direction == GPRS_RLCMAC_UL_TBF) ? "UL" : "DL",
- tfi);
+ poll_tbf->tfi);
/* use free USF */
/* else, we search for uplink ressource */
} else {
@@ -118,34 +130,26 @@ int gprs_rlcmac_rcv_rts_block(uint8_t trx, uint8_t ts, uint16_t arfcn,
}
/* Prio 1: select control message */
- for (i = 0; i < 64; i++) {
- if (i < 32)
- tbf = pdch->ul_tbf[i];
- else
- tbf = pdch->dl_tbf[i & 31];
- /* no TBF for this tfi, go next */
- if (!tbf)
- continue;
- /* schedule PACKET DOWNLINK ASSIGNMENT */
- if (tbf->dl_ass_state == GPRS_RLCMAC_DL_ASS_SEND_ASS)
- msg = gprs_rlcmac_send_packet_downlink_assignment(tbf,
- fn);
- else
- /* schedule PACKET UPLINK ASSIGNMENT */
- if (tbf->ul_ass_state == GPRS_RLCMAC_UL_ASS_SEND_ASS)
- msg = gprs_rlcmac_send_packet_uplink_assignment(tbf,
- fn);
- else
- /* schedule PACKET UPLINK ACK */
- if (tbf->ul_ack_state == GPRS_RLCMAC_UL_ACK_SEND_ACK)
- msg = gprs_rlcmac_send_uplink_ack(tbf, fn);
- if (msg) {
- LOGP(DRLCMACSCHED, LOGL_DEBUG, "Scheduling control "
- "message at RTS for %s TBF=%d\n",
- (tbf->direction == GPRS_RLCMAC_UL_TBF)
- ? "UL" : "DL", tbf->tfi);
- break;
- }
+ /* schedule PACKET DOWNLINK ASSIGNMENT */
+ if (dl_ass_tbf) {
+ tbf = dl_ass_tbf;
+ msg = gprs_rlcmac_send_packet_downlink_assignment(tbf, fn);
+ } else
+ /* schedule PACKET UPLINK ASSIGNMENT */
+ if (ul_ass_tbf) {
+ tbf = ul_ass_tbf;
+ msg = gprs_rlcmac_send_packet_uplink_assignment(tbf, fn);
+ } else
+ /* schedule PACKET UPLINK ACK */
+ if (ul_ack_tbf) {
+ tbf = ul_ack_tbf;
+ msg = gprs_rlcmac_send_uplink_ack(tbf, fn);
+ }
+ if (msg) {
+ LOGP(DRLCMACSCHED, LOGL_DEBUG, "Scheduling control "
+ "message at RTS for %s TBF=%d (TRX=%d, TS=%d)\n",
+ (tbf->direction == GPRS_RLCMAC_UL_TBF)
+ ? "UL" : "DL", tbf->tfi, trx, ts);
}
/* Prio 2: select data message for downlink */
@@ -166,11 +170,13 @@ int gprs_rlcmac_rcv_rts_block(uint8_t trx, uint8_t ts, uint16_t arfcn,
continue;
LOGP(DRLCMACSCHED, LOGL_DEBUG, "Scheduling data "
- "message at RTS for DL TBF=%d\n", tfi);
+ "message at RTS for DL TBF=%d (TRX=%d, "
+ "TS=%d)\n", tfi, trx, ts);
/* next TBF to handle ressource is the next one */
pdch->next_dl_tfi = (tfi + 1) & 31;
/* generate DL data block */
- msg = gprs_rlcmac_send_data_block_acknowledged(tbf, fn);
+ msg = gprs_rlcmac_send_data_block_acknowledged(tbf, fn,
+ ts);
break;
}
}
diff --git a/src/tbf.txt b/src/tbf.txt
index 57254ea3..eab58ba5 100644
--- a/src/tbf.txt
+++ b/src/tbf.txt
@@ -94,11 +94,27 @@ Handling of LLC Frame of downlink TBF and LLC Queue of downlink TBF:
If a new LLC PDU is attached to LLC Frame during WAIT RELEASE state, the
state is changed to FLOW (downlink flow is assigned to MS).
+
Handling of LLC Frame on uplink TBF:
Received uplink blocks are appended to LLC Frame of TBF. If the PDU is
complete, it is forwarded to the upper layer.
+
+Control TS:
+ On uplink or downlink assignment, it is required to have one timeslot that
+ can be used to receive and transmit. This timeslot is used at uplink TBF
+ to acknowledge and to assign other TBF. This timeslot is used at downlink
+ TBF to poll acknowledgement and to assign other TBF.
+
+ The first common TS (first_common_ts) is calculated when channels are
+ allocated. After creation of TBF or after assignment to different TS layout,
+ the first common TS is used for control TS.
+
+ The first common TS (and so control TS) must not need to be allocated to
+ MS as uplink TBF. (E.g. in case of non-available USF for this slot)
+
+
Polling:
In order to poll uplink control block from MS, a special poll state and
frame number is stored at TBF. The scheduler reads that value and will not
@@ -109,6 +125,10 @@ Polling:
- The received frame is bad (BFI).
- The GSM indicates that the block should have been already received.
+ Because polling requires uplink response from MS, the polling must be
+ performed at control TS.
+
+
Data structures of TBFs and PDCHs:
There is a global structure for BTS.