aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIvan Kluchnikov <kluchnikovi@gmail.com>2012-04-17 22:00:31 +0400
committerIvan Kluchnikov <kluchnikovi@gmail.com>2012-04-17 22:00:31 +0400
commit5310d4542c1e97b4ebfaf22aca962eedee3a2833 (patch)
tree1741878e30ced1e10a0209b3a95df2376e234c62
parent27482ba37115b989a7eb9c3adcfd1e7f21224ad5 (diff)
L1 Interface (PCU side): Added functions for handling PhConnectInd and PhRaInd primitives.
Added functions for writing and sending Immediate Assignment message. Modified TBF managment for handling Channel Request and Immediate Assignment messages.
-rw-r--r--gprs_rlcmac.cpp141
-rw-r--r--gprs_rlcmac.h2
-rw-r--r--pcu_l1_if.cpp26
-rw-r--r--pcu_l1_if.h10
4 files changed, 153 insertions, 26 deletions
diff --git a/gprs_rlcmac.cpp b/gprs_rlcmac.cpp
index 87407cda..b78c27e7 100644
--- a/gprs_rlcmac.cpp
+++ b/gprs_rlcmac.cpp
@@ -21,6 +21,7 @@
#include <pcu_l1_if.h>
#include <Threads.h>
#include <gprs_rlcmac.h>
+#include <gsmL1prim.h>
LLIST_HEAD(gprs_rlcmac_tbfs);
void *rlcmac_tall_ctx;
@@ -255,9 +256,97 @@ void write_packet_uplink_assignment(BitVector * dest, uint8_t tfi, uint32_t tll
// dest->writeField(wp,0x0,1); // Measurement Mapping struct not present
}
+
+// GSM 04.08 9.1.18 Immediate assignment
+int write_immediate_assignment(BitVector * dest, uint8_t downlink, uint8_t ra, uint32_t fn,
+ uint8_t ta, uint8_t tfi = 0, uint32_t tlli = 0)
+{
+ unsigned wp = 0;
+
+ dest->writeField(wp,0x0,4); // Skip Indicator
+ dest->writeField(wp,0x6,4); // Protocol Discriminator
+ dest->writeField(wp,0x3F,8); // Immediate Assignment Message Type
+
+ // 10.5.2.25b Dedicated mode or TBF
+ dest->writeField(wp,0x0,1); // spare
+ dest->writeField(wp,0x0,1); // TMA : Two-message assignment: No meaning
+ dest->writeField(wp,downlink,1); // Downlink : Downlink assignment to mobile in packet idle mode
+ dest->writeField(wp,0x1,1); // T/D : TBF or dedicated mode: this message assigns a Temporary Block Flow (TBF).
+
+ dest->writeField(wp,0x0,4); // Page Mode
+
+ // GSM 04.08 10.5.2.25a Packet Channel Description
+ dest->writeField(wp,0x1,5); // Channel type
+ dest->writeField(wp,(l1fh->fl1h)->channel_info.tn,3); // TN
+ dest->writeField(wp,(l1fh->fl1h)->channel_info.tsc,3); // TSC
+ dest->writeField(wp,0x0,3); // non-hopping RF channel configuraion
+ dest->writeField(wp,(l1fh->fl1h)->channel_info.arfcn,10); // ARFCN
+
+ //10.5.2.30 Request Reference
+ dest->writeField(wp,ra,8); // RA
+ dest->writeField(wp,(fn / (26 * 51)) % 32,5); // T1'
+ dest->writeField(wp,fn % 51,6); // T3
+ dest->writeField(wp,fn % 26,5); // T2
+
+ // 10.5.2.40 Timing Advance
+ dest->writeField(wp,0x0,2); // spare
+ dest->writeField(wp,ta,6); // Timing Advance value
+
+ // No mobile allocation in non-hopping systems.
+ // A zero-length LV. Just write L=0.
+ dest->writeField(wp,0,8);
+
+ if (downlink)
+ {
+ // GSM 04.08 10.5.2.16 IA Rest Octets
+ dest->writeField(wp, 3, 2); // "HH"
+ dest->writeField(wp, 1, 2); // "01" Packet Downlink Assignment
+ dest->writeField(wp,tlli,32); // TLLI
+ dest->writeField(wp,0x1,1); // switch TFI : on
+ dest->writeField(wp,tfi,5); // TFI
+ dest->writeField(wp,0x0,1); // RLC acknowledged mode
+ dest->writeField(wp,0x0,1); // ALPHA = present
+ dest->writeField(wp,0x0,5); // GAMMA power control parameter
+ dest->writeField(wp,0x0,1); // Polling Bit
+ dest->writeField(wp,0x1,1); // TA_VALID ???
+ dest->writeField(wp,0x1,1); // switch TIMING_ADVANCE_INDEX = on
+ dest->writeField(wp,0x0,4); // TIMING_ADVANCE_INDEX
+ dest->writeField(wp,0x0,1); // TBF Starting TIME present
+ dest->writeField(wp,0x0,1); // P0 not present
+ dest->writeField(wp,0x1,1); // P0 not present
+ dest->writeField(wp,0xb,4);
+ }
+ else
+ {
+ // GMS 04.08 10.5.2.37b 10.5.2.16
+ dest->writeField(wp, 3, 2); // "HH"
+ dest->writeField(wp, 0, 2); // "0" Packet Uplink Assignment
+ dest->writeField(wp, 1, 1); // Block Allocation : Not Single Block Allocation
+ dest->writeField(wp, tfi, 5); // TFI_ASSIGNMENT Temporary Flow Identity
+ dest->writeField(wp, 0, 1); // POLLING
+ dest->writeField(wp, 0, 1); // ALLOCATION_TYPE: dynamic
+ dest->writeField(wp, 1, 3); // USF
+ dest->writeField(wp, 1, 1); // USF_GRANULARITY
+ dest->writeField(wp, 0 , 1); // "0" power control: Not Present
+ dest->writeField(wp, 0, 2); // CHANNEL_CODING_COMMAND
+ dest->writeField(wp, 1, 1); // TLLI_BLOCK_CHANNEL_CODING
+ dest->writeField(wp, 1 , 1); // "1" Alpha : Present
+ dest->writeField(wp, 0, 4); // Alpha
+ dest->writeField(wp, 0, 5); // Gamma
+ dest->writeField(wp, 0, 1); // TIMING_ADVANCE_INDEX_FLAG
+ dest->writeField(wp, 0, 1); // TBF_STARTING_TIME_FLAG
+ }
+
+ if (wp%8)
+ return wp/8+1;
+ else
+ return wp/8;
+}
+
+
void write_ia_rest_octets_downlink_assignment(BitVector * dest, uint8_t tfi, uint32_t tlli)
{
- // GMS 04.08 10.5.2.16
+ // GSM 04.08 10.5.2.16
unsigned wp = 0;
dest->writeField(wp, 3, 2); // "HH"
dest->writeField(wp, 1, 2); // "01" Packet Downlink Assignment
@@ -326,7 +415,7 @@ void gprs_rlcmac_tx_ul_ack(uint8_t tfi, uint32_t tlli, RlcMacUplinkDataBlock_t *
decode_gsm_rlcmac_downlink(&packet_uplink_ack_vec, packet_uplink_ack);
free(packet_uplink_ack);
COUT("RLCMAC_CONTROL_BLOCK_END------------------------------");
- pcu_l1if_tx(&packet_uplink_ack_vec);
+ pcu_l1if_tx(&packet_uplink_ack_vec, GsmL1_Sapi_Pacch);
}
void gprs_rlcmac_data_block_parse(gprs_rlcmac_tbf* tbf, RlcMacUplinkDataBlock_t * ul_data_block)
@@ -373,14 +462,7 @@ int gprs_rlcmac_rcv_data_block(BitVector *rlc_block)
tbf = tbf_by_tfi(ul_data_block->TFI);
if (!tbf) {
- tbf = tbf_alloc(ul_data_block->TFI);
- if (tbf) {
- tbf->tlli = ul_data_block->TLLI;
- tbf->direction = GPRS_RLCMAC_UL_TBF;
- tbf->state = GPRS_RLCMAC_WAIT_DATA_SEQ_START;
- } else {
- return 0;
- }
+ return 0;
}
switch (tbf->state) {
@@ -433,12 +515,6 @@ int gprs_rlcmac_rcv_control_block(BitVector *rlc_block)
decode_gsm_rlcmac_uplink(rlc_block, ul_control_block);
COUT("RLCMAC_CONTROL_BLOCK_END------------------------------");
- //gprs_rlcmac_control_block_get_tfi_tlli(ul_control_block, &tfi, &tlli);
- //tbf = tbf_by_tfi(tfi);
- //if (!tbf) {
- // return 0;
- //}
-
switch (ul_control_block->u.MESSAGE_TYPE) {
case MT_PACKET_CONTROL_ACK:
tlli = ul_control_block->u.Packet_Control_Acknowledgement.TLLI;
@@ -459,7 +535,7 @@ int gprs_rlcmac_rcv_control_block(BitVector *rlc_block)
BitVector packet_uplink_assignment(23*8);
packet_uplink_assignment.unhex("2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
write_packet_uplink_assignment(&packet_uplink_assignment, tbf->tfi, tbf->tlli);
- pcu_l1if_tx(&packet_uplink_assignment);
+ pcu_l1if_tx(&packet_uplink_assignment, GsmL1_Sapi_Pacch);
break;
}
free(ul_control_block);
@@ -485,6 +561,27 @@ void gprs_rlcmac_rcv_block(BitVector *rlc_block)
}
}
+int gprs_rlcmac_rcv_rach(uint8_t ra, uint32_t Fn, uint16_t ta)
+{
+ struct gprs_rlcmac_tbf *tbf;
+
+ // Create new TBF
+ int tfi = tfi_alloc();
+ if (tfi < 0) {
+ return tfi;
+ }
+ tbf = tbf_alloc(tfi);
+ tbf->direction = GPRS_RLCMAC_UL_TBF;
+ tbf->state = GPRS_RLCMAC_WAIT_DATA_SEQ_START;
+ COUT("[UPLINK TBF : " << tfi << " ] : START");
+
+ COUT("SEND Immidiate Assignment>>>>>>>>>>>>>>>>>>");
+ BitVector immediate_assignment(23*8);
+ immediate_assignment.unhex("2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
+ int len = write_immediate_assignment(&immediate_assignment, 0, ra, Fn, ta, tbf->tfi);
+ pcu_l1if_tx(&immediate_assignment, GsmL1_Sapi_Agch, len);
+}
+
// Send RLC data to OpenBTS.
void gprs_rlcmac_tx_dl_data_block(uint32_t tlli, uint8_t tfi, uint8_t *pdu, int start_index, int end_index, uint8_t bsn, uint8_t fbi)
{
@@ -521,7 +618,7 @@ void gprs_rlcmac_tx_dl_data_block(uint32_t tlli, uint8_t tfi, uint8_t *pdu, int
}
encode_gsm_rlcmac_downlink_data(&data_block_vector, data_block);
free(data_block);
- pcu_l1if_tx(&data_block_vector);
+ pcu_l1if_tx(&data_block_vector, GsmL1_Sapi_Pdtch);
}
int gprs_rlcmac_segment_llc_pdu(struct gprs_rlcmac_tbf *tbf)
@@ -589,9 +686,9 @@ void gprs_rlcmac_tx_ul_ud(gprs_rlcmac_tbf *tbf)
void gprs_rlcmac_downlink_assignment(gprs_rlcmac_tbf *tbf)
{
COUT("SEND IA Rest Octets Downlink Assignment>>>>>>>>>>>>>>>>>>");
- BitVector ia_rest_octets_downlink_assignment(23*8);
- ia_rest_octets_downlink_assignment.unhex("2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
- write_ia_rest_octets_downlink_assignment(&ia_rest_octets_downlink_assignment, tbf->tfi, tbf->tlli);
- pcu_l1if_tx(&ia_rest_octets_downlink_assignment);
+ BitVector immediate_assignment(23*8);
+ immediate_assignment.unhex("2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
+ int len = write_immediate_assignment(&immediate_assignment, 1, 125, get_current_fn(), (l1fh->fl1h)->channel_info.ta, tbf->tfi, tbf->tlli);
+ pcu_l1if_tx(&immediate_assignment, GsmL1_Sapi_Agch, len);
tbf_gsm_timer_start(tbf, 0, 120);
}
diff --git a/gprs_rlcmac.h b/gprs_rlcmac.h
index 38e29630..b5103951 100644
--- a/gprs_rlcmac.h
+++ b/gprs_rlcmac.h
@@ -89,6 +89,8 @@ int gprs_rlcmac_rcv_control_block(BitVector *rlc_block);
void gprs_rlcmac_rcv_block(BitVector *rlc_block);
+int gprs_rlcmac_rcv_rach(uint8_t ra, uint32_t Fn, uint16_t ta);
+
void gprs_rlcmac_tx_dl_data_block(uint32_t tlli, uint8_t tfi, uint8_t *pdu, int start_index, int end_index, uint8_t bsn, uint8_t fbi);
int gprs_rlcmac_segment_llc_pdu(struct gprs_rlcmac_tbf *tbf);
diff --git a/pcu_l1_if.cpp b/pcu_l1_if.cpp
index c3d1b12d..be2cda01 100644
--- a/pcu_l1_if.cpp
+++ b/pcu_l1_if.cpp
@@ -59,6 +59,7 @@ struct msgb *gen_dummy_msg(void)
// RLC/MAC filler with USF=1
BitVector filler("0100000110010100001010110010101100101011001010110010101100101011001010110010101100101011001010110010101100101011001010110010101100101011001010110010101100101011001010110010101100101011");
prim->id = GsmL1_PrimId_PhDataReq;
+ prim->u.phDataReq.sapi = GsmL1_Sapi_Pacch;
filler.pack((unsigned char*)&(prim->u.phDataReq.msgUnitParam.u8Buffer[ofs]));
ofs += filler.size() >> 3;
prim->u.phDataReq.msgUnitParam.u8Size = ofs;
@@ -66,7 +67,7 @@ struct msgb *gen_dummy_msg(void)
}
// Send RLC/MAC block to OpenBTS.
-void pcu_l1if_tx(BitVector * block)
+void pcu_l1if_tx(BitVector * block, GsmL1_Sapi_t sapi, int len)
{
int ofs = 0;
struct msgb *msg = l1p_msgb_alloc();
@@ -75,9 +76,10 @@ void pcu_l1if_tx(BitVector * block)
GsmL1_Prim_t *prim = msgb_l1prim(msg);
prim->id = GsmL1_PrimId_PhDataReq;
+ prim->u.phDataReq.sapi = sapi;
block->pack((unsigned char*)&(prim->u.phDataReq.msgUnitParam.u8Buffer[ofs]));
ofs += block->size() >> 3;
- prim->u.phDataReq.msgUnitParam.u8Size = ofs;
+ prim->u.phDataReq.msgUnitParam.u8Size = len;
COUT("Add Block to WRITE QUEUE: " << *block);
osmo_wqueue_enqueue(queue, msg);
@@ -92,6 +94,15 @@ int pcu_l1if_rx_pdch(GsmL1_PhDataInd_t *data_ind)
gprs_rlcmac_rcv_block(block);
}
+static int handle_ph_connect_ind(struct femtol1_hdl *fl1, GsmL1_PhConnectInd_t *connect_ind)
+{
+ (l1fh->fl1h)->channel_info.arfcn = connect_ind->u16Arfcn;
+ (l1fh->fl1h)->channel_info.tn = connect_ind->u8Tn;
+ (l1fh->fl1h)->channel_info.tsc = connect_ind->u8Tsc;
+ COUT("RX: [ PCU <- BTS ] PhConnectInd: ARFCN: " << connect_ind->u16Arfcn
+ <<" TN: " << (unsigned)connect_ind->u8Tn << " TSC: " << (unsigned)connect_ind->u8Tsc);
+}
+
static int handle_ph_readytosend_ind(struct femtol1_hdl *fl1, GsmL1_PhReadyToSendInd_t *readytosend_ind)
{
struct msgb *resp_msg;
@@ -134,6 +145,14 @@ static int handle_ph_data_ind(struct femtol1_hdl *fl1, GsmL1_PhDataInd_t *data_i
return rc;
}
+static int handle_ph_ra_ind(struct femtol1_hdl *fl1, GsmL1_PhRaInd_t *ra_ind)
+{
+ int rc = 0;
+ (l1fh->fl1h)->channel_info.ta = ra_ind->measParam.i16BurstTiming;
+ rc = gprs_rlcmac_rcv_rach(ra_ind->msgUnitParam.u8Buffer[0], ra_ind->u32Fn, ra_ind->measParam.i16BurstTiming);
+ return rc;
+}
+
/* handle any random indication from the L1 */
int pcu_l1if_handle_l1prim(struct femtol1_hdl *fl1, struct msgb *msg)
{
@@ -142,15 +161,16 @@ int pcu_l1if_handle_l1prim(struct femtol1_hdl *fl1, struct msgb *msg)
switch (l1p->id) {
case GsmL1_PrimId_PhConnectInd:
+ rc = handle_ph_connect_ind(fl1, &l1p->u.phConnectInd);
break;
case GsmL1_PrimId_PhReadyToSendInd:
rc = handle_ph_readytosend_ind(fl1, &l1p->u.phReadyToSendInd);
break;
case GsmL1_PrimId_PhDataInd:
- COUT("RX GsmL1_PrimId_PhDataInd ");
rc = handle_ph_data_ind(fl1, &l1p->u.phDataInd);
break;
case GsmL1_PrimId_PhRaInd:
+ rc = handle_ph_ra_ind(fl1, &l1p->u.phRaInd);
break;
default:
break;
diff --git a/pcu_l1_if.h b/pcu_l1_if.h
index cdd36424..0d326d55 100644
--- a/pcu_l1_if.h
+++ b/pcu_l1_if.h
@@ -47,6 +47,14 @@ struct femtol1_hdl {
struct osmo_fd read_ofd; /* osmo file descriptors */
struct osmo_wqueue write_q;
+
+ struct {
+ uint16_t arfcn;
+ uint8_t tn;
+ uint8_t tsc;
+ uint16_t ta;
+ } channel_info;
+
};
struct l1fwd_hdl {
@@ -62,7 +70,7 @@ extern struct l1fwd_hdl *l1fh;
int get_current_fn();
-void pcu_l1if_tx(BitVector * block);
+void pcu_l1if_tx(BitVector * block, GsmL1_Sapi_t sapi, int len = 23);
int pcu_l1if_handle_l1prim(struct femtol1_hdl *fl1h, struct msgb *msg);