diff options
author | Andreas Eversberg <jolly@eversberg.eu> | 2012-08-07 16:00:56 +0200 |
---|---|---|
committer | Andreas Eversberg <jolly@eversberg.eu> | 2012-08-07 16:00:56 +0200 |
commit | 07e97cf8a551b05d7f5f3f9583b68b2eff0f1c23 (patch) | |
tree | 2e5663d0d7d23aa4153b079894f20b94515fbd7c /src/gprs_rlcmac.cpp | |
parent | cbcd124588abf91be129aee3f37505ca60706de9 (diff) |
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)
Diffstat (limited to 'src/gprs_rlcmac.cpp')
-rw-r--r-- | src/gprs_rlcmac.cpp | 117 |
1 files changed, 95 insertions, 22 deletions
diff --git a/src/gprs_rlcmac.cpp b/src/gprs_rlcmac.cpp index 956d52fc..1aeb9b18 100644 --- a/src/gprs_rlcmac.cpp +++ b/src/gprs_rlcmac.cpp @@ -879,6 +879,67 @@ void tbf_timer_stop(struct gprs_rlcmac_tbf *tbf) } } +/* starting time for assigning single slot + * This offset must be a multiple of 13. */ +#define AGCH_START_OFFSET 52 + +LLIST_HEAD(gprs_rlcmac_sbas); + +int sba_alloc(uint8_t *_trx, uint8_t *_ts, uint32_t *_fn, uint8_t ta) +{ + + struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts; + struct gprs_rlcmac_pdch *pdch; + struct gprs_rlcmac_sba *sba; + uint8_t trx, ts; + uint32_t fn; + + sba = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_sba); + if (!sba) + return -ENOMEM; + + for (trx = 0; trx < 8; trx++) { + for (ts = 0; ts < 8; ts++) { + pdch = &bts->trx[trx].pdch[ts]; + if (!pdch->enable) + continue; + break; + } + if (ts < 8) + break; + } + if (trx == 8) { + LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH available.\n"); + return -EINVAL; + } + + fn = (pdch->last_rts_fn + AGCH_START_OFFSET) % 2715648; + + sba->trx = trx; + sba->ts = ts; + sba->fn = fn; + sba->ta = ta; + + llist_add(&sba->list, &gprs_rlcmac_sbas); + + *_trx = trx; + *_ts = ts; + *_fn = fn; + return 0; +} + +struct gprs_rlcmac_sba *sba_find(uint8_t trx, uint8_t ts, uint32_t fn) +{ + struct gprs_rlcmac_sba *sba; + + llist_for_each_entry(sba, &gprs_rlcmac_sbas, list) { + if (sba->trx == trx && sba->ts == ts && sba->fn == fn) + return sba; + } + + return NULL; +} + #if 0 static void tbf_gsm_timer_cb(void *_tbf) { @@ -1129,9 +1190,9 @@ struct msgb *gprs_rlcmac_send_packet_paging_request( // GSM 04.08 9.1.18 Immediate assignment int write_immediate_assignment(bitvec * dest, uint8_t downlink, uint8_t ra, - uint32_t fn, uint8_t ta, uint16_t arfcn, uint8_t ts, uint8_t tsc, + uint32_t ref_fn, uint8_t ta, uint16_t arfcn, uint8_t ts, uint8_t tsc, uint8_t tfi, uint8_t usf, uint32_t tlli, - uint8_t polling, uint32_t poll_fn) + uint8_t polling, uint32_t fn, uint8_t single_block) { unsigned wp = 0; uint8_t plen; @@ -1157,9 +1218,9 @@ int write_immediate_assignment(bitvec * dest, uint8_t downlink, uint8_t ra, //10.5.2.30 Request Reference bitvec_write_field(dest, wp,ra,8); // RA - bitvec_write_field(dest, wp,(fn / (26 * 51)) % 32,5); // T1' - bitvec_write_field(dest, wp,fn % 51,6); // T3 - bitvec_write_field(dest, wp,fn % 26,5); // T2 + bitvec_write_field(dest, wp,(ref_fn / (26 * 51)) % 32,5); // T1' + bitvec_write_field(dest, wp,ref_fn % 51,6); // T3 + bitvec_write_field(dest, wp,ref_fn % 26,5); // T2 // 10.5.2.40 Timing Advance bitvec_write_field(dest, wp,0x0,2); // spare @@ -1193,9 +1254,9 @@ int write_immediate_assignment(bitvec * dest, uint8_t downlink, uint8_t ra, bitvec_write_field(dest, wp,0x0,4); // TIMING_ADVANCE_INDEX if (polling) { bitvec_write_field(dest, wp,0x1,1); // TBF Starting TIME present - bitvec_write_field(dest, wp,(poll_fn / (26 * 51)) % 32,5); // T1' - bitvec_write_field(dest, wp,poll_fn % 51,6); // T3 - bitvec_write_field(dest, wp,poll_fn % 26,5); // T2 + bitvec_write_field(dest, wp,(fn / (26 * 51)) % 32,5); // T1' + bitvec_write_field(dest, wp,fn % 51,6); // T3 + bitvec_write_field(dest, wp,fn % 26,5); // T2 } else { bitvec_write_field(dest, wp,0x0,1); // TBF Starting TIME present } @@ -1209,20 +1270,32 @@ int write_immediate_assignment(bitvec * dest, uint8_t downlink, uint8_t ra, // GMS 04.08 10.5.2.37b 10.5.2.16 bitvec_write_field(dest, wp, 3, 2); // "HH" bitvec_write_field(dest, wp, 0, 2); // "0" Packet Uplink Assignment - bitvec_write_field(dest, wp, 1, 1); // Block Allocation : Not Single Block Allocation - bitvec_write_field(dest, wp, tfi, 5); // TFI_ASSIGNMENT Temporary Flow Identity - bitvec_write_field(dest, wp, 0, 1); // POLLING - bitvec_write_field(dest, wp, 0, 1); // ALLOCATION_TYPE: dynamic - bitvec_write_field(dest, wp, usf, 3); // USF - bitvec_write_field(dest, wp, 0, 1); // USF_GRANULARITY - bitvec_write_field(dest, wp, 0 , 1); // "0" power control: Not Present - bitvec_write_field(dest, wp, bts->initial_cs-1, 2); // CHANNEL_CODING_COMMAND - bitvec_write_field(dest, wp, 1, 1); // TLLI_BLOCK_CHANNEL_CODING - bitvec_write_field(dest, wp, 1 , 1); // "1" Alpha : Present - bitvec_write_field(dest, wp, 0, 4); // Alpha - bitvec_write_field(dest, wp, 0, 5); // Gamma - bitvec_write_field(dest, wp, 0, 1); // TIMING_ADVANCE_INDEX_FLAG - bitvec_write_field(dest, wp, 0, 1); // TBF_STARTING_TIME_FLAG + if (single_block) { + bitvec_write_field(dest, wp, 0, 1); // Block Allocation : Single Block Allocation + bitvec_write_field(dest, wp, 1, 1); // "1" Alpha : Present + bitvec_write_field(dest, wp, 0, 4); // Alpha + bitvec_write_field(dest, wp, 0, 5); // Gamma + bitvec_write_field(dest, wp, 0, 1); // TIMING_ADVANCE_INDEX_FLAG + bitvec_write_field(dest, wp, 1, 1); // TBF_STARTING_TIME_FLAG + bitvec_write_field(dest, wp,(fn / (26 * 51)) % 32,5); // T1' + bitvec_write_field(dest, wp,fn % 51,6); // T3 + bitvec_write_field(dest, wp,fn % 26,5); // T2 + } else { + bitvec_write_field(dest, wp, 1, 1); // Block Allocation : Not Single Block Allocation + bitvec_write_field(dest, wp, tfi, 5); // TFI_ASSIGNMENT Temporary Flow Identity + bitvec_write_field(dest, wp, 0, 1); // POLLING + bitvec_write_field(dest, wp, 0, 1); // ALLOCATION_TYPE: dynamic + bitvec_write_field(dest, wp, usf, 3); // USF + bitvec_write_field(dest, wp, 0, 1); // USF_GRANULARITY + bitvec_write_field(dest, wp, 0, 1); // "0" power control: Not Present + bitvec_write_field(dest, wp, bts->initial_cs-1, 2); // CHANNEL_CODING_COMMAND + bitvec_write_field(dest, wp, 1, 1); // TLLI_BLOCK_CHANNEL_CODING + bitvec_write_field(dest, wp, 1, 1); // "1" Alpha : Present + bitvec_write_field(dest, wp, 0, 4); // Alpha + bitvec_write_field(dest, wp, 0, 5); // Gamma + bitvec_write_field(dest, wp, 0, 1); // TIMING_ADVANCE_INDEX_FLAG + bitvec_write_field(dest, wp, 0, 1); // TBF_STARTING_TIME_FLAG + } } return plen; |