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/gerrit-log@lists.osmocom.org/.
neels gerrit-no-reply at lists.osmocom.orgneels has uploaded this change for review. ( https://gerrit.osmocom.org/c/libosmocore/+/20333 ) Change subject: add BSSLAP coding for Location Services ...................................................................... add BSSLAP coding for Location Services BSSLAP: there are APDUs transferred in BSSMAP-LE Connection Oriented Information messages on Lb between BSC and SMLC. Add BSSLAP coding for these APDU messages: - TA Layer3 - TA Request - TA Response, possibly containing Location Estimate coded in GAD - Reject - Reset (for intra-BSS handover during TA Request) - Abort (for inter-BSS handover) Add encoding and decoding tests. Change-Id: I6409c4bcac402dc7626a3afce9081c59cd715fe8 --- M include/Makefile.am A include/osmocom/gsm/bsslap.h M src/gsm/Makefile.am A src/gsm/bsslap.c M src/gsm/libosmogsm.map M tests/Makefile.am A tests/bsslap/bsslap_test.c A tests/bsslap/bsslap_test.ok M tests/testsuite.at 9 files changed, 691 insertions(+), 1 deletion(-) git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/33/20333/1 diff --git a/include/Makefile.am b/include/Makefile.am index a505952..7aa6442 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -92,6 +92,7 @@ osmocom/coding/gsm0503_interleaving.h \ osmocom/coding/gsm0503_coding.h \ osmocom/coding/gsm0503_amr_dtx.h \ + osmocom/gsm/bsslap.h \ osmocom/gsm/gad.h \ osmocom/gsm/gsm0808.h \ osmocom/gsm/gsm29205.h \ diff --git a/include/osmocom/gsm/bsslap.h b/include/osmocom/gsm/bsslap.h new file mode 100644 index 0000000..135a943 --- /dev/null +++ b/include/osmocom/gsm/bsslap.h @@ -0,0 +1,105 @@ +/*! \defgroup bsslap Message encoding and decoding for 3GPP TS 48.071 BSS LCS Assistance Protocol (BSSLAP). + * @{ + * \file bsslap.h + */ +/* + * (C) 2020 by sysmocom - s.f.m.c. GmbH <info at sysmocom.de> + * All Rights Reserved + * + * Author: Neels Hofmeyr <neels at hofmeyr.de> + * + * SPDX-License-Identifier: GPL-2.0+ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ +#pragma once + +#include <errno.h> + +#include <osmocom/core/utils.h> +#include <osmocom/gsm/protocol/gsm_08_08.h> +#include <osmocom/gsm/gsm0808.h> +#include <osmocom/gsm/tlv.h> + +enum osmo_bsslap_msgt { + OSMO_BSSLAP_MSGT_TA_REQUEST = 0x1, + OSMO_BSSLAP_MSGT_TA_RESPONSE = 0x2, + OSMO_BSSLAP_MSGT_REJECT = 0xa, + OSMO_BSSLAP_MSGT_RESET = 0xb, + OSMO_BSSLAP_MSGT_ABORT = 0xc, + OSMO_BSSLAP_MSGT_TA_LAYER3 = 0xd, + OSMO_BSSLAP_MSGT_MS_POS_CMD = 0xf, + OSMO_BSSLAP_MSGT_MS_POS_RESP = 0x10, + OSMO_BSSLAP_MSGT_UTDOA_REQ = 0x11, + OSMO_BSSLAP_MSGT_UTDOA_RESP = 0x12, +}; + +extern const struct value_string osmo_bsslap_msgt_names[]; +static inline const char *osmo_bsslap_msgt_name(enum osmo_bsslap_msgt val) +{ return get_value_string(osmo_bsslap_msgt_names, val); } + +enum osmo_bsslap_cause { + OSMO_BSSLAP_CAUSE_CONGESTION = 0x0, + OSMO_BSSLAP_CAUSE_CHAN_MODE_NOT_SUPP = 0x1, + OSMO_BSSLAP_CAUSE_POS_PROC_NOT_SUPP = 0x2, + OSMO_BSSLAP_CAUSE_OTHER_RADIO_EVT_FAIL = 0x3, + OSMO_BSSLAP_CAUSE_INTRA_BSS_HO = 0x4, + OSMO_BSSLAP_CAUSE_SUPERV_TIMER_EXPIRED = 0x5, + OSMO_BSSLAP_CAUSE_INTER_BSS_HO = 0x6, + OSMO_BSSLAP_CAUSE_LOSS_SIG_CONN_MS = 0x7, + OSMO_BSSLAP_CAUSE_INCORR_SERV_CELL_ID = 0x8, + OSMO_BSSLAP_CAUSE_BSSAP_LE_SEGMENT_ERR = 0x9, + OSMO_BSSLAP_CAUSE_CONCUR_POS_PROC_NOT_EN = 0xa, +}; + +struct osmo_bsslap_ta_response { + uint16_t cell_id; + uint8_t ta; + + bool more_items; /*!< always set this to false */ +}; + +struct osmo_bsslap_ta_layer3 { + uint8_t ta; + + bool more_items; /*!< always set this to false */ +}; + +struct osmo_bsslap_reset { + uint16_t cell_id; + uint8_t ta; + struct gsm48_chan_desc chan_desc; + enum osmo_bsslap_cause cause; + + bool more_items; /*!< always set this to false */ +}; + +struct osmo_bsslap_pdu { + enum osmo_bsslap_msgt msg_type; + union { + /* ta_request: a TA Request message consists only of the message type. */ + struct osmo_bsslap_ta_response ta_response; + enum osmo_bsslap_cause reject; + struct osmo_bsslap_reset reset; + enum osmo_bsslap_cause abort; + struct osmo_bsslap_ta_layer3 ta_layer3; + }; +}; + +int osmo_bsslap_enc(struct msgb *msg, const struct osmo_bsslap_pdu *pdu); +const char *osmo_bsslap_dec(struct osmo_bsslap_pdu *pdu, const uint8_t *data, size_t len); + +/*! @} */ diff --git a/src/gsm/Makefile.am b/src/gsm/Makefile.am index 4fa940b..465bae1 100644 --- a/src/gsm/Makefile.am +++ b/src/gsm/Makefile.am @@ -33,7 +33,7 @@ gsup.c gsup_sms.c gprs_gea.c gsm0503_conv.c oap.c gsm0808_utils.c \ gsm23003.c gsm23236.c mncc.c bts_features.c oap_client.c \ gsm29118.c gsm48_rest_octets.c cbsp.c gsm48049.c i460_mux.c \ - gad.c + gad.c bsslap.c libgsmint_la_LDFLAGS = -no-undefined libgsmint_la_LIBADD = $(top_builddir)/src/libosmocore.la diff --git a/src/gsm/bsslap.c b/src/gsm/bsslap.c new file mode 100644 index 0000000..a874789 --- /dev/null +++ b/src/gsm/bsslap.c @@ -0,0 +1,461 @@ +/* 3GPP TS 48.071 BSSLAP protocol definitions */ +/* + * (C) 2020 by sysmocom - s.f.m.c. GmbH <info at sysmocom.de> + * All Rights Reserved + * + * Author: Neels Hofmeyr <neels at hofmeyr.de> + * + * SPDX-License-Identifier: GPL-2.0+ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include <osmocom/core/msgb.h> +#include <osmocom/gsm/bsslap.h> + +#include <osmocom/core/logging.h> + +/*! \addtogroup bsslap + * @{ + * \file bsslap.c + * Message encoding and decoding for 3GPP TS 48.071 BSSLAP protocol. + */ + +enum osmo_bsslap_iei { + OSMO_BSSLAP_IEI_TA = 0x1, + OSMO_BSSLAP_IEI_CELL_ID = 0x9, + OSMO_BSSLAP_IEI_CHAN_DESC = 0x10, + OSMO_BSSLAP_IEI_MEAS_REP = 0x14, + OSMO_BSSLAP_IEI_CAUSE = 0x18, + OSMO_BSSLAP_IEI_RRLP_FLAG = 0x19, + OSMO_BSSLAP_IEI_RRLP = 0x1b, + OSMO_BSSLAP_IEI_CELL_ID_LIST = 0x1c, + OSMO_BSSLAP_IEI_ENH_MEAS_REP = 0x1d, + OSMO_BSSLAP_IEI_LAC = 0x1e, + OSMO_BSSLAP_IEI_FREQ_LIST = 0x21, + OSMO_BSSLAP_IEI_MS_POWER = 0x22, + OSMO_BSSLAP_IEI_DELTA_TIMER = 0x23, + OSMO_BSSLAP_IEI_SERVING_CELL_ID = 0x24, + OSMO_BSSLAP_IEI_ENCR_KEY = 0x25, + OSMO_BSSLAP_IEI_CIPH_MODE_SET = 0x26, + OSMO_BSSLAP_IEI_CHAN_MODE = 0x27, + OSMO_BSSLAP_IEI_MR_CONFIG = 0x28, + OSMO_BSSLAP_IEI_POLLING_REPETITION = 0x29, + OSMO_BSSLAP_IEI_PACKET_CHAN_DESC = 0x2a, + OSMO_BSSLAP_IEI_TLLI = 0x2b, + OSMO_BSSLAP_IEI_TFI = 0x2c, + OSMO_BSSLAP_IEI_TBF_START_TIME = 0x2d, + OSMO_BSSLAP_IEI_PWRUP_START_TIME = 0x2e, + OSMO_BSSLAP_IEI_LONG_ENCR_KEY = 0x2f, + OSMO_BSSLAP_IEI_CONCUR_POS_PROC_F = 0x30, +}; + +static const struct tlv_definition osmo_bsslap_tlvdef = { + .def = { + [OSMO_BSSLAP_IEI_TA] = { TLV_TYPE_TV }, + [OSMO_BSSLAP_IEI_CELL_ID] = { TLV_TYPE_FIXED, 2 }, + [OSMO_BSSLAP_IEI_CHAN_DESC] = { TLV_TYPE_FIXED, 3 }, + [OSMO_BSSLAP_IEI_MEAS_REP] = { TLV_TYPE_TLV }, + [OSMO_BSSLAP_IEI_CAUSE] = { TLV_TYPE_TV }, + [OSMO_BSSLAP_IEI_RRLP_FLAG] = { TLV_TYPE_TV }, + [OSMO_BSSLAP_IEI_RRLP] = { TLV_TYPE_TLV }, + [OSMO_BSSLAP_IEI_CELL_ID_LIST] = { TLV_TYPE_TLV }, + [OSMO_BSSLAP_IEI_ENH_MEAS_REP] = { TLV_TYPE_TLV }, + [OSMO_BSSLAP_IEI_LAC] = { TLV_TYPE_TLV }, + [OSMO_BSSLAP_IEI_FREQ_LIST] = { TLV_TYPE_TLV }, + [OSMO_BSSLAP_IEI_MS_POWER] = { TLV_TYPE_TV }, + [OSMO_BSSLAP_IEI_DELTA_TIMER] = { TLV_TYPE_TV }, + [OSMO_BSSLAP_IEI_SERVING_CELL_ID] = { TLV_TYPE_TLV }, + [OSMO_BSSLAP_IEI_ENCR_KEY] = { TLV_TYPE_FIXED, 8 }, + [OSMO_BSSLAP_IEI_CIPH_MODE_SET] = { TLV_TYPE_TV }, + [OSMO_BSSLAP_IEI_CHAN_MODE] = { TLV_TYPE_TV, 2 }, + [OSMO_BSSLAP_IEI_MR_CONFIG] = { TLV_TYPE_TLV }, + [OSMO_BSSLAP_IEI_POLLING_REPETITION] = { TLV_TYPE_TV }, + [OSMO_BSSLAP_IEI_PACKET_CHAN_DESC] = { TLV_TYPE_FIXED, 4 }, + [OSMO_BSSLAP_IEI_TLLI] = { TLV_TYPE_FIXED, 4 }, + [OSMO_BSSLAP_IEI_TFI] = { TLV_TYPE_TLV }, + [OSMO_BSSLAP_IEI_TBF_START_TIME] = { TLV_TYPE_FIXED, 2 }, + [OSMO_BSSLAP_IEI_PWRUP_START_TIME] = { TLV_TYPE_TLV }, + [OSMO_BSSLAP_IEI_LONG_ENCR_KEY] = { TLV_TYPE_FIXED, 16 }, + [OSMO_BSSLAP_IEI_CONCUR_POS_PROC_F] = { TLV_TYPE_TV }, + }, +}; + +static enum osmo_bsslap_msgt osmo_bsslap_msgt(const uint8_t *data, uint8_t len) +{ + if (!data || len < 1) + return -EINVAL; + return data[0]; +} + +static int osmo_bsslap_parse_tlv(struct tlv_parsed *tp, const uint8_t *data, size_t len) +{ + enum osmo_bsslap_msgt msg_type; + const uint8_t *ies_start; + int ies_len; + + msg_type = osmo_bsslap_msgt(data, len); + if (msg_type < 0) + return -EBADMSG; + + ies_start = &data[1]; + ies_len = len - 1; + + if (tlv_parse2(tp, 1, &osmo_bsslap_tlvdef, ies_start, ies_len, 0, 0) <= 0) + return -EBADMSG; + + return msg_type; +} + +static int osmo_bsslap_ie_dec_cell_id(uint16_t *cell_id, const uint8_t *data, size_t len) +{ + if (len != 2) + return -EINVAL; + *cell_id = osmo_load16be(data); + return 0; +} + +static int osmo_bsslap_ie_dec_ta(uint8_t *ta, const uint8_t *data, size_t len) +{ + if (len != 1) + return -EINVAL; + *ta = data[0]; + return 0; +} + +static int osmo_bsslap_ie_dec_cause(enum osmo_bsslap_cause *cause, const uint8_t *data, size_t len) +{ + if (len != 1) + return -EINVAL; + *cause = data[0]; + return 0; +} + +static int osmo_bsslap_ie_dec_chan_desc(struct gsm48_chan_desc *chan_desc, const uint8_t *data, size_t len) +{ + if (len != sizeof(*chan_desc)) + return -EINVAL; + *chan_desc = *(struct gsm48_chan_desc*)data; + return 0; +} + +static int osmo_bsslap_enc_ta_request(struct msgb *msg) +{ + msgb_put_u8(msg, OSMO_BSSLAP_MSGT_TA_REQUEST); + return 1; +} + +static int osmo_bsslap_enc_ta_response(struct msgb *msg, const struct osmo_bsslap_ta_response *params) +{ + uint8_t *old_tail = msg->tail; + + msgb_put_u8(msg, OSMO_BSSLAP_MSGT_TA_RESPONSE); + + msgb_put_u8(msg, OSMO_BSSLAP_IEI_CELL_ID); + msgb_put_u16(msg, params->cell_id); + + msgb_put_u8(msg, OSMO_BSSLAP_IEI_TA); + msgb_put_u8(msg, params->ta); + + return (msg->tail - old_tail); +} + +static const char *osmo_bsslap_dec_ta_response(struct osmo_bsslap_ta_response *pdu, const uint8_t *data, size_t len) +{ + struct tlv_parsed _tp; + struct tlv_parsed *tp = &_tp; + struct tlv_p_entry *e; + int t; + +#define PARSE_ERR(errmsg) \ + return "Decoding BSSLAP TA Response: " errmsg; + + *pdu = (struct osmo_bsslap_ta_response){}; + + t = osmo_bsslap_parse_tlv(tp, data, len); + if (t < 0) + PARSE_ERR("failed to parse TLV structure"); + + if (t != OSMO_BSSLAP_MSGT_TA_RESPONSE) + PARSE_ERR("unexpected message type"); + + if (!(e = TLVP_GET(tp, OSMO_BSSLAP_IEI_CELL_ID))) + PARSE_ERR("missing mandatory Cell Identity IE"); + if (osmo_bsslap_ie_dec_cell_id(&pdu->cell_id, e->val, e->len)) + PARSE_ERR("cannot parse Cell Identity IE"); + + if (!(e = TLVP_GET(tp, OSMO_BSSLAP_IEI_TA))) + PARSE_ERR("missing mandatory TA IE"); + if (osmo_bsslap_ie_dec_ta(&pdu->ta, e->val, e->len)) + PARSE_ERR("cannot parse TA IE"); + + return NULL; +#undef PARSE_ERR +} + +static int osmo_bsslap_enc_ta_layer3(struct msgb *msg, const struct osmo_bsslap_ta_layer3 *params) +{ + uint8_t *old_tail = msg->tail; + + msgb_put_u8(msg, OSMO_BSSLAP_MSGT_TA_LAYER3); + + msgb_put_u8(msg, OSMO_BSSLAP_IEI_TA); + msgb_put_u8(msg, params->ta); + + return (msg->tail - old_tail); +} + +static const char *osmo_bsslap_dec_ta_layer3(struct osmo_bsslap_ta_layer3 *pdu, const uint8_t *data, size_t len) +{ + struct tlv_parsed _tp; + struct tlv_parsed *tp = &_tp; + struct tlv_p_entry *e; + int t; + +#define PARSE_ERR(errmsg) \ + return "Decoding BSSLAP TA Layer3: " errmsg; + + *pdu = (struct osmo_bsslap_ta_layer3){}; + + t = osmo_bsslap_parse_tlv(tp, data, len); + if (t < 0) + PARSE_ERR("failed to parse TLV structure"); + + if (t != OSMO_BSSLAP_MSGT_TA_LAYER3) + PARSE_ERR("unexpected message type"); + + if (!(e = TLVP_GET(tp, OSMO_BSSLAP_IEI_TA))) + PARSE_ERR("missing mandatory TA IE"); + if (osmo_bsslap_ie_dec_ta(&pdu->ta, e->val, e->len)) + PARSE_ERR("cannot parse TA IE"); + + return NULL; +#undef PARSE_ERR +} + +static int osmo_bsslap_enc_reject(struct msgb *msg, enum osmo_bsslap_cause cause) +{ + msgb_put_u8(msg, OSMO_BSSLAP_MSGT_REJECT); + msgb_put_u8(msg, OSMO_BSSLAP_IEI_CAUSE); + msgb_put_u8(msg, cause); + return 3; +} + +static const char *osmo_bsslap_dec_reject(enum osmo_bsslap_cause *cause, const uint8_t *data, size_t len) +{ + struct tlv_parsed _tp; + struct tlv_parsed *tp = &_tp; + struct tlv_p_entry *e; + int t; + +#define PARSE_ERR(errmsg) \ + return "Decoding BSSLAP Reject: " errmsg; + + *cause = -1; + + t = osmo_bsslap_parse_tlv(tp, data, len); + if (t < 0) + PARSE_ERR("failed to parse TLV structure"); + + if (t != OSMO_BSSLAP_MSGT_REJECT) + PARSE_ERR("unexpected message type"); + + if (!(e = TLVP_GET(tp, OSMO_BSSLAP_IEI_CAUSE))) + PARSE_ERR("missing mandatory Cause IE"); + if (osmo_bsslap_ie_dec_cause(cause, e->val, e->len)) + PARSE_ERR("cannot parse Cause IE"); + + return NULL; +#undef PARSE_ERR +} + +static int osmo_bsslap_enc_abort(struct msgb *msg, enum osmo_bsslap_cause cause) +{ + msgb_put_u8(msg, OSMO_BSSLAP_MSGT_ABORT); + msgb_put_u8(msg, OSMO_BSSLAP_IEI_CAUSE); + msgb_put_u8(msg, cause); + return 3; +} + +static const char *osmo_bsslap_dec_abort(enum osmo_bsslap_cause *cause, const uint8_t *data, size_t len) +{ + struct tlv_parsed _tp; + struct tlv_parsed *tp = &_tp; + struct tlv_p_entry *e; + int t; + +#define PARSE_ERR(errmsg) \ + return "Decoding BSSLAP TA Abort: " errmsg; + + *cause = -1; + + t = osmo_bsslap_parse_tlv(tp, data, len); + if (t < 0) + PARSE_ERR("failed to parse TLV structure"); + + if (t != OSMO_BSSLAP_MSGT_ABORT) + PARSE_ERR("unexpected message type"); + + if (!(e = TLVP_GET(tp, OSMO_BSSLAP_IEI_CAUSE))) + PARSE_ERR("missing mandatory Cause IE"); + if (osmo_bsslap_ie_dec_cause(cause, e->val, e->len)) + PARSE_ERR("cannot parse Cause IE"); + + return NULL; +#undef PARSE_ERR +} + +static int osmo_bsslap_enc_reset(struct msgb *msg, const struct osmo_bsslap_reset *params) +{ + struct gsm48_chan_desc *chan_desc; + uint8_t *old_tail = msg->tail; + + msgb_put_u8(msg, OSMO_BSSLAP_MSGT_RESET); + + msgb_put_u8(msg, OSMO_BSSLAP_IEI_CELL_ID); + msgb_put_u16(msg, params->cell_id); + + msgb_put_u8(msg, OSMO_BSSLAP_IEI_TA); + msgb_put_u8(msg, params->ta); + + msgb_put_u8(msg, OSMO_BSSLAP_IEI_CHAN_DESC); + chan_desc = (void*)msgb_put(msg, sizeof(params->chan_desc)); + *chan_desc = params->chan_desc; + + msgb_put_u8(msg, OSMO_BSSLAP_IEI_CAUSE); + msgb_put_u8(msg, params->cause); + + return (msg->tail - old_tail); +} + +static const char *osmo_bsslap_dec_reset(struct osmo_bsslap_reset *pdu, const uint8_t *data, size_t len) +{ + struct tlv_parsed _tp; + struct tlv_parsed *tp = &_tp; + struct tlv_p_entry *e; + int t; + +#define PARSE_ERR(errmsg) \ + return "Decoding BSSLAP Reset: " errmsg; + + *pdu = (struct osmo_bsslap_reset){}; + + t = osmo_bsslap_parse_tlv(tp, data, len); + if (t < 0) + PARSE_ERR("failed to parse TLV structure"); + + if (t != OSMO_BSSLAP_MSGT_RESET) + PARSE_ERR("unexpected message type"); + + if (!(e = TLVP_GET(tp, OSMO_BSSLAP_IEI_CELL_ID))) + PARSE_ERR("missing mandatory Cell Identity IE"); + if (osmo_bsslap_ie_dec_cell_id(&pdu->cell_id, e->val, e->len)) + PARSE_ERR("cannot parse Cell Identity IE"); + + if (!(e = TLVP_GET(tp, OSMO_BSSLAP_IEI_TA))) + PARSE_ERR("missing mandatory TA IE"); + if (osmo_bsslap_ie_dec_ta(&pdu->ta, e->val, e->len)) + PARSE_ERR("cannot parse TA IE"); + + if (!(e = TLVP_GET(tp, OSMO_BSSLAP_IEI_CHAN_DESC))) + PARSE_ERR("missing mandatory Channel Description IE"); + if (osmo_bsslap_ie_dec_chan_desc(&pdu->chan_desc, e->val, e->len)) + PARSE_ERR("cannot parse Channel Description IE"); + + if (!(e = TLVP_GET(tp, OSMO_BSSLAP_IEI_CAUSE))) + PARSE_ERR("missing mandatory Cause IE"); + if (osmo_bsslap_ie_dec_cause(&pdu->cause, e->val, e->len)) + PARSE_ERR("cannot parse Cause IE"); + + return NULL; +#undef PARSE_ERR +} + +/*! Encode BSSLAP PDU and add to msgb (3GPP TS 48.071). + * \param[out] msg msgb to append to. + * \param[in] pdu PDU data to encode. + * \return number of bytes written, negative on error. + */ +int osmo_bsslap_enc(struct msgb *msg, const struct osmo_bsslap_pdu *pdu) +{ + switch (pdu->msg_type) { + case OSMO_BSSLAP_MSGT_TA_REQUEST: + return osmo_bsslap_enc_ta_request(msg); + case OSMO_BSSLAP_MSGT_TA_RESPONSE: + return osmo_bsslap_enc_ta_response(msg, &pdu->ta_response); + case OSMO_BSSLAP_MSGT_REJECT: + return osmo_bsslap_enc_reject(msg, pdu->reject); + case OSMO_BSSLAP_MSGT_RESET: + return osmo_bsslap_enc_reset(msg, &pdu->reset); + case OSMO_BSSLAP_MSGT_ABORT: + return osmo_bsslap_enc_abort(msg, pdu->abort); + case OSMO_BSSLAP_MSGT_TA_LAYER3: + return osmo_bsslap_enc_ta_layer3(msg, &pdu->ta_layer3); + default: + return -ENOTSUP; + } +} + +/*! Decode BSSLAP PDU (3GPP TS 48.071). + * \param[out] pdu Write decoded values here. + * \param[in] data Pointer to BSSLAP PDU raw data. + * \param[in] len Data length to decode. + * \return NULL upon success, a human readable error message on failure. + */ +const char *osmo_bsslap_dec(struct osmo_bsslap_pdu *pdu, const uint8_t *data, size_t len) +{ + *pdu = (struct osmo_bsslap_pdu){}; + + pdu->msg_type = osmo_bsslap_msgt(data, len); + if (pdu->msg_type < 0) + return "BSSLAP PDU too short"; + + switch (pdu->msg_type) { + case OSMO_BSSLAP_MSGT_TA_REQUEST: + /* The TA Request message contains only the message type. */ + return NULL; + case OSMO_BSSLAP_MSGT_TA_RESPONSE: + return osmo_bsslap_dec_ta_response(&pdu->ta_response, data, len); + case OSMO_BSSLAP_MSGT_REJECT: + return osmo_bsslap_dec_reject(&pdu->reject, data, len); + case OSMO_BSSLAP_MSGT_RESET: + return osmo_bsslap_dec_reset(&pdu->reset, data, len); + case OSMO_BSSLAP_MSGT_ABORT: + return osmo_bsslap_dec_abort(&pdu->abort, data, len); + case OSMO_BSSLAP_MSGT_TA_LAYER3: + return osmo_bsslap_dec_ta_layer3(&pdu->ta_layer3, data, len); + default: + return "Unsupported BSSLAP message type"; + } + + return NULL; +} + +const struct value_string osmo_bsslap_msgt_names[] = { + { OSMO_BSSLAP_MSGT_TA_REQUEST, "TA_REQUEST" }, + { OSMO_BSSLAP_MSGT_TA_RESPONSE, "TA_RESPONSE" }, + { OSMO_BSSLAP_MSGT_REJECT, "REJECT" }, + { OSMO_BSSLAP_MSGT_RESET, "RESET" }, + { OSMO_BSSLAP_MSGT_ABORT, "ABORT" }, + { OSMO_BSSLAP_MSGT_TA_LAYER3, "TA_LAYER3" }, + { OSMO_BSSLAP_MSGT_MS_POS_CMD, "MS_POS_CMD" }, + { OSMO_BSSLAP_MSGT_MS_POS_RESP, "MS_POS_RESP" }, + { OSMO_BSSLAP_MSGT_UTDOA_REQ, "UTDOA_REQ" }, + { OSMO_BSSLAP_MSGT_UTDOA_RESP, "UTDOA_RESP" }, + {} +}; + +/*! @} */ diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index a31f73a..257c3fa 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -705,6 +705,10 @@ osmo_nri_ranges_to_str_buf; osmo_nri_ranges_to_str_c; +osmo_bsslap_enc; +osmo_bsslap_dec; +osmo_bsslap_msgt_names; + osmo_gad_enc; osmo_gad_dec; osmo_gad_to_str_buf; diff --git a/tests/Makefile.am b/tests/Makefile.am index 9a2f217..4dfad1b 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -39,6 +39,7 @@ i460_mux/i460_mux_test \ bitgen/bitgen_test \ gad/gad_test \ + bsslap/bsslap_test \ $(NULL) if ENABLE_MSGFILE @@ -285,6 +286,9 @@ gad_gad_test_SOURCES = gad/gad_test.c gad_gad_test_LDADD = $(LDADD) $(top_builddir)/src/gsm/gad.o +bsslap_bsslap_test_SOURCES = bsslap/bsslap_test.c +bsslap_bsslap_test_LDADD = $(LDADD) $(top_builddir)/src/gsm/libosmogsm.la + # The `:;' works around a Bash 3.2 bug when the output is not writeable. $(srcdir)/package.m4: $(top_srcdir)/configure.ac :;{ \ @@ -366,6 +370,7 @@ i460_mux/i460_mux_test.ok \ bitgen/bitgen_test.ok \ gad/gad_test.ok \ + bsslap/bsslap_test.ok \ $(NULL) if ENABLE_LIBSCTP diff --git a/tests/bsslap/bsslap_test.c b/tests/bsslap/bsslap_test.c new file mode 100644 index 0000000..2b6c35e --- /dev/null +++ b/tests/bsslap/bsslap_test.c @@ -0,0 +1,101 @@ +#include <stdio.h> + +#include <osmocom/core/utils.h> +#include <osmocom/gsm/bsslap.h> + +struct osmo_bsslap_pdu bsslap_test_pdus[] = { + { + .msg_type = OSMO_BSSLAP_MSGT_TA_REQUEST, + }, + { + .msg_type = OSMO_BSSLAP_MSGT_TA_RESPONSE, + .ta_response = { + .cell_id = 23, + .ta = 42, + }, + }, + { + .msg_type = OSMO_BSSLAP_MSGT_REJECT, + .reject = OSMO_BSSLAP_CAUSE_OTHER_RADIO_EVT_FAIL, + }, + { + .msg_type = OSMO_BSSLAP_MSGT_RESET, + .reset = { + .cell_id = 23, + .ta = 42, + .chan_desc = { + .chan_nr = 23, + .h0 = { + .tsc = 5, + .h = 1, + .arfcn_high = 2, + .arfcn_low = 3, + }, + }, + .cause = OSMO_BSSLAP_CAUSE_INTRA_BSS_HO, + }, + }, + { + .msg_type = OSMO_BSSLAP_MSGT_ABORT, + .abort = OSMO_BSSLAP_CAUSE_LOSS_SIG_CONN_MS, + }, + { + .msg_type = OSMO_BSSLAP_MSGT_TA_LAYER3, + .ta_layer3 = { + .ta = 23, + }, + }, +}; + +void test_bsslap_enc_dec() +{ + struct osmo_bsslap_pdu *pdu; + printf("--- %s\n", __func__); + + for (pdu = bsslap_test_pdus; (pdu - bsslap_test_pdus) < ARRAY_SIZE(bsslap_test_pdus); pdu++) { + struct msgb *msg = msgb_alloc(1024, __func__); + struct osmo_bsslap_pdu dec_pdu; + int rc; + const char *errmsg; + rc = osmo_bsslap_enc(msg, pdu); + if (rc <= 0) { + printf("[%ld] %s: ERROR: failed to encode pdu\n", (pdu - bsslap_test_pdus), + osmo_bsslap_msgt_name(pdu->msg_type)); + goto loop_end; + } + if (rc != msg->len) { + printf("[%ld] %s: ERROR: osmo_bsslap_enc() returned length %d but msgb has %d bytes\n", + (pdu - bsslap_test_pdus), osmo_bsslap_msgt_name(pdu->msg_type), + rc, msg->len); + goto loop_end; + } + + memset(&dec_pdu, 0xff, sizeof(dec_pdu)); + errmsg = osmo_bsslap_dec(&dec_pdu, msg->data, msg->len); + if (errmsg) { + printf("[%ld] %s: ERROR: failed to decode pdu: %s\n", (pdu - bsslap_test_pdus), + osmo_bsslap_msgt_name(pdu->msg_type), errmsg); + printf(" encoded data: %s\n", osmo_hexdump(msg->data, msg->len)); + goto loop_end; + } + + if (memcmp(pdu, &dec_pdu, sizeof(dec_pdu))) { + printf("[%ld] %s: ERROR: decoded PDU != encoded PDU\n", (pdu - bsslap_test_pdus), + osmo_bsslap_msgt_name(pdu->msg_type)); + printf(" original struct: %s\n", osmo_hexdump((void*)pdu, sizeof(*pdu))); + printf(" decoded struct: %s\n", osmo_hexdump((void*)&dec_pdu, sizeof(dec_pdu))); + goto loop_end; + } + + printf("[%ld] %s: ok\n", (pdu - bsslap_test_pdus), osmo_bsslap_msgt_name(pdu->msg_type)); + +loop_end: + msgb_free(msg); + } +} + +int main() +{ + test_bsslap_enc_dec(); + return 0; +} diff --git a/tests/bsslap/bsslap_test.ok b/tests/bsslap/bsslap_test.ok new file mode 100644 index 0000000..8e4643c --- /dev/null +++ b/tests/bsslap/bsslap_test.ok @@ -0,0 +1,7 @@ +--- test_bsslap_enc_dec +[0] TA_REQUEST: ok +[1] TA_RESPONSE: ok +[2] REJECT: ok +[3] RESET: ok +[4] ABORT: ok +[5] TA_LAYER3: ok diff --git a/tests/testsuite.at b/tests/testsuite.at index 10cf74b..1fa9a07 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -408,3 +408,9 @@ cat $abs_srcdir/gad/gad_test.ok > expout AT_CHECK([$abs_top_builddir/tests/gad/gad_test], [0], [expout], [ignore]) AT_CLEANUP + +AT_SETUP([bsslap]) +AT_KEYWORDS([bsslap]) +cat $abs_srcdir/bsslap/bsslap_test.ok > expout +AT_CHECK([$abs_top_builddir/tests/bsslap/bsslap_test], [0], [expout], [ignore]) +AT_CLEANUP -- To view, visit https://gerrit.osmocom.org/c/libosmocore/+/20333 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: libosmocore Gerrit-Branch: master Gerrit-Change-Id: I6409c4bcac402dc7626a3afce9081c59cd715fe8 Gerrit-Change-Number: 20333 Gerrit-PatchSet: 1 Gerrit-Owner: neels <nhofmeyr at sysmocom.de> Gerrit-MessageType: newchange -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20201001/f7280aa4/attachment.htm>