aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2012-11-22 14:59:46 +0100
committerHolger Hans Peter Freyther <zecke@selfish.org>2012-12-19 16:37:55 +0100
commitbce5675e5fa1eb4bcbe0dd24d503456eaeb58a0d (patch)
tree338b2407a776d4112de78486892b281407e06a3e /openbsc
parentc751cf92cbc25a5cfca8041ef3fdcc16ed5865ad (diff)
abis: Create a routine that can parse all SW Descriptions of a SW Config
Be able to parse the entire SW Config IE. Parse the SW Descruption into a struct provided by the caller.
Diffstat (limited to 'openbsc')
-rw-r--r--openbsc/.gitignore1
-rw-r--r--openbsc/configure.ac1
-rw-r--r--openbsc/include/openbsc/abis_nm.h15
-rw-r--r--openbsc/src/libbsc/abis_nm.c87
-rw-r--r--openbsc/tests/Makefile.am2
-rw-r--r--openbsc/tests/abis/Makefile.am17
-rw-r--r--openbsc/tests/abis/abis_test.c118
-rw-r--r--openbsc/tests/abis/abis_test.ok9
-rw-r--r--openbsc/tests/testsuite.at6
9 files changed, 223 insertions, 33 deletions
diff --git a/openbsc/.gitignore b/openbsc/.gitignore
index f345baccd..bf909f59f 100644
--- a/openbsc/.gitignore
+++ b/openbsc/.gitignore
@@ -58,6 +58,7 @@ tests/sccp/sccp_test
tests/sms/sms_test
tests/timer/timer_test
tests/gprs/gprs_test
+tests/abis/abis_test
tests/atconfig
tests/atlocal
diff --git a/openbsc/configure.ac b/openbsc/configure.ac
index 1bb660fab..91ae08aeb 100644
--- a/openbsc/configure.ac
+++ b/openbsc/configure.ac
@@ -151,6 +151,7 @@ AC_OUTPUT(
tests/mgcp/Makefile
tests/gprs/Makefile
tests/si/Makefile
+ tests/abis/Makefile
doc/Makefile
doc/examples/Makefile
Makefile)
diff --git a/openbsc/include/openbsc/abis_nm.h b/openbsc/include/openbsc/abis_nm.h
index 9c4cc3309..51f11e975 100644
--- a/openbsc/include/openbsc/abis_nm.h
+++ b/openbsc/include/openbsc/abis_nm.h
@@ -66,6 +66,18 @@ struct abis_nm_cfg {
int (*sw_act_req)(struct msgb *);
};
+struct abis_nm_sw_descr {
+ /* where does it start? how long is it? */
+ const uint8_t *start;
+ size_t len;
+
+ /* the parsed data */
+ const uint8_t *file_id;
+ uint16_t file_id_len;
+ const uint8_t *file_ver;
+ uint16_t file_ver_len;
+};
+
extern int abis_nm_rcvmsg(struct msgb *msg);
int abis_nm_tlv_parse(struct tlv_parsed *tp, struct gsm_bts *bts, const uint8_t *buf, int len);
@@ -167,4 +179,7 @@ int _abis_nm_sendmsg(struct msgb *msg);
void abis_nm_queue_send_next(struct gsm_bts *bts); /* for bs11_config. */
+int abis_nm_parse_sw_config(const uint8_t *data, const size_t len,
+ struct abis_nm_sw_descr *res, const int res_len);
+
#endif /* _NM_H */
diff --git a/openbsc/src/libbsc/abis_nm.c b/openbsc/src/libbsc/abis_nm.c
index e95c0a905..7485a6cce 100644
--- a/openbsc/src/libbsc/abis_nm.c
+++ b/openbsc/src/libbsc/abis_nm.c
@@ -359,7 +359,8 @@ static int ipacc_sw_activate(struct gsm_bts *bts, uint8_t obj_class, uint8_t i0,
return abis_nm_sendmsg(bts, msg);
}
-static int abis_nm_parse_sw_descr(const uint8_t *sw_descr, int sw_descr_len)
+int abis_nm_parse_sw_config(const uint8_t *sw_descr, const size_t sw_descr_len,
+ struct abis_nm_sw_descr *desc, const int res_len)
{
static const struct tlv_definition sw_descr_def = {
.def = {
@@ -368,38 +369,56 @@ static int abis_nm_parse_sw_descr(const uint8_t *sw_descr, int sw_descr_len)
},
};
- uint8_t tag;
- uint16_t tag_len;
- const uint8_t *val;
- int ofs = 0, len;
+ size_t pos = 0;
+ int desc_pos = 0;
- /* Classic TLV parsing doesn't work well with SW_DESCR because of it's
- * nested nature and the fact you have to assume it contains only two sub
- * tags NM_ATT_FILE_VERSION & NM_ATT_FILE_ID to parse it */
+ for (pos = 0; pos < sw_descr_len && desc_pos < res_len; ++desc_pos) {
+ uint8_t tag;
+ uint16_t tag_len;
+ const uint8_t *val;
+ int len;
- if (sw_descr[0] != NM_ATT_SW_DESCR) {
- DEBUGP(DNM, "SW_DESCR attribute identifier not found!\n");
- return -1;
- }
- ofs += 1;
+ memset(&desc[desc_pos], 0, sizeof(desc[desc_pos]));
+ desc[desc_pos].start = &sw_descr[pos];
- len = tlv_parse_one(&tag, &tag_len, &val,
- &sw_descr_def, &sw_descr[ofs], sw_descr_len-ofs);
- if (len < 0 || (tag != NM_ATT_FILE_ID)) {
- DEBUGP(DNM, "FILE_ID attribute identifier not found!\n");
- return -2;
- }
- ofs += len;
+ /* Classic TLV parsing doesn't work well with SW_DESCR because of it's
+ * nested nature and the fact you have to assume it contains only two sub
+ * tags NM_ATT_FILE_VERSION & NM_ATT_FILE_ID to parse it */
+ if (sw_descr[pos] != NM_ATT_SW_DESCR) {
+ LOGP(DNM, LOGL_ERROR,
+ "SW_DESCR attribute identifier not found!\n");
+ return -1;
+ }
- len = tlv_parse_one(&tag, &tag_len, &val,
- &sw_descr_def, &sw_descr[ofs], sw_descr_len-ofs);
- if (len < 0 || (tag != NM_ATT_FILE_VERSION)) {
- DEBUGP(DNM, "FILE_VERSION attribute identifier not found!\n");
- return -3;
+ pos += 1;
+ len = tlv_parse_one(&tag, &tag_len, &val,
+ &sw_descr_def, &sw_descr[pos], sw_descr_len - pos);
+ if (len < 0 || (tag != NM_ATT_FILE_ID)) {
+ LOGP(DNM, LOGL_ERROR,
+ "FILE_ID attribute identifier not found!\n");
+ return -2;
+ }
+ desc[desc_pos].file_id = val;
+ desc[desc_pos].file_id_len = tag_len;
+ pos += len;
+
+
+ len = tlv_parse_one(&tag, &tag_len, &val,
+ &sw_descr_def, &sw_descr[pos], sw_descr_len - pos);
+ if (len < 0 || (tag != NM_ATT_FILE_VERSION)) {
+ LOGP(DNM, LOGL_ERROR,
+ "FILE_VERSION attribute identifier not found!\n");
+ return -3;
+ }
+ desc[desc_pos].file_ver = val;
+ desc[desc_pos].file_ver_len = tag_len;
+ pos += len;
+
+ /* final size */
+ desc[desc_pos].len = &sw_descr[pos] - desc[desc_pos].start;
}
- ofs += len;
- return ofs;
+ return desc_pos;
}
static int abis_nm_rx_sw_act_req(struct msgb *mb)
@@ -409,7 +428,8 @@ static int abis_nm_rx_sw_act_req(struct msgb *mb)
struct e1inp_sign_link *sign_link = mb->dst;
struct tlv_parsed tp;
const uint8_t *sw_config;
- int ret, sw_config_len, sw_descr_len;
+ int ret, sw_config_len;
+ struct abis_nm_sw_descr sw_descr[1];
abis_nm_debugp_foh(DNM, foh);
@@ -439,16 +459,19 @@ static int abis_nm_rx_sw_act_req(struct msgb *mb)
DEBUGP(DNM, "Found SW config: %s\n", osmo_hexdump(sw_config, sw_config_len));
}
- /* Use the first SW_DESCR present in SW config */
- sw_descr_len = abis_nm_parse_sw_descr(sw_config, sw_config_len);
- if (sw_descr_len < 0)
+ /* Parse up to two sw descriptions from the data */
+ ret = abis_nm_parse_sw_config(sw_config, sw_config_len,
+ &sw_descr[0], ARRAY_SIZE(sw_descr));
+ if (ret <= 0) {
+ LOGP(DNM, LOGL_ERROR, "Failed to parse SW Config.\n");
return -EINVAL;
+ }
return ipacc_sw_activate(sign_link->trx->bts, foh->obj_class,
foh->obj_inst.bts_nr,
foh->obj_inst.trx_nr,
foh->obj_inst.ts_nr,
- sw_config, sw_descr_len);
+ sw_descr[0].start, sw_descr[0].len);
}
/* Receive a CHANGE_ADM_STATE_ACK, parse the TLV and update local state */
diff --git a/openbsc/tests/Makefile.am b/openbsc/tests/Makefile.am
index cede8e824..7ea4cff67 100644
--- a/openbsc/tests/Makefile.am
+++ b/openbsc/tests/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = gsm0408 db channel mgcp gprs si
+SUBDIRS = gsm0408 db channel mgcp gprs si abis
if BUILD_NAT
SUBDIRS += bsc-nat
diff --git a/openbsc/tests/abis/Makefile.am b/openbsc/tests/abis/Makefile.am
new file mode 100644
index 000000000..3255ecf55
--- /dev/null
+++ b/openbsc/tests/abis/Makefile.am
@@ -0,0 +1,17 @@
+INCLUDES = $(all_includes) -I$(top_srcdir)/include
+AM_CFLAGS=-Wall -ggdb3 $(LIBOSMOCORE_CFLAGS) $(LIBOSMOABIS_CFLAGS) \
+ $(LIBOSMOGSM_CFLAGS) $(COVERAGE_CFLAGS)
+
+EXTRA_DIST = abis_test.ok
+
+noinst_PROGRAMS = abis_test
+
+abis_test_SOURCES = abis_test.c
+
+abis_test_LDADD = \
+ $(top_builddir)/src/libbsc/libbsc.a \
+ $(top_builddir)/src/libcommon/libcommon.a \
+ $(top_builddir)/src/libbsc/libbsc.a \
+ $(top_builddir)/src/libtrau/libtrau.a \
+ $(LIBOSMOCORE_LIBS) $(LIBOSMOABIS_LIBS) \
+ $(LIBOSMOGSM_LIBS)
diff --git a/openbsc/tests/abis/abis_test.c b/openbsc/tests/abis/abis_test.c
new file mode 100644
index 000000000..a2f6a05c2
--- /dev/null
+++ b/openbsc/tests/abis/abis_test.c
@@ -0,0 +1,118 @@
+/*
+ * (C) 2012 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * 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 <stdio.h>
+#include <stdlib.h>
+
+#include <osmocom/core/application.h>
+#include <osmocom/core/utils.h>
+
+#include <openbsc/gsm_data.h>
+#include <openbsc/abis_nm.h>
+#include <openbsc/debug.h>
+
+static const uint8_t simple_config[] = {
+ /*0, 13, */
+ 66, 18, 0, 3, 1, 2, 3, 19, 0, 3, 3, 4, 5,
+};
+
+static const uint8_t dual_config[] = {
+ /*0, 26, */
+ 66, 18, 0, 3, 1, 2, 3, 19, 0, 3, 3, 4, 5,
+ 66, 18, 0, 3, 9, 7, 5, 19, 0, 3, 6, 7, 8,
+};
+
+static void test_simple_sw_config(void)
+{
+ struct abis_nm_sw_descr descr[1];
+ int rc;
+
+ rc = abis_nm_parse_sw_config(simple_config, ARRAY_SIZE(simple_config),
+ &descr[0], ARRAY_SIZE(descr));
+ if (rc != 1) {
+ printf("FAILED to parse the File Id/File version\n");
+ abort();
+ }
+
+ if (descr[0].len != 13) {
+ printf("WRONG SIZE: %d\n", descr[0].len);
+ abort();
+ }
+
+ printf("Start: %u len: %zu\n", descr[0].start - simple_config, descr[0].len);
+ printf("file_id: %s\n", osmo_hexdump(descr[0].file_id, descr[0].file_id_len));
+ printf("file_ver: %s\n", osmo_hexdump(descr[0].file_ver, descr[0].file_ver_len));
+}
+
+static void test_simple_sw_short(void)
+{
+ struct abis_nm_sw_descr descr[1];
+ int i;
+
+ for (i = 1; i < ARRAY_SIZE(simple_config); ++i) {
+ int rc = abis_nm_parse_sw_config(simple_config,
+ ARRAY_SIZE(simple_config) - i, &descr[0],
+ ARRAY_SIZE(descr));
+ if (rc >= 1) {
+ printf("SHOULD not have parsed: %d\n", rc);
+ abort();
+ }
+ }
+}
+
+static void test_dual_sw_config(void)
+{
+ struct abis_nm_sw_descr descr[2];
+ int rc;
+
+ rc = abis_nm_parse_sw_config(dual_config, ARRAY_SIZE(dual_config),
+ &descr[0], ARRAY_SIZE(descr));
+ if (rc != 2) {
+ printf("FAILED to parse the File Id/File version\n");
+ abort();
+ }
+
+ if (descr[0].len != 13) {
+ printf("WRONG SIZE0: %d\n", descr[0].len);
+ abort();
+ }
+
+ if (descr[1].len != 13) {
+ printf("WRONG SIZE1: %d\n", descr[1].len);
+ abort();
+ }
+
+ printf("Start: %u len: %zu\n", descr[0].start - dual_config, descr[0].len);
+ printf("file_id: %s\n", osmo_hexdump(descr[0].file_id, descr[0].file_id_len));
+ printf("file_ver: %s\n", osmo_hexdump(descr[0].file_ver, descr[0].file_ver_len));
+
+ printf("Start: %u len: %zu\n", descr[1].start - dual_config, descr[1].len);
+ printf("file_id: %s\n", osmo_hexdump(descr[1].file_id, descr[1].file_id_len));
+ printf("file_ver: %s\n", osmo_hexdump(descr[1].file_ver, descr[1].file_ver_len));
+}
+
+int main(int argc, char **argv)
+{
+ osmo_init_logging(&log_info);
+ test_simple_sw_config();
+ test_simple_sw_short();
+ test_dual_sw_config();
+
+ return EXIT_SUCCESS;
+}
diff --git a/openbsc/tests/abis/abis_test.ok b/openbsc/tests/abis/abis_test.ok
new file mode 100644
index 000000000..64019880c
--- /dev/null
+++ b/openbsc/tests/abis/abis_test.ok
@@ -0,0 +1,9 @@
+Start: 0 len: 13
+file_id: 01 02 03
+file_ver: 03 04 05
+Start: 13 len: 26
+file_id: 01 02 03
+file_ver: 03 04 05
+Start: 26 len: 13
+file_id: 09 07 05
+file_ver: 06 07 08
diff --git a/openbsc/tests/testsuite.at b/openbsc/tests/testsuite.at
index 8e1277312..4c5de8d6a 100644
--- a/openbsc/tests/testsuite.at
+++ b/openbsc/tests/testsuite.at
@@ -43,3 +43,9 @@ AT_KEYWORDS([si])
cat $abs_srcdir/si/si_test.ok > expout
AT_CHECK([$abs_top_builddir/tests/si/si_test], [], [expout], [ignore])
AT_CLEANUP
+
+AT_SETUP([abis])
+AT_KEYWORDS([abis])
+cat $abs_srcdir/abis/abis_test.ok > expout
+AT_CHECK([$abs_top_builddir/tests/abis/abis_test], [], [expout], [ignore])
+AT_CLEANUP