From b0c7ea72c8157f1b8124bbe105aa05c46a77a005 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Fri, 13 Jul 2012 14:46:03 +0200 Subject: Changed data structures for TBF and PDCH instances, to allow multislot The new data structure is required to define slot/TFI assigment for MS with multislot capability. Now there are two lists for TBFs: uplink and downlink. It is possible to have different TBFs with same TFI in the same direction, as long as they are assigned on different timeslots. See tbf.txt for description. Note: This does not implement any multislot support. It defines the new data structure. Currently only the first slot is assigned. --- src/gprs_rlcmac_data.cpp | 103 +++++++++++++++++++++++------------------------ 1 file changed, 50 insertions(+), 53 deletions(-) (limited to 'src/gprs_rlcmac_data.cpp') diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp index 7beca38f..0e8aca3e 100644 --- a/src/gprs_rlcmac_data.cpp +++ b/src/gprs_rlcmac_data.cpp @@ -64,7 +64,8 @@ struct rlc_li_field { int gprs_rlcmac_poll_timeout(struct gprs_rlcmac_tbf *tbf) { - LOGP(DRLCMAC, LOGL_NOTICE, "Poll timeout for TBF=%d\n", tbf->tfi); + LOGP(DRLCMAC, LOGL_NOTICE, "Poll timeout for %s TBF=%d\n", + (tbf->direction == GPRS_RLCMAC_UL_TBF) ? "UL" : "DL", tbf->tfi); tbf->poll_state = GPRS_RLCMAC_POLL_NONE; @@ -120,9 +121,10 @@ int gprs_rlcmac_poll_timeout(struct gprs_rlcmac_tbf *tbf) } /* Received Uplink RLC control block. */ -int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint32_t fn) +int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint8_t trx, uint8_t ts, + uint32_t fn) { - uint8_t tfi = 0; + int8_t tfi = 0; /* must be signed */ uint32_t tlli = 0; struct gprs_rlcmac_tbf *tbf; @@ -134,7 +136,7 @@ int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint32_t fn) switch (ul_control_block->u.MESSAGE_TYPE) { case MT_PACKET_CONTROL_ACK: tlli = ul_control_block->u.Packet_Control_Acknowledgement.TLLI; - tbf = tbf_by_poll_fn(fn); + 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); @@ -171,7 +173,7 @@ int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint32_t fn) break; case MT_PACKET_DOWNLINK_ACK_NACK: tfi = ul_control_block->u.Packet_Downlink_Ack_Nack.DOWNLINK_TFI; - tbf = tbf_by_poll_fn(fn); + 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); @@ -191,32 +193,31 @@ int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint32_t fn) ul_control_block->u.Packet_Downlink_Ack_Nack.Ack_Nack_Description.RECEIVED_BLOCK_BITMAP); /* check for channel request */ if (ul_control_block->u.Packet_Downlink_Ack_Nack.Exist_Channel_Request_Description) { - uint8_t trx, ts, usf; + uint8_t trx, ts; struct gprs_rlcmac_tbf *ul_tbf; struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts; LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF in ack " "message, so we provide one:\n"); uplink_request: - /* create new tbf */ - tfi = tfi_alloc(&trx, &ts); + /* create new TBF, use sme TRX as DL TBF */ + tfi = tfi_alloc(GPRS_RLCMAC_UL_TBF, &trx, &ts, tbf->trx, tbf->first_ts); if (tfi < 0) { LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH ressource\n"); /* FIXME: send reject */ break; } - usf = find_free_usf(trx, ts); - if (usf < 0) { - LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH ressource for USF\n"); + /* FIXME: set number of downlink slots according to + * multislot class */ + ul_tbf = tbf_alloc(GPRS_RLCMAC_UL_TBF, tfi, trx, ts, 1); + if (!ul_tbf) { + LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH ressource\n"); /* FIXME: send reject */ break; } - ul_tbf = tbf_alloc(tfi, trx, ts); ul_tbf->tlli = tbf->tlli; ul_tbf->tlli_valid = 1; /* no content resolution */ ul_tbf->ta = tbf->ta; /* use current TA */ - ul_tbf->direction = GPRS_RLCMAC_UL_TBF; - ul_tbf->dir.ul.usf = usf; tbf_new_state(ul_tbf, GPRS_RLCMAC_FLOW); tbf_timer_start(ul_tbf, 3169, bts->t3169, 0); /* schedule uplink assignment */ @@ -235,14 +236,14 @@ uplink_request: } 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(tfi, GPRS_RLCMAC_DL_TBF); + tbf = tbf_by_tfi(tfi, trx, ts, 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(tfi, GPRS_RLCMAC_UL_TBF); + tbf = tbf_by_tfi(tfi, trx, ts, GPRS_RLCMAC_UL_TBF); if (!tbf) { LOGP(DRLCMAC, LOGL_NOTICE, "PACKET RESSOURCE REQ unknown uplink TBF=%d\n", tlli); break; @@ -250,7 +251,7 @@ uplink_request: } tlli = tbf->tlli; } - LOGP(DRLCMAC, LOGL_DEBUG, "RX: [PCU <- BTS] TFI: %u TLLI: 0x%08x Packet ressource request\n", tbf->tfi, tbf->tlli); + LOGP(DRLCMAC, LOGL_INFO, "RX: [PCU <- BTS] %s TFI: %u TLLI: 0x%08x Packet ressource request\n", (tbf->direction == GPRS_RLCMAC_UL_TBF) ? "UL" : "DL", tbf->tfi, tbf->tlli); #warning FIXME puts("FIXME: UL request during UL request"); exit(0); @@ -271,7 +272,8 @@ void tbf_timer_cb(void *_tbf) { struct gprs_rlcmac_tbf *tbf = (struct gprs_rlcmac_tbf *)_tbf; - LOGP(DRLCMAC, LOGL_DEBUG, "TBF=%d timer %u expired.\n", tbf->tfi, + LOGP(DRLCMAC, LOGL_DEBUG, "%s TBF=%d timer %u expired.\n", + (tbf->direction == GPRS_RLCMAC_UL_TBF) ? "UL" : "DL", tbf->tfi, tbf->T); tbf->num_T_exp++; @@ -495,8 +497,7 @@ static int gprs_rlcmac_assemble_llc(struct gprs_rlcmac_tbf *tbf, uint8_t *data, if (i != frames - 1) { /* send frame to SGSN */ LOGP(DRLCMACUL, LOGL_INFO, "Complete UL frame for " - "TBF=%d: %s\n", tbf->tfi, - osmo_hexdump(tbf->llc_frame, tbf->llc_index)); + "TBF=%d: len=%d\n", tbf->tfi, tbf->llc_index); gprs_rlcmac_tx_ul_ud(tbf); tbf->llc_index = 0; /* reset frame space */ /* also check if CV==0, because the frame may fill up the @@ -507,8 +508,7 @@ static int gprs_rlcmac_assemble_llc(struct gprs_rlcmac_tbf *tbf, uint8_t *data, /* send frame to SGSN */ LOGP(DRLCMACUL, LOGL_INFO, "Complete UL frame for " "TBF=%d that fits precisely in last block: " - "%s\n", tbf->tfi, - osmo_hexdump(tbf->llc_frame, tbf->llc_index)); + "len=%d\n", tbf->tfi, tbf->llc_index); gprs_rlcmac_tx_ul_ud(tbf); tbf->llc_index = 0; /* reset frame space */ } @@ -550,6 +550,7 @@ 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 @@ -562,7 +563,8 @@ struct msgb *gprs_rlcmac_send_uplink_ack(struct gprs_rlcmac_tbf *tbf, * * The blocks are defragmented and forwarded as LLC frames, if complete. */ -int gprs_rlcmac_rcv_data_block_acknowledged(uint8_t *data, uint8_t len) +int gprs_rlcmac_rcv_data_block_acknowledged(uint8_t trx, uint8_t ts, + uint8_t *data, uint8_t len) { struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts; struct gprs_rlcmac_tbf *tbf; @@ -592,19 +594,13 @@ int gprs_rlcmac_rcv_data_block_acknowledged(uint8_t *data, uint8_t len) } /* find TBF inst from given TFI */ - tbf = tbf_by_tfi(rh->tfi, GPRS_RLCMAC_UL_TBF); + tbf = tbf_by_tfi(rh->tfi, trx, ts, GPRS_RLCMAC_UL_TBF); if (!tbf) { LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA unknown TBF=%d\n", rh->tfi); return 0; } - if (tbf->direction != GPRS_RLCMAC_UL_TBF) { - LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA TBF=%d not Uplink " - "tbf\n", rh->tfi); - return 0; - } - LOGP(DRLCMACUL, LOGL_DEBUG, "UL DATA TBF=%d received (V(Q)=%d .. " "V(R)=%d)\n", rh->tfi, tbf->dir.ul.v_q, tbf->dir.ul.v_r); @@ -755,12 +751,14 @@ struct msgb *gprs_rlcmac_send_packet_uplink_assignment( struct msgb *msg; struct gprs_rlcmac_tbf *new_tbf; +#if POLLING_ASSIGNMENT == 1 if (tbf->poll_state != GPRS_RLCMAC_POLL_NONE) { LOGP(DRLCMACUL, LOGL_DEBUG, "Polling is already " "sheduled for TBF=%d, so we must wait for uplink " "assignment...\n", tbf->tfi); return NULL; } +#endif /* on down TBF we get the uplink TBF to be assigned. */ if (tbf->direction == GPRS_RLCMAC_DL_TBF) @@ -788,9 +786,8 @@ struct msgb *gprs_rlcmac_send_packet_uplink_assignment( bitvec_unhex(ass_vec, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b"); write_packet_uplink_assignment(ass_vec, tbf->tfi, - (tbf->direction == GPRS_RLCMAC_DL_TBF), 0, 0, new_tbf->tfi, - new_tbf->dir.ul.usf, new_tbf->arfcn, new_tbf->ts, new_tbf->ta, - new_tbf->tsc, POLLING_ASSIGNMENT); + (tbf->direction == GPRS_RLCMAC_DL_TBF), 0, 0, new_tbf, + POLLING_ASSIGNMENT); bitvec_pack(ass_vec, msgb_put(msg, 23)); RlcMacDownlink_t * mac_control_block = (RlcMacDownlink_t *)malloc(sizeof(RlcMacDownlink_t)); LOGP(DRLCMAC, LOGL_DEBUG, "+++++++++++++++++++++++++ TX : Packet Uplink Assignment +++++++++++++++++++++++++\n"); @@ -803,6 +800,7 @@ 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; @@ -816,31 +814,29 @@ int gprs_rlcmac_rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta) struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts; struct gprs_rlcmac_tbf *tbf; uint8_t trx, ts; - int tfi, usf; /* must be signed */ + int8_t tfi; /* must be signed */ LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF on RACH, so we provide " "one:\n"); // Create new TBF - tfi = tfi_alloc(&trx, &ts); + tfi = tfi_alloc(GPRS_RLCMAC_UL_TBF, &trx, &ts, -1, -1); if (tfi < 0) { LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH ressource\n"); /* FIXME: send reject */ return -EBUSY; } - usf = find_free_usf(trx, ts); - if (usf < 0) { - LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH ressource for USF\n"); + /* select only one TS, since we don't know the multislot class yet */ + tbf = tbf_alloc(GPRS_RLCMAC_UL_TBF, tfi, trx, ts, 1); + if (!tbf) { + LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH ressource\n"); /* FIXME: send reject */ return -EBUSY; } - tbf = tbf_alloc(tfi, trx, ts); if (qta < 0) qta = 0; if (qta > 252) qta = 252; tbf->ta = qta >> 2; - tbf->direction = GPRS_RLCMAC_UL_TBF; - tbf->dir.ul.usf = usf; tbf_new_state(tbf, GPRS_RLCMAC_FLOW); tbf_timer_start(tbf, 3169, bts->t3169, 0); LOGP(DRLCMAC, LOGL_DEBUG, "TBF: [UPLINK] START TFI: %u\n", tbf->tfi); @@ -848,7 +844,7 @@ int gprs_rlcmac_rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta) LOGP(DRLCMAC, LOGL_INFO, "TX: START TFI: %u Immediate Assignment Uplink (AGCH)\n", tbf->tfi); bitvec *immediate_assignment = bitvec_alloc(22) /* without plen */; bitvec_unhex(immediate_assignment, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b"); - int plen = write_immediate_assignment(immediate_assignment, 0, ra, Fn, tbf->ta, tbf->arfcn, tbf->ts, tbf->tsc, tbf->tfi, usf, 0, 0, 0); + int plen = write_immediate_assignment(immediate_assignment, 0, ra, Fn, tbf->ta, tbf->arfcn, tbf->first_ts, tbf->tsc, tbf->tfi, tbf->dir.ul.usf[tbf->first_ts], 0, 0, 0); pcu_l1if_tx_agch(immediate_assignment, plen); bitvec_free(immediate_assignment); @@ -1013,8 +1009,7 @@ do_resend: "header, and we are done\n", chunk, space); LOGP(DRLCMACDL, LOGL_INFO, "Complete DL frame for " "TBF=%d that fits precisely in last block: " - "%s\n", tbf->tfi, - osmo_hexdump(tbf->llc_frame, tbf->llc_length)); + "len=%d\n", tbf->tfi, tbf->llc_length); /* block is filled, so there is no extension */ *e_pointer |= 0x01; /* fill space */ @@ -1072,9 +1067,8 @@ do_resend: memcpy(data, tbf->llc_frame + tbf->llc_index, chunk); data += chunk; space -= chunk; - LOGP(DRLCMACDL, LOGL_INFO, "Complete DL frame for TBF=%d: %s\n", - tbf->tfi, - osmo_hexdump(tbf->llc_frame, tbf->llc_length)); + LOGP(DRLCMACDL, LOGL_INFO, "Complete DL frame for TBF=%d: " + "len=%d\n", tbf->tfi, tbf->llc_length); /* reset LLC frame */ tbf->llc_index = tbf->llc_length = 0; /* dequeue next LLC frame, if any */ @@ -1150,6 +1144,7 @@ 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 */ @@ -1286,12 +1281,14 @@ struct msgb *gprs_rlcmac_send_packet_downlink_assignment( struct msgb *msg; struct gprs_rlcmac_tbf *new_tbf; +#if POLLING_ASSIGNMENT == 1 if (tbf->poll_state != GPRS_RLCMAC_POLL_NONE) { - LOGP(DRLCMACDL, LOGL_DEBUG, "Polling is already " + LOGP(DRLCMAC, LOGL_DEBUG, "Polling is already " "sheduled for TBF=%d, so we must wait for downlink " "assignment...\n", tbf->tfi); return NULL; } +#endif /* on uplink TBF we get the downlink TBF to be assigned. */ if (tbf->direction == GPRS_RLCMAC_UL_TBF) @@ -1319,8 +1316,7 @@ struct msgb *gprs_rlcmac_send_packet_downlink_assignment( LOGP(DRLCMAC, LOGL_INFO, "TBF: START TFI: %u TLLI: 0x%08x Packet Downlink Assignment (PACCH)\n", new_tbf->tfi, new_tbf->tlli); RlcMacDownlink_t * mac_control_block = (RlcMacDownlink_t *)malloc(sizeof(RlcMacDownlink_t)); write_packet_downlink_assignment(mac_control_block, tbf->tfi, - (tbf->direction == GPRS_RLCMAC_DL_TBF), new_tbf->tfi, - new_tbf->arfcn, new_tbf->ts, new_tbf->ta, new_tbf->tsc, + (tbf->direction == GPRS_RLCMAC_DL_TBF), new_tbf, POLLING_ASSIGNMENT); LOGP(DRLCMAC, LOGL_DEBUG, "+++++++++++++++++++++++++ TX : Packet Downlink Assignment +++++++++++++++++++++++++\n"); encode_gsm_rlcmac_downlink(ass_vec, mac_control_block); @@ -1333,6 +1329,7 @@ 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; @@ -1349,7 +1346,7 @@ static void gprs_rlcmac_downlink_assignment(gprs_rlcmac_tbf *tbf, uint8_t poll, bitvec_unhex(immediate_assignment, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b"); /* use request reference that has maximum distance to current time, * so the assignment will not conflict with possible RACH requests. */ - int plen = write_immediate_assignment(immediate_assignment, 1, 125, (tbf->pdch->last_rts_fn + 21216) % 2715648, tbf->ta, tbf->arfcn, tbf->ts, tbf->tsc, tbf->tfi, 0, tbf->tlli, poll, tbf->poll_fn); + int plen = write_immediate_assignment(immediate_assignment, 1, 125, (tbf->pdch[tbf->first_ts]->last_rts_fn + 21216) % 2715648, tbf->ta, tbf->arfcn, tbf->first_ts, tbf->tsc, tbf->tfi, 0, tbf->tlli, poll, tbf->poll_fn); pcu_l1if_tx_pch(immediate_assignment, plen, imsi); bitvec_free(immediate_assignment); } @@ -1381,8 +1378,8 @@ void gprs_rlcmac_trigger_downlink_assignment(gprs_rlcmac_tbf *tbf, tbf_timer_start(tbf, 1234, 1,0); #else LOGP(DRLCMAC, LOGL_DEBUG, "Send dowlink assignment on " - "PACCH, because %slink TBF=%d exists for TLLI=0x%08x\n", - (tbf->direction == GPRS_RLCMAC_DL_TBF) ? "down" : "up", + "PACCH, because %s TBF=%d exists for TLLI=0x%08x\n", + (old_tbf->direction == GPRS_RLCMAC_UL_TBF) ? "UL" : "DL", old_tbf->tfi, old_tbf->tlli); old_tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_SEND_ASS; /* use TA from old TBF */ -- cgit v1.2.3 From f298fa87b948b03ed71bc8538c14778b680612dc Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Fri, 13 Jul 2012 14:50:57 +0200 Subject: multislot: Extracted "slot allocation algorithm" from tbf allocator The current available algorithm only supports selecting a single slot for downlink/uplink. (In the future, a multislot algorithm will follow.) --- src/gprs_rlcmac_data.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/gprs_rlcmac_data.cpp') 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 */ -- cgit v1.2.3 From 592e04ab6d19612ebde5f4a4b9c1cda67ad055db Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Sun, 15 Jul 2012 06:25:37 +0200 Subject: 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. --- src/gprs_rlcmac_data.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'src/gprs_rlcmac_data.cpp') 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; -- cgit v1.2.3 From 5e043dac8c961995f6bd94b6c0206063efea63ec Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Sun, 15 Jul 2012 06:51:30 +0200 Subject: Polling for downlink ack/nack is performed only on suitable slot The slot must be the control channel TS, which is selected by the allocation algorithm. The MS must be able to respond at this TS. The counter to trigger polling is incremented until polling has to be performed. Then the counter stops. When the transmission of data block is requested on control channel TS, the counter is reset. The counter-value is also used to poll immediately when the transmission has finished. --- src/gprs_rlcmac_data.cpp | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) (limited to 'src/gprs_rlcmac_data.cpp') diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp index bbbcfd55..c95f41cf 100644 --- a/src/gprs_rlcmac_data.cpp +++ b/src/gprs_rlcmac_data.cpp @@ -1092,6 +1092,8 @@ do_resend: "done.\n"); li->e = 1; /* we cannot extend */ rh->fbi = 1; /* we indicate final block */ + tbf->dir.dl.tx_counter = ACK_AFTER_FRAMES + 1; + /* + 1 indicates: force polling */ tbf_new_state(tbf, GPRS_RLCMAC_FINISHED); break; } @@ -1116,27 +1118,31 @@ tx_block: len = tbf->rlc_block_len[index]; rh = (struct rlc_dl_header *)data; - /* Increment TX-counter */ - tbf->dir.dl.tx_counter++; - /* Clear Polling, if still set in history buffer */ rh->s_p = 0; /* poll after ACK_AFTER_FRAMES frames, or when final block is tx. */ - if (rh->fbi == 1 || (tbf->dir.dl.tx_counter % ACK_AFTER_FRAMES) == 0) { - if (rh->fbi == 1) { + if (tbf->dir.dl.tx_counter >= ACK_AFTER_FRAMES) { + if (tbf->dir.dl.tx_counter > ACK_AFTER_FRAMES) { + /* if rx_counter is ACK_AFTER_FRAMES + 1, this + * indicates: poll caused by final ack. */ LOGP(DRLCMACDL, LOGL_DEBUG, "- Scheduling Ack/Nack " "polling, because final block sent.\n"); - } - if ((tbf->dir.dl.tx_counter % ACK_AFTER_FRAMES) == 0) { + } else { LOGP(DRLCMACDL, LOGL_DEBUG, "- Scheduling Ack/Nack " "polling, because %d blocks sent.\n", ACK_AFTER_FRAMES); } + tbf->dir.dl.tx_counter = 0; + /* scheduling not possible, because: */ if (tbf->poll_state != GPRS_RLCMAC_POLL_NONE) - LOGP(DRLCMACDL, LOGL_DEBUG, "Polling is already " + LOGP(DRLCMAC, LOGL_DEBUG, "Polling is already " "sheduled for TBF=%d, so we must wait for " "requesting downlink ack\n", tbf->tfi); + else if (tbf->control_ts != ts) + LOGP(DRLCMAC, LOGL_DEBUG, "Polling cannot be " + "sheduled in this TS %d, waiting for " + "TS %d\n", ts, tbf->control_ts); else { /* start timer whenever we send the final block */ if (rh->fbi == 1) @@ -1149,7 +1155,13 @@ tx_block: /* set polling in header */ rh->rrbp = 0; /* N+13 */ rh->s_p = 1; /* Polling */ + + /* Increment TX-counter */ + tbf->dir.dl.tx_counter++; } + } else { + /* Increment TX-counter */ + tbf->dir.dl.tx_counter++; } /* return data block as message */ -- cgit v1.2.3 From 6664a903652aac7284d22e072a4b64210b6f7d6e Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Sun, 15 Jul 2012 06:52:19 +0200 Subject: Downlink transfer is finished if all packets are acknowleged It turned out that the final ack flag may not be set, but all packets have been acknowledged. This patch will finish transfer in case all blocks are acknowledged. --- src/gprs_rlcmac_data.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'src/gprs_rlcmac_data.cpp') diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp index c95f41cf..9b3a0953 100644 --- a/src/gprs_rlcmac_data.cpp +++ b/src/gprs_rlcmac_data.cpp @@ -917,9 +917,8 @@ do_resend: * indication from MS. This should never happen if MS works * correctly. */ if (tbf->dir.dl.v_s == tbf->dir.dl.v_a) { - LOGP(DRLCMACDL, LOGL_ERROR, "- MS acked all block " - "(including final block), but did not include " - "FINAL_ACK_INDICATION!\n"); + LOGP(DRLCMACDL, LOGL_ERROR, "- MS acked all block, " + "but we still transmitting!\n"); /* we just send final block again */ index = ((tbf->dir.dl.v_s - 1) & mod_sns_half); goto tx_block; @@ -1251,7 +1250,12 @@ int gprs_rlcmac_downlink_ack(struct gprs_rlcmac_tbf *tbf, uint8_t final, "X=Resend-Unacked\n", tbf->dir.dl.v_a, show_v_b, (tbf->dir.dl.v_s - 1) & mod_sns); - return 0; + if (tbf->state == GPRS_RLCMAC_FINISHED + && tbf->dir.dl.v_s == tbf->dir.dl.v_a) { + LOGP(DRLCMACDL, LOGL_NOTICE, "Received final block, " + "bit without final ack inidcation\n"); + } else + return 0; } LOGP(DRLCMACDL, LOGL_DEBUG, "- Final ACK received.\n"); -- cgit v1.2.3 From ee31b78cfd0945e92a8e11e1460e57886cd5b854 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Sun, 15 Jul 2012 16:27:01 +0200 Subject: Fixed contention resolution issue In order to do downlink assignment during uplink TBF, the content resolution must be completed. It is completed when the first Packet Uplink Ack/Nack message is transmitted to the mobile. --- src/gprs_rlcmac_data.cpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'src/gprs_rlcmac_data.cpp') diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp index 9b3a0953..76cc0332 100644 --- a/src/gprs_rlcmac_data.cpp +++ b/src/gprs_rlcmac_data.cpp @@ -218,7 +218,7 @@ uplink_request: break; } ul_tbf->tlli = tbf->tlli; - ul_tbf->tlli_valid = 1; /* no content resolution */ + ul_tbf->tlli_valid = 1; /* no contention resolution */ ul_tbf->ta = tbf->ta; /* use current TA */ tbf_new_state(ul_tbf, GPRS_RLCMAC_FLOW); tbf_timer_start(ul_tbf, 3169, bts->t3169, 0); @@ -550,6 +550,10 @@ struct msgb *gprs_rlcmac_send_uplink_ack(struct gprs_rlcmac_tbf *tbf, bitvec_free(ack_vec); free(mac_control_block); + /* now we must set this flag, so we are allowed to assign downlink + * TBF on PACCH. it is only allowed when TLLI is aknowledged. */ + tbf->contention_resolution_done = 1; + if (final) { tbf->poll_state = GPRS_RLCMAC_POLL_SCHED; tbf->poll_fn = (fn + 13) % 2715648; @@ -1143,6 +1147,8 @@ tx_block: "sheduled in this TS %d, waiting for " "TS %d\n", ts, tbf->control_ts); else { + LOGP(DRLCMAC, LOGL_DEBUG, "Polling sheduled in this " + "TS %d\n", ts); /* start timer whenever we send the final block */ if (rh->fbi == 1) tbf_timer_start(tbf, 3191, bts->t3191, 0); @@ -1308,9 +1314,17 @@ struct msgb *gprs_rlcmac_send_packet_downlink_assignment( #endif /* on uplink TBF we get the downlink TBF to be assigned. */ - if (tbf->direction == GPRS_RLCMAC_UL_TBF) + if (tbf->direction == GPRS_RLCMAC_UL_TBF) { + /* be sure to check first, if contention resolution is done, + * otherwise we cannot send the assignment yet */ + if (!tbf->contention_resolution_done) { + LOGP(DRLCMAC, LOGL_NOTICE, "Cannot assign DL TBF now, " + "because contention resolution is not " + "finished.\n"); + return NULL; + } new_tbf = tbf_by_tlli(tbf->tlli, GPRS_RLCMAC_DL_TBF); - else + } else new_tbf = tbf; if (!new_tbf) { LOGP(DRLCMACDL, LOGL_ERROR, "We have a schedule for downlink " -- cgit v1.2.3 From c8466f42c5c562da91e170e0942afd09e0cb4406 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Sun, 15 Jul 2012 19:34:53 +0200 Subject: Ignore Packet Resource Request --- src/gprs_rlcmac_data.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'src/gprs_rlcmac_data.cpp') diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp index 76cc0332..bb0b2272 100644 --- a/src/gprs_rlcmac_data.cpp +++ b/src/gprs_rlcmac_data.cpp @@ -124,6 +124,7 @@ int gprs_rlcmac_poll_timeout(struct gprs_rlcmac_tbf *tbf) int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint8_t trx, uint8_t ts, uint32_t fn) { + struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts; int8_t tfi = 0; /* must be signed */ uint32_t tlli = 0; struct gprs_rlcmac_tbf *tbf; @@ -197,7 +198,6 @@ int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint8_t trx, uint8_t ts, if (ul_control_block->u.Packet_Downlink_Ack_Nack.Exist_Channel_Request_Description) { uint8_t trx, ts; struct gprs_rlcmac_tbf *ul_tbf; - struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts; LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF in ack " "message, so we provide one:\n"); @@ -253,11 +253,7 @@ uplink_request: } tlli = tbf->tlli; } - LOGP(DRLCMAC, LOGL_INFO, "RX: [PCU <- BTS] %s TFI: %u TLLI: 0x%08x Packet ressource request\n", (tbf->direction == GPRS_RLCMAC_UL_TBF) ? "UL" : "DL", tbf->tfi, tbf->tlli); -#warning FIXME -puts("FIXME: UL request during UL request"); exit(0); - - + 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; default: LOGP(DRLCMAC, LOGL_NOTICE, "RX: [PCU <- BTS] unknown control block received\n"); -- cgit v1.2.3 From 67a19769741625827e3bac838233f3028c4c85cc Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Sun, 15 Jul 2012 19:35:46 +0200 Subject: No content resolution is required when UL TBF is requested during DL TBF --- src/gprs_rlcmac_data.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/gprs_rlcmac_data.cpp') diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp index bb0b2272..1b35d79f 100644 --- a/src/gprs_rlcmac_data.cpp +++ b/src/gprs_rlcmac_data.cpp @@ -219,6 +219,7 @@ uplink_request: } ul_tbf->tlli = tbf->tlli; ul_tbf->tlli_valid = 1; /* no contention resolution */ + ul_tbf->contention_resolution_done = 1; ul_tbf->ta = tbf->ta; /* use current TA */ tbf_new_state(ul_tbf, GPRS_RLCMAC_FLOW); tbf_timer_start(ul_tbf, 3169, bts->t3169, 0); -- cgit v1.2.3 From 67e4f2f1fdba2048082311cc08a36d4758427cd3 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Sun, 15 Jul 2012 19:36:49 +0200 Subject: If we already sent final Packet Uplink Ack/Nack, request DL TBF on PCH If network does not respond fast enough, the MS might already received final Packet Uplink Ack/Nack, so we need to assign new DL TBF on PCH. --- src/gprs_rlcmac_data.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/gprs_rlcmac_data.cpp') diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp index 1b35d79f..8e195b8c 100644 --- a/src/gprs_rlcmac_data.cpp +++ b/src/gprs_rlcmac_data.cpp @@ -1397,7 +1397,8 @@ void gprs_rlcmac_trigger_downlink_assignment(gprs_rlcmac_tbf *tbf, old_tbf = tbf_by_tlli(tbf->tlli, GPRS_RLCMAC_DL_TBF); else old_tbf = tbf_by_tlli(tbf->tlli, GPRS_RLCMAC_UL_TBF); - if (old_tbf) { + if (old_tbf && (old_tbf->state != GPRS_RLCMAC_FINISHED || + old_tbf->ul_ack_state != GPRS_RLCMAC_UL_ACK_WAIT_ACK)) { #ifdef DEBUG_DL_ASS_IDLE LOGP(DRLCMAC, LOGL_ERROR, "We must wait for current TBF to be " "released.\n"); -- cgit v1.2.3 From f54a89e8813b850f1c92d722db9dc0220c58b70b Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Mon, 16 Jul 2012 11:56:11 +0200 Subject: Change polling interval for Packet Downlink Ack/Nack This lowers the risk for stalling of transmit window. --- src/gprs_rlcmac_data.cpp | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) (limited to 'src/gprs_rlcmac_data.cpp') diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp index 8e195b8c..edb91992 100644 --- a/src/gprs_rlcmac_data.cpp +++ b/src/gprs_rlcmac_data.cpp @@ -22,8 +22,11 @@ #include #include -/* After receiving these framess, we send ack/nack. */ -#define ACK_AFTER_FRAMES 20 +/* After receiving these frames, we send ack/nack. */ +#define SEND_ACK_AFTER_FRAMES 20 + +/* After sending these frames, we poll for ack/nack. */ +#define POLL_ACK_AFTER_FRAMES 10 /* If acknowledgement to uplink/downlin assignmentshould be polled */ #define POLLING_ASSIGNMENT 0 @@ -717,9 +720,9 @@ int gprs_rlcmac_rcv_data_block_acknowledged(uint8_t trx, uint8_t ts, /* If TLLI is included or if we received half of the window, we send * an ack/nack */ if (rh->si || rh->ti || tbf->state == GPRS_RLCMAC_FINISHED - || (tbf->dir.ul.rx_counter % ACK_AFTER_FRAMES) == 0) { + || (tbf->dir.ul.rx_counter % SEND_ACK_AFTER_FRAMES) == 0) { if (rh->si) { - LOGP(DRLCMACUL, LOGL_DEBUG, "- Scheduling Ack/Nack, " + LOGP(DRLCMACUL, LOGL_NOTICE, "- Scheduling Ack/Nack, " "because MS is stalled.\n"); } if (rh->ti) { @@ -730,10 +733,10 @@ int gprs_rlcmac_rcv_data_block_acknowledged(uint8_t trx, uint8_t ts, LOGP(DRLCMACUL, LOGL_DEBUG, "- Scheduling Ack/Nack, " "because last block has CV==0.\n"); } - if ((tbf->dir.ul.rx_counter % ACK_AFTER_FRAMES) == 0) { + if ((tbf->dir.ul.rx_counter % SEND_ACK_AFTER_FRAMES) == 0) { LOGP(DRLCMACUL, LOGL_DEBUG, "- Scheduling Ack/Nack, " "because %d frames received.\n", - ACK_AFTER_FRAMES); + SEND_ACK_AFTER_FRAMES); } if (tbf->ul_ack_state == GPRS_RLCMAC_UL_ACK_NONE) { /* trigger sending at next RTS */ @@ -1092,8 +1095,8 @@ do_resend: "done.\n"); li->e = 1; /* we cannot extend */ rh->fbi = 1; /* we indicate final block */ - tbf->dir.dl.tx_counter = ACK_AFTER_FRAMES + 1; - /* + 1 indicates: force polling */ + tbf->dir.dl.tx_counter = POLL_ACK_AFTER_FRAMES + 1; + /* + 1 indicates: first final ack */ tbf_new_state(tbf, GPRS_RLCMAC_FINISHED); break; } @@ -1121,17 +1124,18 @@ tx_block: /* Clear Polling, if still set in history buffer */ rh->s_p = 0; - /* poll after ACK_AFTER_FRAMES frames, or when final block is tx. */ - if (tbf->dir.dl.tx_counter >= ACK_AFTER_FRAMES) { - if (tbf->dir.dl.tx_counter > ACK_AFTER_FRAMES) { - /* if rx_counter is ACK_AFTER_FRAMES + 1, this + /* poll after POLL_ACK_AFTER_FRAMES frames, or when final block is tx. + */ + if (tbf->dir.dl.tx_counter >= POLL_ACK_AFTER_FRAMES) { + if (tbf->dir.dl.tx_counter > POLL_ACK_AFTER_FRAMES) { + /* if rx_counter is POLL_ACK_AFTER_FRAMES + 1, this * indicates: poll caused by final ack. */ LOGP(DRLCMACDL, LOGL_DEBUG, "- Scheduling Ack/Nack " "polling, because final block sent.\n"); } else { LOGP(DRLCMACDL, LOGL_DEBUG, "- Scheduling Ack/Nack " "polling, because %d blocks sent.\n", - ACK_AFTER_FRAMES); + POLL_ACK_AFTER_FRAMES); } tbf->dir.dl.tx_counter = 0; /* scheduling not possible, because: */ -- cgit v1.2.3 From 0f13c4014785069022cedeee28cc4d865dcf0668 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Mon, 16 Jul 2012 11:59:23 +0200 Subject: Check for downlink sequence is out of range This may happen, if Packer Downlink Assignment was not received by MS, so old TBF with old sequence number is still alive. In this case we free TBF. --- src/gprs_rlcmac_data.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'src/gprs_rlcmac_data.cpp') diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp index edb91992..1264cec5 100644 --- a/src/gprs_rlcmac_data.cpp +++ b/src/gprs_rlcmac_data.cpp @@ -131,6 +131,7 @@ int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint8_t trx, uint8_t ts, int8_t tfi = 0; /* must be signed */ uint32_t tlli = 0; struct gprs_rlcmac_tbf *tbf; + int rc; RlcMacUplink_t * ul_control_block = (RlcMacUplink_t *)malloc(sizeof(RlcMacUplink_t)); LOGP(DRLCMAC, LOGL_DEBUG, "+++++++++++++++++++++++++ RX : Uplink Control Block +++++++++++++++++++++++++\n"); @@ -193,10 +194,14 @@ int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint8_t trx, uint8_t ts, 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; - gprs_rlcmac_downlink_ack(tbf, + 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) { uint8_t trx, ts; @@ -1228,8 +1233,15 @@ int gprs_rlcmac_downlink_ack(struct gprs_rlcmac_tbf *tbf, uint8_t final, } } } else { - LOGP(DRLCMACDL, LOGL_DEBUG, "- ack range is out of " - "V(A)..V(S) range\n"); + /* this might happpen, if the downlink assignment + * was not received by ms and the ack refers + * to previous TBF + * FIXME: we should implement polling for + * control ack!*/ + LOGP(DRLCMACDL, LOGL_NOTICE, "- ack range is out of " + "V(A)..V(S) range (DL TBF=%d) Free TFB!\n", + tbf->tfi); + return 1; /* indicate to free TBF */ } /* raise V(A), if possible */ -- cgit v1.2.3 From 4b470ffe07fb9906e68687809c5153102244d2b8 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Mon, 16 Jul 2012 12:02:40 +0200 Subject: Changed log levels, to indicate abnormal events --- src/gprs_rlcmac_data.cpp | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) (limited to 'src/gprs_rlcmac_data.cpp') diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp index 1264cec5..10bc0177 100644 --- a/src/gprs_rlcmac_data.cpp +++ b/src/gprs_rlcmac_data.cpp @@ -73,7 +73,7 @@ int gprs_rlcmac_poll_timeout(struct gprs_rlcmac_tbf *tbf) tbf->poll_state = GPRS_RLCMAC_POLL_NONE; if (tbf->ul_ack_state == GPRS_RLCMAC_UL_ACK_WAIT_ACK) { - LOGP(DRLCMAC, LOGL_DEBUG, "- Timeout for polling PACKET " + LOGP(DRLCMAC, LOGL_NOTICE, "- Timeout for polling PACKET " "CONTROL ACK for PACKET UPLINK ACK\n"); tbf->ul_ack_state = GPRS_RLCMAC_UL_ACK_NONE; if (tbf->state == GPRS_RLCMAC_FINISHED) { @@ -81,7 +81,8 @@ int gprs_rlcmac_poll_timeout(struct gprs_rlcmac_tbf *tbf) tbf->dir.ul.n3103++; if (tbf->dir.ul.n3103 == bts->n3103) { - LOGP(DRLCMAC, LOGL_DEBUG, "- N3103 exceeded\n"); + LOGP(DRLCMAC, LOGL_NOTICE, + "- N3103 exceeded\n"); tbf_new_state(tbf, GPRS_RLCMAC_RELEASING); tbf_timer_start(tbf, 3169, bts->t3169, 0); return 0; @@ -91,17 +92,17 @@ int gprs_rlcmac_poll_timeout(struct gprs_rlcmac_tbf *tbf) } } else if (tbf->ul_ass_state == GPRS_RLCMAC_UL_ASS_WAIT_ACK) { - LOGP(DRLCMAC, LOGL_DEBUG, "- Timeout for polling PACKET " + LOGP(DRLCMAC, LOGL_NOTICE, "- Timeout for polling PACKET " "CONTROL ACK for PACKET UPLINK ASSIGNMENT.\n"); tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_NONE; } else if (tbf->dl_ass_state == GPRS_RLCMAC_DL_ASS_WAIT_ACK) { - LOGP(DRLCMAC, LOGL_DEBUG, "- Timeout for polling PACKET " + LOGP(DRLCMAC, LOGL_NOTICE, "- Timeout for polling PACKET " "CONTROL ACK for PACKET DOWNLINK ASSIGNMENT.\n"); tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_NONE; /* in case out downlink assigment failed: */ if (tbf->state == GPRS_RLCMAC_ASSIGN) { - LOGP(DRLCMAC, LOGL_DEBUG, "- Assignment failed\n"); + LOGP(DRLCMAC, LOGL_NOTICE, "- Assignment failed\n"); tbf_free(tbf); } } else @@ -109,16 +110,17 @@ int gprs_rlcmac_poll_timeout(struct gprs_rlcmac_tbf *tbf) { struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts; - LOGP(DRLCMAC, LOGL_DEBUG, "- Timeout for polling PACKET " + LOGP(DRLCMAC, LOGL_NOTICE, "- Timeout for polling PACKET " " DOWNLINK ACK.\n"); tbf->dir.dl.n3105++; if (tbf->dir.dl.n3105 == bts->n3105) { - LOGP(DRLCMAC, LOGL_DEBUG, "- N3105 exceeded\n"); + LOGP(DRLCMAC, LOGL_NOTICE, "- N3105 exceeded\n"); tbf_new_state(tbf, GPRS_RLCMAC_RELEASING); tbf_timer_start(tbf, 3195, bts->t3195, 0); return 0; } - } + } else + LOGP(DRLCMAC, LOGL_ERROR, "- Poll Timeout, but no event!\n"); return 0; } @@ -916,7 +918,7 @@ do_resend: "because all blocks have been transmitted.\n", tbf->dir.dl.v_a); else - LOGP(DRLCMACDL, LOGL_DEBUG, "- Restarting at BSN %d, " + LOGP(DRLCMACDL, LOGL_NOTICE, "- Restarting at BSN %d, " "because all window is stalled.\n", tbf->dir.dl.v_a); /* If V(S) == V(A) and finished state, we would have received @@ -1207,8 +1209,8 @@ int gprs_rlcmac_downlink_ack(struct gprs_rlcmac_tbf *tbf, uint8_t final, } show_rbb[64] = '\0'; LOGP(DRLCMACDL, LOGL_DEBUG, "- ack: (BSN=%d)\"%s\"" - "(BSN=%d) 1=ACK o=NACK\n", ssn - 64, show_rbb, - ssn - 1); + "(BSN=%d) 1=ACK o=NACK\n", (ssn - 64) & mod_sns, + show_rbb, (ssn - 1) & mod_sns); /* apply received array to receive state (SSN-64..SSN-1) */ /* calculate distance of ssn from V(S) */ @@ -1272,12 +1274,11 @@ int gprs_rlcmac_downlink_ack(struct gprs_rlcmac_tbf *tbf, uint8_t final, if (tbf->state == GPRS_RLCMAC_FINISHED && tbf->dir.dl.v_s == tbf->dir.dl.v_a) { LOGP(DRLCMACDL, LOGL_NOTICE, "Received final block, " - "bit without final ack inidcation\n"); + "but without final ack inidcation\n"); } else return 0; - } - - LOGP(DRLCMACDL, LOGL_DEBUG, "- Final ACK received.\n"); + } else + LOGP(DRLCMACDL, LOGL_DEBUG, "- Final ACK received.\n"); /* check for LLC PDU in the LLC Queue */ msg = msgb_dequeue(&tbf->llc_queue); -- cgit v1.2.3 From 24131bf55bc010e8238b7b1bb2b761dae4137dee Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Sat, 21 Jul 2012 11:09:58 +0200 Subject: Add check of lifetime of LLC frame If lifetime expires of queued LLC frames, they are discarded. The number of discarded frames and the sum of their octets are reported to SGSN via LLC-DISCARDED message. The lifetime can be overridden via VTY. The value can be centi-seconds or "infinite". --- src/gprs_rlcmac_data.cpp | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) (limited to 'src/gprs_rlcmac_data.cpp') diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp index 10bc0177..2f67bd0a 100644 --- a/src/gprs_rlcmac_data.cpp +++ b/src/gprs_rlcmac_data.cpp @@ -22,6 +22,11 @@ #include #include +extern "C" { +int bssgp_tx_llc_discarded(struct bssgp_bvc_ctx *bctx, uint32_t tlli, + uint8_t num_frames, uint32_t num_octets); +} + /* After receiving these frames, we send ack/nack. */ #define SEND_ACK_AFTER_FRAMES 20 @@ -868,6 +873,44 @@ int gprs_rlcmac_rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta) * DL data block flow */ +static struct msgb *llc_dequeue(struct gprs_rlcmac_tbf *tbf) +{ + struct msgb *msg; + struct timeval *tv, tv_now; + uint32_t octets = 0, frames = 0; + + gettimeofday(&tv_now, NULL); + + while ((msg = msgb_dequeue(&tbf->llc_queue))) { + tv = (struct timeval *)msg->data; + msgb_pull(msg, sizeof(*tv)); + if (tv->tv_sec /* not infinite */ + && (tv_now.tv_sec > tv->tv_sec /* and secs expired */ + || (tv_now.tv_sec == tv->tv_sec /* .. or if secs equal .. */ + && tv_now.tv_usec > tv->tv_usec))) { /* .. usecs expired */ + LOGP(DRLCMACDL, LOGL_NOTICE, "Discarding LLC PDU of " + "DL TBF=%d, because lifetime limit reached\n", + tbf->tfi); + frames++; + octets += msg->len; + msgb_free(msg); + continue; + } + break; + } + + if (frames) { + if (frames > 0xff) + frames = 0xff; + if (octets > 0xffffff) + octets = 0xffffff; + bssgp_tx_llc_discarded(bctx, tbf->tlli, frames, octets); + } + + return msg; +} + + /* send DL data block * * The messages are fragmented and forwarded as data blocks. @@ -1083,7 +1126,7 @@ do_resend: /* reset LLC frame */ tbf->llc_index = tbf->llc_length = 0; /* dequeue next LLC frame, if any */ - msg = msgb_dequeue(&tbf->llc_queue); + msg = llc_dequeue(tbf); if (msg) { LOGP(DRLCMACDL, LOGL_INFO, "- Dequeue next LLC for " "TBF=%d (len=%d)\n", tbf->tfi, msg->len); @@ -1281,7 +1324,7 @@ int gprs_rlcmac_downlink_ack(struct gprs_rlcmac_tbf *tbf, uint8_t final, LOGP(DRLCMACDL, LOGL_DEBUG, "- Final ACK received.\n"); /* check for LLC PDU in the LLC Queue */ - msg = msgb_dequeue(&tbf->llc_queue); + msg = llc_dequeue(tbf); if (!msg) { struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts; -- cgit v1.2.3 From 642c7d3f5b3a199cf69b88d21056cbfffd748595 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Mon, 23 Jul 2012 17:58:55 +0200 Subject: Fix: We don't use timer to define when assignment is complete on PACCH Instead we use the event of sending assignment message. Then we set the TBF state to 'FLOW'. --- src/gprs_rlcmac_data.cpp | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) (limited to 'src/gprs_rlcmac_data.cpp') diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp index 2f67bd0a..4109161d 100644 --- a/src/gprs_rlcmac_data.cpp +++ b/src/gprs_rlcmac_data.cpp @@ -174,11 +174,31 @@ int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint8_t trx, uint8_t ts, 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); tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_NONE; + if (tbf->direction == GPRS_RLCMAC_UL_TBF) + tbf = 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); + 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); tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_NONE; + if (tbf->direction == GPRS_RLCMAC_DL_TBF) + tbf = 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); + tbf_assign_control_ts(tbf); break; } LOGP(DRLCMAC, LOGL_ERROR, "Error: received PACET CONTROL ACK " @@ -236,7 +256,7 @@ uplink_request: ul_tbf->tlli_valid = 1; /* no contention resolution */ ul_tbf->contention_resolution_done = 1; ul_tbf->ta = tbf->ta; /* use current TA */ - tbf_new_state(ul_tbf, GPRS_RLCMAC_FLOW); + tbf_new_state(ul_tbf, GPRS_RLCMAC_ASSIGN); tbf_timer_start(ul_tbf, 3169, bts->t3169, 0); /* schedule uplink assignment */ tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_SEND_ASS; @@ -821,6 +841,8 @@ struct msgb *gprs_rlcmac_send_packet_uplink_assignment( tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_WAIT_ACK; #else tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_NONE; + tbf_new_state(new_tbf, GPRS_RLCMAC_FLOW); + tbf_assign_control_ts(new_tbf); #endif return msg; @@ -1420,6 +1442,8 @@ struct msgb *gprs_rlcmac_send_packet_downlink_assignment( tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_WAIT_ACK; #else tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_NONE; + tbf_new_state(new_tbf, GPRS_RLCMAC_FLOW); + tbf_assign_control_ts(new_tbf); #endif return msg; @@ -1474,8 +1498,6 @@ void gprs_rlcmac_trigger_downlink_assignment(gprs_rlcmac_tbf *tbf, tbf->ta = old_tbf->ta; /* change state */ tbf_new_state(tbf, GPRS_RLCMAC_ASSIGN); - /* start timer */ - tbf_timer_start(tbf, 0, Tassign_pacch); #endif } else { LOGP(DRLCMAC, LOGL_DEBUG, "Send dowlink assignment for TBF=%d on PCH, no TBF exist (IMSI=%s)\n", tbf->tfi, imsi); -- cgit v1.2.3 From 7438df7d705fe34932da0b482bcf14cc67146094 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Mon, 23 Jul 2012 18:04:49 +0200 Subject: Fix: Send downlink assignment on PCH twice to make reception more safe If the mobile is not fast enough switching back to CCCH, the second assignment, which is sent later is usefull in this case. --- src/gprs_rlcmac_data.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/gprs_rlcmac_data.cpp') diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp index 4109161d..7610dcb6 100644 --- a/src/gprs_rlcmac_data.cpp +++ b/src/gprs_rlcmac_data.cpp @@ -1505,10 +1505,12 @@ void gprs_rlcmac_trigger_downlink_assignment(gprs_rlcmac_tbf *tbf, LOGP(DRLCMAC, LOGL_ERROR, "No valid IMSI!\n"); return; } - /* send immediate assignment */ - gprs_rlcmac_downlink_assignment(tbf, 0, imsi); /* change state */ tbf_new_state(tbf, GPRS_RLCMAC_ASSIGN); + /* send immediate assignment */ + gprs_rlcmac_downlink_assignment(tbf, 0, imsi); + /* send immediate assignment */ + gprs_rlcmac_downlink_assignment(tbf, 0, imsi); /* start timer */ tbf_timer_start(tbf, 0, Tassign_agch); } -- cgit v1.2.3 From bc65586917eed2ac5a6ac00551b4f35935d0426c Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Mon, 23 Jul 2012 18:13:31 +0200 Subject: Fix: Kill pending downlink TBF, if mobile requests uplink TBF on RACH If the mobile misses assignment, it changes back to idle mode. In this case we must kill the pending downlink TBF, because it is not used by mobile and we can assign a new downlink TBF for new downlink data. (We may not have two downlink TBF with same TLLI!) --- src/gprs_rlcmac_data.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/gprs_rlcmac_data.cpp') diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp index 7610dcb6..2a4c7b1a 100644 --- a/src/gprs_rlcmac_data.cpp +++ b/src/gprs_rlcmac_data.cpp @@ -644,6 +644,8 @@ int gprs_rlcmac_rcv_data_block_acknowledged(uint8_t trx, uint8_t ts, /* get TLLI */ if (!tbf->tlli_valid) { + struct gprs_rlcmac_tbf *dl_tbf; + /* no TLLI yet */ if (!rh->ti) { LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA TBF=%d without " @@ -659,6 +661,13 @@ int gprs_rlcmac_rcv_data_block_acknowledged(uint8_t trx, uint8_t ts, tbf->tlli_valid = 1; LOGP(DRLCMACUL, LOGL_INFO, "Decoded premier TLLI=0x%08x of " "UL DATA TBF=%d.\n", tbf->tlli, rh->tfi); + if ((dl_tbf = tbf_by_tlli(tbf->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", tbf->tlli, + dl_tbf->tfi); + tbf_free(dl_tbf); + } /* already have TLLI, but we stille get another one */ } else if (rh->ti) { uint32_t tlli; -- cgit v1.2.3 From 7f5352c17bf08cbeba44849978ee984832f3e510 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Mon, 23 Jul 2012 18:20:36 +0200 Subject: Fix: gprs_rlcmac_trigger_downlink_assignment() selects correct channel In order to select correct channel (PCH or PACCH), a tbf pointer is set in case of PACCH. The tbf pointer points to TBF whose PACCH is used. --- src/gprs_rlcmac_data.cpp | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) (limited to 'src/gprs_rlcmac_data.cpp') diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp index 2a4c7b1a..e2549d41 100644 --- a/src/gprs_rlcmac_data.cpp +++ b/src/gprs_rlcmac_data.cpp @@ -315,7 +315,7 @@ void tbf_timer_cb(void *_tbf) switch (tbf->T) { #ifdef DEBUG_DL_ASS_IDLE case 1234: - gprs_rlcmac_trigger_downlink_assignment(tbf, 0, debug_imsi); + gprs_rlcmac_trigger_downlink_assignment(tbf, NULL, debug_imsi); break; #endif case 0: /* assignment */ @@ -1380,7 +1380,7 @@ int gprs_rlcmac_downlink_ack(struct gprs_rlcmac_tbf *tbf, uint8_t final, "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); + gprs_rlcmac_trigger_downlink_assignment(tbf, tbf, NULL); return 0; } @@ -1406,7 +1406,7 @@ struct msgb *gprs_rlcmac_send_packet_downlink_assignment( /* be sure to check first, if contention resolution is done, * otherwise we cannot send the assignment yet */ if (!tbf->contention_resolution_done) { - LOGP(DRLCMAC, LOGL_NOTICE, "Cannot assign DL TBF now, " + LOGP(DRLCMAC, LOGL_DEBUG, "Cannot assign DL TBF now, " "because contention resolution is not " "finished.\n"); return NULL; @@ -1472,11 +1472,9 @@ static void gprs_rlcmac_downlink_assignment(gprs_rlcmac_tbf *tbf, uint8_t poll, } /* depending on the current TBF, we assign on PACCH or AGCH */ -void gprs_rlcmac_trigger_downlink_assignment(gprs_rlcmac_tbf *tbf, - uint8_t old_downlink, char *imsi) +void gprs_rlcmac_trigger_downlink_assignment(struct gprs_rlcmac_tbf *tbf, + struct gprs_rlcmac_tbf *old_tbf, char *imsi) { - gprs_rlcmac_tbf *old_tbf; - #ifdef DEBUG_DL_ASS_IDLE strncpy(debug_imsi, imsi); LOGP(DRLCMAC, LOGL_ERROR, "**** DEBUGGING DOWNLINK ASSIGNMENT ****\n"); @@ -1486,12 +1484,7 @@ void gprs_rlcmac_trigger_downlink_assignment(gprs_rlcmac_tbf *tbf, tbf_timer_stop(tbf); /* check for downlink tbf: */ - if (old_downlink) - old_tbf = tbf_by_tlli(tbf->tlli, GPRS_RLCMAC_DL_TBF); - else - old_tbf = tbf_by_tlli(tbf->tlli, GPRS_RLCMAC_UL_TBF); - if (old_tbf && (old_tbf->state != GPRS_RLCMAC_FINISHED || - old_tbf->ul_ack_state != GPRS_RLCMAC_UL_ACK_WAIT_ACK)) { + if (old_tbf) { #ifdef DEBUG_DL_ASS_IDLE LOGP(DRLCMAC, LOGL_ERROR, "We must wait for current TBF to be " "released.\n"); @@ -1500,8 +1493,8 @@ void gprs_rlcmac_trigger_downlink_assignment(gprs_rlcmac_tbf *tbf, #else LOGP(DRLCMAC, LOGL_DEBUG, "Send dowlink assignment on " "PACCH, because %s TBF=%d exists for TLLI=0x%08x\n", - (old_tbf->direction == GPRS_RLCMAC_UL_TBF) ? "UL" : "DL", - old_tbf->tfi, old_tbf->tlli); + (old_tbf->direction == GPRS_RLCMAC_UL_TBF) + ? "UL" : "DL", old_tbf->tfi, old_tbf->tlli); old_tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_SEND_ASS; /* use TA from old TBF */ tbf->ta = old_tbf->ta; -- cgit v1.2.3 From b3ded4cf98d0ad877f4dc541e938cd6126bc9e5d Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Tue, 24 Jul 2012 10:47:24 +0200 Subject: Added debugging of downlink bandwidth --- src/gprs_rlcmac_data.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'src/gprs_rlcmac_data.cpp') diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp index e2549d41..687a75da 100644 --- a/src/gprs_rlcmac_data.cpp +++ b/src/gprs_rlcmac_data.cpp @@ -941,6 +941,28 @@ static struct msgb *llc_dequeue(struct gprs_rlcmac_tbf *tbf) return msg; } +static int gprs_rlcmac_debug_bw(struct gprs_rlcmac_tbf *tbf, uint16_t octets) +{ + struct timeval now_tv, *bw_tv = &tbf->bw_tv; + uint32_t elapsed; + + tbf->bw_octets += octets; + + gettimeofday(&now_tv, NULL); + elapsed = ((now_tv.tv_sec - bw_tv->tv_sec) << 7) + + ((now_tv.tv_usec - bw_tv->tv_usec) << 7) / 1000000; + if (elapsed < 128) + return 0; + + LOGP(DRLCMACBW, LOGL_DEBUG, "DL Bandwitdh of TLLI=0x%08x: %d KBits/s\n", + tbf->tlli, tbf->bw_octets / elapsed); + + /* reset bandwidth values timestamp */ + memcpy(bw_tv, &now_tv, sizeof(struct timeval)); + tbf->bw_octets = 0; + + return 0; +} /* send DL data block * @@ -1095,6 +1117,7 @@ do_resend: LOGP(DRLCMACDL, LOGL_INFO, "Complete DL frame for " "TBF=%d that fits precisely in last block: " "len=%d\n", tbf->tfi, tbf->llc_length); + gprs_rlcmac_debug_bw(tbf, tbf->llc_length); /* block is filled, so there is no extension */ *e_pointer |= 0x01; /* fill space */ @@ -1154,6 +1177,7 @@ do_resend: space -= chunk; LOGP(DRLCMACDL, LOGL_INFO, "Complete DL frame for TBF=%d: " "len=%d\n", tbf->tfi, tbf->llc_length); + gprs_rlcmac_debug_bw(tbf, tbf->llc_length); /* reset LLC frame */ tbf->llc_index = tbf->llc_length = 0; /* dequeue next LLC frame, if any */ -- cgit v1.2.3 From 6681bb8d0c847ad59a1e6109689ec322884e8e27 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Wed, 25 Jul 2012 08:48:44 +0200 Subject: Replaced malloc() by talloc_zero() to be able to track memeory leaks --- src/gprs_rlcmac_data.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'src/gprs_rlcmac_data.cpp') diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp index 687a75da..58985e0d 100644 --- a/src/gprs_rlcmac_data.cpp +++ b/src/gprs_rlcmac_data.cpp @@ -22,6 +22,8 @@ #include #include +extern void *tall_pcu_ctx; + extern "C" { int bssgp_tx_llc_discarded(struct bssgp_bvc_ctx *bctx, uint32_t tlli, uint8_t num_frames, uint32_t num_octets); @@ -140,7 +142,7 @@ int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint8_t trx, uint8_t ts, struct gprs_rlcmac_tbf *tbf; int rc; - RlcMacUplink_t * ul_control_block = (RlcMacUplink_t *)malloc(sizeof(RlcMacUplink_t)); + 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"); @@ -294,7 +296,7 @@ uplink_request: default: LOGP(DRLCMAC, LOGL_NOTICE, "RX: [PCU <- BTS] unknown control block received\n"); } - free(ul_control_block); + talloc_free(ul_control_block); return 1; } @@ -575,12 +577,12 @@ struct msgb *gprs_rlcmac_send_uplink_ack(struct gprs_rlcmac_tbf *tbf, } bitvec_unhex(ack_vec, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b"); - RlcMacDownlink_t * mac_control_block = (RlcMacDownlink_t *)malloc(sizeof(RlcMacDownlink_t)); + RlcMacDownlink_t * mac_control_block = (RlcMacDownlink_t *)talloc_zero(tall_pcu_ctx, RlcMacDownlink_t); write_packet_uplink_ack(mac_control_block, tbf, final); encode_gsm_rlcmac_downlink(ack_vec, mac_control_block); bitvec_pack(ack_vec, msgb_put(msg, 23)); bitvec_free(ack_vec); - free(mac_control_block); + talloc_free(mac_control_block); /* now we must set this flag, so we are allowed to assign downlink * TBF on PACCH. it is only allowed when TLLI is aknowledged. */ @@ -836,12 +838,13 @@ struct msgb *gprs_rlcmac_send_packet_uplink_assignment( (tbf->direction == GPRS_RLCMAC_DL_TBF), 0, 0, new_tbf, POLLING_ASSIGNMENT); bitvec_pack(ass_vec, msgb_put(msg, 23)); - RlcMacDownlink_t * mac_control_block = (RlcMacDownlink_t *)malloc(sizeof(RlcMacDownlink_t)); + RlcMacDownlink_t * mac_control_block = (RlcMacDownlink_t *)talloc_zero(tall_pcu_ctx, RlcMacDownlink_t); LOGP(DRLCMAC, LOGL_DEBUG, "+++++++++++++++++++++++++ TX : Packet Uplink Assignment +++++++++++++++++++++++++\n"); decode_gsm_rlcmac_downlink(ass_vec, mac_control_block); LOGPC(DCSN1, LOGL_NOTICE, "\n"); LOGP(DRLCMAC, LOGL_DEBUG, "------------------------- TX : Packet Uplink Assignment -------------------------\n"); bitvec_free(ass_vec); + talloc_free(mac_control_block); #if POLLING_ASSIGNMENT == 1 FIXME process does not work, also the acknowledgement is not checked. @@ -1457,7 +1460,7 @@ struct msgb *gprs_rlcmac_send_packet_downlink_assignment( bitvec_unhex(ass_vec, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b"); LOGP(DRLCMAC, LOGL_INFO, "TBF: START TFI: %u TLLI: 0x%08x Packet Downlink Assignment (PACCH)\n", new_tbf->tfi, new_tbf->tlli); - RlcMacDownlink_t * mac_control_block = (RlcMacDownlink_t *)malloc(sizeof(RlcMacDownlink_t)); + RlcMacDownlink_t * mac_control_block = (RlcMacDownlink_t *)talloc_zero(tall_pcu_ctx, RlcMacDownlink_t); write_packet_downlink_assignment(mac_control_block, tbf->tfi, (tbf->direction == GPRS_RLCMAC_DL_TBF), new_tbf, POLLING_ASSIGNMENT); @@ -1467,7 +1470,7 @@ struct msgb *gprs_rlcmac_send_packet_downlink_assignment( LOGP(DRLCMAC, LOGL_DEBUG, "------------------------- TX : Packet Downlink Assignment -------------------------\n"); bitvec_pack(ass_vec, msgb_put(msg, 23)); bitvec_free(ass_vec); - free(mac_control_block); + talloc_free(mac_control_block); #if POLLING_ASSIGNMENT == 1 tbf->poll_state = GPRS_RLCMAC_POLL_SCHED; -- cgit v1.2.3 From 08e93cdc3fe54df7753170e973d119c6bbbb6181 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Thu, 26 Jul 2012 08:13:06 +0200 Subject: Use final_ack_sent and contention_resolution_done to define ongoing UL TBF Both flags can be used to determine wether assignment must be sent on PCH or on AGCH. Before contention resolution is done, mobile will ignore downlink assinment. When final uplink acknowledge was sent, the mobile will go back to PCH after reception of akcnowledge. --- src/gprs_rlcmac_data.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/gprs_rlcmac_data.cpp') diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp index 58985e0d..69cfe136 100644 --- a/src/gprs_rlcmac_data.cpp +++ b/src/gprs_rlcmac_data.cpp @@ -256,7 +256,7 @@ uplink_request: } ul_tbf->tlli = tbf->tlli; ul_tbf->tlli_valid = 1; /* no contention resolution */ - ul_tbf->contention_resolution_done = 1; + ul_tbf->dir.ul.contention_resolution_done = 1; ul_tbf->ta = tbf->ta; /* use current TA */ tbf_new_state(ul_tbf, GPRS_RLCMAC_ASSIGN); tbf_timer_start(ul_tbf, 3169, bts->t3169, 0); @@ -586,13 +586,14 @@ struct msgb *gprs_rlcmac_send_uplink_ack(struct gprs_rlcmac_tbf *tbf, /* now we must set this flag, so we are allowed to assign downlink * TBF on PACCH. it is only allowed when TLLI is aknowledged. */ - tbf->contention_resolution_done = 1; + tbf->dir.ul.contention_resolution_done = 1; if (final) { tbf->poll_state = GPRS_RLCMAC_POLL_SCHED; tbf->poll_fn = (fn + 13) % 2715648; /* waiting for final acknowledge */ tbf->ul_ack_state = GPRS_RLCMAC_UL_ACK_WAIT_ACK; + tbf->dir.ul.final_ack_sent = 1; } else tbf->ul_ack_state = GPRS_RLCMAC_UL_ACK_NONE; @@ -1432,7 +1433,7 @@ struct msgb *gprs_rlcmac_send_packet_downlink_assignment( if (tbf->direction == GPRS_RLCMAC_UL_TBF) { /* be sure to check first, if contention resolution is done, * otherwise we cannot send the assignment yet */ - if (!tbf->contention_resolution_done) { + if (!tbf->dir.ul.contention_resolution_done) { LOGP(DRLCMAC, LOGL_DEBUG, "Cannot assign DL TBF now, " "because contention resolution is not " "finished.\n"); -- cgit v1.2.3 From 802bb6eac834b8beffc5eb47a583842fb31d6e52 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Mon, 6 Aug 2012 11:15:05 +0200 Subject: Adding polling for packet control ack at packet downlink/uplink assignment --- src/gprs_rlcmac_data.cpp | 91 +++++++++++++++++++++++++++++++----------------- 1 file changed, 59 insertions(+), 32 deletions(-) (limited to 'src/gprs_rlcmac_data.cpp') diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp index 69cfe136..f56d848e 100644 --- a/src/gprs_rlcmac_data.cpp +++ b/src/gprs_rlcmac_data.cpp @@ -35,8 +35,9 @@ int bssgp_tx_llc_discarded(struct bssgp_bvc_ctx *bctx, uint32_t tlli, /* After sending these frames, we poll for ack/nack. */ #define POLL_ACK_AFTER_FRAMES 10 -/* If acknowledgement to uplink/downlin assignmentshould be polled */ -#define POLLING_ASSIGNMENT 0 +/* If acknowledgement to uplink/downlink assignmentshould be polled */ +#define POLLING_ASSIGNMENT_DL 1 +#define POLLING_ASSIGNMENT_UL 1 extern "C" { /* TS 04.60 10.2.2 */ @@ -99,28 +100,44 @@ int gprs_rlcmac_poll_timeout(struct gprs_rlcmac_tbf *tbf) } } else if (tbf->ul_ass_state == GPRS_RLCMAC_UL_ASS_WAIT_ACK) { + struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts; + LOGP(DRLCMAC, LOGL_NOTICE, "- Timeout for polling PACKET " "CONTROL ACK for PACKET UPLINK ASSIGNMENT.\n"); tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_NONE; + tbf->n3105++; + if (tbf->n3105 == bts->n3105) { + LOGP(DRLCMAC, LOGL_NOTICE, "- N3105 exceeded\n"); + tbf_new_state(tbf, GPRS_RLCMAC_RELEASING); + tbf_timer_start(tbf, 3195, bts->t3195, 0); + return 0; + } + /* reschedule UL assignment */ + tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_SEND_ASS; } else if (tbf->dl_ass_state == GPRS_RLCMAC_DL_ASS_WAIT_ACK) { + struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts; + LOGP(DRLCMAC, LOGL_NOTICE, "- Timeout for polling PACKET " "CONTROL ACK for PACKET DOWNLINK ASSIGNMENT.\n"); tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_NONE; - /* in case out downlink assigment failed: */ - if (tbf->state == GPRS_RLCMAC_ASSIGN) { - LOGP(DRLCMAC, LOGL_NOTICE, "- Assignment failed\n"); - tbf_free(tbf); + tbf->n3105++; + if (tbf->n3105 == bts->n3105) { + LOGP(DRLCMAC, LOGL_NOTICE, "- N3105 exceeded\n"); + tbf_new_state(tbf, GPRS_RLCMAC_RELEASING); + tbf_timer_start(tbf, 3195, bts->t3195, 0); + return 0; } + /* reschedule DL assignment */ + tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_SEND_ASS; } else - if (tbf->direction == GPRS_RLCMAC_DL_TBF) - { + if (tbf->direction == GPRS_RLCMAC_DL_TBF) { struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts; LOGP(DRLCMAC, LOGL_NOTICE, "- Timeout for polling PACKET " " DOWNLINK ACK.\n"); - tbf->dir.dl.n3105++; - if (tbf->dir.dl.n3105 == bts->n3105) { + tbf->n3105++; + if (tbf->n3105 == bts->n3105) { LOGP(DRLCMAC, LOGL_NOTICE, "- N3105 exceeded\n"); tbf_new_state(tbf, GPRS_RLCMAC_RELEASING); tbf_timer_start(tbf, 3195, bts->t3195, 0); @@ -175,6 +192,8 @@ int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint8_t trx, uint8_t ts, } 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; if (tbf->direction == GPRS_RLCMAC_UL_TBF) tbf = tbf_by_tlli(tbf->tlli, @@ -190,6 +209,8 @@ int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint8_t trx, uint8_t ts, } 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; if (tbf->direction == GPRS_RLCMAC_DL_TBF) tbf = tbf_by_tlli(tbf->tlli, @@ -216,7 +237,7 @@ int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint8_t trx, uint8_t ts, break; } /* reset N3105 */ - tbf->dir.dl.n3105 = 0; + tbf->n3105 = 0; /* stop timer T3191 */ tbf_timer_stop(tbf); tlli = tbf->tlli; @@ -801,7 +822,7 @@ struct msgb *gprs_rlcmac_send_packet_uplink_assignment( struct msgb *msg; struct gprs_rlcmac_tbf *new_tbf; -#if POLLING_ASSIGNMENT == 1 +#if POLLING_ASSIGNMENT_UL == 1 if (tbf->poll_state != GPRS_RLCMAC_POLL_NONE) { LOGP(DRLCMACUL, LOGL_DEBUG, "Polling is already " "sheduled for TBF=%d, so we must wait for uplink " @@ -837,7 +858,7 @@ struct msgb *gprs_rlcmac_send_packet_uplink_assignment( "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b"); write_packet_uplink_assignment(ass_vec, tbf->tfi, (tbf->direction == GPRS_RLCMAC_DL_TBF), 0, 0, new_tbf, - POLLING_ASSIGNMENT); + POLLING_ASSIGNMENT_UL); bitvec_pack(ass_vec, msgb_put(msg, 23)); RlcMacDownlink_t * mac_control_block = (RlcMacDownlink_t *)talloc_zero(tall_pcu_ctx, RlcMacDownlink_t); LOGP(DRLCMAC, LOGL_DEBUG, "+++++++++++++++++++++++++ TX : Packet Uplink Assignment +++++++++++++++++++++++++\n"); @@ -847,8 +868,7 @@ struct msgb *gprs_rlcmac_send_packet_uplink_assignment( bitvec_free(ass_vec); talloc_free(mac_control_block); -#if POLLING_ASSIGNMENT == 1 - FIXME process does not work, also the acknowledgement is not checked. +#if POLLING_ASSIGNMENT_UL == 1 tbf->poll_state = GPRS_RLCMAC_POLL_SCHED; tbf->poll_fn = (fn + 13) % 2715648; tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_WAIT_ACK; @@ -1419,15 +1439,22 @@ struct msgb *gprs_rlcmac_send_packet_downlink_assignment( { struct msgb *msg; struct gprs_rlcmac_tbf *new_tbf; + int poll_ass_dl = POLLING_ASSIGNMENT_DL; -#if POLLING_ASSIGNMENT == 1 - if (tbf->poll_state != GPRS_RLCMAC_POLL_NONE) { - LOGP(DRLCMAC, LOGL_DEBUG, "Polling is already " - "sheduled for TBF=%d, so we must wait for downlink " - "assignment...\n", tbf->tfi); - return NULL; + if (poll_ass_dl && tbf->direction == GPRS_RLCMAC_DL_TBF + && tbf->control_ts != tbf->first_common_ts) { + LOGP(DRLCMAC, LOGL_NOTICE, "Cannot poll for downlink " + "assigment, because MS cannot reply.\n"); + poll_ass_dl = 0; + } + if (poll_ass_dl) { + if (tbf->poll_state != GPRS_RLCMAC_POLL_NONE) { + LOGP(DRLCMAC, LOGL_DEBUG, "Polling is already sheduled " + "for TBF=%d, so we must wait for downlink " + "assignment...\n", tbf->tfi); + return NULL; + } } -#endif /* on uplink TBF we get the downlink TBF to be assigned. */ if (tbf->direction == GPRS_RLCMAC_UL_TBF) { @@ -1464,7 +1491,7 @@ struct msgb *gprs_rlcmac_send_packet_downlink_assignment( RlcMacDownlink_t * mac_control_block = (RlcMacDownlink_t *)talloc_zero(tall_pcu_ctx, RlcMacDownlink_t); write_packet_downlink_assignment(mac_control_block, tbf->tfi, (tbf->direction == GPRS_RLCMAC_DL_TBF), new_tbf, - POLLING_ASSIGNMENT); + poll_ass_dl); LOGP(DRLCMAC, LOGL_DEBUG, "+++++++++++++++++++++++++ TX : Packet Downlink Assignment +++++++++++++++++++++++++\n"); encode_gsm_rlcmac_downlink(ass_vec, mac_control_block); LOGPC(DCSN1, LOGL_NOTICE, "\n"); @@ -1473,15 +1500,15 @@ struct msgb *gprs_rlcmac_send_packet_downlink_assignment( bitvec_free(ass_vec); talloc_free(mac_control_block); -#if POLLING_ASSIGNMENT == 1 - tbf->poll_state = GPRS_RLCMAC_POLL_SCHED; - tbf->poll_fn = (fn + 13) % 2715648; - tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_WAIT_ACK; -#else - tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_NONE; - tbf_new_state(new_tbf, GPRS_RLCMAC_FLOW); - tbf_assign_control_ts(new_tbf); -#endif + if (poll_ass_dl) { + tbf->poll_state = GPRS_RLCMAC_POLL_SCHED; + tbf->poll_fn = (fn + 13) % 2715648; + tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_WAIT_ACK; + } else { + tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_NONE; + tbf_new_state(new_tbf, GPRS_RLCMAC_FLOW); + tbf_assign_control_ts(new_tbf); + } return msg; } -- cgit v1.2.3 From 14db19ed11d38f0d6f08bb1d6139b7b90f4fdc37 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Mon, 6 Aug 2012 15:03:03 +0200 Subject: Adding flags for debugging assignment and polling timeout --- src/gprs_rlcmac_data.cpp | 85 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 77 insertions(+), 8 deletions(-) (limited to 'src/gprs_rlcmac_data.cpp') diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp index f56d848e..d59153f7 100644 --- a/src/gprs_rlcmac_data.cpp +++ b/src/gprs_rlcmac_data.cpp @@ -73,6 +73,24 @@ struct rlc_li_field { } __attribute__ ((packed)); } +static int gprs_rlcmac_diag(struct gprs_rlcmac_tbf *tbf) +{ + if ((tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))) + LOGP(DRLCMAC, LOGL_NOTICE, "- Assignment was on CCCH\n"); + if ((tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH))) + LOGP(DRLCMAC, LOGL_NOTICE, "- Assignment was on PACCH\n"); + if ((tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_UL_DATA))) + LOGP(DRLCMAC, LOGL_NOTICE, "- Uplink data was received\n"); + else if (tbf->direction == GPRS_RLCMAC_UL_TBF) + LOGP(DRLCMAC, LOGL_NOTICE, "- No uplink data received yet\n"); + if ((tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_DL_ACK))) + LOGP(DRLCMAC, LOGL_NOTICE, "- Downlink ACK was received\n"); + else if (tbf->direction == GPRS_RLCMAC_DL_TBF) + LOGP(DRLCMAC, LOGL_NOTICE, "- No downlink ACK received yet\n"); + + return 0; +} + int gprs_rlcmac_poll_timeout(struct gprs_rlcmac_tbf *tbf) { LOGP(DRLCMAC, LOGL_NOTICE, "Poll timeout for %s TBF=%d\n", @@ -81,8 +99,12 @@ int gprs_rlcmac_poll_timeout(struct gprs_rlcmac_tbf *tbf) tbf->poll_state = GPRS_RLCMAC_POLL_NONE; if (tbf->ul_ack_state == GPRS_RLCMAC_UL_ACK_WAIT_ACK) { - LOGP(DRLCMAC, LOGL_NOTICE, "- Timeout for polling PACKET " - "CONTROL ACK for PACKET UPLINK ACK\n"); + if (!(tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_TO_UL_ACK))) { + LOGP(DRLCMAC, LOGL_NOTICE, "- Timeout for polling " + "PACKET CONTROL ACK for PACKET UPLINK ACK\n"); + gprs_rlcmac_diag(tbf); + tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_TO_UL_ACK); + } tbf->ul_ack_state = GPRS_RLCMAC_UL_ACK_NONE; if (tbf->state == GPRS_RLCMAC_FINISHED) { struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts; @@ -102,8 +124,13 @@ int gprs_rlcmac_poll_timeout(struct gprs_rlcmac_tbf *tbf) if (tbf->ul_ass_state == GPRS_RLCMAC_UL_ASS_WAIT_ACK) { struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts; - LOGP(DRLCMAC, LOGL_NOTICE, "- Timeout for polling PACKET " - "CONTROL ACK for PACKET UPLINK ASSIGNMENT.\n"); + if (!(tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_TO_UL_ASS))) { + LOGP(DRLCMAC, LOGL_NOTICE, "- Timeout for polling " + "PACKET CONTROL ACK for PACKET UPLINK " + "ASSIGNMENT.\n"); + gprs_rlcmac_diag(tbf); + tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_TO_UL_ASS); + } tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_NONE; tbf->n3105++; if (tbf->n3105 == bts->n3105) { @@ -118,8 +145,13 @@ int gprs_rlcmac_poll_timeout(struct gprs_rlcmac_tbf *tbf) if (tbf->dl_ass_state == GPRS_RLCMAC_DL_ASS_WAIT_ACK) { struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts; - LOGP(DRLCMAC, LOGL_NOTICE, "- Timeout for polling PACKET " - "CONTROL ACK for PACKET DOWNLINK ASSIGNMENT.\n"); + if (!(tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_TO_DL_ASS))) { + LOGP(DRLCMAC, LOGL_NOTICE, "- Timeout for polling " + "PACKET CONTROL ACK for PACKET DOWNLINK " + "ASSIGNMENT.\n"); + gprs_rlcmac_diag(tbf); + tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_TO_DL_ASS); + } tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_NONE; tbf->n3105++; if (tbf->n3105 == bts->n3105) { @@ -134,8 +166,12 @@ int gprs_rlcmac_poll_timeout(struct gprs_rlcmac_tbf *tbf) if (tbf->direction == GPRS_RLCMAC_DL_TBF) { struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts; - LOGP(DRLCMAC, LOGL_NOTICE, "- Timeout for polling PACKET " - " DOWNLINK ACK.\n"); + if (!(tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_TO_DL_ACK))) { + LOGP(DRLCMAC, LOGL_NOTICE, "- Timeout for polling " + "PACKET DOWNLINK ACK.\n"); + gprs_rlcmac_diag(tbf); + tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_TO_DL_ACK); + } tbf->n3105++; if (tbf->n3105 == bts->n3105) { LOGP(DRLCMAC, LOGL_NOTICE, "- N3105 exceeded\n"); @@ -187,6 +223,13 @@ int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint8_t trx, uint8_t ts, 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; + 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\n"); + } tbf_free(tbf); break; } @@ -204,6 +247,13 @@ int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint8_t trx, uint8_t ts, break; } tbf_new_state(tbf, GPRS_RLCMAC_FLOW); + 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\n"); + } tbf_assign_control_ts(tbf); break; } @@ -221,6 +271,13 @@ int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint8_t trx, uint8_t ts, 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\n"); + } tbf_assign_control_ts(tbf); break; } @@ -236,6 +293,11 @@ int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint8_t trx, uint8_t ts, fn, tfi, trx, ts); 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\n"); + } /* reset N3105 */ tbf->n3105 = 0; /* stop timer T3191 */ @@ -280,6 +342,7 @@ uplink_request: ul_tbf->dir.ul.contention_resolution_done = 1; ul_tbf->ta = tbf->ta; /* use current TA */ tbf_new_state(ul_tbf, GPRS_RLCMAC_ASSIGN); + ul_tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_PACCH); tbf_timer_start(ul_tbf, 3169, bts->t3169, 0); /* schedule uplink assignment */ tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_SEND_ASS; @@ -355,6 +418,7 @@ void tbf_timer_cb(void *_tbf) case 3195: LOGP(DRLCMAC, LOGL_NOTICE, "TBF T%d timeout during " "transsmission\n", tbf->T); + gprs_rlcmac_diag(tbf); /* fall through */ case 3193: LOGP(DRLCMAC, LOGL_DEBUG, "TBF will be freed due to timeout\n"); @@ -662,6 +726,7 @@ int gprs_rlcmac_rcv_data_block_acknowledged(uint8_t trx, uint8_t ts, rh->tfi); return 0; } + tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_UL_DATA); LOGP(DRLCMACUL, LOGL_DEBUG, "UL DATA TBF=%d received (V(Q)=%d .. " "V(R)=%d)\n", rh->tfi, tbf->dir.ul.v_q, tbf->dir.ul.v_r); @@ -910,6 +975,7 @@ int gprs_rlcmac_rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta) qta = 252; tbf->ta = qta >> 2; tbf_new_state(tbf, GPRS_RLCMAC_FLOW); + tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_CCCH); tbf_timer_start(tbf, 3169, bts->t3169, 0); LOGP(DRLCMAC, LOGL_DEBUG, "TBF: [UPLINK] START TFI: %u\n", tbf->tfi); LOGP(DRLCMAC, LOGL_DEBUG, "RX: [PCU <- BTS] TFI: %u RACH qbit-ta=%d ra=%d, Fn=%d (%d,%d,%d)\n", tbf->tfi, qta, ra, Fn, (Fn / (26 * 51)) % 32, Fn % 51, Fn % 26); @@ -1427,6 +1493,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->state_flags = 0; tbf_update(tbf); gprs_rlcmac_trigger_downlink_assignment(tbf, tbf, NULL); @@ -1555,6 +1622,7 @@ void gprs_rlcmac_trigger_downlink_assignment(struct gprs_rlcmac_tbf *tbf, tbf->ta = old_tbf->ta; /* change state */ tbf_new_state(tbf, GPRS_RLCMAC_ASSIGN); + tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_PACCH); #endif } else { LOGP(DRLCMAC, LOGL_DEBUG, "Send dowlink assignment for TBF=%d on PCH, no TBF exist (IMSI=%s)\n", tbf->tfi, imsi); @@ -1564,6 +1632,7 @@ void gprs_rlcmac_trigger_downlink_assignment(struct gprs_rlcmac_tbf *tbf, } /* change state */ tbf_new_state(tbf, GPRS_RLCMAC_ASSIGN); + tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_CCCH); /* send immediate assignment */ gprs_rlcmac_downlink_assignment(tbf, 0, imsi); /* send immediate assignment */ -- cgit v1.2.3 From cbcd124588abf91be129aee3f37505ca60706de9 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Tue, 7 Aug 2012 15:48:21 +0200 Subject: Fix: Add timer for downlink TBF in assignment state This is required, since the UL TBF which is used to assign downlink TBF may be freed due to timeouts. --- src/gprs_rlcmac_data.cpp | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) (limited to 'src/gprs_rlcmac_data.cpp') diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp index d59153f7..a1bed3c6 100644 --- a/src/gprs_rlcmac_data.cpp +++ b/src/gprs_rlcmac_data.cpp @@ -247,6 +247,8 @@ int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint8_t trx, uint8_t ts, 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 &= @@ -405,13 +407,24 @@ void tbf_timer_cb(void *_tbf) break; #endif case 0: /* assignment */ - /* change state to FLOW, so scheduler will start transmission */ - if (tbf->state == GPRS_RLCMAC_ASSIGN) { - tbf_new_state(tbf, GPRS_RLCMAC_FLOW); - tbf_assign_control_ts(tbf); - } else - LOGP(DRLCMAC, LOGL_ERROR, "Error: TBF is not in assign " - "state\n"); + if ((tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH))) { + if (tbf->state == GPRS_RLCMAC_ASSIGN) { + LOGP(DRLCMAC, LOGL_NOTICE, "Releasing due to " + "PACCH assignment timeout.\n"); + tbf_free(tbf); + } else + LOGP(DRLCMAC, LOGL_ERROR, "Error: TBF is not " + "in assign state\n"); + } + if ((tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))) { + /* change state to FLOW, so scheduler will start transmission */ + if (tbf->state == GPRS_RLCMAC_ASSIGN) { + tbf_new_state(tbf, GPRS_RLCMAC_FLOW); + tbf_assign_control_ts(tbf); + } else + LOGP(DRLCMAC, LOGL_ERROR, "Error: TBF is not " + "in assign state\n"); + } break; case 3169: case 3191: @@ -1575,6 +1588,9 @@ struct msgb *gprs_rlcmac_send_packet_downlink_assignment( tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_NONE; tbf_new_state(new_tbf, GPRS_RLCMAC_FLOW); tbf_assign_control_ts(new_tbf); + /* stop pending assignment timer */ + tbf_timer_stop(new_tbf); + } return msg; @@ -1623,6 +1639,8 @@ void gprs_rlcmac_trigger_downlink_assignment(struct gprs_rlcmac_tbf *tbf, /* change state */ tbf_new_state(tbf, GPRS_RLCMAC_ASSIGN); tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_PACCH); + /* start timer */ + tbf_timer_start(tbf, 0, Tassign_pacch); #endif } else { LOGP(DRLCMAC, LOGL_DEBUG, "Send dowlink assignment for TBF=%d on PCH, no TBF exist (IMSI=%s)\n", tbf->tfi, imsi); -- cgit v1.2.3 From 07e97cf8a551b05d7f5f3f9583b68b2eff0f1c23 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Tue, 7 Aug 2012 16:00:56 +0200 Subject: Adding single block allocation It is mandatory to support it because MS may request a single block. In this case the network must assign a single block. It is possible to force single block allocation for all uplink requests on RACH. (VTY option) --- src/gprs_rlcmac_data.cpp | 213 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 156 insertions(+), 57 deletions(-) (limited to 'src/gprs_rlcmac_data.cpp') diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp index a1bed3c6..98ce1b4b 100644 --- a/src/gprs_rlcmac_data.cpp +++ b/src/gprs_rlcmac_data.cpp @@ -185,11 +185,61 @@ int gprs_rlcmac_poll_timeout(struct gprs_rlcmac_tbf *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; +} + +static struct gprs_rlcmac_tbf *alloc_ul_tbf(int8_t use_trx, int8_t first_ts, + uint8_t ms_class, uint32_t tlli, uint8_t ta, + struct gprs_rlcmac_tbf *dl_tbf) +{ + struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts; + uint8_t trx, ts; + struct gprs_rlcmac_tbf *tbf; + uint8_t tfi; + + /* create new TBF, use sme TRX as DL TBF */ + tfi = tfi_alloc(GPRS_RLCMAC_UL_TBF, &trx, &ts, use_trx, first_ts); + if (tfi < 0) { + LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH ressource\n"); + /* FIXME: send reject */ + return NULL; + } + /* use multislot class of downlink TBF */ + tbf = tbf_alloc(dl_tbf, GPRS_RLCMAC_UL_TBF, tfi, trx, ts, ms_class, 0); + if (!tbf) { + LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH ressource\n"); + /* FIXME: send reject */ + return NULL; + } + tbf->tlli = tlli; + tbf->tlli_valid = 1; /* no contention resolution */ + tbf->dir.ul.contention_resolution_done = 1; + tbf->ta = ta; /* use current TA */ + tbf_new_state(tbf, GPRS_RLCMAC_ASSIGN); + tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_PACCH); + tbf_timer_start(tbf, 3169, bts->t3169, 0); + + return tbf; +} + + + /* Received Uplink RLC control block. */ int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint8_t trx, uint8_t ts, uint32_t fn) { - struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts; int8_t tfi = 0; /* must be signed */ uint32_t tlli = 0; struct gprs_rlcmac_tbf *tbf; @@ -318,34 +368,10 @@ int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint8_t trx, uint8_t ts, } /* check for channel request */ if (ul_control_block->u.Packet_Downlink_Ack_Nack.Exist_Channel_Request_Description) { - uint8_t trx, ts; - struct gprs_rlcmac_tbf *ul_tbf; - LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF in ack " "message, so we provide one:\n"); -uplink_request: - /* create new TBF, use sme TRX as DL TBF */ - tfi = tfi_alloc(GPRS_RLCMAC_UL_TBF, &trx, &ts, tbf->trx, tbf->first_ts); - if (tfi < 0) { - LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH ressource\n"); - /* FIXME: send reject */ - break; - } - /* use multislot class of downlink TBF */ - 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 */ - break; - } - ul_tbf->tlli = tbf->tlli; - ul_tbf->tlli_valid = 1; /* no contention resolution */ - ul_tbf->dir.ul.contention_resolution_done = 1; - ul_tbf->ta = tbf->ta; /* use current TA */ - tbf_new_state(ul_tbf, GPRS_RLCMAC_ASSIGN); - ul_tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_PACCH); - tbf_timer_start(ul_tbf, 3169, bts->t3169, 0); + + alloc_ul_tbf(tbf->trx, tbf->first_ts, tbf->ms_class, tbf->tlli, tbf->ta, tbf); /* schedule uplink assignment */ tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_SEND_ASS; } @@ -355,7 +381,23 @@ uplink_request: tlli = ul_control_block->u.Packet_Resource_Request.ID.u.TLLI; tbf = tbf_by_tlli(tlli, GPRS_RLCMAC_UL_TBF); if (!tbf) { - LOGP(DRLCMAC, LOGL_NOTICE, "PACKET RESSOURCE REQ unknown uplink TLLI=0x%08x\n", tlli); + uint8_t ms_class = 0; + LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF " + "in packet ressource request of single " + "block, so we provide one:\n"); + 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 = alloc_ul_tbf(trx, ts, ms_class, tlli, 0, NULL); +#warning FIXME TA!!! + 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; break; } tfi = tbf->tfi; @@ -658,11 +700,18 @@ struct msgb *gprs_rlcmac_send_uplink_ack(struct gprs_rlcmac_tbf *tbf, int final = (tbf->state == GPRS_RLCMAC_FINISHED); struct msgb *msg; - if (final && tbf->poll_state != GPRS_RLCMAC_POLL_NONE) { - LOGP(DRLCMACUL, LOGL_DEBUG, "Polling is already " - "sheduled for TBF=%d, so we must wait for final uplink " - "ack...\n", tbf->tfi); + if (final) { + if (tbf->poll_state != GPRS_RLCMAC_POLL_NONE) { + LOGP(DRLCMACUL, LOGL_DEBUG, "Polling is already " + "sheduled for TBF=%d, so we must wait for " + "final uplink ack...\n", tbf->tfi); return NULL; + } + if (sba_find(tbf->trx, tbf->control_ts, (fn + 13) % 2715648)) { + LOGP(DRLCMACUL, LOGL_DEBUG, "Polling is already " + "scheduled for single block allocation...\n"); + return NULL; + } } msg = msgb_alloc(23, "rlcmac_ul_ack"); @@ -907,6 +956,11 @@ struct msgb *gprs_rlcmac_send_packet_uplink_assignment( "assignment...\n", tbf->tfi); return NULL; } + if (sba_find(tbf->trx, tbf->control_ts, (fn + 13) % 2715648)) { + LOGP(DRLCMACUL, LOGL_DEBUG, "Polling is already scheduled for " + "single block allocation...\n"); + return NULL; + } #endif /* on down TBF we get the uplink TBF to be assigned. */ @@ -935,8 +989,8 @@ struct msgb *gprs_rlcmac_send_packet_uplink_assignment( bitvec_unhex(ass_vec, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b"); write_packet_uplink_assignment(ass_vec, tbf->tfi, - (tbf->direction == GPRS_RLCMAC_DL_TBF), 0, 0, new_tbf, - POLLING_ASSIGNMENT_UL); + (tbf->direction == GPRS_RLCMAC_DL_TBF), tbf->tlli, + tbf->tlli_valid, new_tbf, POLLING_ASSIGNMENT_UL); bitvec_pack(ass_vec, msgb_put(msg, 23)); RlcMacDownlink_t * mac_control_block = (RlcMacDownlink_t *)talloc_zero(tall_pcu_ctx, RlcMacDownlink_t); LOGP(DRLCMAC, LOGL_DEBUG, "+++++++++++++++++++++++++ TX : Packet Uplink Assignment +++++++++++++++++++++++++\n"); @@ -965,37 +1019,73 @@ int gprs_rlcmac_rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta) struct gprs_rlcmac_tbf *tbf; uint8_t trx, ts; int8_t tfi; /* must be signed */ + uint8_t sb = 0; + uint32_t sb_fn = 0; + int rc; + uint8_t plen; LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF on RACH, so we provide " "one:\n"); - // Create new TBF - tfi = tfi_alloc(GPRS_RLCMAC_UL_TBF, &trx, &ts, -1, -1); - if (tfi < 0) { - LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH ressource\n"); - /* FIXME: send reject */ - return -EBUSY; - } - /* set class to 0, since we don't know the multislot class yet */ - 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 */ - return -EBUSY; + if ((ra & 0xf8) == 0x70) { + LOGP(DRLCMAC, LOGL_DEBUG, "MS requests single block " + "allocation\n"); + sb = 1; + } else if (bts->force_two_phase) { + LOGP(DRLCMAC, LOGL_DEBUG, "MS requests single phase access, " + "but we force two phase access\n"); + sb = 1; } if (qta < 0) qta = 0; if (qta > 252) qta = 252; - tbf->ta = qta >> 2; - tbf_new_state(tbf, GPRS_RLCMAC_FLOW); - tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_CCCH); - tbf_timer_start(tbf, 3169, bts->t3169, 0); - LOGP(DRLCMAC, LOGL_DEBUG, "TBF: [UPLINK] START TFI: %u\n", tbf->tfi); - LOGP(DRLCMAC, LOGL_DEBUG, "RX: [PCU <- BTS] TFI: %u RACH qbit-ta=%d ra=%d, Fn=%d (%d,%d,%d)\n", tbf->tfi, qta, ra, Fn, (Fn / (26 * 51)) % 32, Fn % 51, Fn % 26); - LOGP(DRLCMAC, LOGL_INFO, "TX: START TFI: %u Immediate Assignment Uplink (AGCH)\n", tbf->tfi); + if (sb) { + rc = sba_alloc(&trx, &ts, &sb_fn, qta >> 2); + if (rc < 0) + return rc; + LOGP(DRLCMAC, LOGL_DEBUG, "RX: [PCU <- BTS] RACH qbit-ta=%d " + "ra=0x%02x, Fn=%d (%d,%d,%d)\n", qta, ra, Fn, + (Fn / (26 * 51)) % 32, Fn % 51, Fn % 26); + LOGP(DRLCMAC, LOGL_INFO, "TX: Immediate Assignment Uplink " + "(AGCH)\n"); + } else { + // Create new TBF + tfi = tfi_alloc(GPRS_RLCMAC_UL_TBF, &trx, &ts, -1, -1); + if (tfi < 0) { + LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH ressource\n"); + /* FIXME: send reject */ + return -EBUSY; + } + /* set class to 0, since we don't know the multislot class yet */ + 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 */ + return -EBUSY; + } + tbf->ta = qta >> 2; + tbf_new_state(tbf, GPRS_RLCMAC_FLOW); + tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_CCCH); + tbf_timer_start(tbf, 3169, bts->t3169, 0); + LOGP(DRLCMAC, LOGL_DEBUG, "TBF: [UPLINK] START TFI: %u\n", + tbf->tfi); + LOGP(DRLCMAC, LOGL_DEBUG, "RX: [PCU <- BTS] TFI: %u RACH " + "qbit-ta=%d ra=0x%02x, Fn=%d (%d,%d,%d)\n", tbf->tfi, + qta, ra, Fn, (Fn / (26 * 51)) % 32, Fn % 51, Fn % 26); + LOGP(DRLCMAC, LOGL_INFO, "TX: START TFI: %u Immediate " + "Assignment Uplink (AGCH)\n", tbf->tfi); + } bitvec *immediate_assignment = bitvec_alloc(22) /* without plen */; - bitvec_unhex(immediate_assignment, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b"); - int plen = write_immediate_assignment(immediate_assignment, 0, ra, Fn, tbf->ta, tbf->arfcn, tbf->first_ts, tbf->tsc, tbf->tfi, tbf->dir.ul.usf[tbf->first_ts], 0, 0, 0); + bitvec_unhex(immediate_assignment, + "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b"); + if (sb) + plen = write_immediate_assignment(immediate_assignment, 0, ra, + Fn, qta >> 2, bts->trx[trx].arfcn, ts, + bts->trx[trx].pdch[ts].tsc, 0, 0, 0, 0, sb_fn, 1); + else + plen = write_immediate_assignment(immediate_assignment, 0, ra, + Fn, tbf->ta, tbf->arfcn, tbf->first_ts, tbf->tsc, + tbf->tfi, tbf->dir.ul.usf[tbf->first_ts], 0, 0, 0, 0); pcu_l1if_tx_agch(immediate_assignment, plen); bitvec_free(immediate_assignment); @@ -1355,6 +1445,10 @@ tx_block: LOGP(DRLCMAC, LOGL_DEBUG, "Polling cannot be " "sheduled in this TS %d, waiting for " "TS %d\n", ts, tbf->control_ts); + else if (sba_find(tbf->trx, ts, (fn + 13) % 2715648)) + LOGP(DRLCMAC, LOGL_DEBUG, "Polling cannot be " + "sheduled, because single block alllocation " + "already exists\n"); else { LOGP(DRLCMAC, LOGL_DEBUG, "Polling sheduled in this " "TS %d\n", ts); @@ -1534,6 +1628,11 @@ struct msgb *gprs_rlcmac_send_packet_downlink_assignment( "assignment...\n", tbf->tfi); return NULL; } + if (sba_find(tbf->trx, tbf->control_ts, (fn + 13) % 2715648)) { + LOGP(DRLCMACUL, LOGL_DEBUG, "Polling is already " + "scheduled for single block allocation...\n"); + return NULL; + } } /* on uplink TBF we get the downlink TBF to be assigned. */ @@ -1604,7 +1703,7 @@ static void gprs_rlcmac_downlink_assignment(gprs_rlcmac_tbf *tbf, uint8_t poll, bitvec_unhex(immediate_assignment, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b"); /* use request reference that has maximum distance to current time, * so the assignment will not conflict with possible RACH requests. */ - int plen = write_immediate_assignment(immediate_assignment, 1, 125, (tbf->pdch[tbf->first_ts]->last_rts_fn + 21216) % 2715648, tbf->ta, tbf->arfcn, tbf->first_ts, tbf->tsc, tbf->tfi, 0, tbf->tlli, poll, tbf->poll_fn); + int plen = write_immediate_assignment(immediate_assignment, 1, 125, (tbf->pdch[tbf->first_ts]->last_rts_fn + 21216) % 2715648, tbf->ta, tbf->arfcn, tbf->first_ts, tbf->tsc, tbf->tfi, 0, tbf->tlli, poll, tbf->poll_fn, 0); pcu_l1if_tx_pch(immediate_assignment, plen, imsi); bitvec_free(immediate_assignment); } -- cgit v1.2.3 From adb2f185387fd2d6a40a8bdceb336132f8dd19ca Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Tue, 7 Aug 2012 17:06:08 +0200 Subject: Assign TFI to complete TRX, not just one TS This is required, since we may change slot allocation. In case of a change, we do not want to be unable to change, if the same TFI on one of the other slots is already in use by a different TBF (having same TFI, but on different slot). --- src/gprs_rlcmac_data.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/gprs_rlcmac_data.cpp') diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp index 98ce1b4b..265aed6a 100644 --- a/src/gprs_rlcmac_data.cpp +++ b/src/gprs_rlcmac_data.cpp @@ -404,14 +404,14 @@ int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint8_t trx, uint8_t ts, } 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(tfi, trx, ts, GPRS_RLCMAC_DL_TBF); + tbf = tbf_by_tfi(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(tfi, trx, ts, GPRS_RLCMAC_UL_TBF); + tbf = tbf_by_tfi(tfi, trx, GPRS_RLCMAC_UL_TBF); if (!tbf) { LOGP(DRLCMAC, LOGL_NOTICE, "PACKET RESSOURCE REQ unknown uplink TBF=%d\n", tlli); break; @@ -782,7 +782,7 @@ int gprs_rlcmac_rcv_data_block_acknowledged(uint8_t trx, uint8_t ts, } /* find TBF inst from given TFI */ - tbf = tbf_by_tfi(rh->tfi, trx, ts, GPRS_RLCMAC_UL_TBF); + tbf = tbf_by_tfi(rh->tfi, trx, GPRS_RLCMAC_UL_TBF); if (!tbf) { LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA unknown TBF=%d\n", rh->tfi); -- cgit v1.2.3 From df4d20e95bd7a065aa9d27b97ed9743e618496f1 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Mon, 24 Sep 2012 13:49:38 +0200 Subject: Fix: T3193 is now started with the correct value --- src/gprs_rlcmac_data.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/gprs_rlcmac_data.cpp') diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp index 265aed6a..8bb1df65 100644 --- a/src/gprs_rlcmac_data.cpp +++ b/src/gprs_rlcmac_data.cpp @@ -1585,7 +1585,7 @@ int gprs_rlcmac_downlink_ack(struct gprs_rlcmac_tbf *tbf, uint8_t final, "release.\n"); /* start T3193 */ tbf_timer_start(tbf, 3193, bts->t3193_msec / 1000, - bts->t3193_msec & 1000); + (bts->t3193_msec % 1000) * 1000); tbf_new_state(tbf, GPRS_RLCMAC_WAIT_RELEASE); return 0; -- cgit v1.2.3 From aafcbbb252dfff7a627ed45706c3b2f99f0729a5 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Thu, 27 Sep 2012 09:20:45 +0200 Subject: Set Alpha and Gamma at assingment messages for power control The initial power control value Alpha must be set in SI13. --- src/gprs_rlcmac_data.cpp | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'src/gprs_rlcmac_data.cpp') diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp index 8bb1df65..b6d50622 100644 --- a/src/gprs_rlcmac_data.cpp +++ b/src/gprs_rlcmac_data.cpp @@ -946,6 +946,7 @@ int gprs_rlcmac_rcv_data_block_acknowledged(uint8_t trx, uint8_t ts, struct msgb *gprs_rlcmac_send_packet_uplink_assignment( struct gprs_rlcmac_tbf *tbf, uint32_t fn) { + struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts; struct msgb *msg; struct gprs_rlcmac_tbf *new_tbf; @@ -990,7 +991,8 @@ struct msgb *gprs_rlcmac_send_packet_uplink_assignment( "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b"); write_packet_uplink_assignment(ass_vec, tbf->tfi, (tbf->direction == GPRS_RLCMAC_DL_TBF), tbf->tlli, - tbf->tlli_valid, new_tbf, POLLING_ASSIGNMENT_UL); + tbf->tlli_valid, new_tbf, POLLING_ASSIGNMENT_UL, bts->alpha, + bts->gamma); bitvec_pack(ass_vec, msgb_put(msg, 23)); RlcMacDownlink_t * mac_control_block = (RlcMacDownlink_t *)talloc_zero(tall_pcu_ctx, RlcMacDownlink_t); LOGP(DRLCMAC, LOGL_DEBUG, "+++++++++++++++++++++++++ TX : Packet Uplink Assignment +++++++++++++++++++++++++\n"); @@ -1081,11 +1083,13 @@ int gprs_rlcmac_rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta) if (sb) plen = write_immediate_assignment(immediate_assignment, 0, ra, Fn, qta >> 2, bts->trx[trx].arfcn, ts, - bts->trx[trx].pdch[ts].tsc, 0, 0, 0, 0, sb_fn, 1); + bts->trx[trx].pdch[ts].tsc, 0, 0, 0, 0, sb_fn, 1, + bts->alpha, bts->gamma); else plen = write_immediate_assignment(immediate_assignment, 0, ra, Fn, tbf->ta, tbf->arfcn, tbf->first_ts, tbf->tsc, - tbf->tfi, tbf->dir.ul.usf[tbf->first_ts], 0, 0, 0, 0); + tbf->tfi, tbf->dir.ul.usf[tbf->first_ts], 0, 0, 0, 0, + bts->alpha, bts->gamma); pcu_l1if_tx_agch(immediate_assignment, plen); bitvec_free(immediate_assignment); @@ -1611,6 +1615,7 @@ int gprs_rlcmac_downlink_ack(struct gprs_rlcmac_tbf *tbf, uint8_t final, struct msgb *gprs_rlcmac_send_packet_downlink_assignment( struct gprs_rlcmac_tbf *tbf, uint32_t fn) { + struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts; struct msgb *msg; struct gprs_rlcmac_tbf *new_tbf; int poll_ass_dl = POLLING_ASSIGNMENT_DL; @@ -1670,7 +1675,7 @@ struct msgb *gprs_rlcmac_send_packet_downlink_assignment( RlcMacDownlink_t * mac_control_block = (RlcMacDownlink_t *)talloc_zero(tall_pcu_ctx, RlcMacDownlink_t); write_packet_downlink_assignment(mac_control_block, tbf->tfi, (tbf->direction == GPRS_RLCMAC_DL_TBF), new_tbf, - poll_ass_dl); + poll_ass_dl, bts->alpha, bts->gamma); LOGP(DRLCMAC, LOGL_DEBUG, "+++++++++++++++++++++++++ TX : Packet Downlink Assignment +++++++++++++++++++++++++\n"); encode_gsm_rlcmac_downlink(ass_vec, mac_control_block); LOGPC(DCSN1, LOGL_NOTICE, "\n"); @@ -1698,12 +1703,18 @@ struct msgb *gprs_rlcmac_send_packet_downlink_assignment( static void gprs_rlcmac_downlink_assignment(gprs_rlcmac_tbf *tbf, uint8_t poll, char *imsi) { + struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts; + int plen; + LOGP(DRLCMAC, LOGL_INFO, "TX: START TFI: %u TLLI: 0x%08x Immediate Assignment Downlink (PCH)\n", tbf->tfi, tbf->tlli); bitvec *immediate_assignment = bitvec_alloc(22); /* without plen */ bitvec_unhex(immediate_assignment, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b"); /* use request reference that has maximum distance to current time, * so the assignment will not conflict with possible RACH requests. */ - int plen = write_immediate_assignment(immediate_assignment, 1, 125, (tbf->pdch[tbf->first_ts]->last_rts_fn + 21216) % 2715648, tbf->ta, tbf->arfcn, tbf->first_ts, tbf->tsc, tbf->tfi, 0, tbf->tlli, poll, tbf->poll_fn, 0); + plen = write_immediate_assignment(immediate_assignment, 1, 125, + (tbf->pdch[tbf->first_ts]->last_rts_fn + 21216) % 2715648, tbf->ta, + tbf->arfcn, tbf->first_ts, tbf->tsc, tbf->tfi, 0, tbf->tlli, poll, + tbf->poll_fn, 0, bts->alpha, bts->gamma); pcu_l1if_tx_pch(immediate_assignment, plen, imsi); bitvec_free(immediate_assignment); } -- cgit v1.2.3 From 99a107dbeef03b2e80aff82023cdfc5c10109b5b Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Thu, 27 Sep 2012 09:21:52 +0200 Subject: Free existing UL/DL TBF, if RACH has been received from MS In this case the mobile has lost existing flows, so it make sense to free them. The TFI(s) can be re-used immidiately, because they are not associated by MS anymore. --- src/gprs_rlcmac_data.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'src/gprs_rlcmac_data.cpp') diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp index b6d50622..dedf98a8 100644 --- a/src/gprs_rlcmac_data.cpp +++ b/src/gprs_rlcmac_data.cpp @@ -380,8 +380,25 @@ int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint8_t trx, uint8_t ts, if (ul_control_block->u.Packet_Resource_Request.ID.UnionType) { tlli = ul_control_block->u.Packet_Resource_Request.ID.u.TLLI; tbf = 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; + + if ((dl_tbf = 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"); -- cgit v1.2.3 From a9be1547b1b4459d64d92207da2a29e41fcb3ba2 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Thu, 27 Sep 2012 09:23:24 +0200 Subject: Use PCH confirm from BTS to start downlink packet flow Since we don't know when the IMM.ASS message is sent on it's paging group on PCH, we will wait for confirm from BTS and start packet flow then. --- src/gprs_rlcmac_data.cpp | 67 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 7 deletions(-) (limited to 'src/gprs_rlcmac_data.cpp') diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp index dedf98a8..66d29c6d 100644 --- a/src/gprs_rlcmac_data.cpp +++ b/src/gprs_rlcmac_data.cpp @@ -73,6 +73,9 @@ struct rlc_li_field { } __attribute__ ((packed)); } +static void gprs_rlcmac_downlink_assignment(gprs_rlcmac_tbf *tbf, uint8_t poll, + char *imsi); + static int gprs_rlcmac_diag(struct gprs_rlcmac_tbf *tbf) { if ((tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))) @@ -179,6 +182,16 @@ int gprs_rlcmac_poll_timeout(struct gprs_rlcmac_tbf *tbf) tbf_timer_start(tbf, 3195, bts->t3195, 0); return 0; } + /* resend IMM.ASS on CCCH on timeout */ + if ((tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)) + && !(tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_DL_ACK))) { + LOGP(DRLCMAC, LOGL_DEBUG, "Re-send dowlink assignment " + "for TBF=%d on PCH (IMSI=%s)\n", tbf->tfi, + tbf->dir.dl.imsi); + /* send immediate assignment */ + gprs_rlcmac_downlink_assignment(tbf, 0, tbf->dir.dl.imsi); + tbf->dir.dl.wait_confirm = 1; + } } else LOGP(DRLCMAC, LOGL_ERROR, "- Poll Timeout, but no event!\n"); @@ -477,12 +490,13 @@ void tbf_timer_cb(void *_tbf) } if ((tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))) { /* change state to FLOW, so scheduler will start transmission */ + tbf->dir.dl.wait_confirm = 0; if (tbf->state == GPRS_RLCMAC_ASSIGN) { tbf_new_state(tbf, GPRS_RLCMAC_FLOW); tbf_assign_control_ts(tbf); } else - LOGP(DRLCMAC, LOGL_ERROR, "Error: TBF is not " - "in assign state\n"); + LOGP(DRLCMAC, LOGL_NOTICE, "Continue flow after " + "IMM.ASS confirm\n"); } break; case 3169: @@ -1621,7 +1635,8 @@ 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->state_flags = 0; + tbf->state_flags &= GPRS_RLCMAC_FLAG_TO_MASK; /* keep TO flags */ + tbf->state_flags &= ~(1 << GPRS_RLCMAC_FLAG_CCCH); tbf_update(tbf); gprs_rlcmac_trigger_downlink_assignment(tbf, tbf, NULL); @@ -1778,12 +1793,50 @@ void gprs_rlcmac_trigger_downlink_assignment(struct gprs_rlcmac_tbf *tbf, /* change state */ tbf_new_state(tbf, GPRS_RLCMAC_ASSIGN); tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_CCCH); + strncpy(tbf->dir.dl.imsi, imsi, sizeof(tbf->dir.dl.imsi)); /* send immediate assignment */ gprs_rlcmac_downlink_assignment(tbf, 0, imsi); - /* send immediate assignment */ - gprs_rlcmac_downlink_assignment(tbf, 0, imsi); - /* start timer */ + tbf->dir.dl.wait_confirm = 1; + } +} + +int gprs_rlcmac_imm_ass_cnf(uint8_t *data, uint32_t fn) +{ + struct gprs_rlcmac_tbf *tbf; + uint8_t plen; + uint32_t tlli; + + /* move to IA Rest Octets */ + plen = data[0] >> 2; + data += 1 + plen; + + if ((*data & 0xf0) != 0xd0) { + LOGP(DRLCMAC, LOGL_ERROR, "Got IMM.ASS confirm, but rest " + "octets do not start with bit sequence 'HH01' " + "(Packet Downlink Assignment)\n"); + return -EINVAL; + } + + /* get TLLI from downlink assignment */ + tlli = (*data++) << 28; + tlli |= (*data++) << 20; + tlli |= (*data++) << 12; + tlli |= (*data++) << 4; + tlli |= (*data++) >> 4; + + tbf = tbf_by_tlli(tlli, GPRS_RLCMAC_DL_TBF); + if (!tbf) { + LOGP(DRLCMAC, LOGL_ERROR, "Got IMM.ASS confirm, but TLLI=%08x " + "does not exit\n", tlli); + return -EINVAL; + } + + LOGP(DRLCMAC, LOGL_DEBUG, "Got IMM.ASS confirm for TLLI=%08x\n", tlli); + + if (tbf->dir.dl.wait_confirm) { tbf_timer_start(tbf, 0, Tassign_agch); } - } + + return 0; +} -- cgit v1.2.3 From 5f14bd941074b978ff92594544a9b62f9c366984 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Wed, 3 Oct 2012 14:20:26 +0200 Subject: Fix: Poll correctly for downlink acknowlege, to prevent window stalling --- src/gprs_rlcmac_data.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'src/gprs_rlcmac_data.cpp') diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp index 66d29c6d..147054e0 100644 --- a/src/gprs_rlcmac_data.cpp +++ b/src/gprs_rlcmac_data.cpp @@ -33,7 +33,7 @@ int bssgp_tx_llc_discarded(struct bssgp_bvc_ctx *bctx, uint32_t tlli, #define SEND_ACK_AFTER_FRAMES 20 /* After sending these frames, we poll for ack/nack. */ -#define POLL_ACK_AFTER_FRAMES 10 +#define POLL_ACK_AFTER_FRAMES 20 /* If acknowledgement to uplink/downlink assignmentshould be polled */ #define POLLING_ASSIGNMENT_DL 1 @@ -1212,6 +1212,7 @@ struct msgb *gprs_rlcmac_send_data_block_acknowledged( uint8_t *delimiter, *data, *e_pointer; uint8_t len; uint16_t space, chunk; + int first_fin_ack; LOGP(DRLCMACDL, LOGL_DEBUG, "DL DATA TBF=%d downlink (V(A)==%d .. " "V(S)==%d)\n", tbf->tfi, tbf->dir.dl.v_a, tbf->dir.dl.v_s); @@ -1428,7 +1429,7 @@ do_resend: "done.\n"); li->e = 1; /* we cannot extend */ rh->fbi = 1; /* we indicate final block */ - tbf->dir.dl.tx_counter = POLL_ACK_AFTER_FRAMES + 1; + first_fin_ack = 1; /* + 1 indicates: first final ack */ tbf_new_state(tbf, GPRS_RLCMAC_FINISHED); break; @@ -1459,18 +1460,15 @@ tx_block: /* poll after POLL_ACK_AFTER_FRAMES frames, or when final block is tx. */ - if (tbf->dir.dl.tx_counter >= POLL_ACK_AFTER_FRAMES) { - if (tbf->dir.dl.tx_counter > POLL_ACK_AFTER_FRAMES) { - /* if rx_counter is POLL_ACK_AFTER_FRAMES + 1, this - * indicates: poll caused by final ack. */ + if (tbf->dir.dl.tx_counter >= POLL_ACK_AFTER_FRAMES || first_fin_ack) { + if (first_fin_ack) { LOGP(DRLCMACDL, LOGL_DEBUG, "- Scheduling Ack/Nack " - "polling, because final block sent.\n"); + "polling, because first final block sent.\n"); } else { LOGP(DRLCMACDL, LOGL_DEBUG, "- Scheduling Ack/Nack " "polling, because %d blocks sent.\n", POLL_ACK_AFTER_FRAMES); } - tbf->dir.dl.tx_counter = 0; /* scheduling not possible, because: */ if (tbf->poll_state != GPRS_RLCMAC_POLL_NONE) LOGP(DRLCMAC, LOGL_DEBUG, "Polling is already " @@ -1487,6 +1485,7 @@ tx_block: else { LOGP(DRLCMAC, LOGL_DEBUG, "Polling sheduled in this " "TS %d\n", ts); + tbf->dir.dl.tx_counter = 0; /* start timer whenever we send the final block */ if (rh->fbi == 1) tbf_timer_start(tbf, 3191, bts->t3191, 0); -- cgit v1.2.3 From 3b1332cdb4a2b9e61ca71386072e915e6f5d30ba Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Wed, 3 Oct 2012 14:20:53 +0200 Subject: Replace switch/case construct by a structure, to define coding schemes A new attribute at TBF instance indicates the current scheme used. --- src/gprs_rlcmac_data.cpp | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) (limited to 'src/gprs_rlcmac_data.cpp') diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp index 147054e0..2d03ac59 100644 --- a/src/gprs_rlcmac_data.cpp +++ b/src/gprs_rlcmac_data.cpp @@ -1289,23 +1289,13 @@ do_resend: /* now we still have untransmitted LLC data, so we fill mac block */ index = tbf->dir.dl.v_s & mod_sns_half; data = tbf->rlc_block[index]; - switch (bts->initial_cs) { - case 2: /* CS-2 */ - block_length = 34; - block_data = 33; - break; - case 3: /* CS-3 */ - block_length = 40; - block_data = 39; - break; - case 4: /* CS-4 */ - block_length = 54; - block_data = 53; - break; - default: /* CS-1 */ - block_length = 23; - block_data = 23; + if (tbf->cs == 0) { + tbf->cs = bts->initial_cs; + if (tbf->cs < 1 || tbf->cs > 4) + tbf->cs = 1; } + block_length = gprs_rlcmac_cs[tbf->cs].block_length; + block_data = gprs_rlcmac_cs[tbf->cs].block_data; memset(data, 0x2b, block_data); /* spare bits will be left 0 */ rh = (struct rlc_dl_header *)data; rh->pt = 0; /* Data Block */ -- cgit v1.2.3 From 499ff415a92909d125499d70ba8288bbc6ed8f60 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Wed, 3 Oct 2012 14:21:36 +0200 Subject: Allow setting of seperate coding schemes for uplink and downlink --- src/gprs_rlcmac_data.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/gprs_rlcmac_data.cpp') diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp index 2d03ac59..7b0d83f7 100644 --- a/src/gprs_rlcmac_data.cpp +++ b/src/gprs_rlcmac_data.cpp @@ -1290,7 +1290,7 @@ do_resend: index = tbf->dir.dl.v_s & mod_sns_half; data = tbf->rlc_block[index]; if (tbf->cs == 0) { - tbf->cs = bts->initial_cs; + tbf->cs = bts->initial_cs_dl; if (tbf->cs < 1 || tbf->cs > 4) tbf->cs = 1; } -- cgit v1.2.3