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.