[PATCH 03/20] Add BCCH message to PH-/MPH-/TCH-SAP interface

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.com
Sun Oct 6 20:56:15 UTC 2013


Looks 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




More information about the OpenBSC mailing list