aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gprs_rlcmac.cpp48
-rw-r--r--src/gprs_rlcmac.h9
-rw-r--r--src/gprs_rlcmac_data.cpp21
-rw-r--r--src/pcu_main.cpp1
-rw-r--r--src/pcu_vty.c35
5 files changed, 90 insertions, 24 deletions
diff --git a/src/gprs_rlcmac.cpp b/src/gprs_rlcmac.cpp
index f7ec8477..64bbe75f 100644
--- a/src/gprs_rlcmac.cpp
+++ b/src/gprs_rlcmac.cpp
@@ -1161,7 +1161,8 @@ struct msgb *gprs_rlcmac_send_packet_paging_request(
int write_immediate_assignment(bitvec * dest, uint8_t downlink, uint8_t ra,
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 fn, uint8_t single_block)
+ uint8_t polling, uint32_t fn, uint8_t single_block, uint8_t alpha,
+ uint8_t gamma)
{
unsigned wp = 0;
uint8_t plen;
@@ -1215,8 +1216,13 @@ int write_immediate_assignment(bitvec * dest, uint8_t downlink, uint8_t ra,
bitvec_write_field(dest, wp,0x1,1); // switch TFI : on
bitvec_write_field(dest, wp,tfi,5); // TFI
bitvec_write_field(dest, wp,0x0,1); // RLC acknowledged mode
- bitvec_write_field(dest, wp,0x0,1); // ALPHA = not present
- bitvec_write_field(dest, wp,0x0,5); // GAMMA power control parameter
+ if (alpha) {
+ bitvec_write_field(dest, wp,0x1,1); // ALPHA = present
+ bitvec_write_field(dest, wp,alpha,4); // ALPHA
+ } else {
+ bitvec_write_field(dest, wp,0x0,1); // ALPHA = not present
+ }
+ bitvec_write_field(dest, wp,gamma,5); // GAMMA power control parameter
bitvec_write_field(dest, wp,polling,1); // Polling Bit
bitvec_write_field(dest, wp,!polling,1); // TA_VALID ???
bitvec_write_field(dest, wp,0x1,1); // switch TIMING_ADVANCE_INDEX = on
@@ -1241,9 +1247,12 @@ int write_immediate_assignment(bitvec * dest, uint8_t downlink, uint8_t ra,
bitvec_write_field(dest, wp, 0, 2); // "0" Packet Uplink Assignment
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
+ if (alpha) {
+ bitvec_write_field(dest, wp,0x1,1); // ALPHA = present
+ bitvec_write_field(dest, wp,alpha,4); // ALPHA = present
+ } else
+ bitvec_write_field(dest, wp,0x0,1); // ALPHA = not present
+ bitvec_write_field(dest, wp,gamma,5); // GAMMA power control parameter
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'
@@ -1259,9 +1268,12 @@ int write_immediate_assignment(bitvec * dest, uint8_t downlink, uint8_t ra,
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
+ if (alpha) {
+ bitvec_write_field(dest, wp,0x1,1); // ALPHA = present
+ bitvec_write_field(dest, wp,alpha,4); // ALPHA
+ } else
+ bitvec_write_field(dest, wp,0x0,1); // ALPHA = not present
+ bitvec_write_field(dest, wp,gamma,5); // GAMMA power control parameter
bitvec_write_field(dest, wp, 0, 1); // TIMING_ADVANCE_INDEX_FLAG
bitvec_write_field(dest, wp, 0, 1); // TBF_STARTING_TIME_FLAG
}
@@ -1273,7 +1285,8 @@ int write_immediate_assignment(bitvec * dest, uint8_t downlink, uint8_t ra,
/* generate uplink assignment */
void write_packet_uplink_assignment(bitvec * dest, uint8_t old_tfi,
uint8_t old_downlink, uint32_t tlli, uint8_t use_tlli,
- struct gprs_rlcmac_tbf *tbf, uint8_t poll)
+ struct gprs_rlcmac_tbf *tbf, uint8_t poll, uint8_t alpha,
+ uint8_t gamma)
{
// TODO We should use our implementation of encode RLC/MAC Control messages.
struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
@@ -1326,12 +1339,18 @@ void write_packet_uplink_assignment(bitvec * dest, uint8_t old_tfi,
bitvec_write_field(dest, wp,0x0,1); //
bitvec_write_field(dest, wp,0x0,1); // TBF Starting Time = off
- bitvec_write_field(dest, wp,0x0,1); // Timeslot Allocation
+ if (alpha || gamma) {
+ bitvec_write_field(dest, wp,0x1,1); // Timeslot Allocation with Power Control
+ bitvec_write_field(dest, wp,alpha,4); // ALPHA
+ } else
+ bitvec_write_field(dest, wp,0x0,1); // Timeslot Allocation
for (ts = 0; ts < 8; ts++) {
if (tbf->pdch[ts]) {
bitvec_write_field(dest, wp,0x1,1); // USF_TN(i): on
bitvec_write_field(dest, wp,tbf->dir.ul.usf[ts],3); // USF_TN(i)
+ if (alpha || gamma)
+ bitvec_write_field(dest, wp,gamma,5); // GAMMA power control parameter
} else
bitvec_write_field(dest, wp,0x0,1); // USF_TN(i): off
}
@@ -1341,7 +1360,8 @@ void write_packet_uplink_assignment(bitvec * dest, uint8_t old_tfi,
/* generate downlink assignment */
void write_packet_downlink_assignment(RlcMacDownlink_t * block, uint8_t old_tfi,
- uint8_t old_downlink, struct gprs_rlcmac_tbf *tbf, uint8_t poll)
+ uint8_t old_downlink, struct gprs_rlcmac_tbf *tbf, uint8_t poll,
+ uint8_t alpha, uint8_t gamma)
{
// Packet downlink assignment TS 44.060 11.2.7
@@ -1385,14 +1405,14 @@ void write_packet_downlink_assignment(RlcMacDownlink_t * block, uint8_t old_tfi,
block->u.Packet_Downlink_Assignment.DOWNLINK_TFI_ASSIGNMENT = tbf->tfi; // TFI
block->u.Packet_Downlink_Assignment.Exist_Power_Control_Parameters = 0x1; // Power Control Parameters = on
- block->u.Packet_Downlink_Assignment.Power_Control_Parameters.ALPHA = 0x0; // ALPHA
+ block->u.Packet_Downlink_Assignment.Power_Control_Parameters.ALPHA = alpha; // ALPHA
for (tn = 0; tn < 8; tn++)
{
if (tbf->pdch[tn])
{
block->u.Packet_Downlink_Assignment.Power_Control_Parameters.Slot[tn].Exist = 0x1; // Slot[i] = on
- block->u.Packet_Downlink_Assignment.Power_Control_Parameters.Slot[tn].GAMMA_TN = 0x0; // GAMMA_TN
+ block->u.Packet_Downlink_Assignment.Power_Control_Parameters.Slot[tn].GAMMA_TN = gamma; // GAMMA_TN
}
else
{
diff --git a/src/gprs_rlcmac.h b/src/gprs_rlcmac.h
index e7a68a4f..46439911 100644
--- a/src/gprs_rlcmac.h
+++ b/src/gprs_rlcmac.h
@@ -83,6 +83,7 @@ struct gprs_rlcmac_bts {
struct gprs_rlcmac_tbf *tbf, uint32_t cust);
uint32_t alloc_algorithm_curst; /* options to customize algorithm */
uint8_t force_two_phase;
+ uint8_t alpha, gamma;
};
extern struct gprs_rlcmac_bts *gprs_rlcmac_bts;
@@ -292,14 +293,16 @@ int gprs_rlcmac_rcv_block(uint8_t trx, uint8_t ts, uint8_t *data, uint8_t len,
int write_immediate_assignment(bitvec * dest, uint8_t downlink, uint8_t ra,
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 fn, uint8_t single_block);
+ uint32_t fn, uint8_t single_block, uint8_t alpha, uint8_t gamma);
void write_packet_uplink_assignment(bitvec * dest, uint8_t old_tfi,
uint8_t old_downlink, uint32_t tlli, uint8_t use_tlli,
- struct gprs_rlcmac_tbf *tbf, uint8_t poll);
+ struct gprs_rlcmac_tbf *tbf, uint8_t poll, uint8_t alpha,
+ uint8_t gamma);
void write_packet_downlink_assignment(RlcMacDownlink_t * block, uint8_t old_tfi,
- uint8_t old_downlink, struct gprs_rlcmac_tbf *tbf, uint8_t poll);
+ uint8_t old_downlink, struct gprs_rlcmac_tbf *tbf, uint8_t poll,
+ uint8_t alpha, uint8_t gamma);
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);
}
diff --git a/src/pcu_main.cpp b/src/pcu_main.cpp
index 2392152a..ba31ca7e 100644
--- a/src/pcu_main.cpp
+++ b/src/pcu_main.cpp
@@ -153,6 +153,7 @@ int main(int argc, char *argv[])
bts->n3101 = 10;
bts->n3103 = 4;
bts->n3105 = 8;
+ bts->alpha = 10; /* a = 1.0 */
msgb_set_talloc_ctx(tall_pcu_ctx);
diff --git a/src/pcu_vty.c b/src/pcu_vty.c
index 8d5b47b1..d7c2c2cd 100644
--- a/src/pcu_vty.c
+++ b/src/pcu_vty.c
@@ -94,6 +94,8 @@ static int config_write_pcu(struct vty *vty)
vty_out(vty, " alloc-algorithm b%s", VTY_NEWLINE);
if (bts->force_two_phase)
vty_out(vty, " two-phase-access%s", VTY_NEWLINE);
+ vty_out(vty, " alpha %d%s", bts->alpha, VTY_NEWLINE);
+ vty_out(vty, " gamma %d%s", bts->gamma * 2, VTY_NEWLINE);
}
@@ -110,9 +112,9 @@ DEFUN(cfg_pcu,
DEFUN(cfg_pcu_fc_interval,
cfg_pcu_fc_interval_cmd,
- "flow-control-interval <1..10>",
+ "flow-control-interval <1-10>",
"Interval between sending subsequent Flow Control PDUs\n"
- "Tiem in seconds\n")
+ "Interval time in seconds\n")
{
struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
@@ -234,6 +236,33 @@ DEFUN(cfg_pcu_no_two_phase,
return CMD_SUCCESS;
}
+DEFUN(cfg_pcu_alpha,
+ cfg_pcu_alpha_cmd,
+ "alpha <0-10>",
+ "Alpha parameter for MS power control in units of 0.1 (see TS 05.08) "
+ "NOTE: Be sure to set Alpha value at System information 13 too.\n"
+ "Alpha in units of 0.1\n")
+{
+ struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
+
+ bts->alpha = atoi(argv[0]);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_pcu_gamma,
+ cfg_pcu_gamma_cmd,
+ "gamma <0-62>",
+ "Gamma parameter for MS power control in units of dB (see TS 05.08)\n"
+ "Gamma in even unit of dBs\n")
+{
+ struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts;
+
+ bts->gamma = atoi(argv[0]) / 2;
+
+ return CMD_SUCCESS;
+}
+
static const char pcu_copyright[] =
"Copyright (C) 2012 by ...\r\n"
"License GNU GPL version 2 or later\r\n"
@@ -266,6 +295,8 @@ int pcu_vty_init(const struct log_info *cat)
install_element(PCU_NODE, &cfg_pcu_alloc_cmd);
install_element(PCU_NODE, &cfg_pcu_two_phase_cmd);
install_element(PCU_NODE, &cfg_pcu_fc_interval_cmd);
+ install_element(PCU_NODE, &cfg_pcu_alpha_cmd);
+ install_element(PCU_NODE, &cfg_pcu_gamma_cmd);
install_element(PCU_NODE, &ournode_end_cmd);
return 0;