This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/OpenBSC@lists.osmocom.org/.
Alexander Chemeris alexander.chemeris at gmail.comLooks good to me from the code structure perspective. On Thu, Sep 19, 2013 at 2:11 PM, Andreas Eversberg <jolly at eversberg.eu> wrote: > This first part moves BCCH message primitives from osmo-bts-sysmo to common > part. A new file "common/l1sap.c" is introduced to implement handling of > layer 1 messages from/to BTS model. > --- > include/osmo-bts/bts_model.h | 2 + > src/common/Makefile.am | 2 +- > src/common/l1sap.c | 150 ++++++++++++++++++++++++++++++++++++++ > src/osmo-bts-sysmo/l1_if.c | 167 +++++++++++++++++++++++++++++++++++++++---- > tests/stubs.c | 2 + > 5 files changed, 310 insertions(+), 13 deletions(-) > create mode 100644 src/common/l1sap.c > > diff --git a/include/osmo-bts/bts_model.h b/include/osmo-bts/bts_model.h > index bfa6bd8..f6545cc 100644 > --- a/include/osmo-bts/bts_model.h > +++ b/include/osmo-bts/bts_model.h > @@ -43,4 +43,6 @@ int bts_model_vty_init(struct gsm_bts *bts); > void bts_model_config_write_bts(struct vty *vty, struct gsm_bts *bts); > void bts_model_config_write_trx(struct vty *vty, struct gsm_bts_trx *trx); > > +int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap); > + > #endif > diff --git a/src/common/Makefile.am b/src/common/Makefile.am > index b2f6f8e..1c6ff9e 100644 > --- a/src/common/Makefile.am > +++ b/src/common/Makefile.am > @@ -5,4 +5,4 @@ LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOTRAU_LIBS) > noinst_LIBRARIES = libbts.a > libbts_a_SOURCES = gsm_data_shared.c sysinfo.c logging.c abis.c oml.c bts.c \ > rsl.c vty.c paging.c measurement.c amr.c lchan.c \ > - load_indication.c pcu_sock.c > + load_indication.c pcu_sock.c l1sap.c > diff --git a/src/common/l1sap.c b/src/common/l1sap.c > new file mode 100644 > index 0000000..f4f3246 > --- /dev/null > +++ b/src/common/l1sap.c > @@ -0,0 +1,150 @@ > +/* L1 SAP primitives */ > + > +/* (C) 2011 by Harald Welte <laforge at gnumonks.org> > + * (C) 2013 by Andreas Eversberg <jolly at eversberg.eu> > + * > + * All Rights Reserved > + * > + * 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 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/>. > + * > + */ > + > +#include <stdint.h> > +#include <unistd.h> > +#include <errno.h> > +#include <fcntl.h> > + > +#include <sys/types.h> > +#include <sys/stat.h> > + > +#include <osmocom/core/msgb.h> > +#include <osmocom/gsm/l1sap.h> > +#include <osmocom/core/gsmtap.h> > +#include <osmocom/core/gsmtap_util.h> > +#include <osmocom/core/utils.h> > + > +#include <osmocom/trau/osmo_ortp.h> > + > +#include <osmo-bts/logging.h> > +#include <osmo-bts/gsm_data.h> > +#include <osmo-bts/l1sap.h> > +#include <osmo-bts/pcu_if.h> > +#include <osmo-bts/measurement.h> > +#include <osmo-bts/bts.h> > +#include <osmo-bts/rsl.h> > +#include <osmo-bts/bts_model.h> > + > +static int l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap); > + > +static const uint8_t fill_frame[GSM_MACBLOCK_LEN] = { > + 0x03, 0x03, 0x01, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, > + 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, > + 0x2B, 0x2B, 0x2B > +}; > + > +/* allocate a msgb containing a osmo_phsap_prim + optional l2 data > + * in order to wrap femtobts header arround l2 data, there must be enough space > + * in front and behind data pointer */ > +struct msgb *l1sap_msgb_alloc(unsigned int l2_len) > +{ > + struct msgb *msg = msgb_alloc_headroom(512, 128, "l1sap_prim"); > + > + if (!msg) > + return NULL; > + > + msg->l1h = msgb_put(msg, sizeof(struct osmo_phsap_prim)); > + > + return msg; > +} > + > +/* PH-RTS-IND prim recevied from bts model */ > +static int l1sap_ph_rts_ind(struct gsm_bts_trx *trx, > + struct osmo_phsap_prim *l1sap, struct ph_data_param *rts_ind) > +{ > + struct msgb *msg = l1sap->oph.msg; > + struct gsm_time g_time; > + uint8_t chan_nr, link_id; > + uint8_t tn; > + uint32_t fn; > + uint8_t *p, *si; > + > + chan_nr = rts_ind->chan_nr; > + link_id = rts_ind->link_id; > + fn = rts_ind->fn; > + tn = L1SAP_CHAN2TS(chan_nr); > + > + gsm_fn2gsmtime(&g_time, fn); > + > + DEBUGP(DL1P, "Rx PH-RTS.ind %02u/%02u/%02u chan_nr=%d link_id=%d\n", > + g_time.t1, g_time.t2, g_time.t3, chan_nr, link_id); > + > + /* reuse PH-RTS.ind for PH-DATA.req */ > + if (!msg) { > + LOGP(DL1P, LOGL_FATAL, "RTS without msg to be reused. Please " > + "fix!\n"); > + abort(); > + } > + msgb_trim(msg, sizeof(*l1sap)); > + osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_PH_DATA, PRIM_OP_REQUEST, > + msg); > + msg->l2h = msg->l1h + sizeof(*l1sap); > + > + if (L1SAP_IS_CHAN_BCCH(chan_nr)) { > + p = msgb_put(msg, GSM_MACBLOCK_LEN); > + /* get them from bts->si_buf[] */ > + si = bts_sysinfo_get(trx->bts, &g_time); > + if (si) > + memcpy(p, si, GSM_MACBLOCK_LEN); > + else > + memcpy(p, fill_frame, GSM_MACBLOCK_LEN); > + } > + > + DEBUGP(DL1P, "Tx PH-DATA.req %02u/%02u/%02u chan_nr=%d link_id=%d\n", > + g_time.t1, g_time.t2, g_time.t3, chan_nr, link_id); > + > + l1sap_down(trx, l1sap); > + > + /* don't free, because we forwarded data */ > + return 1; > +} > + > +/* any L1 prim received from bts model */ > +int l1sap_up(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) > +{ > + struct msgb *msg = l1sap->oph.msg; > + int rc = 0; > + > + switch (OSMO_PRIM_HDR(&l1sap->oph)) { > + case OSMO_PRIM(PRIM_PH_RTS, PRIM_OP_INDICATION): > + rc = l1sap_ph_rts_ind(trx, l1sap, &l1sap->u.data); > + break; > + default: > + LOGP(DL1P, LOGL_NOTICE, "unknown prim %d op %d\n", > + l1sap->oph.primitive, l1sap->oph.operation); > + break; > + } > + > + /* Special return value '1' means: do not free */ > + if (rc != 1) > + msgb_free(msg); > + > + return rc; > +} > + > +/* any L1 prim sent to bts model */ > +static int l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) > +{ > + return bts_model_l1sap_down(trx, l1sap); > +} > + > diff --git a/src/osmo-bts-sysmo/l1_if.c b/src/osmo-bts-sysmo/l1_if.c > index e16bb49..93b4de7 100644 > --- a/src/osmo-bts-sysmo/l1_if.c > +++ b/src/osmo-bts-sysmo/l1_if.c > @@ -47,6 +47,7 @@ > #include <osmo-bts/paging.h> > #include <osmo-bts/measurement.h> > #include <osmo-bts/pcu_if.h> > +#include <osmo-bts/l1sap.h> > > #include <sysmocom/femtobts/superfemto.h> > #include <sysmocom/femtobts/gsml1prim.h> > @@ -366,8 +367,135 @@ static const uint8_t fill_frame[GSM_MACBLOCK_LEN] = { > 0x2B, 0x2B, 0x2B > }; > > +static int ph_data_req(struct gsm_bts_trx *trx, struct msgb *msg, > + struct osmo_phsap_prim *l1sap) > +{ > + struct femtol1_hdl *fl1 = trx_femtol1_hdl(trx); > + uint32_t u32Fn; > + uint8_t u8Tn, subCh, u8BlockNbr = 0, sapi; > + uint8_t chan_nr, link_id; > + GsmL1_Prim_t *l1p; > + int len; > + > + if (!msg) { > + LOGP(DL1C, LOGL_FATAL, "PH-DATA.req without msg. " > + "Please fix!\n"); > + abort(); > + } > + chan_nr = l1sap->u.data.chan_nr; > + link_id = l1sap->u.data.link_id; > + u32Fn = l1sap->u.data.fn; > + u8Tn = L1SAP_CHAN2TS(chan_nr); > + subCh = 0x1f; > + if (L1SAP_IS_CHAN_BCCH(chan_nr)) { > + sapi = GsmL1_Sapi_Bcch; > + } else { > + LOGP(DL1C, LOGL_NOTICE, "unknown prim %d op %d " > + "chan_nr %d link_id %d\n", l1sap->oph.primitive, > + l1sap->oph.operation, chan_nr, link_id); > + return -EINVAL; > + } > + > + /* pull and trim msg to start of payload */ > + msgb_pull(msg, sizeof(*l1sap)); > + len = msg->len; > + msgb_trim(msg, 0); > + > + /* convert l1sap message to GsmL1 primitive, keep payload */ > + if (len) { > + /* data request */ > + GsmL1_PhDataReq_t *data_req; > + GsmL1_MsgUnitParam_t *msu_param; > + uint8_t *temp; > + > + /* wrap zeroed l1p structure arrount payload > + * this must be done in three steps, since the actual > + * payload is not at the end but inside the l1p structure. */ > + temp = l1p->u.phDataReq.msgUnitParam.u8Buffer; > + msgb_push(msg, temp - (uint8_t *)l1p); > + memset(msg->data, 0, msg->len); > + msgb_put(msg, len); > + memset(msg->tail, 0, sizeof(*l1p) - msg->len); > + msgb_put(msg, sizeof(*l1p) - msg->len); > + msg->l1h = msg->data; > + > + l1p = msgb_l1prim(msg); > + l1p->id = GsmL1_PrimId_PhDataReq; > + data_req = &l1p->u.phDataReq; > + data_req->hLayer1 = fl1->hLayer1; > + data_req->u8Tn = u8Tn; > + data_req->u32Fn = u32Fn; > + data_req->sapi = sapi; > + data_req->subCh = subCh; > + data_req->u8BlockNbr = u8BlockNbr; > + msu_param = &data_req->msgUnitParam; > + msu_param->u8Size = len; > + } else { > + /* empty frame */ > + GsmL1_PhEmptyFrameReq_t *empty_req; > + > + /* put l1p structure */ > + msgb_put(msg, sizeof(*l1p)); > + memset(msg->data, 0, msg->len); > + msg->l1h = msg->data; > + > + l1p = msgb_l1prim(msg); > + l1p->id = GsmL1_PrimId_PhEmptyFrameReq; > + empty_req = &l1p->u.phEmptyFrameReq; > + empty_req->hLayer1 = fl1->hLayer1; > + empty_req->u8Tn = u8Tn; > + empty_req->u32Fn = u32Fn; > + empty_req->sapi = sapi; > + empty_req->subCh = subCh; > + empty_req->u8BlockNbr = u8BlockNbr; > + } > + > + /* send message to DSP's queue */ > + osmo_wqueue_enqueue(&fl1->write_q[MQ_L1_WRITE], msg); > + > + return 0; > +} > + > +/* primitive from common part */ > +int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) > +{ > + struct msgb *msg = l1sap->oph.msg; > + int rc = 0; > + > + switch (OSMO_PRIM_HDR(&l1sap->oph)) { > + case OSMO_PRIM(PRIM_PH_DATA, PRIM_OP_REQUEST): > + rc = ph_data_req(trx, msg, l1sap); > + break; > + default: > + LOGP(DL1C, LOGL_NOTICE, "unknown prim %d op %d\n", > + l1sap->oph.primitive, l1sap->oph.operation); > + rc = -EINVAL; > + } > + > + if (rc) > + msgb_free(msg); > + return rc; > +} > + > +static uint8_t chan_nr_by_sapi(enum gsm_phys_chan_config pchan, > + GsmL1_Sapi_t sapi, GsmL1_SubCh_t subCh, > + uint8_t u8Tn, uint32_t u32Fn) > +{ > + uint8_t cbits = 0; > + switch (sapi) { > + case GsmL1_Sapi_Bcch: > + cbits = 0x10; > + break; > + default: > + return 0; > + } > + > + return (cbits << 3) | u8Tn; > +} > + > static int handle_ph_readytosend_ind(struct femtol1_hdl *fl1, > - GsmL1_PhReadyToSendInd_t *rts_ind) > + GsmL1_PhReadyToSendInd_t *rts_ind, > + struct msgb *l1p_msg) > { > struct gsm_bts_trx *trx = fl1->priv; > struct gsm_bts *bts = trx->bts; > @@ -379,9 +507,31 @@ static int handle_ph_readytosend_ind(struct femtol1_hdl *fl1, > struct gsm_lchan *lchan; > struct gsm_time g_time; > uint32_t t3p; > - uint8_t *si; > struct osmo_phsap_prim pp; > int rc; > + struct osmo_phsap_prim *l1sap; > + uint8_t chan_nr, link_id; > + uint32_t fn; > + > + > + /* check if primitive should be handled by common part */ > + chan_nr = chan_nr_by_sapi(trx->ts[rts_ind->u8Tn].pchan, rts_ind->sapi, > + rts_ind->subCh, rts_ind->u8Tn, rts_ind->u32Fn); > + if (chan_nr) { > + fn = rts_ind->u32Fn; > + link_id = 0; > + rc = msgb_trim(l1p_msg, sizeof(*l1sap)); > + if (rc < 0) > + MSGB_ABORT(l1p_msg, "No room for primitive\n"); > + l1sap = msgb_l1sap_prim(l1p_msg); > + osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_PH_RTS, > + PRIM_OP_INDICATION, l1p_msg); > + l1sap->u.data.link_id = link_id; > + l1sap->u.data.chan_nr = chan_nr; > + l1sap->u.data.fn = fn; > + > + return l1sap_up(trx, l1sap); > + } > > gsm_fn2gsmtime(&g_time, rts_ind->u32Fn); > > @@ -460,14 +610,6 @@ static int handle_ph_readytosend_ind(struct femtol1_hdl *fl1, > msu_param->u8Buffer[2] = (g_time.t1 << 7) | (g_time.t2 << 2) | (t3p >> 1); > msu_param->u8Buffer[3] = (t3p & 1); > break; > - case GsmL1_Sapi_Bcch: > - /* get them from bts->si_buf[] */ > - si = bts_sysinfo_get(bts, &g_time); > - if (si) > - memcpy(msu_param->u8Buffer, si, GSM_MACBLOCK_LEN); > - else > - memcpy(msu_param->u8Buffer, fill_frame, GSM_MACBLOCK_LEN); > - break; > case GsmL1_Sapi_Sacch: > /* resolve the L2 entity using rts_ind->hLayer2 */ > lchan = l1if_hLayer_to_lchan(trx, rts_ind->hLayer2); > @@ -555,6 +697,7 @@ tx: > /* transmit */ > osmo_wqueue_enqueue(&fl1->write_q[MQ_L1_WRITE], resp_msg); > > + msgb_free(l1p_msg); > return 0; > > empty_frame: > @@ -885,8 +1028,8 @@ static int l1if_handle_ind(struct femtol1_hdl *fl1, struct msgb *msg) > case GsmL1_PrimId_PhConnectInd: > break; > case GsmL1_PrimId_PhReadyToSendInd: > - rc = handle_ph_readytosend_ind(fl1, &l1p->u.phReadyToSendInd); > - break; > + return handle_ph_readytosend_ind(fl1, &l1p->u.phReadyToSendInd, > + msg); > case GsmL1_PrimId_PhDataInd: > rc = handle_ph_data_ind(fl1, &l1p->u.phDataInd, msg); > break; > diff --git a/tests/stubs.c b/tests/stubs.c > index c46bb4a..64b30c0 100644 > --- a/tests/stubs.c > +++ b/tests/stubs.c > @@ -39,6 +39,8 @@ int bts_model_rsl_mode_modify(struct gsm_lchan *lchan) > { return 0; } > void bts_model_rtp_rx_cb(struct osmo_rtp_socket *rs, const uint8_t *rtp_pl, > unsigned int rtp_pl_len) {} > +int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) > +{ return 0; } > > int l1if_pdch_req(struct gsm_bts_trx_ts *ts, int is_ptcch, uint32_t fn, > uint16_t arfcn, uint8_t block_nr, uint8_t *data, uint8_t len) > -- > 1.8.1.5 > > -- Regards, Alexander Chemeris. CEO, Fairwaves LLC / ООО УмРадио http://fairwaves.ru