aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gprs_rlcmac.cpp133
-rw-r--r--src/gprs_rlcmac.h6
-rw-r--r--src/gprs_rlcmac_data.cpp10
-rw-r--r--src/pcu_main.cpp3
4 files changed, 92 insertions, 60 deletions
diff --git a/src/gprs_rlcmac.cpp b/src/gprs_rlcmac.cpp
index ab04aeab..3db405f2 100644
--- a/src/gprs_rlcmac.cpp
+++ b/src/gprs_rlcmac.cpp
@@ -176,17 +176,16 @@ struct gprs_rlcmac_tbf *tbf_by_poll_fn(uint32_t fn, uint8_t trx, uint8_t 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 num_ts)
+ uint8_t tfi, uint8_t trx, uint8_t first_ts, uint8_t ms_class)
{
struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
- struct gprs_rlcmac_pdch *pdch;
struct gprs_rlcmac_tbf *tbf;
- uint8_t ts_count, ts;
- int8_t usf, tsc = -1; /* both must be signed */
+ int rc;
LOGP(DRLCMAC, LOGL_DEBUG, "********** TBF starts here **********\n");
- LOGP(DRLCMAC, LOGL_INFO, "Allocating %s TBF with TFI=%d on TRX=%d.\n",
- (dir == GPRS_RLCMAC_UL_TBF) ? "UL" : "DL", tfi, trx);
+ LOGP(DRLCMAC, LOGL_INFO, "Allocating %s TBF: TFI=%d TRX=%d "
+ "MS_CLASS=%d\n", (dir == GPRS_RLCMAC_UL_TBF) ? "UL" : "DL",
+ tfi, trx, ms_class);
if (trx >= 8 || first_ts >= 8 || tfi >= 32)
return NULL;
@@ -199,12 +198,34 @@ struct gprs_rlcmac_tbf *tbf_alloc(enum gprs_rlcmac_tbf_direction dir,
tbf->tfi = tfi;
tbf->trx = trx;
tbf->arfcn = bts->trx[trx].arfcn;
- /* assign free TS to TBF, where TFI is free
- * for uplink: assign free USF to each uplink TS
- * Note that the first TS must be free, because it was selected by
- * tfi_alloc(). */
- for (ts_count = 0, ts = first_ts; ts < 8; ts++) {
- pdch = &bts->trx[trx].pdch[ts];
+ tbf->first_ts = first_ts;
+ 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);
+ else
+ rc = alloc_algorithm_a(tbf);
+ /* if no ressource */
+ if (rc < 0) {
+ talloc_free(tbf);
+ return NULL;
+ }
+
+ INIT_LLIST_HEAD(&tbf->llc_queue);
+ if (dir == GPRS_RLCMAC_UL_TBF)
+ llist_add(&tbf->list, &gprs_rlcmac_ul_tbfs);
+ else
+ llist_add(&tbf->list, &gprs_rlcmac_dl_tbfs);
+
+ 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)
@@ -214,55 +235,59 @@ struct gprs_rlcmac_tbf *tbf_alloc(enum gprs_rlcmac_tbf_direction dir,
"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, trx);
+ ts, tbf->trx);
continue;
}
- if (dir == GPRS_RLCMAC_UL_TBF) {
- /* if TFI is free on TS */
- if (!pdch->ul_tbf[tfi]) {
- /* if USF available */
- usf = find_free_usf(pdch, ts);
- if (usf >= 0) {
- LOGP(DRLCMAC, LOGL_DEBUG, " Assign "
- "uplink TS=%d USF=%d\n",
- ts, usf);
- pdch->ul_tbf[tfi] = tbf;
- tbf->pdch[ts] = pdch;
- ts_count++;
- } else
- LOGP(DRLCMAC, LOGL_DEBUG, " Skipping "
- "TS=%d, no USF available\n",
- ts);
- }
- } else {
- /* if TFI is free on TS */
- if (!pdch->dl_tbf[tfi]) {
- LOGP(DRLCMAC, LOGL_DEBUG, " Assign downlink "
- "TS=%d\n", ts);
- pdch->dl_tbf[tfi] = tbf;
+#endif
+
+int alloc_algorithm_a(struct gprs_rlcmac_tbf *tbf)
+{
+ 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 */
+
+ pdch = &bts->trx[tbf->trx].pdch[ts];
+ if (!pdch->enable) {
+ LOGP(DRLCMAC, LOGL_ERROR, "TS=%d not enabled.", ts);
+ return -EIO;
+ }
+ tbf->tsc = pdch->tsc;
+ if (tbf->direction == GPRS_RLCMAC_UL_TBF) {
+ /* if TFI is free on TS */
+ if (!pdch->ul_tbf[tbf->tfi]) {
+ /* if USF available */
+ usf = find_free_usf(pdch, ts);
+ if (usf >= 0) {
+ LOGP(DRLCMAC, LOGL_DEBUG, " Assign uplink "
+ "TS=%d USF=%d\n", ts, usf);
+ pdch->ul_tbf[tbf->tfi] = tbf;
tbf->pdch[ts] = pdch;
- ts_count++;
+ } else {
+ LOGP(DRLCMAC, LOGL_NOTICE, " Failed allocating "
+ "TS=%d, no USF available\n", ts);
+ return -EBUSY;
}
+ } else {
+ 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",
+ ts);
+ pdch->dl_tbf[tbf->tfi] = tbf;
+ tbf->pdch[ts] = pdch;
+ } else {
+ LOGP(DRLCMAC, LOGL_NOTICE, " Failed allocating "
+ "TS=%d, TFI is not available\n", ts);
+ return -EBUSY;
}
- if (ts_count == num_ts)
- break;
- }
- if (!ts_count) { /* implies that direction is uplink */
- LOGP(DRLCMAC, LOGL_NOTICE, "No USF available\n");
- talloc_free(tbf);
- return NULL;
}
- tbf->first_ts = first_ts;
- tbf->ws = 64;
- tbf->sns = 128;
- INIT_LLIST_HEAD(&tbf->llc_queue);
- if (dir == GPRS_RLCMAC_UL_TBF)
- llist_add(&tbf->list, &gprs_rlcmac_ul_tbfs);
- else
- llist_add(&tbf->list, &gprs_rlcmac_dl_tbfs);
-
- return tbf;
+ return 0;
}
void tbf_free(struct gprs_rlcmac_tbf *tbf)
diff --git a/src/gprs_rlcmac.h b/src/gprs_rlcmac.h
index db0e9ab9..71edf3df 100644
--- a/src/gprs_rlcmac.h
+++ b/src/gprs_rlcmac.h
@@ -71,6 +71,7 @@ struct gprs_rlcmac_bts {
uint8_t n3103;
uint8_t n3105;
struct gprs_rlcmac_trx trx[8];
+ int (*alloc_algorithm)(struct gprs_rlcmac_tbf *tbf);
};
extern struct gprs_rlcmac_bts *gprs_rlcmac_bts;
@@ -135,6 +136,7 @@ struct gprs_rlcmac_tbf {
uint16_t arfcn;
uint8_t tsc;
uint8_t first_ts;
+ uint8_t ms_class;
struct gprs_rlcmac_pdch *pdch[8]; /* list of PDCHs allocated to TBF */
uint16_t ta;
uint8_t llc_frame[LLC_MAX_LEN]; /* current DL or UL frame */
@@ -196,7 +198,9 @@ 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 num_ts);
+ uint8_t tfi, uint8_t trx, uint8_t first_ts, uint8_t ms_class);
+
+int alloc_algorithm_a(struct gprs_rlcmac_tbf *tbf);
struct gprs_rlcmac_tbf *tbf_by_tfi(uint8_t tfi, uint8_t trx, uint8_t ts,
enum gprs_rlcmac_tbf_direction dir);
diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp
index 0e8aca3e..1b936fc7 100644
--- a/src/gprs_rlcmac_data.cpp
+++ b/src/gprs_rlcmac_data.cpp
@@ -207,9 +207,9 @@ uplink_request:
/* FIXME: send reject */
break;
}
- /* FIXME: set number of downlink slots according to
- * multislot class */
- ul_tbf = tbf_alloc(GPRS_RLCMAC_UL_TBF, tfi, trx, ts, 1);
+ /* use multislot class of downlink TBF */
+ ul_tbf = tbf_alloc(GPRS_RLCMAC_UL_TBF, tfi, trx, ts,
+ tbf->ms_class);
if (!ul_tbf) {
LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH ressource\n");
/* FIXME: send reject */
@@ -825,8 +825,8 @@ int gprs_rlcmac_rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta)
/* FIXME: send reject */
return -EBUSY;
}
- /* select only one TS, since we don't know the multislot class yet */
- tbf = tbf_alloc(GPRS_RLCMAC_UL_TBF, tfi, trx, ts, 1);
+ /* set class to 0, since we don't know the multislot class yet */
+ tbf = tbf_alloc(GPRS_RLCMAC_UL_TBF, tfi, trx, ts, 0);
if (!tbf) {
LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH ressource\n");
/* FIXME: send reject */
diff --git a/src/pcu_main.cpp b/src/pcu_main.cpp
index 2c6d7638..9fd04559 100644
--- a/src/pcu_main.cpp
+++ b/src/pcu_main.cpp
@@ -183,6 +183,9 @@ int main(int argc, char *argv[])
exit(1);
}
+ if (!bts->alloc_algorithm)
+ bts->alloc_algorithm = alloc_algorithm_a;
+
rc = pcu_l1if_open();
if (rc < 0)