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.
zecke/hacks/quick-exit
Ivan Kluchnikov 11 years ago
parent 27482ba371
commit 5310d4542c
  1. 141
      gprs_rlcmac.cpp
  2. 2
      gprs_rlcmac.h
  3. 26
      pcu_l1_if.cpp
  4. 10
      pcu_l1_if.h

@ -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);
}

@ -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);

@ -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;

@ -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);

Loading…
Cancel
Save