Added L1 interface between PCU and OpenBTS for communication (PCU side).
This commit is contained in:
parent
c320d86052
commit
e3a059656f
|
@ -0,0 +1,410 @@
|
|||
/*
|
||||
* Copyright 2012 Thomas Cooper <tacooper@vt.edu>
|
||||
*
|
||||
* This software is distributed under the terms of the GNU Affero Public License.
|
||||
* See the COPYING file in the main directory for details.
|
||||
*
|
||||
* This use of this software may be subject to additional restrictions.
|
||||
* See the LEGAL file in the main directory for details.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef GSML1PRIM_H
|
||||
#define GSML1PRIM_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef enum GsmL1_SubCh_t {
|
||||
GsmL1_SubCh_NA,
|
||||
} GsmL1_SubCh_t;
|
||||
|
||||
typedef enum GsmL1_Sapi_t {
|
||||
GsmL1_Sapi_Fcch,
|
||||
GsmL1_Sapi_Sch,
|
||||
GsmL1_Sapi_Sacch,
|
||||
GsmL1_Sapi_Sdcch,
|
||||
GsmL1_Sapi_Bcch,
|
||||
GsmL1_Sapi_Pch,
|
||||
GsmL1_Sapi_Agch,
|
||||
GsmL1_Sapi_Cbch,
|
||||
GsmL1_Sapi_Rach,
|
||||
GsmL1_Sapi_TchF,
|
||||
GsmL1_Sapi_FacchF,
|
||||
GsmL1_Sapi_TchH,
|
||||
GsmL1_Sapi_FacchH,
|
||||
GsmL1_Sapi_Nch,
|
||||
GsmL1_Sapi_Pdtch,
|
||||
GsmL1_Sapi_Pacch,
|
||||
GsmL1_Sapi_Pbcch,
|
||||
GsmL1_Sapi_Pagch,
|
||||
GsmL1_Sapi_Ppch,
|
||||
GsmL1_Sapi_Pnch,
|
||||
GsmL1_Sapi_Ptcch,
|
||||
GsmL1_Sapi_Prach,
|
||||
GsmL1_Sapi_Idle,
|
||||
GsmL1_Sapi_NUM,
|
||||
} GsmL1_Sapi_t;
|
||||
|
||||
typedef enum GsmL1_Status_t {
|
||||
GsmL1_Status_Success,
|
||||
GsmL1_Status_Generic,
|
||||
GsmL1_Status_NoMemory,
|
||||
GsmL1_Status_Timeout,
|
||||
GsmL1_Status_InvalidParam,
|
||||
GsmL1_Status_Busy,
|
||||
GsmL1_Status_NoRessource,
|
||||
GsmL1_Status_Uninitialized,
|
||||
GsmL1_Status_NullInterface,
|
||||
GsmL1_Status_NullFctnPtr,
|
||||
GsmL1_Status_BadCrc,
|
||||
GsmL1_Status_BadUsf,
|
||||
GsmL1_Status_InvalidCPS,
|
||||
GsmL1_Status_UnexpectedBurst,
|
||||
GsmL1_Status_UnavailCodec,
|
||||
GsmL1_Status_CriticalError,
|
||||
GsmL1_Status_OverheatError,
|
||||
GsmL1_Status_DeviceError,
|
||||
GsmL1_Status_FacchError,
|
||||
GsmL1_Status_AlreadyDeactivated,
|
||||
GsmL1_Status_TxBurstFifoOvrn,
|
||||
GsmL1_Status_TxBurstFifoUndr,
|
||||
GsmL1_Status_NotSynchronized,
|
||||
GsmL1_Status_Unsupported,
|
||||
GSML1_STATUS_NUM,
|
||||
} GsmL1_Status_t;
|
||||
|
||||
typedef enum GsmL1_PrimId_t {
|
||||
GsmL1_PrimId_MphInitReq,
|
||||
GsmL1_PrimId_MphCloseReq,
|
||||
GsmL1_PrimId_MphConnectReq,
|
||||
GsmL1_PrimId_MphDisconnectReq,
|
||||
GsmL1_PrimId_MphActivateReq,
|
||||
GsmL1_PrimId_MphDeactivateReq,
|
||||
GsmL1_PrimId_MphConfigReq,
|
||||
GsmL1_PrimId_MphMeasureReq,
|
||||
GsmL1_PrimId_MphInitCnf,
|
||||
GsmL1_PrimId_MphCloseCnf,
|
||||
GsmL1_PrimId_MphConnectCnf,
|
||||
GsmL1_PrimId_MphDisconnectCnf,
|
||||
GsmL1_PrimId_MphActivateCnf,
|
||||
GsmL1_PrimId_MphDeactivateCnf,
|
||||
GsmL1_PrimId_MphConfigCnf,
|
||||
GsmL1_PrimId_MphMeasureCnf,
|
||||
GsmL1_PrimId_MphTimeInd,
|
||||
GsmL1_PrimId_MphSyncInd,
|
||||
GsmL1_PrimId_PhEmptyFrameReq,
|
||||
GsmL1_PrimId_PhDataReq,
|
||||
GsmL1_PrimId_PhConnectInd,
|
||||
GsmL1_PrimId_PhReadyToSendInd,
|
||||
GsmL1_PrimId_PhDataInd,
|
||||
GsmL1_PrimId_PhRaInd,
|
||||
GsmL1_PrimId_NUM,
|
||||
} GsmL1_PrimId_t;
|
||||
|
||||
typedef enum GsmL1_Dir_t {
|
||||
GsmL1_Dir_TxDownlink,
|
||||
GsmL1_Dir_RxUplink,
|
||||
} GsmL1_Dir_t;
|
||||
|
||||
typedef enum GsmL1_DevType_t {
|
||||
GsmL1_DevType_TxdRxu,
|
||||
} GsmL1_DevType_t;
|
||||
|
||||
typedef enum GsmL1_TchPlType_t {
|
||||
GsmL1_TchPlType_NA,
|
||||
GsmL1_TchPlType_Efr,
|
||||
GsmL1_TchPlType_Fr,
|
||||
GsmL1_TchPlType_Hr,
|
||||
GsmL1_TchPlType_Amr,
|
||||
GsmL1_TchPlType_Amr_SidBad,
|
||||
GsmL1_TchPlType_Amr_Onset,
|
||||
GsmL1_TchPlType_Amr_Ratscch,
|
||||
GsmL1_TchPlType_Amr_SidUpdateInH,
|
||||
GsmL1_TchPlType_Amr_SidFirstP1,
|
||||
GsmL1_TchPlType_Amr_SidFirstP2,
|
||||
GsmL1_TchPlType_Amr_SidFirstInH,
|
||||
GsmL1_TchPlType_Amr_RatscchMarker,
|
||||
GsmL1_TchPlType_Amr_RatscchData,
|
||||
} GsmL1_TchPlType_t;
|
||||
|
||||
typedef enum GsmL1_ConfigParamId_t {
|
||||
GsmL1_ConfigParamId_SetNbTsc,
|
||||
GsmL1_ConfigParamId_SetTxPowerLevel,
|
||||
GsmL1_ConfigParamId_SetLogChParams,
|
||||
GsmL1_ConfigParamId_SetCipheringParams,
|
||||
} GsmL1_ConfigParamId_t;
|
||||
|
||||
typedef struct GsmL1_DeviceParam_t {
|
||||
enum GsmL1_DevType_t devType;
|
||||
int freqBand;
|
||||
uint16_t u16Arfcn;
|
||||
uint16_t u16BcchArfcn;
|
||||
uint8_t u8NbTsc;
|
||||
uint8_t u8Ncc;
|
||||
float fRxPowerLevel;
|
||||
float fTxPowerLevel;
|
||||
} GsmL1_DeviceParam_t;
|
||||
|
||||
typedef struct GsmL1_MsgUnitParam_t {
|
||||
uint8_t u8Buffer[256];
|
||||
uint8_t u8Size;
|
||||
} GsmL1_MsgUnitParam_t;
|
||||
|
||||
typedef struct GsmL1_MeasParam_t {
|
||||
float fRssi;
|
||||
float fLinkQuality;
|
||||
float fBer;
|
||||
int16_t i16BurstTiming;
|
||||
} GsmL1_MeasParam_t;
|
||||
|
||||
typedef struct GsmL1_LogChParam_t {
|
||||
union {
|
||||
struct {
|
||||
enum GsmL1_TchPlType_t tchPlType;
|
||||
|
||||
enum {
|
||||
GsmL1_AmrCmiPhase_NA,
|
||||
GsmL1_AmrCmiPhase_Odd,
|
||||
} amrCmiPhase;
|
||||
|
||||
enum {
|
||||
GsmL1_AmrCodecMode_Unset,
|
||||
} amrInitCodecMode;
|
||||
|
||||
enum {
|
||||
GsmL1_AmrCodec_Unset,
|
||||
GsmL1_AmrCodec_4_75,
|
||||
GsmL1_AmrCodec_5_15,
|
||||
GsmL1_AmrCodec_5_9,
|
||||
GsmL1_AmrCodec_6_7,
|
||||
GsmL1_AmrCodec_7_4,
|
||||
GsmL1_AmrCodec_7_95,
|
||||
GsmL1_AmrCodec_10_2,
|
||||
GsmL1_AmrCodec_12_2,
|
||||
} amrActiveCodecSet[8];
|
||||
} tch;
|
||||
|
||||
struct {
|
||||
uint8_t u8Bsic;
|
||||
uint8_t u8NbrOfAgch;
|
||||
} rach;
|
||||
|
||||
struct {
|
||||
uint8_t u8MsPowerLevel;
|
||||
} sacch;
|
||||
|
||||
struct {
|
||||
uint8_t u8NbrOfAgch;
|
||||
} agch;
|
||||
};
|
||||
} GsmL1_LogChParam_t;
|
||||
|
||||
typedef enum GsmL1_LogChComb_t {
|
||||
GsmL1_LogChComb_0,
|
||||
GsmL1_LogChComb_I,
|
||||
GsmL1_LogChComb_II,
|
||||
GsmL1_LogChComb_IV,
|
||||
GsmL1_LogChComb_V,
|
||||
GsmL1_LogChComb_VII,
|
||||
GsmL1_LogChComb_XIII,
|
||||
} GsmL1_LogChComb_t;
|
||||
|
||||
enum {
|
||||
GsmL1_FreqBand_850,
|
||||
GsmL1_FreqBand_900,
|
||||
GsmL1_FreqBand_1800,
|
||||
GsmL1_FreqBand_1900,
|
||||
};
|
||||
|
||||
typedef struct GsmL1_MphInitReq_t {
|
||||
struct GsmL1_DeviceParam_t deviceParam;
|
||||
} GsmL1_MphInitReq_t;
|
||||
|
||||
typedef struct GsmL1_MphCloseReq_t {
|
||||
uint32_t hLayer1;
|
||||
} GsmL1_MphCloseReq_t;
|
||||
|
||||
typedef struct GsmL1_MphConnectReq_t {
|
||||
uint32_t hLayer1;
|
||||
uint8_t u8Tn;
|
||||
enum GsmL1_LogChComb_t logChComb;
|
||||
} GsmL1_MphConnectReq_t;
|
||||
|
||||
typedef struct GsmL1_MphDisconnectReq_t {
|
||||
uint32_t hLayer1;
|
||||
} GsmL1_MphDisconnectReq_t;
|
||||
|
||||
typedef struct GsmL1_MphActivateReq_t {
|
||||
uint32_t hLayer1;
|
||||
struct GsmL1_LogChParam_t logChPrm;
|
||||
uint8_t u8Tn;
|
||||
enum GsmL1_SubCh_t subCh;
|
||||
enum GsmL1_Dir_t dir;
|
||||
enum GsmL1_Sapi_t sapi;
|
||||
uint32_t hLayer2;
|
||||
float fBFILevel;
|
||||
} GsmL1_MphActivateReq_t;
|
||||
|
||||
typedef struct GsmL1_MphDeactivateReq_t {
|
||||
uint32_t hLayer1;
|
||||
uint8_t u8Tn;
|
||||
enum GsmL1_SubCh_t subCh;
|
||||
enum GsmL1_Dir_t dir;
|
||||
enum GsmL1_Sapi_t sapi;
|
||||
} GsmL1_MphDeactivateReq_t;
|
||||
|
||||
typedef struct GsmL1_ConfigParam_t {
|
||||
struct {
|
||||
enum GsmL1_Sapi_t sapi;
|
||||
uint8_t u8Tn;
|
||||
enum GsmL1_SubCh_t subCh;
|
||||
enum GsmL1_Dir_t dir;
|
||||
struct GsmL1_LogChParam_t logChParams;
|
||||
} setLogChParams;
|
||||
} GsmL1_ConfigParam_t;
|
||||
|
||||
typedef struct GsmL1_MphConfigReq_t {
|
||||
uint32_t hLayer1;
|
||||
enum GsmL1_ConfigParamId_t cfgParamId;
|
||||
struct GsmL1_ConfigParam_t cfgParams;
|
||||
} GsmL1_MphConfigReq_t;
|
||||
|
||||
typedef struct GsmL1_MphConfigCnf_t {
|
||||
enum GsmL1_Status_t status;
|
||||
enum GsmL1_ConfigParamId_t cfgParamId;
|
||||
struct GsmL1_ConfigParam_t cfgParams;
|
||||
} GsmL1_MphConfigCnf_t;
|
||||
|
||||
typedef struct GsmL1_MphMeasureReq_t {
|
||||
uint32_t hLayer1;
|
||||
} GsmL1_MphMeasureReq_t;
|
||||
|
||||
typedef struct GsmL1_MphInitCnf_t {
|
||||
uint32_t hLayer1;
|
||||
enum GsmL1_Status_t status;
|
||||
} GsmL1_MphInitCnf_t;
|
||||
|
||||
typedef struct GsmL1_MphCloseCnf_t {
|
||||
enum GsmL1_Status_t status;
|
||||
} GsmL1_MphCloseCnf_t;
|
||||
|
||||
typedef struct GsmL1_MphConnectCnf_t {
|
||||
enum GsmL1_Status_t status;
|
||||
} GsmL1_MphConnectCnf_t;
|
||||
|
||||
typedef struct GsmL1_MphDisconnectCnf_t {
|
||||
enum GsmL1_Status_t status;
|
||||
} GsmL1_MphDisconnectCnf_t;
|
||||
|
||||
typedef struct GsmL1_MphActivateCnf_t {
|
||||
enum GsmL1_Status_t status;
|
||||
uint8_t u8Tn;
|
||||
int sapi;
|
||||
} GsmL1_MphActivateCnf_t;
|
||||
|
||||
typedef struct GsmL1_MphDeactivateCnf_t {
|
||||
enum GsmL1_Status_t status;
|
||||
uint8_t u8Tn;
|
||||
enum GsmL1_Sapi_t sapi;
|
||||
} GsmL1_MphDeactivateCnf_t;
|
||||
|
||||
typedef struct GsmL1_MphMeasureCnf_t {
|
||||
enum GsmL1_Status_t status;
|
||||
} GsmL1_MphMeasureCnf_t;
|
||||
|
||||
typedef struct GsmL1_MphTimeInd_t {
|
||||
uint32_t u32Fn;
|
||||
} GsmL1_MphTimeInd_t;
|
||||
|
||||
typedef struct GsmL1_MphSyncInd_t {
|
||||
} GsmL1_MphSyncInd_t;
|
||||
|
||||
typedef struct GsmL1_PhEmptyFrameReq_t {
|
||||
uint32_t hLayer1;
|
||||
uint8_t u8Tn;
|
||||
uint32_t u32Fn;
|
||||
enum GsmL1_Sapi_t sapi;
|
||||
enum GsmL1_SubCh_t subCh;
|
||||
uint8_t u8BlockNbr;
|
||||
} GsmL1_PhEmptyFrameReq_t;
|
||||
|
||||
typedef struct GsmL1_PhDataReq_t {
|
||||
uint32_t hLayer1;
|
||||
uint8_t u8Tn;
|
||||
uint32_t u32Fn;
|
||||
enum GsmL1_Sapi_t sapi;
|
||||
enum GsmL1_SubCh_t subCh;
|
||||
uint8_t u8BlockNbr;
|
||||
struct GsmL1_MsgUnitParam_t msgUnitParam;
|
||||
} GsmL1_PhDataReq_t;
|
||||
|
||||
typedef struct GsmL1_PhConnectInd_t {
|
||||
} GsmL1_PhConnectInd_t;
|
||||
|
||||
typedef struct GsmL1_PhReadyToSendInd_t {
|
||||
uint32_t hLayer1;
|
||||
uint8_t u8Tn;
|
||||
uint32_t u32Fn;
|
||||
enum GsmL1_Sapi_t sapi;
|
||||
enum GsmL1_SubCh_t subCh;
|
||||
uint8_t u8BlockNbr;
|
||||
uint32_t hLayer2;
|
||||
} GsmL1_PhReadyToSendInd_t;
|
||||
|
||||
typedef struct GsmL1_PhDataInd_t {
|
||||
struct GsmL1_MeasParam_t measParam;
|
||||
struct GsmL1_MsgUnitParam_t msgUnitParam;
|
||||
enum GsmL1_Sapi_t sapi;
|
||||
uint32_t hLayer2;
|
||||
} GsmL1_PhDataInd_t;
|
||||
|
||||
typedef struct GsmL1_PhRaInd_t {
|
||||
struct GsmL1_MeasParam_t measParam;
|
||||
struct GsmL1_MsgUnitParam_t msgUnitParam;
|
||||
uint32_t u32Fn;
|
||||
uint32_t hLayer2;
|
||||
} GsmL1_PhRaInd_t;
|
||||
|
||||
typedef struct GsmL1_Prim_t {
|
||||
union {
|
||||
struct GsmL1_MphInitReq_t mphInitReq;
|
||||
struct GsmL1_MphCloseReq_t mphCloseReq;
|
||||
struct GsmL1_MphConnectReq_t mphConnectReq;
|
||||
struct GsmL1_MphDisconnectReq_t mphDisconnectReq;
|
||||
struct GsmL1_MphActivateReq_t mphActivateReq;
|
||||
struct GsmL1_MphDeactivateReq_t mphDeactivateReq;
|
||||
struct GsmL1_MphConfigReq_t mphConfigReq;
|
||||
struct GsmL1_MphMeasureReq_t mphMeasureReq;
|
||||
struct GsmL1_MphInitCnf_t mphInitCnf;
|
||||
struct GsmL1_MphCloseCnf_t mphCloseCnf;
|
||||
struct GsmL1_MphConnectCnf_t mphConnectCnf;
|
||||
struct GsmL1_MphDisconnectCnf_t mphDisconnectCnf;
|
||||
struct GsmL1_MphActivateCnf_t mphActivateCnf;
|
||||
struct GsmL1_MphDeactivateCnf_t mphDeactivateCnf;
|
||||
struct GsmL1_MphConfigCnf_t mphConfigCnf;
|
||||
struct GsmL1_MphMeasureCnf_t mphMeasureCnf;
|
||||
struct GsmL1_MphTimeInd_t mphTimeInd;
|
||||
struct GsmL1_MphSyncInd_t mphSyncInd;
|
||||
struct GsmL1_PhEmptyFrameReq_t phEmptyFrameReq;
|
||||
struct GsmL1_PhDataReq_t phDataReq;
|
||||
struct GsmL1_PhConnectInd_t phConnectInd;
|
||||
struct GsmL1_PhReadyToSendInd_t phReadyToSendInd;
|
||||
struct GsmL1_PhDataInd_t phDataInd;
|
||||
struct GsmL1_PhRaInd_t phRaInd;
|
||||
} u;
|
||||
|
||||
enum GsmL1_PrimId_t id;
|
||||
} GsmL1_Prim_t;
|
|
@ -26,34 +26,99 @@
|
|||
#define MAX_UDP_LENGTH 1500
|
||||
|
||||
// TODO: We should take ports and IP from config.
|
||||
UDPSocket pcu_l1if_socket(5070, "127.0.0.1", 5934);
|
||||
UDPSocket pcu_gsmtap_socket(5077, "127.0.0.1", 4729);
|
||||
|
||||
|
||||
struct msgb *l1p_msgb_alloc(void)
|
||||
{
|
||||
struct msgb *msg = msgb_alloc(sizeof(GsmL1_Prim_t), "l1_prim");
|
||||
|
||||
if (msg)
|
||||
msg->l1h = msgb_put(msg, sizeof(GsmL1_Prim_t));
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
// Send RLC/MAC block to OpenBTS.
|
||||
void pcu_l1if_tx(BitVector * block)
|
||||
{
|
||||
char buffer[MAX_UDP_LENGTH];
|
||||
int ofs = 0;
|
||||
block->pack((unsigned char*)&buffer[ofs]);
|
||||
struct msgb *msg = l1p_msgb_alloc();
|
||||
GsmL1_Prim_t *prim = msgb_l1prim(msg);
|
||||
|
||||
prim->id = GsmL1_PrimId_PhDataReq;
|
||||
block->pack((unsigned char*)&(prim->u.phDataReq.msgUnitParam.u8Buffer[ofs]));
|
||||
ofs += block->size() >> 3;
|
||||
prim->u.phDataReq.msgUnitParam.u8Size = ofs;
|
||||
|
||||
COUT("Send to OpenBTS: " << *block);
|
||||
pcu_l1if_socket.write(buffer, ofs);
|
||||
osmo_wqueue_enqueue(&l1fh->udp_wq, msg);
|
||||
}
|
||||
|
||||
// Recieve RLC/MAC block from OpenBTS.
|
||||
void *pcu_l1if_rx(void *)
|
||||
int pcu_l1if_rx_pdch(GsmL1_PhDataInd_t *data_ind)
|
||||
{
|
||||
BitVector *block = new BitVector(23*8);
|
||||
pcu_l1if_socket.nonblocking();
|
||||
while (1) {
|
||||
char buf[MAX_UDP_LENGTH];
|
||||
int count = pcu_l1if_socket.read(buf, 3000);
|
||||
if (count>0) {
|
||||
block->unpack((const unsigned char*)buf);
|
||||
block->unpack((const unsigned char*)data_ind->msgUnitParam.u8Buffer);
|
||||
COUT("Recieve from OpenBTS (MS): " << *block);
|
||||
|
||||
gprs_rlcmac_rcv_block(block);
|
||||
}
|
||||
|
||||
static int handle_ph_data_ind(struct femtol1_hdl *fl1, GsmL1_PhDataInd_t *data_ind,
|
||||
struct msgb *l1p_msg)
|
||||
{
|
||||
int rc = 0;
|
||||
switch (data_ind->sapi) {
|
||||
case GsmL1_Sapi_Rach:
|
||||
break;
|
||||
case GsmL1_Sapi_Pdtch:
|
||||
case GsmL1_Sapi_Pacch:
|
||||
pcu_l1if_rx_pdch(data_ind);
|
||||
break;
|
||||
case GsmL1_Sapi_Pbcch:
|
||||
case GsmL1_Sapi_Pagch:
|
||||
case GsmL1_Sapi_Ppch:
|
||||
case GsmL1_Sapi_Pnch:
|
||||
case GsmL1_Sapi_Ptcch:
|
||||
case GsmL1_Sapi_Prach:
|
||||
break;
|
||||
default:
|
||||
//LOGP(DGPRS, LOGL_NOTICE, "Rx PH-DATA.ind for unknown L1 SAPI %u \n", data_ind->sapi);
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* handle any random indication from the L1 */
|
||||
int pcu_l1if_handle_l1prim(struct femtol1_hdl *fl1, struct msgb *msg)
|
||||
{
|
||||
GsmL1_Prim_t *l1p = msgb_l1prim(msg);
|
||||
int rc = 0;
|
||||
|
||||
switch (l1p->id) {
|
||||
case GsmL1_PrimId_MphTimeInd:
|
||||
break;
|
||||
case GsmL1_PrimId_MphSyncInd:
|
||||
break;
|
||||
case GsmL1_PrimId_PhConnectInd:
|
||||
break;
|
||||
case GsmL1_PrimId_PhReadyToSendInd:
|
||||
break;
|
||||
case GsmL1_PrimId_PhDataInd:
|
||||
rc = handle_ph_data_ind(fl1, &l1p->u.phDataInd, msg);
|
||||
break;
|
||||
case GsmL1_PrimId_PhRaInd:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Special return value '1' means: do not free */
|
||||
if (rc != 1)
|
||||
msgb_free(msg);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void gsmtap_send_llc(uint8_t * data, unsigned len)
|
||||
|
|
39
pcu_l1_if.h
39
pcu_l1_if.h
|
@ -20,11 +20,48 @@
|
|||
#ifndef PCU_L1_IF_H
|
||||
#define PCU_L1_IF_H
|
||||
|
||||
|
||||
#include <BitVector.h>
|
||||
#include <gsmL1prim.h>
|
||||
extern "C" {
|
||||
#include <osmocom/core/write_queue.h>
|
||||
#include <osmocom/core/socket.h>
|
||||
#include <osmocom/core/timer.h>
|
||||
#include <osmocom/gsm/gsm_utils.h>
|
||||
}
|
||||
|
||||
#define msgb_l1prim(msg) ((GsmL1_Prim_t *)(msg)->l1h)
|
||||
|
||||
struct femtol1_hdl {
|
||||
struct gsm_time gsm_time;
|
||||
uint32_t hLayer1; /* handle to the L1 instance in the DSP */
|
||||
uint32_t dsp_trace_f;
|
||||
uint16_t clk_cal;
|
||||
struct llist_head wlc_list;
|
||||
|
||||
void *priv; /* user reference */
|
||||
|
||||
struct osmo_timer_list alive_timer;
|
||||
unsigned int alive_prim_cnt;
|
||||
|
||||
struct osmo_fd read_ofd; /* osmo file descriptors */
|
||||
struct osmo_wqueue write_q;
|
||||
};
|
||||
|
||||
struct l1fwd_hdl {
|
||||
struct sockaddr_storage remote_sa;
|
||||
socklen_t remote_sa_len;
|
||||
|
||||
struct osmo_wqueue udp_wq;
|
||||
|
||||
struct femtol1_hdl *fl1h;
|
||||
};
|
||||
|
||||
extern struct l1fwd_hdl *l1fh;
|
||||
|
||||
void pcu_l1if_tx(BitVector * block);
|
||||
|
||||
void *pcu_l1if_rx(void *);
|
||||
int pcu_l1if_handle_l1prim(struct femtol1_hdl *fl1h, struct msgb *msg);
|
||||
|
||||
void gsmtap_send_llc(uint8_t * data, unsigned len);
|
||||
|
||||
|
|
93
pcu_main.cpp
93
pcu_main.cpp
|
@ -26,7 +26,9 @@
|
|||
#define SGSN_IP "127.0.0.1"
|
||||
#define SGSN_PORT 23000
|
||||
#define NSVCI 4
|
||||
#define PCU_L1_IF_PORT 5944
|
||||
|
||||
struct l1fwd_hdl *l1fh = talloc_zero(NULL, struct l1fwd_hdl);
|
||||
|
||||
int sgsn_ns_cb(enum gprs_ns_evt event, struct gprs_nsvc *nsvc, struct msgb *msg, uint16_t bvci)
|
||||
{
|
||||
|
@ -46,16 +48,100 @@ int sgsn_ns_cb(enum gprs_ns_evt event, struct gprs_nsvc *nsvc, struct msgb *msg,
|
|||
return rc;
|
||||
}
|
||||
|
||||
/* data has arrived on the udp socket */
|
||||
static int udp_read_cb(struct osmo_fd *ofd)
|
||||
{
|
||||
struct msgb *msg = msgb_alloc_headroom(2048, 128, "udp_rx");
|
||||
struct l1fwd_hdl *l1fh = (l1fwd_hdl *)ofd->data;
|
||||
struct femtol1_hdl *fl1h = l1fh->fl1h;
|
||||
int rc;
|
||||
|
||||
if (!msg)
|
||||
return -ENOMEM;
|
||||
|
||||
msg->l1h = msg->data;
|
||||
|
||||
l1fh->remote_sa_len = sizeof(l1fh->remote_sa);
|
||||
rc = recvfrom(ofd->fd, msg->l1h, msgb_tailroom(msg), 0,
|
||||
(struct sockaddr *) &l1fh->remote_sa, &l1fh->remote_sa_len);
|
||||
if (rc < 0) {
|
||||
perror("read from udp");
|
||||
msgb_free(msg);
|
||||
return rc;
|
||||
} else if (rc == 0) {
|
||||
perror("len=0 read from udp");
|
||||
msgb_free(msg);
|
||||
return rc;
|
||||
}
|
||||
msgb_put(msg, rc);
|
||||
|
||||
rc = pcu_l1if_handle_l1prim(fl1h, msg);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* callback when we can write to the UDP socket */
|
||||
static int udp_write_cb(struct osmo_fd *ofd, struct msgb *msg)
|
||||
{
|
||||
int rc;
|
||||
struct l1fwd_hdl *l1fh = (l1fwd_hdl *)ofd->data;
|
||||
|
||||
DEBUGP(DGPRS, "UDP: Writing %u bytes for MQ_L1_WRITE queue\n", msgb_l1len(msg));
|
||||
|
||||
rc = sendto(ofd->fd, msg->l1h, msgb_l1len(msg), 0,
|
||||
(const struct sockaddr *)&l1fh->remote_sa, l1fh->remote_sa_len);
|
||||
if (rc < 0) {
|
||||
LOGP(DGPRS, LOGL_ERROR, "error writing to L1 msg_queue: %s\n",
|
||||
strerror(errno));
|
||||
return rc;
|
||||
} else if (rc < msgb_l1len(msg)) {
|
||||
LOGP(DGPRS, LOGL_ERROR, "short write to L1 msg_queue: "
|
||||
"%u < %u\n", rc, msgb_l1len(msg));
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pcu_l1if_open()
|
||||
{
|
||||
//struct l1fwd_hdl *l1fh;
|
||||
struct femtol1_hdl *fl1h;
|
||||
int rc;
|
||||
|
||||
/* allocate new femtol1_handle */
|
||||
fl1h = talloc_zero(NULL, struct femtol1_hdl);
|
||||
INIT_LLIST_HEAD(&fl1h->wlc_list);
|
||||
|
||||
l1fh->fl1h = fl1h;
|
||||
fl1h->priv = l1fh;
|
||||
|
||||
/* Open UDP */
|
||||
struct osmo_wqueue *wq = &l1fh->udp_wq;
|
||||
|
||||
osmo_wqueue_init(wq, 10);
|
||||
wq->write_cb = udp_write_cb;
|
||||
wq->read_cb = udp_read_cb;
|
||||
wq->bfd.when |= BSC_FD_READ;
|
||||
wq->bfd.data = l1fh;
|
||||
wq->bfd.priv_nr = 0;
|
||||
rc = osmo_sock_init_ofd(&wq->bfd, AF_UNSPEC, SOCK_DGRAM,
|
||||
IPPROTO_UDP, NULL, PCU_L1_IF_PORT,
|
||||
OSMO_SOCK_F_BIND);
|
||||
if (rc < 0) {
|
||||
perror("sock_init");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
uint16_t nsvci = NSVCI;
|
||||
struct gprs_ns_inst *sgsn_nsi;
|
||||
struct gprs_nsvc *nsvc;
|
||||
// Socket for reading BitVectors (RLC/MAC Frames) from OpenBTS application.
|
||||
Thread pcu_l1if;
|
||||
pcu_l1if.start(pcu_l1if_rx, NULL);
|
||||
|
||||
osmo_init_logging(&log_info);
|
||||
pcu_l1if_open();
|
||||
|
||||
sgsn_nsi = gprs_ns_instantiate(&sgsn_ns_cb);
|
||||
bssgp_nsi = sgsn_nsi;
|
||||
|
||||
|
@ -92,3 +178,4 @@ int main(int argc, char *argv[])
|
|||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue