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>