aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2012-07-15 06:25:37 +0200
committerAndreas Eversberg <jolly@eversberg.eu>2012-07-15 06:25:37 +0200
commit592e04ab6d19612ebde5f4a4b9c1cda67ad055db (patch)
tree810da935492a8cb4266829cc642e5809e0e9fe77
parent51ab134fa8e7f16b627a038ecbfa2051421261de (diff)
multislot: Rework of handling control channel / polling
In order to send control blocks to MS and receive control blocks from MS (polling), it is required to select one timeslot that the MS must be able to send and receive. The allocation algorithm must take care of selecting that slot.
-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 5f967ee..fb29803 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 3db405f..145049e 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 71edf3d..1e6bc0d 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 1b936fc..bbbcfd5 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 7d9a156..f88b09b 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 57254ea..eab58ba 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.