aboutsummaryrefslogtreecommitdiffstats
path: root/tests/libosmo-gtlv/test_tliv
diff options
context:
space:
mode:
authorNeels Hofmeyr <nhofmeyr@sysmocom.de>2022-03-14 16:38:15 +0100
committerNeels Hofmeyr <neels@hofmeyr.de>2022-06-16 13:04:33 +0200
commit8b58faa4c2e1b52802293f4dce9fcc8dc3843b47 (patch)
tree45ac008dd575470212b72ac5d52df2cbc04e5d35 /tests/libosmo-gtlv/test_tliv
parente011b04c6b2e31bdc46320e5d8a4f48715681f15 (diff)
libosmo-gtlv: add TLIV capability
During code review, it was indicated that some TLV protocols that we will likely deal with in the near future also employ an I, and instance value of a tag. Add TLIV support. A usage example for a manually implemented TLIV structure is found in tests/libosmo-gtlv/gtlv_test.c. A usage example for a generated TLIV protocol is found in tests/libosmo-gtlv/test_tliv/. Related: SYS#5599 Change-Id: I0a076e54dfba6038cc779cb7c8f3967d212226aa
Diffstat (limited to 'tests/libosmo-gtlv/test_tliv')
-rw-r--r--tests/libosmo-gtlv/test_tliv/Makefile.am60
-rw-r--r--tests/libosmo-gtlv/test_tliv/gen__myproto_ies_auto.c71
-rw-r--r--tests/libosmo-gtlv/test_tliv/myproto_ies_custom.c68
-rw-r--r--tests/libosmo-gtlv/test_tliv/myproto_ies_custom.h50
-rw-r--r--tests/libosmo-gtlv/test_tliv/tliv_test.c217
-rw-r--r--tests/libosmo-gtlv/test_tliv/tliv_test.ok32
6 files changed, 498 insertions, 0 deletions
diff --git a/tests/libosmo-gtlv/test_tliv/Makefile.am b/tests/libosmo-gtlv/test_tliv/Makefile.am
new file mode 100644
index 0000000..eb95e12
--- /dev/null
+++ b/tests/libosmo-gtlv/test_tliv/Makefile.am
@@ -0,0 +1,60 @@
+AM_CPPFLAGS = \
+ $(all_includes) \
+ -I$(top_srcdir)/include \
+ -I$(bulddir) \
+ $(NULL)
+
+AM_CFLAGS = \
+ -Wall \
+ $(LIBOSMOCORE_CFLAGS) \
+ $(NULL)
+
+noinst_PROGRAMS = \
+ gen__myproto_ies_auto \
+ tliv_test \
+ $(NULL)
+
+EXTRA_DIST = \
+ myproto_ies_custom.h \
+ tliv_test.ok \
+ $(NULL)
+
+BUILT_SOURCES = \
+ myproto_ies_auto.h \
+ myproto_ies_auto.c \
+ $(NULL)
+
+CLEANFILES = \
+ myproto_ies_auto.h \
+ myproto_ies_auto.c \
+ $(NULL)
+
+gen__myproto_ies_auto_SOURCES = \
+ gen__myproto_ies_auto.c \
+ myproto_ies_custom.c \
+ $(NULL)
+
+gen__myproto_ies_auto_LDADD = \
+ $(top_builddir)/src/libosmo-gtlv/libosmo-gtlv.a \
+ $(LIBOSMOCORE_LIBS) \
+ $(NULL)
+
+myproto_ies_auto.h: $(builddir)/gen__myproto_ies_auto
+ $(builddir)/gen__myproto_ies_auto h > $(builddir)/myproto_ies_auto.h
+myproto_ies_auto.c: $(builddir)/gen__myproto_ies_auto
+ $(builddir)/gen__myproto_ies_auto c > $(builddir)/myproto_ies_auto.c
+
+tliv_test_SOURCES = \
+ tliv_test.c \
+ myproto_ies_custom.c \
+ myproto_ies_auto.c \
+ $(NULL)
+
+tliv_test_LDADD = \
+ $(top_builddir)/src/libosmo-gtlv/libosmo-gtlv.a \
+ $(LIBOSMOCORE_LIBS) \
+ $(NULL)
+
+.PHONY: update_exp
+update_exp:
+ $(builddir)/tliv_test >$(srcdir)/tliv_test.ok
diff --git a/tests/libosmo-gtlv/test_tliv/gen__myproto_ies_auto.c b/tests/libosmo-gtlv/test_tliv/gen__myproto_ies_auto.c
new file mode 100644
index 0000000..21e70d9
--- /dev/null
+++ b/tests/libosmo-gtlv/test_tliv/gen__myproto_ies_auto.c
@@ -0,0 +1,71 @@
+/*
+ * (C) 2021-2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ * All Rights Reserved.
+ *
+ * Author: Neels Janosch Hofmeyr <nhofmeyr@sysmocom.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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <osmocom/core/utils.h>
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/gtlv/gtlv_gen.h>
+
+#define O OSMO_GTLV_GEN_O
+#define M OSMO_GTLV_GEN_M
+#define O_MULTI OSMO_GTLV_GEN_O_MULTI
+#define M_MULTI OSMO_GTLV_GEN_M_MULTI
+#define O_INST OSMO_GTLV_GEN_O_INST
+#define M_INST OSMO_GTLV_GEN_M_INST
+
+#define AUTO osmo_gtlv_gen_ie_auto
+
+static const struct osmo_gtlv_gen_ie bar = {
+ .tag_name = "bar",
+};
+
+static const struct osmo_gtlv_gen_ie_o ies_in_moo_msg[] = {
+ M_INST("MYPROTO_IEI_BAR_ALPHA", bar, "bar_alpha"),
+ O_INST("MYPROTO_IEI_BAR_BETA", bar, "bar_beta"),
+ M_INST("MYPROTO_IEI_BAR_GAMMA", bar, "bar_gamma"),
+ {}
+};
+
+static const struct osmo_gtlv_gen_msg msg_defs[] = {
+ { "moo", ies_in_moo_msg },
+ {}
+};
+
+int main(int argc, const char **argv)
+{
+ struct osmo_gtlv_gen_cfg cfg = {
+ .proto_name = "myproto",
+ .message_type_enum = "enum myproto_msg_type",
+ .message_type_prefix = "MYPROTO_MSGT_",
+ .tag_enum = "enum myproto_iei",
+ .tag_prefix = "MYPROTO_IEI_",
+ .decoded_type_prefix = "struct myproto_ie_",
+ .h_header = "#include \"myproto_ies_custom.h\"",
+ .c_header = "#include <myproto_ies_auto.h>",
+ .msg_defs = msg_defs,
+ .add_enc_to_str = true,
+ };
+ return osmo_gtlv_gen_main(&cfg, argc, argv);
+}
diff --git a/tests/libosmo-gtlv/test_tliv/myproto_ies_custom.c b/tests/libosmo-gtlv/test_tliv/myproto_ies_custom.c
new file mode 100644
index 0000000..54164ce
--- /dev/null
+++ b/tests/libosmo-gtlv/test_tliv/myproto_ies_custom.c
@@ -0,0 +1,68 @@
+/* Example for defining custom IES for gtlv_gen. */
+/*
+ * (C) 2021-2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ * All Rights Reserved.
+ *
+ * Author: Neels Janosch Hofmeyr <nhofmeyr@sysmocom.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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <errno.h>
+#include <inttypes.h>
+
+#include <osmocom/core/bits.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/gtlv/gtlv.h>
+
+#include <myproto_ies_custom.h>
+
+int myproto_dec_bar(void *decoded_struct, void *decode_to, const struct osmo_gtlv_load *gtlv)
+{
+ struct myproto_ie_bar *bar = decode_to;
+ if (gtlv->len < 2)
+ return -EINVAL;
+ *bar = (struct myproto_ie_bar){
+ .a = gtlv->val[0],
+ .b = (gtlv->val[1] == 1),
+ };
+ return 0;
+}
+
+int myproto_enc_bar(struct osmo_gtlv_put *gtlv, void *decoded_struct, void *encode_from)
+{
+ struct myproto_ie_bar *bar = encode_from;
+ msgb_put_u8(gtlv->dst, bar->a);
+ msgb_put_u8(gtlv->dst, bar->b ? 1 : 0);
+ return 0;
+}
+
+int myproto_enc_to_str_bar(char *buf, size_t buflen, void *encode_from)
+{
+ struct myproto_ie_bar *bar = encode_from;
+ return snprintf(buf, buflen, "%d,%s", bar->a, bar->b ? "true" : "false");
+}
+
+const struct value_string myproto_msg_type_names[] = {
+ { MYPROTO_MSGT_MOO, "MOO" },
+ {}
+};
+
+const struct value_string myproto_iei_names[] = {
+ { MYPROTO_IEI_BAR, "BAR" },
+ {}
+};
diff --git a/tests/libosmo-gtlv/test_tliv/myproto_ies_custom.h b/tests/libosmo-gtlv/test_tliv/myproto_ies_custom.h
new file mode 100644
index 0000000..64e06ff
--- /dev/null
+++ b/tests/libosmo-gtlv/test_tliv/myproto_ies_custom.h
@@ -0,0 +1,50 @@
+/* Definitions for decoded message IEs, to be used by the auto-generated myproto_ies_auto.c. */
+/*
+ * (C) 2021-2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ * All Rights Reserved.
+ *
+ * Author: Neels Janosch Hofmeyr <nhofmeyr@sysmocom.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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <osmocom/core/utils.h>
+
+enum myproto_msg_type {
+ MYPROTO_MSGT_MOO = 1,
+};
+
+extern const struct value_string myproto_msg_type_names[];
+
+enum myproto_iei {
+ MYPROTO_IEI_BAR = 1,
+};
+
+enum myproto_iei_bar_inst {
+ MYPROTO_IEI_BAR_ALPHA = 2,
+ MYPROTO_IEI_BAR_BETA = 3,
+ MYPROTO_IEI_BAR_GAMMA = 5,
+};
+
+extern const struct value_string myproto_iei_names[];
+
+struct myproto_ie_bar {
+ int a;
+ bool b;
+};
diff --git a/tests/libosmo-gtlv/test_tliv/tliv_test.c b/tests/libosmo-gtlv/test_tliv/tliv_test.c
new file mode 100644
index 0000000..fd4e310
--- /dev/null
+++ b/tests/libosmo-gtlv/test_tliv/tliv_test.c
@@ -0,0 +1,217 @@
+/*
+ * (C) 2021-2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ * All Rights Reserved.
+ *
+ * Author: Neels Janosch Hofmeyr <nhofmeyr@sysmocom.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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdio.h>
+#include <errno.h>
+
+#include <osmocom/core/application.h>
+#include <osmocom/core/utils.h>
+#include <osmocom/core/msgb.h>
+
+#include <osmocom/gtlv/gtlv.h>
+
+#include <myproto_ies_auto.h>
+
+struct myproto_msg {
+ enum myproto_msg_type type;
+ union myproto_ies ies;
+};
+
+static void err_cb(void *data, void *decoded_struct, const char *file, int line, const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ //printf("ERR: %s:%d ", file, line);
+ printf("ERR: ");
+ vprintf(fmt, args);
+ va_end(args);
+}
+
+static int myproto_msg_enc(struct msgb *dst, const struct myproto_msg *msg, const struct osmo_gtlv_cfg *cfg)
+{
+ struct osmo_gtlv_put gtlv = {
+ .cfg = cfg,
+ .dst = dst,
+ };
+
+ msgb_put_u8(gtlv.dst, msg->type);
+ return myproto_ies_encode(&gtlv, (void *)&msg->ies, msg->type, err_cb, NULL, myproto_iei_names);
+}
+
+static int myproto_msg_dec(struct myproto_msg *msg, const uint8_t *data, size_t data_len,
+ const struct osmo_gtlv_cfg *cfg, bool ordered)
+{
+ struct osmo_gtlv_load gtlv;
+ if (data_len < 1)
+ return -EINVAL;
+ msg->type = data[0];
+ gtlv = (struct osmo_gtlv_load){
+ .cfg = cfg,
+ .src = { data + 1, data_len - 1 },
+ };
+ return myproto_ies_decode(&msg->ies, &gtlv, ordered, msg->type, err_cb, NULL, myproto_iei_names);
+}
+
+void *ctx;
+
+struct myproto_msg tests[] = {
+ {
+ MYPROTO_MSGT_MOO,
+ {
+ .moo = {
+ .bar_alpha = { 23, true },
+ .bar_gamma = { 42, false },
+ },
+ },
+ },
+ {
+ MYPROTO_MSGT_MOO,
+ {
+ .moo = {
+ .bar_alpha = { 11, true },
+ .bar_beta_present = true,
+ .bar_beta = { 22, false },
+ .bar_gamma = { 33, true },
+ },
+ },
+ },
+};
+
+int myproto_msg_to_str_buf(char *buf, size_t buflen, const struct myproto_msg *m)
+{
+ struct osmo_strbuf sb = { .buf = buf, .len = buflen };
+ OSMO_STRBUF_PRINTF(sb, "%s={", get_value_string(myproto_msg_type_names, m->type));
+ OSMO_STRBUF_APPEND(sb, osmo_gtlvs_encode_to_str_buf, &m->ies, 0, myproto_get_msg_coding(m->type),
+ myproto_iei_names);
+ OSMO_STRBUF_PRINTF(sb, " }");
+ return sb.chars_needed;
+
+}
+
+char *myproto_msg_to_str(const struct myproto_msg *m)
+{
+ OSMO_NAME_C_IMPL(ctx, 256, "ERROR", myproto_msg_to_str_buf, m)
+}
+
+void test_enc_dec(const char *label, const struct osmo_gtlv_cfg *cfg, bool ordered)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(tests); i++) {
+ int rc;
+ const struct myproto_msg *orig = &tests[i];
+ struct myproto_msg parsed = {};
+ struct msgb *msg;
+
+ printf("\n=== start %s %s[%d]\n", label, __func__, i);
+ printf("encoded: %s\n", myproto_msg_to_str(orig));
+
+ msg = msgb_alloc(1024, __func__);
+ rc = myproto_msg_enc(msg, orig, cfg);
+ printf("myproto_msg_enc() rc = %d\n", rc);
+ printf("%s.\n", osmo_hexdump(msg->data, msg->len));
+
+ rc = myproto_msg_dec(&parsed, msg->data, msg->len, cfg, ordered);
+ printf("myproto_msg_dec() rc = %d\n", rc);
+ printf("decoded: %s\n", myproto_msg_to_str(&parsed));
+ if (strcmp(myproto_msg_to_str(orig), myproto_msg_to_str(&parsed))) {
+ printf(" ERROR: parsed != orig\n");
+ exit(1);
+ }
+
+ msgb_free(msg);
+ printf("=== end %s %s[%d]\n", label, __func__, i);
+ }
+}
+
+/* Example of defining a TLI, with an instance indicator */
+static int tliv_load_tl(struct osmo_gtlv_load *gtlv, const uint8_t *src_data, size_t src_data_len)
+{
+ /* already validated in next_tl_valid(): src_data_len >= cfg->tl_min_size == 2. */
+ gtlv->ti.tag = src_data[0];
+ gtlv->len = src_data[1];
+
+ switch (gtlv->ti.tag) {
+ /* All tags that are TLIV go here */
+ case MYPROTO_IEI_BAR:
+ if (src_data_len < 3)
+ return -ENOSPC;
+ gtlv->ti.instance_present = true;
+ gtlv->ti.instance = src_data[2];
+ gtlv->val = src_data + 3;
+ /* In this example, the I is part of the len */
+ gtlv->len--;
+ return 0;
+ default:
+ gtlv->val = src_data + 2;
+ return 0;
+ }
+}
+
+static int tliv_store_tl(uint8_t *dst_data, size_t dst_data_avail, const struct osmo_gtlv_tag_inst *ti, size_t len,
+ struct osmo_gtlv_put *gtlv)
+{
+ if (ti->tag > UINT8_MAX)
+ return -EINVAL;
+ if (len > UINT8_MAX)
+ return -EMSGSIZE;
+ if (dst_data_avail < 2)
+ return -ENOSPC;
+
+ dst_data[0] = ti->tag;
+
+ switch (ti->tag) {
+ /* All tags that are TLIV go here */
+ case MYPROTO_IEI_BAR:
+ if (dst_data_avail < 3)
+ return -ENOSPC;
+ if (!ti->instance_present)
+ return -EINVAL;
+ if (ti->instance > UINT8_MAX)
+ return -EINVAL;
+ /* here, I is part of the len in L; the passed len reflects only the value, so add 1 for I */
+ dst_data[1] = len + 1;
+ dst_data[2] = ti->instance;
+ return 3;
+ default:
+ dst_data[1] = len;
+ return 2;
+ }
+}
+
+const struct osmo_gtlv_cfg osmo_tliv_cfg = {
+ .tl_min_size = 2,
+ .load_tl = tliv_load_tl,
+ .store_tl = tliv_store_tl,
+};
+
+int main()
+{
+ ctx = talloc_named_const(NULL, 0, "test_gen_tlv");
+ msgb_talloc_ctx_init(ctx, 0);
+
+ test_enc_dec("tliv ordered", &osmo_tliv_cfg, true);
+ test_enc_dec("tliv unordered", &osmo_tliv_cfg, false);
+
+ talloc_free(ctx);
+ return 0;
+}
diff --git a/tests/libosmo-gtlv/test_tliv/tliv_test.ok b/tests/libosmo-gtlv/test_tliv/tliv_test.ok
new file mode 100644
index 0000000..184ffa6
--- /dev/null
+++ b/tests/libosmo-gtlv/test_tliv/tliv_test.ok
@@ -0,0 +1,32 @@
+
+=== start tliv ordered test_enc_dec[0]
+encoded: MOO={ 'BAR'=23,true 'BAR'=42,false }
+myproto_msg_enc() rc = 0
+01 01 03 02 17 01 01 03 05 2a 00 .
+myproto_msg_dec() rc = 0
+decoded: MOO={ 'BAR'=23,true 'BAR'=42,false }
+=== end tliv ordered test_enc_dec[0]
+
+=== start tliv ordered test_enc_dec[1]
+encoded: MOO={ 'BAR'=11,true 'BAR'=22,false 'BAR'=33,true }
+myproto_msg_enc() rc = 0
+01 01 03 02 0b 01 01 03 03 16 00 01 03 05 21 01 .
+myproto_msg_dec() rc = 0
+decoded: MOO={ 'BAR'=11,true 'BAR'=22,false 'BAR'=33,true }
+=== end tliv ordered test_enc_dec[1]
+
+=== start tliv unordered test_enc_dec[0]
+encoded: MOO={ 'BAR'=23,true 'BAR'=42,false }
+myproto_msg_enc() rc = 0
+01 01 03 02 17 01 01 03 05 2a 00 .
+myproto_msg_dec() rc = 0
+decoded: MOO={ 'BAR'=23,true 'BAR'=42,false }
+=== end tliv unordered test_enc_dec[0]
+
+=== start tliv unordered test_enc_dec[1]
+encoded: MOO={ 'BAR'=11,true 'BAR'=22,false 'BAR'=33,true }
+myproto_msg_enc() rc = 0
+01 01 03 02 0b 01 01 03 03 16 00 01 03 05 21 01 .
+myproto_msg_dec() rc = 0
+decoded: MOO={ 'BAR'=11,true 'BAR'=22,false 'BAR'=33,true }
+=== end tliv unordered test_enc_dec[1]