neels has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-upf/+/28287 )
Change subject: move libosmo-gtlv to libosmocore.git ......................................................................
move libosmo-gtlv to libosmocore.git
Related: SYS#5895 Related: I25ab400f0c5707fdc0d8e480aca19871c2e26e71 (libosmocore) Change-Id: Id72cdf94da60d4b6d09d0044c74e672c4412c15d --- M configure.ac M include/osmocom/Makefile.am D include/osmocom/gtlv/Makefile.am D include/osmocom/gtlv/gtlv.h D include/osmocom/gtlv/gtlv_dec_enc.h D include/osmocom/gtlv/gtlv_gen.h M include/osmocom/pfcp/Makefile.am M src/Makefile.am D src/libosmo-gtlv/Makefile.am D src/libosmo-gtlv/gtlv.c D src/libosmo-gtlv/gtlv_dec_enc.c D src/libosmo-gtlv/gtlv_gen.c M src/libosmo-pfcp/Makefile.am M tests/Makefile.am D tests/libosmo-gtlv/Makefile.am D tests/libosmo-gtlv/gtlv_dec_enc_test.c D tests/libosmo-gtlv/gtlv_dec_enc_test.ok D tests/libosmo-gtlv/gtlv_test.c D tests/libosmo-gtlv/gtlv_test.ok D tests/libosmo-gtlv/test_gtlv_gen/Makefile.am D tests/libosmo-gtlv/test_gtlv_gen/gen__myproto_ies_auto.c D tests/libosmo-gtlv/test_gtlv_gen/gtlv_gen_test.c D tests/libosmo-gtlv/test_gtlv_gen/gtlv_gen_test.ok D tests/libosmo-gtlv/test_gtlv_gen/myproto_ies_custom.c D tests/libosmo-gtlv/test_gtlv_gen/myproto_ies_custom.h D tests/libosmo-gtlv/test_tliv/Makefile.am D tests/libosmo-gtlv/test_tliv/gen__myproto_ies_auto.c D tests/libosmo-gtlv/test_tliv/myproto_ies_custom.c D tests/libosmo-gtlv/test_tliv/myproto_ies_custom.h D tests/libosmo-gtlv/test_tliv/tliv_test.c D tests/libosmo-gtlv/test_tliv/tliv_test.ok M tests/libosmo-pfcp/Makefile.am M tests/testsuite.at 33 files changed, 7 insertions(+), 4,769 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-upf refs/changes/87/28287/1
diff --git a/configure.ac b/configure.ac index 1b2cdea..683a6b0 100644 --- a/configure.ac +++ b/configure.ac @@ -42,6 +42,7 @@ PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.5.0) PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.5.0) PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.5.0) +PKG_CHECK_MODULES(LIBOSMOGTLV, libosmo-gtlv >= 1.5.0)
dnl checks for header files AC_HEADER_STDC @@ -197,18 +198,13 @@ AC_OUTPUT( include/Makefile include/osmocom/Makefile - include/osmocom/gtlv/Makefile include/osmocom/pfcp/Makefile include/osmocom/upf/Makefile src/Makefile - src/libosmo-gtlv/Makefile src/libosmo-pfcp/Makefile src/osmo-upf/Makefile tests/Makefile tests/atlocal - tests/libosmo-gtlv/Makefile - tests/libosmo-gtlv/test_gtlv_gen/Makefile - tests/libosmo-gtlv/test_tliv/Makefile tests/libosmo-pfcp/Makefile doc/Makefile doc/examples/Makefile diff --git a/include/osmocom/Makefile.am b/include/osmocom/Makefile.am index 9ed7a41..5a1276e 100644 --- a/include/osmocom/Makefile.am +++ b/include/osmocom/Makefile.am @@ -1,5 +1,4 @@ SUBDIRS = \ - gtlv \ pfcp \ upf \ $(NULL) diff --git a/include/osmocom/gtlv/Makefile.am b/include/osmocom/gtlv/Makefile.am deleted file mode 100644 index fc0cff2..0000000 --- a/include/osmocom/gtlv/Makefile.am +++ /dev/null @@ -1,7 +0,0 @@ -tlv_HEADERS = \ - gtlv.h \ - gtlv_dec_enc.h \ - gtlv_gen.h \ - $(NULL) - -tlvdir = $(includedir)/osmocom/gtlv diff --git a/include/osmocom/gtlv/gtlv.h b/include/osmocom/gtlv/gtlv.h deleted file mode 100644 index d800f71..0000000 --- a/include/osmocom/gtlv/gtlv.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * (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 <stdint.h> -#include <stdio.h> -#include <stdbool.h> - -struct msgb; -struct osmo_gtlv_load; -struct osmo_gtlv_put; -struct value_string; - -struct osmo_gtlv_tag_inst { - unsigned int tag; - bool instance_present; - unsigned int instance; -}; - -int osmo_gtlv_tag_inst_cmp(const struct osmo_gtlv_tag_inst *a, const struct osmo_gtlv_tag_inst *b); - -int osmo_gtlv_tag_inst_to_str_buf(char *buf, size_t buflen, const struct osmo_gtlv_tag_inst *ti, - const struct value_string *tag_names); -char *osmo_gtlv_tag_inst_to_str_c(void *ctx, const struct osmo_gtlv_tag_inst *ti, - const struct value_string *tag_names); - -/*! TL configuration for osmo_gtlv_load*() and osmo_gtlv_put*(). Depending on these implementations provided by the caller, - * osmo_gtlv can load any sizes of tag and length fields (that don't surpass the value range of unsigned int and size_t, - * respectively), as well as TV (fixed-length) or TvLV (variable-sized length). - * - * See osmo_t8l8v_cfg and osmo_t16l16v_cfg, ready implementations for plain 8bit and 16bit TLV protocols. - * - * libosmo-pfcp serves as example for using this entire TLV API, uncluding de/encoding to structs and generating parts - * of the TLV parsing code based on message definitions. It uses osmo_t16l16v_cfg. - */ -struct osmo_gtlv_cfg { - /*! The length in bytes of the shortest possible TL header (e.g. 4 for T16L16V, or 1 for 8bit tags where TV IEs - * without a length exist). A src_data_len passed to store_tl() below is guaranteed to be >= this value. If at - * any point there is remaining message data smaller than this value, a parsing error is returned. - */ - size_t tl_min_size; - - /*! Read one TL from the start of src_data. - * \param gtlv Return the T (tag) value read from src_data in gtlv->tag. - * Return the L (length) value read from src_data in gtlv->len. - * Return the I (instance) value read from src_data in gtlv->len; ignore if there is no I. - * Return the position just after the TL in gtlv->*val. If there is V data, point at the start of the - * V data in src_data. If there is no V data, point at the byte just after the TL part in src_data. - * \param src_data Part of raw message being decoded. - * \param src_data_len Remaining message data length at src_data. - * \return 0 on success, negative on error. - */ - int (*load_tl)(struct osmo_gtlv_load *gtlv, const uint8_t *src_data, size_t src_data_len); - - /*! Write a TL to dst_data, and return the size of the TL written. - * This is also invoked by osmo_gtlv_put_update_tl() to overwrite a previous TL header. If the TL part's size - * can be different than the first time (e.g. due to a large L value in a TvLV protocol), an implementation can - * use the 'gtlv' arg to figure out how to memmove the message data: - * When invoked by osmo_gtlv_put_tl(), dst_data == gtlv->dst->tail and dst_data_avail == msgb_tailroom(). - * When invoked by osmo_gtlv_put_update_tl(), dst_data < gtlv->dst->tail, dst_data points at the start of the - * TL section written earlier by osmo_gtlv_put_tl() and dst_data_avail == the size of the TL written earlier. - * - * \param dst_data Write TL data to the start of this buffer. - * \param dst_data_avail Remaining available space in dst_data. - * \param tag The T value to store in dst_data. - * \param instance The I value to store in dst_data (if this tag is a TLIV); ignore when not a TLIV. - * \param len The L value to store in dst_data. - * \param gtlv Backpointer to the osmo_gtlv_put struct, including gtlv->dst, the underlying msgb. - * \return the size of the TL part in bytes on success, -EINVAL if tag is invalid, -EMSGSIZE if len is too large - * or dst_data_avail is too small for the TL. - */ - int (*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); -}; - -/*! Configuration that allows parsing an 8bit tag and 8bit length TLV. */ -extern const struct osmo_gtlv_cfg osmo_t8l8v_cfg; - -/*! Configuration that allows parsing a 16bit tag and 16bit length TLV (see for example PFCP). */ -extern const struct osmo_gtlv_cfg osmo_t16l16v_cfg; - -/*! State for loading a TLV structure from raw data. */ -struct osmo_gtlv_load { - /*! Caller-defined context pointer available for use by load_tl() and store_tl() implementations. */ - void *priv; - - /*! Definition of tag and length sizes (by function pointers). */ - const struct osmo_gtlv_cfg *cfg; - - /*! Overall message buffer being parsed. */ - struct { - const uint8_t *data; - size_t len; - } src; - - /*! Return value from last invocation of osmo_gtlv_load_next*(): tag value of parsed IE. */ - struct osmo_gtlv_tag_inst ti; - /*! Return value from last invocation of osmo_gtlv_load_next*(): Start of the IE's payload data (after tag and - * length). If the end of the src buffer is reached, val == NULL. If a TLV contained no value part, len == 0, - * but this still points just after the TL. */ - const uint8_t *val; - /*! Return value from last invocation of osmo_gtlv_load_next*(): Length of the IE's payload data (without tag and - * length) */ - size_t len; -}; - -/* Start or restart the gtlv from the first IE in the overall TLV data. */ -static inline void osmo_gtlv_load_start(struct osmo_gtlv_load *gtlv) -{ - gtlv->val = NULL; -} - -int osmo_gtlv_load_next(struct osmo_gtlv_load *gtlv); -int osmo_gtlv_load_peek_tag(const struct osmo_gtlv_load *gtlv, struct osmo_gtlv_tag_inst *ti); -int osmo_gtlv_load_next_by_tag(struct osmo_gtlv_load *gtlv, unsigned int tag); -int osmo_gtlv_load_next_by_tag_inst(struct osmo_gtlv_load *gtlv, const struct osmo_gtlv_tag_inst *ti); - -/* State for storing a TLV structure into a msgb. */ -struct osmo_gtlv_put { - /*! Caller-defined context pointer available for use by load_tl() and store_tl() implementations. */ - void *priv; - - /* Definition of tag and length sizes (by function pointers). */ - const struct osmo_gtlv_cfg *cfg; - - /* msgb to append new TL to */ - struct msgb *dst; - /* What was the last TL written and where are its TL and V */ - struct osmo_gtlv_tag_inst last_ti; - uint8_t *last_tl; - uint8_t *last_val; -}; - -int osmo_gtlv_put_tl(struct osmo_gtlv_put *gtlv, unsigned int tag, size_t len); -int osmo_gtlv_put_tli(struct osmo_gtlv_put *gtlv, const struct osmo_gtlv_tag_inst *ti, size_t len); -int osmo_gtlv_put_update_tl(struct osmo_gtlv_put *gtlv); diff --git a/include/osmocom/gtlv/gtlv_dec_enc.h b/include/osmocom/gtlv/gtlv_dec_enc.h deleted file mode 100644 index 132239f..0000000 --- a/include/osmocom/gtlv/gtlv_dec_enc.h +++ /dev/null @@ -1,201 +0,0 @@ -/* Decode and encode the value parts of a TLV structure */ -/* - * (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 <stdbool.h> - -#include <osmocom/gtlv/gtlv.h> - -struct value_string; - -/* User defined function to decode a single TLV value part. See struct osmo_gtlv_coding. - * \param decoded_struct Pointer to the root struct, as context information, e.g. for logging. - * \param decode_to Pointer to the struct member, write the decoded value here. - * \param gtlv TLV loader, pointing at a gtlv->val of gtlv->len bytes. - * \return 0 on success, nonzero on error, e.g. -EINVAL if the gtlv->val is invalid. - */ -typedef int (*osmo_gtlv_dec_func)(void *decoded_struct, void *decode_to, const struct osmo_gtlv_load *gtlv); - -/* User defined function to encode a single TLV value part. See struct osmo_gtlv_coding. - * \param gtlv TLV writer, pointing at a gtlv->dst to msgb_put() data in. - * \param decoded_struct Pointer to the root struct, as context information, e.g. for logging. - * \param encode_from Pointer to the struct member, obtain the value to encode from here. - * \return 0 on success, nonzero on error, e.g. -EINVAL if encode_from has an un-encodable value. - */ -typedef int (*osmo_gtlv_enc_func)(struct osmo_gtlv_put *gtlv, const void *decoded_struct, const void *encode_from); - -/* Optional user defined function to convert a decoded IE struct (the Value part stored as C struct) to string. See - * struct osmo_gtlv_coding. - * \param buf Return string in this buffer. - * \param buflen Size of buf. - * \param str_of Pointer to the struct member described by an osmo_gtlv_coding, obtain the value to encode from here. - * \return number of characters that would be written if the buffer is large enough, like snprintf(). - */ -typedef int (*osmo_gtlv_enc_to_str_func)(char *buf, size_t buflen, const void *str_of); - -/* Whether TLV structures nested inside the value data of an outer IE should be parsed in the same order. */ -enum osmo_gtlv_coding_nested_ies_ordered { - /*! When stepping into nested IEs, keep the same ordering requirement as the outer IE. */ - OSMO_GTLV_NESTED_IES_ORDERING_SAME = 0, - /*! Require IEs in a PDU to appear exactly in the order defined by osmo_gtlv_coding arrays. Causes a parsing - * failure if the TLVs appear in a different order. Does much less iterating looking for matching tags when - * decoding (faster). */ - OSMO_GTLV_NESTED_IES_ORDERED, - /*! Do not require IEs to be in the defined order in decoded PDUs. When encoding a TLV, IEs will always be - * encoded in the order they are defined. This has an effect on decoding only. */ - OSMO_GTLV_NESTED_IES_UNORDERED, -}; - -#define OSMO_ARRAY_PITCH(arr) ((char *)(&(arr)[1]) - (char *)(arr)) -#define OSMO_MEMB_ARRAY_PITCH(obj_type, arr_memb) OSMO_ARRAY_PITCH(((obj_type *)0)->arr_memb) - -/*! Definition of how to decode/encode a IE to/from a struct. - * Kept in lists describing TLV structures, and nestable. - * - * Instance lists of this can be composed manually, or auto-generated using gtlv_gen.c. Auto-generating has the benefit - * that the decoded structs to match the IEs are also generated at the same time and thus always match the message - * definitions. For an example, see tests/libosmo-gtlv/test_gtlv_gen/. */ -struct osmo_gtlv_coding { - /*! the IEI discriminator, and optional instance number */ - struct osmo_gtlv_tag_inst ti; - - /*! Decoding function callback. Invoked for each defined and present IE encountered in the message. - * Return 0 on success, negative on failure. */ - osmo_gtlv_dec_func dec_func; - /*! Encoding function callback. Invoked for each defined and present IE encountered in the message. - * Return 0 on success, negative on failure. */ - osmo_gtlv_enc_func enc_func; - - /*! Means to output the decoded value to a human readable string, optional. */ - osmo_gtlv_enc_to_str_func enc_to_str_func; - - /*! offsetof(decoded_struct_type, member_var): how far into the base struct you find a specific field for decoded - * value. For example, memb_ofs = offsetof(struct foo_msg, ies.bar_response.cause). - * When decoding, the decoded value is written here, when encoding it is read from here. */ - unsigned int memb_ofs; - /*! For repeated IEs (.has_count = true), the array pitch / the offset to add to get to the next array index. */ - unsigned int memb_array_pitch; - - /*! True for optional/conditional IEs. */ - bool has_presence_flag; - /* For optional/conditional IEs (has_presence_flag = true), the offset of the bool foo_present flag, - * For example, if there are - * - * struct foo_msg { - * struct baz baz; - * bool baz_present; - * }; - * - * then set - * memb_ofs = offsetof(struct foo_msg, baz); - * has_presence_flag = true; - * presence_flag_ofs = offsetof(struct foo_msg, baz_present); - */ - unsigned int presence_flag_ofs; - - /*! True for repeated IEs, for array members: - * - * struct foo_msg { - * struct moo moo[10]; - * unsigned int moo_count; - * }; - * - * memb_ofs = offsetof(struct foo_msg, moo); - * has_count = true; - * count_ofs = offsetof(struct foo_msg, moo_count); - * count_max = 10; - */ - bool has_count; - /*! For repeated IEs, the offset of the unsigned int foo_count indicator of how many array indexes are - * in use. See has_count. */ - unsigned int count_ofs; - /*! Maximum array size for member_var[]. See has_count. */ - unsigned int count_max; - /*! If nonzero, it is an error when less than this amount of the repeated IE have been decoded. */ - unsigned int count_mandatory; - - /*! For nested TLVs: if this IE's value part is itself a separate TLV structure, point this at the list of IE - * coding definitions for the inner IEs. - * In this example, the nested IEs decode/encode to different sub structs depending on the tag value. - * - * struct bar { - * int aaa; - * int bbb; - * }; - * - * struct foo_msg { - * struct bar bar; - * struct bar other_bar; - * }; - * - * struct osmo_gtlv_coding bar_nested_ies[] = { - * { FOO_IEI_AAA, .memb_ofs = offsetof(struct bar, aaa), }, - * { FOO_IEI_BBB, .memb_ofs = offsetof(struct bar, bbb), }, - * {} - * }; - * - * struct osmo_gtlv_coding foo_msg_ies[] = { - * { FOO_IEI_GOO, .memb_ofs = offsetof(struct foo_msg, bar), .nested_ies = bar_nested_ies, }, - * { FOO_IEI_OTHER_GOO, .memb_ofs = offsetof(struct foo_msg, other_bar), .nested_ies = bar_nested_ies, }, - * {} - * }; - */ - const struct osmo_gtlv_coding *nested_ies; - - /*! If the nested TLV has a different tag/length size than the outer TLV structure, provide a different config - * here. If they are the same, just keep this NULL. */ - const struct osmo_gtlv_cfg *nested_ies_cfg; - - /*! When stepping into nested IEs, what is the ordering requirement for the nested TLV structure? */ - enum osmo_gtlv_coding_nested_ies_ordered nested_ies_ordered; -}; - - -/*! User defined hook for error logging during TLV and value decoding. - * \param decoded_struct Pointer to the base struct describing this message, for context. - * \param file Source file of where the error occurred. - * \param line Source file line of where the error occurred. - * \param fmt Error message string format. - * \param ... Error message string args. - */ -typedef void (*osmo_gtlv_err_cb)(void *data, void *decoded_struct, const char *file, int line, const char *fmt, ...); - -int osmo_gtlvs_decode(void *decoded_struct, unsigned int obj_ofs, struct osmo_gtlv_load *gtlv, bool tlv_ordered, - const struct osmo_gtlv_coding *ie_coding, - osmo_gtlv_err_cb err_cb, void *err_cb_data, const struct value_string *iei_strs); - -int osmo_gtlvs_encode(struct osmo_gtlv_put *gtlv, const void *decoded_struct, unsigned int obj_ofs, - const struct osmo_gtlv_coding *ie_coding, - osmo_gtlv_err_cb err_cb, void *err_cb_data, const struct value_string *iei_strs); - -int osmo_gtlvs_encode_to_str_buf(char *buf, size_t buflen, const void *decoded_struct, unsigned int obj_ofs, - const struct osmo_gtlv_coding *ie_coding, const struct value_string *iei_strs); -char *osmo_gtlvs_encode_to_str_c(void *ctx, const void *decoded_struct, unsigned int obj_ofs, - const struct osmo_gtlv_coding *ie_coding, const struct value_string *iei_strs); - -static inline bool osmo_gtlv_coding_end(const struct osmo_gtlv_coding *iec) -{ - return iec->dec_func == NULL && iec->enc_func == NULL && iec->nested_ies == NULL; -} diff --git a/include/osmocom/gtlv/gtlv_gen.h b/include/osmocom/gtlv/gtlv_gen.h deleted file mode 100644 index 71cec92..0000000 --- a/include/osmocom/gtlv/gtlv_gen.h +++ /dev/null @@ -1,176 +0,0 @@ -/* Write h and c source files for TLV protocol definitions, based on very sparse TLV definitions. - * For a usage example see tests/libosmo-gtlv/test_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/. - * - */ - -#pragma once - -#include <stdbool.h> - -struct osmo_gtlv_gen_ie; - -/* O means optional, M means mandatory. - * If all of the IE struct, tag name and functions can be derived from the name, just pass osmo_gtlv_gen_ie_auto as - * TLV_GEN_IE. */ -#define OSMO_GTLV_GEN_O(TLV_GEN_IE, MEMB_NAME) { MEMB_NAME, .optional = true, .ie = &(TLV_GEN_IE) } -#define OSMO_GTLV_GEN_M(TLV_GEN_IE, MEMB_NAME) { MEMB_NAME, .ie = &(TLV_GEN_IE) } -#define OSMO_GTLV_GEN_O_MULTI(MAX, TLV_GEN_IE, MEMB_NAME) { MEMB_NAME, .multi = MAX, .ie = &(TLV_GEN_IE) } -#define OSMO_GTLV_GEN_M_MULTI(MAX, MAND_COUNT, TLV_GEN_IE, MEMB_NAME) \ - { MEMB_NAME, .multi = MAX, .multi_mandatory = MAND_COUNT, .ie = &(TLV_GEN_IE) } -#define OSMO_GTLV_GEN_O_INST(INSTANCE, TLV_GEN_IE, MEMB_NAME) { MEMB_NAME, .optional = true, .instance = INSTANCE, .ie = &TLV_GEN_IE } -#define OSMO_GTLV_GEN_M_INST(INSTANCE, TLV_GEN_IE, MEMB_NAME) { MEMB_NAME, .instance = INSTANCE, .ie = &(TLV_GEN_IE) } - -#define OSMO_GTLV_GEN_NO_INSTANCE INT_MAX - -/*! osmo_gtlv_gen_ie with all members == NULL, so that all are derived from the member name. */ -extern const struct osmo_gtlv_gen_ie osmo_gtlv_gen_ie_auto; - -/*! Modifier for Mandatory/Optional/Multiple around an osmo_gtlv_gen_ie. */ -struct osmo_gtlv_gen_ie_o { - /*! The C name of the member in a decoded struct, to be of the type defined by .ie. - * All parts of .ie, if NULL, are derived from this name. - * - * For example, simply this - * - * struct osmo_gtlv_gen_ie_o foo[] = { - * OSMO_GTLV_GEN_O("bar", NULL), - * }; - * - * Generates - * - * struct myproto_msg_foo { - * struct myproto_ie_bar bar; - * } - * - * and an osmo_gtlv_coding entry of - * - * { MYPROTO_IEI_BAR, - * .memb_ofs = offsetof(struct myproto_msg_foo, bar), - * .dec_func = myproto_dec_bar, - * .enc_func = myproto_enc_bar, - * .enc_to_str_func = myproto_enc_to_str_bar, - * } - * - * See also osmo_gtlv_gen_cfg.add_enc_to_str. - */ - const char *name; - - /*! Whether to add a bool foo_present, and to skip encoding/decoding if false. - * Only useful for non-multi IEs (compare OSMO_GTLV_GEN_O_MULTI() vs OSMO_GTLV_GEN_M_MULTI()). */ - bool optional; - - /*! If non-NULL, the member is an array: foo[123] with an unsigned int foo_count. - * Set to the maximum number of array elements; for foo[123] set .multi = 123. */ - unsigned int multi; - /*! Number of mandatory occurences of the IE, only has an effect if .multi > 0. */ - unsigned int multi_mandatory; - - /* If any, the instance nr to match, in C that yields an unsigned int. - * e.g. "1" or "MYPROTO_FOO_INST_ONE". */ - const char *instance; - - /*! IE decoding / encoding instructions. If NULL, the entire IE definition is derived from .name. - * 'MYPROTO_IEI_NAME', 'myproto_dec_name()', 'myproto_enc_name()', 'myproto_enc_to_str_name()'. - * Your myproto_ies_custom.h needs to define an enum value MYPROTO_IEI_NAME and*/ - const struct osmo_gtlv_gen_ie *ie; -}; - -/*! Define decoding and encoding of a single IE, i.e. one full TLV. */ -struct osmo_gtlv_gen_ie { - /*! like "uint32_t" or "struct foo". - * If NULL, use "struct myproto_ie_<name>" instead, where <name> comes from the osmo_gtlv_gen_ie_o. - * When there are nested IEs, the struct definition is auto-generated, deriving the struct members from the - * nested_ies list. - * When there are no nested IEs, the type needs to be defined manually by a myproto_ies_custom.h. */ - const char *decoded_type; - - /*! C name of this tag value, e.g. "foo" to use tag "MYPROTO_IEI_FOO". - * If NULL, take "MYPROTO_IEI_"+upper(memb_name) instead, where memb_name comes from the osmo_gtlv_gen_ie_o. - * decoded_type and/or dec_enc may be derived from this, if they are NULL. */ - const char *tag_name; - - /*! Name suffix of the dec/enc functions. "foo" -> myproto_dec_foo(), myproto_enc_foo(), - * myproto_enc_to_str_foo(). - * These functions need to be implemented manually in a myproto_ies_custom.c. - * When osmo_gtlv_gen_cfg.add_enc_to_str is false, the myproto_enc_to_str_foo() is not required. */ - const char *dec_enc; - - /*! List of inner IEs terminated by {}. If non-NULL, this is a "Grouped IE" with an inner TLV structure inside - * this IE's V part. */ - const struct osmo_gtlv_gen_ie_o *nested_ies; - - /*! To place a spec comment in the generated code. */ - const char *spec_ref; -}; - -/*! General TLV decoding and encoding definitions applying to all IEs (and nested IEs). */ -struct osmo_gtlv_gen_cfg { - /*! Name of the protocol for use in C type or function names, like "myproto". */ - const char *proto_name; - - /*! When placing comments to spec references, prefix with this. For example, "3GPP TS 12.345 ". */ - const char *spec_ref_prefix; - - /*! The type to pass a message discriminator as, like 'enum myproto_message_types' */ - const char *message_type_enum; - /*! To reference a message type discriminator like MYPROTO_MSGT_FOO, this would be "MYPROTO_MSGT_". */ - const char *message_type_prefix; - - /*! Type to use to represent tag IEI in decoded form. - * For example "enum foo_msg_iei". */ - const char *tag_enum; - /*! The tag IEI enum value is uppercase(tag_prefix + (iedef->tag_name or iedef->name)). - * For example, with tag_prefix = "OSMO_FOO_IEI_", we would generate code like - * enum osmo_foo_iei tag = OSMO_FOO_IEI_BAR; */ - const char *tag_prefix; - - /*! When an osmo_gtlv_gen_ie provides no decoded_type string, it is derived from .name and this prefix is - * added. For example, with decoded_type_prefix = "struct foo_ie_", the decoded_type defaults to - * struct foo_ie_bar for an IE definition with name = "bar". */ - const char *decoded_type_prefix; - - /*! To include user defined headers, set to something like "#include <osmocom/foo/foo_tlv_devs.h". This is put at - * the head of the generated .h file. */ - const char *h_header; - - /*! To include user defined headers, set to something like "#include <osmocom/foo/foo_msg.h". This is put at - * the head of the generated .c file. */ - const char *c_header; - - /*! Array of message IE definitions, indexed by message type. */ - const struct osmo_gtlv_gen_msg *msg_defs; - - /*! Whether to add to_str functions. When true, every automatically derived IE (that has no nested IEs) needs to - * have a myproto_enc_to_str_foo() defined by a myproto_ies_custom.c. When false, osmo_gtlvs_encode_to_str_buf() - * will print '?' instead of the IE contents. */ - bool add_enc_to_str; -}; - -/*! For generating the outer union that composes a protocol's PDU variants, an entry of the list of message names and - * IEs in each message. */ -struct osmo_gtlv_gen_msg { - const char *name; - const struct osmo_gtlv_gen_ie_o *ies; -}; - -int osmo_gtlv_gen_main(const struct osmo_gtlv_gen_cfg *cfg, int argc, const char **argv); diff --git a/include/osmocom/pfcp/Makefile.am b/include/osmocom/pfcp/Makefile.am index 5d2db19..a9bdeab 100644 --- a/include/osmocom/pfcp/Makefile.am +++ b/include/osmocom/pfcp/Makefile.am @@ -17,9 +17,6 @@ pfcp_ies_auto.h \ $(NULL)
-pfcp_ies_auto.h: $(top_srcdir)/src/libosmo-pfcp/gen__pfcp_ies_auto.c \ - $(top_srcdir)/src/libosmo-gtlv/gtlv_gen.c \ - $(top_srcdir)/include/osmocom/gtlv/gtlv_gen.h - $(MAKE) -C $(top_builddir)/src/libosmo-gtlv +pfcp_ies_auto.h: $(top_srcdir)/src/libosmo-pfcp/gen__pfcp_ies_auto.c $(MAKE) -C $(top_builddir)/src/libosmo-pfcp gen__pfcp_ies_auto $(top_builddir)/src/libosmo-pfcp/gen__pfcp_ies_auto h > $(builddir)/pfcp_ies_auto.h diff --git a/src/Makefile.am b/src/Makefile.am index 34cf082..78c8adb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,5 +1,4 @@ SUBDIRS = \ - libosmo-gtlv \ libosmo-pfcp \ osmo-upf \ $(NULL) diff --git a/src/libosmo-gtlv/Makefile.am b/src/libosmo-gtlv/Makefile.am deleted file mode 100644 index 248ff67..0000000 --- a/src/libosmo-gtlv/Makefile.am +++ /dev/null @@ -1,27 +0,0 @@ -AM_CPPFLAGS = \ - $(all_includes) \ - -I$(top_srcdir)/include \ - -I$(top_builddir) \ - -I$(builddir) \ - $(NULL) - -AM_CFLAGS = \ - -Wall \ - $(LIBOSMOCORE_CFLAGS) \ - $(COVERAGE_CFLAGS) \ - $(NULL) - -AM_LDFLAGS = \ - $(LIBOSMOCORE_LIBS) \ - $(COVERAGE_LDFLAGS) \ - $(NULL) - -noinst_LIBRARIES = \ - libosmo-gtlv.a \ - $(NULL) - -libosmo_gtlv_a_SOURCES = \ - gtlv.c \ - gtlv_dec_enc.c \ - gtlv_gen.c \ - $(NULL) diff --git a/src/libosmo-gtlv/gtlv.c b/src/libosmo-gtlv/gtlv.c deleted file mode 100644 index 9bdbe75..0000000 --- a/src/libosmo-gtlv/gtlv.c +++ /dev/null @@ -1,342 +0,0 @@ -/* - * (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 <osmocom/core/bits.h> -#include <osmocom/core/msgb.h> -#include <osmocom/gtlv/gtlv.h> - -int osmo_gtlv_tag_inst_cmp(const struct osmo_gtlv_tag_inst *a, const struct osmo_gtlv_tag_inst *b) -{ - int cmp; - if (a == b) - return 0; - if (!a) - return -1; - if (!b) - return 1; - cmp = OSMO_CMP(a->tag, b->tag); - if (cmp) - return cmp; - cmp = OSMO_CMP(a->instance_present ? 1 : 0, b->instance_present ? 1 : 0); - if (cmp) - return cmp; - if (a->instance_present) - return OSMO_CMP(a->instance, b->instance); - return 0; -} - -int osmo_gtlv_tag_inst_to_str_buf(char *buf, size_t buflen, const struct osmo_gtlv_tag_inst *ti, - const struct value_string *tag_names) -{ - struct osmo_strbuf sb = { .buf = buf, .len = buflen }; - if (!tag_names) - OSMO_STRBUF_PRINTF(sb, "%u", ti->tag); - else - OSMO_STRBUF_PRINTF(sb, "%s", get_value_string(tag_names, ti->tag)); - if (ti->instance_present) - OSMO_STRBUF_PRINTF(sb, "[%u]", ti->instance); - return sb.chars_needed; -} - -char *osmo_gtlv_tag_inst_to_str_c(void *ctx, const struct osmo_gtlv_tag_inst *ti, - const struct value_string *tag_names) -{ - OSMO_NAME_C_IMPL(ctx, 64, "ERROR", osmo_gtlv_tag_inst_to_str_buf, ti, tag_names) -} - -static int next_tl_valid(const struct osmo_gtlv_load *gtlv, const uint8_t **ie_start_p, size_t *buflen_left_p) -{ - const uint8_t *ie_start; - size_t buflen_left; - - /* Start of next IE, or first IE for first invocation. */ - if (!gtlv->val) - ie_start = gtlv->src.data; - else - ie_start = gtlv->val + gtlv->len; - - /* Sanity */ - if (ie_start < gtlv->src.data || ie_start > gtlv->src.data + gtlv->src.len) - return -ENOSPC; - - buflen_left = gtlv->src.len - (ie_start - gtlv->src.data); - - /* Too short for parsing an IE? Check also against integer overflow. */ - if (buflen_left && ((buflen_left < gtlv->cfg->tl_min_size) || (buflen_left > gtlv->src.len))) - return -EBADMSG; - - *ie_start_p = ie_start; - *buflen_left_p = buflen_left; - return 0; -} - -/* Return a TLV IE from a message buffer. - * - * Return the first or next TLV data found in the data buffer, based on the state of the gtlv parameter. - * When gtlv->val is NULL, return the first IE in the data buffer. - * Otherwise assume that gtlv points at a valid IE in the data structure, and return the subsequent IE. - * - * Usage example: - * - * struct osmo_gtlv gtlv = { - * .cfg = osmo_t16l16v_cfg, - * .src = { .data = msgb_l3(msg), .len = msgb_l3len(msg) }, - * }; - * for (;;) { - * if (osmo_gtlv_next(>lv)) { - * printf("Error\n"); - * break; - * } - * if (!gtlv.val) { - * printf("End\n"); - * break; - * } - * printf("Tag %u: %zu octets: %s\n", gtlv.tag, gtlv.len, osmo_hexdump(gtlv.val, gtlv.len)); - * } - * - * \param[inout] gtlv Buffer to return the IE data, and state for TLV parsing position. gtlv->msg should indicate the - * overall message buffer. The other gtlv members should be zero initialized before the first call, and - * remain unchanged between invocations of this function. - * \returns 0 on success, negative on TLV parsing error. The IE data is returned in gtlv->tag, gtlv->len and gtlv->val; - * gtlv->val == NULL if no more IEs remain in the buffer. - */ -int osmo_gtlv_load_next(struct osmo_gtlv_load *gtlv) -{ - const uint8_t *ie_start; - const uint8_t *ie_end; - size_t buflen_left; - int rc; - - rc = next_tl_valid(gtlv, &ie_start, &buflen_left); - if (rc) - return rc; - - /* No more IEs? */ - if (!buflen_left) { - gtlv->val = NULL; - return 0; - } - - /* Locate next IE */ - OSMO_ASSERT(gtlv->cfg->load_tl); - gtlv->ti = (struct osmo_gtlv_tag_inst){}; - rc = gtlv->cfg->load_tl(gtlv, ie_start, buflen_left); - if (rc) - return rc; - - /* Sanity */ - ie_end = gtlv->val + gtlv->len; - if (ie_end < gtlv->src.data || ie_end > gtlv->src.data + gtlv->src.len) - return -EBADMSG; - - return 0; -} - -/* Return the tag of the IE that osmo_gtlv_next() would yield, do not change the gtlv state. - * - * \param[in] gtlv state for TLV parsing position; is not modified. - * \param[out] tag the tag number on success, if NULL don't return the tag. - * \param[out] instance the instance number or OSMO_GTLV_NO_INSTANCE if there is no instance value, - * if NULL don't return the instance value. - * \returns 0 on success, negative on TLV parsing error, -ENOENT when no more tags follow. - */ -int osmo_gtlv_load_peek_tag(const struct osmo_gtlv_load *gtlv, struct osmo_gtlv_tag_inst *ti) -{ - const uint8_t *ie_start; - size_t buflen_left; - int rc; - /* Guard against modification by load_tl(). */ - struct osmo_gtlv_load mtlv = *gtlv; - mtlv.ti = (struct osmo_gtlv_tag_inst){}; - - rc = next_tl_valid(&mtlv, &ie_start, &buflen_left); - if (rc) - return rc; - - if (!buflen_left) - return -ENOENT; - - /* Return next IE tag*/ - OSMO_ASSERT(mtlv.cfg->load_tl); - rc = gtlv->cfg->load_tl(&mtlv, ie_start, buflen_left); - if (rc) - return -EBADMSG; - if (ti) - *ti = mtlv.ti; - return 0; -} - -/* Same as osmo_gtlv_load_next(), but skip any IEs until the given tag is reached. Change the gtlv state only when success - * is returned. - * \param[out] gtlv Return the next IE's TLV info. - * \param[in] tag Tag value to match. - * \param[in] instance Instance value to match; For IEs that have no instance value (no TLIV), pass - * OSMO_GTLV_NO_INSTANCE. - * \return 0 when the tag is found. Return -ENOENT when no such tag follows and keep the gtlv unchanged. */ -int osmo_gtlv_load_next_by_tag(struct osmo_gtlv_load *gtlv, unsigned int tag) -{ - struct osmo_gtlv_tag_inst ti = { .tag = tag }; - return osmo_gtlv_load_next_by_tag_inst(gtlv, &ti); -} - -int osmo_gtlv_load_next_by_tag_inst(struct osmo_gtlv_load *gtlv, const struct osmo_gtlv_tag_inst *ti) -{ - struct osmo_gtlv_load work = *gtlv; - for (;;) { - int rc = osmo_gtlv_load_next(&work); - if (rc) - return rc; - if (!work.val) - return -ENOENT; - if (!osmo_gtlv_tag_inst_cmp(&work.ti, ti)) { - *gtlv = work; - return 0; - } - } -} - -/* Put tag header and length at the end of the msgb, according to gtlv->cfg->store_tl(). - * If the length is not known yet, it can be passed as 0 at first, and osmo_gtlv_put_update_tl() can determine the - * resulting length after the value part was put into the msgb. - * - * Usage example: - * - * struct msgb *msg = msgb_alloc(1024, "foo"), - * struct osmo_gtlv_put gtlv = { - * .cfg = osmo_t16l16v_cfg, - * .dst = msg, - * } - * - * osmo_gtlv_put_tl(gtlv, 23, 0); // tag 23, length 0 = not known yet - * - * msgb_put(msg, 42); - * ... - * msgb_put(msg, 42); - * ... - * msgb_put(msg, 42); - * - * osmo_gtlv_put_update_tl(gtlv); - * - * Return 0 on success, -EINVAL if the tag value is invalid, -EMSGSIZE if len is too large. - */ -int osmo_gtlv_put_tl(struct osmo_gtlv_put *gtlv, unsigned int tag, size_t len) -{ - struct osmo_gtlv_tag_inst ti = { .tag = tag }; - return osmo_gtlv_put_tli(gtlv, &ti, len); -} - -/* Put tag header, instance value and length at the end of the msgb, according to gtlv->cfg->store_tl(). - * This is the same as osmo_gtlv_put_tl(), only osmo_gtlv_put_tl() passes instance = 0. - */ -int osmo_gtlv_put_tli(struct osmo_gtlv_put *gtlv, const struct osmo_gtlv_tag_inst *ti, size_t len) -{ - int rc; - uint8_t *last_tl; - OSMO_ASSERT(gtlv->cfg->store_tl); - last_tl = gtlv->dst->tail; - rc = gtlv->cfg->store_tl(gtlv->dst->tail, msgb_tailroom(gtlv->dst), ti, len, gtlv); - if (rc < 0) - return rc; - if (rc > 0) - msgb_put(gtlv->dst, rc); - gtlv->last_ti = *ti; - gtlv->last_tl = last_tl; - gtlv->last_val = gtlv->dst->tail; - return 0; -} - -/* Update the length of the last put IE header (last call to osmo_gtlv_put_tl()) to match with the current - * gtlv->dst->tail. - * Return 0 on success, -EMSGSIZE if the amount of data written since osmo_gtlv_put_tl() is too large. - */ -int osmo_gtlv_put_update_tl(struct osmo_gtlv_put *gtlv) -{ - size_t len = gtlv->dst->tail - gtlv->last_val; - int rc = gtlv->cfg->store_tl(gtlv->last_tl, gtlv->last_val - gtlv->last_tl, >lv->last_ti, len, gtlv); - if (rc < 0) - return rc; - /* In case the TL has changed in size, hopefully the implementation has moved the msgb data. Make sure last_val - * points at the right place now. */ - gtlv->last_val = gtlv->last_tl + rc; - return 0; -} - -static int t8l8v_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]; - gtlv->val = src_data + 2; - return 0; -} - -static int t8l8v_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; - dst_data[1] = len; - return 2; -} - -const struct osmo_gtlv_cfg osmo_t8l8v_cfg = { - .tl_min_size = 2, - .load_tl = t8l8v_load_tl, - .store_tl = t8l8v_store_tl, -}; - -static int t16l16v_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 == 4. */ - gtlv->ti.tag = osmo_load16be(src_data); - gtlv->len = osmo_load16be(src_data + 2); - gtlv->val = src_data + 4; - return 0; -} - -static int t16l16v_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 > UINT16_MAX) - return -EINVAL; - if (len > UINT16_MAX) - return -EMSGSIZE; - if (dst_data_avail < 4) - return -ENOSPC; - osmo_store16be(ti->tag, dst_data); - osmo_store16be(len, dst_data + 2); - return 4; -} - -const struct osmo_gtlv_cfg osmo_t16l16v_cfg = { - .tl_min_size = 4, - .load_tl = t16l16v_load_tl, - .store_tl = t16l16v_store_tl, -}; diff --git a/src/libosmo-gtlv/gtlv_dec_enc.c b/src/libosmo-gtlv/gtlv_dec_enc.c deleted file mode 100644 index 2e5509a..0000000 --- a/src/libosmo-gtlv/gtlv_dec_enc.c +++ /dev/null @@ -1,530 +0,0 @@ -/* - * (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 <string.h> - -#include <osmocom/core/utils.h> - -#include <osmocom/gtlv/gtlv_dec_enc.h> - -/* Reverse offsetof(): return the address of the struct member for a given osmo_gtlv_msg and member ofs_foo value. */ -#define MEMB(M, MEMB_OFS) ((void *)((char *)(M) + (MEMB_OFS))) - -#define RETURN_ERROR(RC, TAG_INST, FMT, ARGS...) \ - do {\ - if (err_cb) { \ - if ((TAG_INST).instance_present) \ - err_cb(err_cb_data, (void *)decoded_struct, __FILE__, __LINE__, \ - "tag 0x%x = %s instance %u: " FMT " (%d: %s)\n", \ - (TAG_INST).tag, get_value_string(iei_strs, (TAG_INST).tag), \ - (TAG_INST).instance, ##ARGS, \ - RC, strerror((RC) > 0 ? (RC) : -(RC))); \ - else \ - err_cb(err_cb_data, (void *)decoded_struct, __FILE__, __LINE__, \ - "tag 0x%x = %s: " FMT " (%d: %s)\n", \ - (TAG_INST).tag, get_value_string(iei_strs, (TAG_INST).tag), ##ARGS, \ - RC, strerror((RC) > 0 ? (RC) : -(RC))); \ - } \ - return RC; \ - } while (0) - - -/*! Decode a TLV structure from raw data to a decoded struct, for unordered TLV IEs. - * How to decode IE values and where to place them in the decoded struct, is defined by ie_coding, an array terminated - * by a '{}' entry. - * The IEs may appear in any ordering in the TLV data. - * For unordered decoding, only IEs with has_presence_flag == true or has_count == true may repeat. Other IE definitions - * cause the last read TLV to overwrite all previous decodings, all into the first occurrence in ie_coding. - * \param[out] decoded_struct Pointer to the struct to write parsed IE data to. - * \param[in] obj_ofs Pass as zero. Used for nested IEs: offset added to decoded_struct to get to a sub-struct. - * \param[in] gtlv TLV data to parse, as given in gtlv->msg.*. Must be ready for osmo_gtlv_load_start(). - * \param[in] ie_coding A list of permitted/expected IEI tags and instructions for decoding. - * \param[in] err_cb Function to call to report an error message, or NULL. - * \param[in] err_cb_data Caller supplied context to pass to the err_cb as 'data' argument. - * \param[in] iei_strs value_string array to give IEI names in error messages passed to err_cb(), or NULL. - * \return 0 on success, negative on error. - */ -static int osmo_gtlvs_decode_unordered(void *decoded_struct, unsigned int obj_ofs, struct osmo_gtlv_load *gtlv, - const struct osmo_gtlv_coding *ie_coding, - osmo_gtlv_err_cb err_cb, void *err_cb_data, const struct value_string *iei_strs) -{ - void *obj = MEMB(decoded_struct, obj_ofs); - const struct osmo_gtlv_coding *iec; - unsigned int *multi_count_p; - - /* To check for presence of mandatory IEs, need to keep a flag stack of seen ie_coding entries. This array has - * to have at least the nr of entries that the ie_coding array has. Let's allow up to this many ie_coding - * entries to avoid dynamic allocation. Seems like enough. */ - bool seen_ie_coding_entries[4096] = {}; - bool *seen_p; -#define CHECK_SEEN(IEC) do { \ - unsigned int ie_coding_idx = (IEC) - ie_coding; \ - if (ie_coding_idx >= ARRAY_SIZE(seen_ie_coding_entries)) \ - RETURN_ERROR(-ENOTSUP, gtlv->ti, \ - "Too many IE definitions for decoding an unordered TLV structure"); \ - seen_p = &seen_ie_coding_entries[ie_coding_idx]; \ - } while (0) - - - osmo_gtlv_load_start(gtlv); - - /* IEs are allowed to come in any order. So traverse the TLV structure once, and find an IE parser for each (if - * any). */ - for (;;) { - int rc; - bool *presence_flag_p; - unsigned int memb_next_array_idx; - unsigned int memb_ofs; - unsigned int ie_max_allowed_count; - - rc = osmo_gtlv_load_next(gtlv); - if (rc) - RETURN_ERROR(rc, gtlv->ti, "Decoding IEs failed on or after this tag"); - if (!gtlv->val) { - /* End of the TLV structure */ - break; - } - - /* ie_max_allowed_count counts how often the same IEI may appear in a message until all struct members - * that can store them are filled up. */ - ie_max_allowed_count = 0; - - do { - /* Find the IE coding for this tag */ - for (iec = ie_coding; - !osmo_gtlv_coding_end(iec) && osmo_gtlv_tag_inst_cmp(&iec->ti, >lv->ti); - iec++); - /* No such IE coding found. */ - if (osmo_gtlv_coding_end(iec)) - break; - - /* Keep track how often this tag can occur */ - ie_max_allowed_count += iec->has_count ? iec->count_max : 1; - - /* Was this iec instance already decoded? Then skip to the next one, if any. */ - presence_flag_p = iec->has_presence_flag ? MEMB(obj, iec->presence_flag_ofs) : NULL; - multi_count_p = iec->has_count ? MEMB(obj, iec->count_ofs) : NULL; - if ((presence_flag_p && *presence_flag_p) - || (multi_count_p && *multi_count_p >= iec->count_max)) - continue; - /* For IEs with a presence flag or a multi count, the decoded struct provides the information - * whether the IE has already been decoded. Do the same for mandatory IEs, using local state in - * seen_ie_coding_entries[]. */ - CHECK_SEEN(iec); - if (*seen_p) - continue; - } while (0); - if (osmo_gtlv_coding_end(iec)) { - if (ie_max_allowed_count) { - /* There have been IE definitions for this IEI, but all slots to decode it are already - * filled. */ - RETURN_ERROR(-ENOTSUP, gtlv->ti, "Only %u instances of this IE are supported per message", - ie_max_allowed_count); - } - /* No such IE defined in ie_coding, just skip the TLV. */ - continue; - } - - /* If this is a repeated IE, decode into the correct array index memb[idx], - * next idx == (*multi_count_p). We've already guaranteed above that *multi_count_p < count_max. */ - memb_next_array_idx = multi_count_p ? *multi_count_p : 0; - memb_ofs = iec->memb_ofs + memb_next_array_idx * iec->memb_array_pitch; - - /* Decode IE value part */ - if (iec->nested_ies) { - /* A nested IE: the value part of this TLV is in turn a TLV structure. Decode the inner - * IEs. */ - struct osmo_gtlv_load inner_tlv = { - .cfg = iec->nested_ies_cfg ? : gtlv->cfg, - .src = { - .data = gtlv->val, - .len = gtlv->len, - } - }; - bool ordered; - switch (iec->nested_ies_ordered) { - case OSMO_GTLV_NESTED_IES_ORDERED: - ordered = true; - break; - case OSMO_GTLV_NESTED_IES_ORDERING_SAME: - case OSMO_GTLV_NESTED_IES_UNORDERED: - ordered = false; - break; - default: - OSMO_ASSERT(0); - } - rc = osmo_gtlvs_decode(decoded_struct, obj_ofs + memb_ofs, &inner_tlv, ordered, iec->nested_ies, - err_cb, err_cb_data, iei_strs); - if (rc) - RETURN_ERROR(rc, gtlv->ti, "Error while decoding TLV structure nested inside this IE"); - } else { - /* Normal IE, decode the specific IE data. */ - if (!iec->dec_func) - RETURN_ERROR(-EIO, gtlv->ti, "IE definition lacks a dec_func()"); - rc = iec->dec_func(decoded_struct, MEMB(obj, memb_ofs), gtlv); - if (rc) - RETURN_ERROR(rc, gtlv->ti, "Error while decoding this IE"); - } - - if (multi_count_p) { - /* A repeated IE, record that we've added one entry. This increments the foo_count value in the - * decoded osmo_gtlv_msg.ies.*. - * For example, multi_count_p points at osmo_gtlv_msg_session_est_req.create_pdr_count, - * and memb_ofs points at osmo_gtlv_msg_session_est_req.create_pdr. */ - (*multi_count_p)++; - } - if (presence_flag_p) { - *presence_flag_p = true; - } - CHECK_SEEN(iec); - *seen_p = true; - } - - /* Check presence of mandatory IEs */ - for (iec = ie_coding; !osmo_gtlv_coding_end(iec); iec++) { - if (iec->has_presence_flag) - continue; - multi_count_p = iec->has_count ? MEMB(obj, iec->count_ofs) : NULL; - if (multi_count_p) { - if (*multi_count_p < iec->count_mandatory) - RETURN_ERROR(-EINVAL, iec->ti, "%u instances of this IE are mandatory, got %u", - iec->count_mandatory, *multi_count_p); - continue; - } - /* Neither an optional nor a multi member, hence it must be mandatory. */ - CHECK_SEEN(iec); - if (!*seen_p) - RETURN_ERROR(-EINVAL, iec->ti, "Missing mandatory IE"); - } - return 0; -} - -/*! Decode a TLV structure from raw data to a decoded struct, for ordered TLV IEs. - * How to decode IE values and where to place them in the decoded struct, is defined by ie_coding, an array terminated - * by a '{}' entry. - * The IEs in the TLV structure must appear in the same order as they are defined in ie_coding. - * cause the last read TLV to overwrite all previous decodings, all into the first occurrence in ie_coding. - * \param[out] decoded_struct Pointer to the struct to write parsed IE data to. - * \param[in] obj_ofs Pass as zero. Used for nested IEs: offset added to decoded_struct to get to a sub-struct. - * \param[in] gtlv TLV data to parse, as given in gtlv->msg.*. Must be ready for osmo_gtlv_load_start(). - * \param[in] ie_coding A list of permitted/expected IEI tags and instructions for decoding. - * \param[in] err_cb Function to call to report an error message, or NULL. - * \param[in] err_cb_data Caller supplied context to pass to the err_cb as 'data' argument. - * \param[in] iei_strs value_string array to give IEI names in error messages passed to err_cb(), or NULL. - * \return 0 on success, negative on error. - */ -static int osmo_gtlvs_decode_ordered(void *decoded_struct, unsigned int obj_ofs, struct osmo_gtlv_load *gtlv, - const struct osmo_gtlv_coding *ie_coding, - osmo_gtlv_err_cb err_cb, void *err_cb_data, const struct value_string *iei_strs) -{ - void *obj = MEMB(decoded_struct, obj_ofs); - - osmo_gtlv_load_start(gtlv); - - for (; !osmo_gtlv_coding_end(ie_coding); ie_coding++) { - int rc; - bool *presence_flag = ie_coding->has_presence_flag ? MEMB(obj, ie_coding->presence_flag_ofs) : NULL; - unsigned int *multi_count = ie_coding->has_count ? MEMB(obj, ie_coding->count_ofs) : NULL; - struct osmo_gtlv_tag_inst peek_ti; - - rc = osmo_gtlv_load_next_by_tag_inst(gtlv, &ie_coding->ti); - switch (rc) { - case 0: - break; - case -ENOENT: - if (!presence_flag && (!multi_count || *multi_count < ie_coding->count_mandatory)) - RETURN_ERROR(rc, ie_coding->ti, "Missing mandatory IE"); - if (presence_flag) - *presence_flag = false; - continue; - default: - RETURN_ERROR(rc, ie_coding->ti, "Error in TLV structure"); - } - - for (;;) { - /* If this is a repeated IE, decode into the correct array index memb[idx], - * next idx == (*multi_count) */ - unsigned int memb_next_array_idx = multi_count ? *multi_count : 0; - unsigned int memb_ofs = ie_coding->memb_ofs + memb_next_array_idx * ie_coding->memb_array_pitch; - - if (multi_count && memb_next_array_idx >= ie_coding->count_max) - RETURN_ERROR(-ENOTSUP, ie_coding->ti, "Only %u instances of this IE are supported per message", - ie_coding->count_max); - - /* Decode IE value part */ - if (ie_coding->nested_ies) { - /* A nested IE: the value part of this TLV is in turn a TLV structure. Decode the inner - * IEs. */ - struct osmo_gtlv_load inner_tlv = { - .cfg = ie_coding->nested_ies_cfg ? : gtlv->cfg, - .src = { - .data = gtlv->val, - .len = gtlv->len, - } - }; - bool ordered; - switch (ie_coding->nested_ies_ordered) { - case OSMO_GTLV_NESTED_IES_ORDERING_SAME: - case OSMO_GTLV_NESTED_IES_ORDERED: - ordered = true; - break; - case OSMO_GTLV_NESTED_IES_UNORDERED: - ordered = false; - break; - default: - OSMO_ASSERT(0); - } - rc = osmo_gtlvs_decode(decoded_struct, obj_ofs + memb_ofs, &inner_tlv, ordered, - ie_coding->nested_ies, err_cb, err_cb_data, iei_strs); - if (rc) - RETURN_ERROR(rc, ie_coding->ti, - "Error while decoding TLV structure nested inside this IE"); - } else { - /* Normal IE, decode the specific IE data. */ - if (!ie_coding->dec_func) - RETURN_ERROR(-EIO, ie_coding->ti, "IE definition lacks a dec_func()"); - rc = ie_coding->dec_func(decoded_struct, MEMB(obj, memb_ofs), gtlv); - if (rc) - RETURN_ERROR(rc, ie_coding->ti, "Error while decoding this IE"); - } - - if (presence_flag) - *presence_flag = true; - - if (!multi_count) { - /* Not a repeated IE. */ - break; - } - - /* A repeated IE, record that we've added one entry. This increments the foo_count value in the - * decoded osmo_pfcp_msg.ies.*. - * For example, multi_count points at osmo_pfcp_msg_session_est_req.create_pdr_count, - * and memb_ofs points at osmo_pfcp_msg_session_est_req.create_pdr. */ - (*multi_count)++; - - /* Does another one of these IEs follow? */ - if (osmo_gtlv_load_peek_tag(gtlv, &peek_ti) - || osmo_gtlv_tag_inst_cmp(&peek_ti, >lv->ti)) { - /* Next tag is a different IE, end the repetition. */ - break; - } - - /* continue, parsing the next repetition of this tag. */ - rc = osmo_gtlv_load_next(gtlv); - if (rc) - return rc; - } - /* continue parsing the next tag. */ - } - return 0; -} - -/*! Decode an entire TLV message from raw data to decoded struct. - * How to decode IE values and where to put them in the decoded struct is defined by ie_coding, an array terminated by - * a '{}' entry. - * \param[out] decoded_struct Pointer to the struct to write parsed IE data to. - * \param[in] obj_ofs Pass as zero. Used for nested IEs: offset added to decoded_struct to get to a sub-struct. - * \param[in] gtlv TLV data to parse, as given in gtlv->msg.*. Must be ready for osmo_gtlv_load_start(). - * \param[in] ie_coding A list of permitted/expected IEI tags and instructions for decoding. - * \param[in] err_cb Function to call to report an error message, or NULL. - * \param[in] err_cb_data Caller supplied context to pass to the err_cb as 'data' argument. - * \param[in] iei_strs value_string array to give IEI names in error messages passed to err_cb(), or NULL. - * \return 0 on success, negative on error. - */ -int osmo_gtlvs_decode(void *decoded_struct, unsigned int obj_ofs, struct osmo_gtlv_load *gtlv, bool tlv_ordered, - const struct osmo_gtlv_coding *ie_coding, - osmo_gtlv_err_cb err_cb, void *err_cb_data, const struct value_string *iei_strs) -{ - if (!ie_coding) - return -ENOTSUP; - if (tlv_ordered) - return osmo_gtlvs_decode_ordered(decoded_struct, obj_ofs, gtlv, ie_coding, err_cb, err_cb_data, iei_strs); - else - return osmo_gtlvs_decode_unordered(decoded_struct, obj_ofs, gtlv, ie_coding, err_cb, err_cb_data, - iei_strs); -} - -/*! Encode a TLV structure from decoded struct to raw data. - * How to encode IE values and where to read them in the decoded struct is defined by ie_coding, an array terminated by - * a '{}' entry. - * The IEs will be encoded in the order they appear in ie_coding. - * \param[out] gtlv Write data using this TLV definition to gtlv->dst. - * \param[in] decoded_struct C struct data to encode. - * \param[in] obj_ofs Nesting offset, pass as 0. - * \param[in] ie_coding A {} terminated list of IEI tags to encode (if present) and instructions for encoding. - * \param[in] err_cb Function to call to report an error message, or NULL. - * \param[in] err_cb_data Caller supplied context to pass to the err_cb as 'data' argument. - * \param[in] iei_strs value_string array to give IEI names in error messages passed to err_cb(), or NULL. - * \return 0 on success, negative on error. - */ -int osmo_gtlvs_encode(struct osmo_gtlv_put *gtlv, const void *decoded_struct, unsigned int obj_ofs, - const struct osmo_gtlv_coding *ie_coding, - osmo_gtlv_err_cb err_cb, void *err_cb_data, const struct value_string *iei_strs) -{ - void *obj = MEMB(decoded_struct, obj_ofs); - - if (!ie_coding) - return -ENOTSUP; - - for (; !osmo_gtlv_coding_end(ie_coding); ie_coding++) { - int rc; - bool *presence_flag_p = ie_coding->has_presence_flag ? MEMB(obj, ie_coding->presence_flag_ofs) : NULL; - unsigned int *multi_count_p = ie_coding->has_count ? MEMB(obj, ie_coding->count_ofs) : NULL; - unsigned int n; - unsigned int i; - - if (presence_flag_p && !*presence_flag_p) - continue; - - if (multi_count_p) { - n = *multi_count_p; - if (!ie_coding->memb_array_pitch) - RETURN_ERROR(-EFAULT, ie_coding->ti, - "Error in protocol definition: The ie_coding lacks a memb_array_pitch" - " value, cannot be used as multi-IE\n"); - } else { - n = 1; - } - - for (i = 0; i < n; i++) { - unsigned int memb_ofs; - - osmo_gtlv_put_tli(gtlv, &ie_coding->ti, 0); - - /* If this is a repeated IE, encode from the correct array index */ - if (multi_count_p && i >= ie_coding->count_max) - RETURN_ERROR(-ENOTSUP, ie_coding->ti, - "Only %u instances of this IE are supported per message", ie_coding->count_max); - memb_ofs = ie_coding->memb_ofs + i * ie_coding->memb_array_pitch; - - if (ie_coding->nested_ies) { - struct osmo_gtlv_put nested_tlv = { - .cfg = ie_coding->nested_ies_cfg ? : gtlv->cfg, - .dst = gtlv->dst, - }; - rc = osmo_gtlvs_encode(&nested_tlv, decoded_struct, obj_ofs + memb_ofs, - ie_coding->nested_ies, err_cb, err_cb_data, iei_strs); - if (rc) - RETURN_ERROR(rc, ie_coding->ti, - "Error while encoding TLV structure nested inside this IE"); - } else { - rc = ie_coding->enc_func(gtlv, decoded_struct, MEMB(obj, memb_ofs)); - if (rc) - RETURN_ERROR(rc, ie_coding->ti, "Error while encoding this IE"); - } - - osmo_gtlv_put_update_tl(gtlv); - } - } - return 0; -} - -/*! Compose a human readable string describing a decoded struct. - * How to encode IE values and where to read them in the decoded struct is defined by ie_coding, an array terminated by - * a '{}' entry. - * The IEs will be encoded in the order they appear in ie_coding. - * \param[out] buf Return the string in this buffer. - * \param[in] buflen Size of buf. - * \param[in] decoded_struct C struct data to encode. - * \param[in] obj_ofs Nesting offset, pass as 0. - * \param[in] ie_coding A {} terminated list of IEI tags to encode (if present) and instructions for encoding. - * \param[in] iei_strs value_string array to give IEI names in tag headers, or NULL. - * \return number of characters that would be written if the buffer is large enough, like snprintf(). - */ -int osmo_gtlvs_encode_to_str_buf(char *buf, size_t buflen, const void *decoded_struct, unsigned int obj_ofs, - const struct osmo_gtlv_coding *ie_coding, const struct value_string *iei_strs) -{ - struct osmo_strbuf sb = { .buf = buf, .len = buflen }; - - void *obj = MEMB(decoded_struct, obj_ofs); - - if (!ie_coding) - return -ENOTSUP; - - for (; !osmo_gtlv_coding_end(ie_coding); ie_coding++) { - bool *presence_flag_p = ie_coding->has_presence_flag ? MEMB(obj, ie_coding->presence_flag_ofs) : NULL; - unsigned int *multi_count_p = ie_coding->has_count ? MEMB(obj, ie_coding->count_ofs) : NULL; - unsigned int n; - unsigned int i; - - if (presence_flag_p && !*presence_flag_p) - continue; - - if (multi_count_p) { - n = *multi_count_p; - } else { - n = 1; - } - - if (!n) - continue; - - OSMO_STRBUF_PRINTF(sb, " '%s'=", get_value_string(iei_strs, ie_coding->ti.tag)); - if (multi_count_p) - OSMO_STRBUF_PRINTF(sb, "{ "); - - for (i = 0; i < n; i++) { - unsigned int memb_ofs; - - /* If this is a repeated IE, encode from the correct array index */ - if (multi_count_p && i >= ie_coding->count_max) - return -ENOTSUP; - if (i > 0) - OSMO_STRBUF_PRINTF(sb, ", "); - - memb_ofs = ie_coding->memb_ofs + i * ie_coding->memb_array_pitch; - - if (ie_coding->nested_ies) { - OSMO_STRBUF_PRINTF(sb, "{"); - OSMO_STRBUF_APPEND(sb, osmo_gtlvs_encode_to_str_buf, decoded_struct, obj_ofs + memb_ofs, - ie_coding->nested_ies, iei_strs); - OSMO_STRBUF_PRINTF(sb, " }"); - } else { - if (ie_coding->enc_to_str_func) - OSMO_STRBUF_APPEND(sb, ie_coding->enc_to_str_func, MEMB(obj, memb_ofs)); - else - OSMO_STRBUF_PRINTF(sb, "(enc_to_str_func==NULL)"); - } - } - - if (multi_count_p) - OSMO_STRBUF_PRINTF(sb, " }"); - } - return sb.chars_needed; -} - -/*! Compose a human readable string describing a decoded struct. - * Like osmo_gtlvs_encode_to_str_buf() but returns a talloc allocated string. - * \param[in] ctx talloc context to allocate from, e.g. OTC_SELECT. - * \param[in] decoded_struct C struct data to encode. - * \param[in] obj_ofs Nesting offset, pass as 0. - * \param[in] ie_coding A {} terminated list of IEI tags to encode (if present) and instructions for encoding. - * \param[in] iei_strs value_string array to give IEI names in tag headers, or NULL. - * \return human readable string. - */ -char *osmo_gtlvs_encode_to_str_c(void *ctx, const void *decoded_struct, unsigned int obj_ofs, - const struct osmo_gtlv_coding *ie_coding, const struct value_string *iei_strs) -{ - OSMO_NAME_C_IMPL(ctx, 256, "ERROR", osmo_gtlvs_encode_to_str_buf, decoded_struct, obj_ofs, ie_coding, iei_strs) -} diff --git a/src/libosmo-gtlv/gtlv_gen.c b/src/libosmo-gtlv/gtlv_gen.c deleted file mode 100644 index fd3fbd9..0000000 --- a/src/libosmo-gtlv/gtlv_gen.c +++ /dev/null @@ -1,420 +0,0 @@ -/* Write h and c source files for TLV protocol definitions, based on very sparse TLV definitions. - * For a usage example see tests/libosmo-gtlv/test_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 <string.h> - -#include <osmocom/core/linuxlist.h> -#include <osmocom/core/talloc.h> -#include <osmocom/core/utils.h> - -#include <osmocom/gtlv/gtlv_gen.h> - -static const struct osmo_gtlv_gen_cfg *g_cfg = NULL; - -const struct osmo_gtlv_gen_ie osmo_gtlv_gen_ie_auto = {}; - -/* Helps avoid redundant definitions of the same type. */ -struct seen_entry { - struct llist_head entry; - char str[256]; - const void *from_def; -}; -static LLIST_HEAD(seen_list); - -static bool seen(const char *str, const void *from_def) -{ - struct seen_entry *s; - llist_for_each_entry(s, &seen_list, entry) { - if (!strcmp(s->str, str)) { - if (from_def != s->from_def) { - fprintf(stderr, "ERROR: %s: multiple definitions use the same name: '%s'\n", - g_cfg->proto_name, str); - exit(1); - } - return true; - } - } - s = talloc_zero(NULL, struct seen_entry); - OSMO_STRLCPY_ARRAY(s->str, str); - s->from_def = from_def; - llist_add(&s->entry, &seen_list); - return false; -} -static void clear_seen() -{ - struct seen_entry *s; - while ((s = llist_first_entry_or_null(&seen_list, struct seen_entry, entry))) { - llist_del(&s->entry); - talloc_free(s); - } -} - -/* Return "struct foo_ie_bar" from g_cfg->decoded_type_prefix and ie. */ -static inline const char *decoded_type(const struct osmo_gtlv_gen_ie_o *ie_o) -{ - static char b[255]; - const struct osmo_gtlv_gen_ie *ie = ie_o->ie; - const char *tag_name; - if (ie && ie->decoded_type) - return ie->decoded_type; - /* "struct foo_ie_" + "bar" = struct foo_ie_bar*/ - tag_name = ie ? ie->tag_name : NULL; - snprintf(b, sizeof(b), "%s%s", g_cfg->decoded_type_prefix, tag_name ? : ie_o->name); - return b; -} - -/* --- .h file --- */ - -/* Write a listing of struct members like - * bool foo_present; - * int foo; - * struct myproto_ie_bar bar; - * struct abc abc[10]; - * int abc_count; - */ -static void write_ie_members(const struct osmo_gtlv_gen_ie_o ies[]) -{ - const struct osmo_gtlv_gen_ie_o *ie_o; - for (ie_o = ies; ie_o->ie; ie_o++) { - if (ie_o->optional) - printf("\tbool %s_present;\n", ie_o->name); - printf("\t%s %s", decoded_type(ie_o), ie_o->name); - if (ie_o->multi) { - printf("[%u];\n", ie_o->multi); - printf("\tunsigned int %s_count", ie_o->name); - } - printf(";\n"); - } -} - -/* Traverse nesting levels in the message definitions and generate the structs for all as needed. */ -static void write_ie_auto_structs(const struct osmo_gtlv_gen_ie_o ies[]) -{ - const struct osmo_gtlv_gen_ie_o *ie_o; - if (!ies) - return; - for (ie_o = ies; ie_o->ie; ie_o++) { - const struct osmo_gtlv_gen_ie *ie = ie_o->ie; - if (!ie || !ie->nested_ies) - continue; - /* Recurse to write inner layers first, so that they can be referenced in outer layers. */ - write_ie_auto_structs(ie->nested_ies); - - /* Various IE definitions can use the same underlying type. Only generate each type once. */ - if (seen(decoded_type(ie_o), NULL)) - continue; - - /* Print: - * - * * spec ref *\ - * struct myproto_ie_goo { - * bool foo_present; - * int foo; - * struct myproto_ie_bar bar; - * struct abc abc[10]; - * int abc_count; - * }; - */ - printf("\n"); - if (ie->spec_ref) - printf("/* %s%s */\n", g_cfg->spec_ref_prefix, ie->spec_ref); - printf("%s {\n", decoded_type(ie_o)); - write_ie_members(ie->nested_ies); - printf("};\n"); - } -} - -/* Write all auto-generated structs, starting with the outer message definitions and nesting into all contained IE - * definitions. */ -static void write_auto_structs() -{ - const struct osmo_gtlv_gen_msg *gen_msg; - clear_seen(); - for (gen_msg = g_cfg->msg_defs; gen_msg->name; gen_msg++) { - write_ie_auto_structs(gen_msg->ies); - } -} - -/* Write the struct definitions for each message, i.e. for each entry in the outer PDU's message union, as well as the - * union itself. - * - * struct myproto_msg_foo { - * ... - * }: - * struct myproto_msg_goo { - * ... - * }; - * union myproto_ies { - * myproto_msg_foo foo; - * myproto_msg_goo goo; - * }; - */ -static void write_msg_union() -{ - const struct osmo_gtlv_gen_msg *gen_msg; - for (gen_msg = g_cfg->msg_defs; gen_msg->name; gen_msg++) { - /* "struct foo_msg" + "_%s" { * - * struct foo_msg_goo_request { ... }; */ - printf("\nstruct %s_msg_%s {\n", - g_cfg->proto_name, - gen_msg->name); - write_ie_members(gen_msg->ies); - printf("};\n"); - } - - printf("\nunion %s_ies {\n", g_cfg->proto_name); - for (gen_msg = g_cfg->msg_defs; gen_msg->name; gen_msg++) { - printf("\tstruct %s_msg_%s %s;\n", g_cfg->proto_name, - gen_msg->name, gen_msg->name); - } - printf("};\n"); -} - -/* Write the C header, myproto_ies_auto.h */ -static void write_h() -{ - printf("/* THIS FILE IS GENERATED FROM %s */\n", __FILE__); - printf("#include <stdint.h>\n"); - printf("#include <osmocom/gtlv/gtlv_dec_enc.h>\n"); - if (g_cfg->h_header) - printf("\n%s\n", g_cfg->h_header); - write_auto_structs(); - write_msg_union(); - printf("\nconst struct osmo_gtlv_coding *%s_get_msg_coding(%s message_type);\n", - g_cfg->proto_name, g_cfg->message_type_enum ? : "int"); - printf("\n" - "int %s_ies_decode(union %s_ies *dst, struct osmo_gtlv_load *gtlv, bool tlv_ordered,\n" - " %s message_type, osmo_gtlv_err_cb err_cb, void *err_cb_data, const struct value_string *iei_strs);\n", - g_cfg->proto_name, g_cfg->proto_name, g_cfg->message_type_enum ? : "int"); - printf("\n" - "int %s_ies_encode(struct osmo_gtlv_put *gtlv, const union %s_ies *src,\n" - " %s message_type, osmo_gtlv_err_cb err_cb, void *err_cb_data, const struct value_string *iei_strs);\n", - g_cfg->proto_name, g_cfg->proto_name, g_cfg->message_type_enum ? : "int"); - printf("\n" - "int %s_ies_encode_to_str(char *buf, size_t buflen, const union %s_ies *src,\n" - " %s message_type, const struct value_string *iei_strs);\n", - g_cfg->proto_name, g_cfg->proto_name, g_cfg->message_type_enum ? : "int"); -} - -/* --- .c file --- */ - -/* Write a listing of: - * extern int myproto_dec_foo(...); - * extern int myproto_enc_foo(...); - */ -static void write_extern_dec_enc(const struct osmo_gtlv_gen_ie_o *ies) -{ - const struct osmo_gtlv_gen_ie_o *ie_o; - for (ie_o = ies; ie_o->ie; ie_o++) { - const struct osmo_gtlv_gen_ie *ie = ie_o->ie; - const char *dec_enc = ie_o->name; - if (ie) - dec_enc = ie->dec_enc ? : (ie->tag_name ? : ie_o->name); - if (ie && ie->nested_ies) { - write_extern_dec_enc(ie->nested_ies); - continue; - } - if (seen(dec_enc, NULL)) - continue; - printf("extern int %s_dec_%s(void *decoded_struct, void *decode_to, const struct osmo_gtlv_load *gtlv);\n", - g_cfg->proto_name, dec_enc); - printf("extern int %s_enc_%s(struct osmo_gtlv_put *gtlv, const void *decoded_struct, const void *encode_from);\n", - g_cfg->proto_name, dec_enc); - if (g_cfg->add_enc_to_str) - printf("extern int %s_enc_to_str_%s(char *buf, size_t buflen, const void *encode_from);\n", - g_cfg->proto_name, dec_enc); - } -} - -/* For a nested IE, write the struct osmo_gtlv_coding array of the inner IEs. - * { { MYPROTO_IEI_BAR }, - * .memb_ofs = offsetof(struct myproto_foo, bar), - * .dec_func = myproto_dec_bar, - * .enc_func = myproto_enc_bar, - * }, - */ -static void write_ies_array(const char *indent, const struct osmo_gtlv_gen_ie_o *ies, const char *obj_type, const char *substruct) -{ -#define printi(FMT, ARGS...) printf("%s" FMT, indent, ##ARGS) - - const struct osmo_gtlv_gen_ie_o *ie_o; - for (ie_o = ies; ie_o->ie; ie_o++) { - const struct osmo_gtlv_gen_ie *ie = ie_o->ie; - const char *tag_name = (ie && ie->tag_name) ? ie->tag_name : ie_o->name; - printi("{ { %s%s", g_cfg->tag_prefix, osmo_str_toupper(tag_name)); - if (ie_o->instance) - printf(", true, %s", ie_o->instance); - printf(" },\n"); - printi(" .memb_ofs = offsetof(%s, %s%s),\n", obj_type, substruct, ie_o->name); - if (ie->nested_ies) { - printi(" .nested_ies = ies_in_%s,\n", tag_name); - } else { - const char *dec_enc = ie->dec_enc ? : (ie->tag_name ? : ie_o->name); - printi(" .dec_func = %s_dec_%s,\n", g_cfg->proto_name, dec_enc); - printi(" .enc_func = %s_enc_%s,\n", g_cfg->proto_name, dec_enc); - if (g_cfg->add_enc_to_str) - printi(" .enc_to_str_func = %s_enc_to_str_%s,\n", g_cfg->proto_name, dec_enc); - } - if (ie_o->multi) { - printi(" .memb_array_pitch = OSMO_MEMB_ARRAY_PITCH(%s, %s%s),\n", - obj_type, substruct, ie_o->name); - printi(" .has_count = true, .count_max = %u,\n", ie_o->multi); - printi(" .count_mandatory = %u,\n", ie_o->multi_mandatory); - printi(" .count_ofs = offsetof(%s, %s%s_count),\n", obj_type, substruct, ie_o->name); - } - if (ie_o->optional) { - printi(" .has_presence_flag = true,\n"); - printi(" .presence_flag_ofs = offsetof(%s, %s%s_present),\n", obj_type, substruct, ie_o->name); - } - printi("},\n"); - } -} - -/* For a nested IE, write the struct osmo_gtlv_coding array of the inner IEs. - * static const struct osmo_gtlv_coding ies_in_foo[] = { - * { {MYPROTO_IEI_BAR}, - * .memb_ofs = offsetof(struct myproto_foo, bar), - * .dec_func = myproto_dec_bar, - * .enc_func = myproto_enc_bar, - * }, - * ... - * }; - */ -static void write_nested_ies_array(const struct osmo_gtlv_gen_ie_o *ies) -{ - const char *indent = "\t"; - const struct osmo_gtlv_gen_ie_o *ie_o; - for (ie_o = ies; ie_o->ie; ie_o++) { - const struct osmo_gtlv_gen_ie *ie = ie_o->ie; - if (!ie || !ie->nested_ies) - continue; - write_nested_ies_array(ie->nested_ies); - - const char *ies_in_name = ie->tag_name ? : ie_o->name; - if (seen(ies_in_name, ie)) - continue; - - printf("\nstatic const struct osmo_gtlv_coding ies_in_%s[] = {\n", ies_in_name); - write_ies_array(indent, ie->nested_ies, decoded_type(ie_o), ""); - printi("{}\n"); - printf("};\n"); - } -} - -/* Write the bulk of the C code: on the basis of the list of messages (g_cfg->msg_defs), write all dec/enc function - * declarations, all IEs arrays as well as the list of message types, first triggering to write the C code for any inner - * layers. */ -static void write_c() -{ - const struct osmo_gtlv_gen_msg *gen_msg; - - printf("/* THIS FILE IS GENERATED FROM %s */\n", __FILE__); - printf("#include <stddef.h>\n"); - printf("#include <errno.h>\n"); - printf("#include <osmocom/core/utils.h>\n"); - printf("#include <osmocom/gtlv/gtlv.h>\n"); - printf("#include <osmocom/gtlv/gtlv_dec_enc.h>\n"); - printf("#include <osmocom/gtlv/gtlv_gen.h>\n"); - if (g_cfg->c_header) - printf("\n%s\n", g_cfg->c_header); - - printf("\n"); - clear_seen(); - for (gen_msg = g_cfg->msg_defs; gen_msg->name; gen_msg++) { - write_extern_dec_enc(gen_msg->ies); - } - - clear_seen(); - for (gen_msg = g_cfg->msg_defs; gen_msg->name; gen_msg++) { - write_nested_ies_array(gen_msg->ies); - } - - for (gen_msg = g_cfg->msg_defs; gen_msg->name; gen_msg++) { - char *obj_type = talloc_asprintf(NULL, "union %s_ies", g_cfg->proto_name); - char *substruct = talloc_asprintf(NULL, "%s.", gen_msg->name); - printf("\nstatic const struct osmo_gtlv_coding ies_in_msg_%s[] = {\n", gen_msg->name); - write_ies_array("\t", gen_msg->ies, obj_type, substruct); - printf("\t{}\n};\n"); - talloc_free(substruct); - talloc_free(obj_type); - } - printf("\nstatic const struct osmo_gtlv_coding *msg_defs[] = {\n"); - for (gen_msg = g_cfg->msg_defs; gen_msg->name; gen_msg++) { - printf("\t[%s%s] = ies_in_msg_%s,\n", g_cfg->message_type_prefix, osmo_str_toupper(gen_msg->name), gen_msg->name); - } - printf("};\n"); - - /* print this code snippet into the .c file, because only there can we do ARRAY_SIZE(foo_msg_coding). */ - printf("\n" - "const struct osmo_gtlv_coding *%s_get_msg_coding(%s message_type)\n" - "{\n" - " if (message_type >= ARRAY_SIZE(msg_defs))\n" - " return NULL;\n" - " return msg_defs[message_type];\n" - "}\n", - g_cfg->proto_name, g_cfg->message_type_enum ? : "int"); - - printf("\n" - "int %s_ies_decode(union %s_ies *dst, struct osmo_gtlv_load *gtlv, bool tlv_ordered,\n" - " %s message_type,\n" - " osmo_gtlv_err_cb err_cb, void *err_cb_data, const struct value_string *iei_strs)\n" - "{\n" - " return osmo_gtlvs_decode(dst, 0, gtlv, tlv_ordered, %s_get_msg_coding(message_type), err_cb, err_cb_data, iei_strs);\n" - "}\n", - g_cfg->proto_name, g_cfg->proto_name, g_cfg->message_type_enum ? : "int", g_cfg->proto_name); - printf("\n" - "int %s_ies_encode(struct osmo_gtlv_put *gtlv, const union %s_ies *src,\n" - " %s message_type, osmo_gtlv_err_cb err_cb, void *err_cb_data, const struct value_string *iei_strs)\n" - "{\n" - " return osmo_gtlvs_encode(gtlv, src, 0, %s_get_msg_coding(message_type), err_cb, err_cb_data, iei_strs);\n" - "}\n", - g_cfg->proto_name, g_cfg->proto_name, g_cfg->message_type_enum ? : "int", g_cfg->proto_name); - printf("\n" - "int %s_ies_encode_to_str(char *buf, size_t buflen, const union %s_ies *src,\n" - " %s message_type, const struct value_string *iei_strs)\n" - "{\n" - " return osmo_gtlvs_encode_to_str_buf(buf, buflen, src, 0, %s_get_msg_coding(message_type), iei_strs);\n" - "}\n", - g_cfg->proto_name, g_cfg->proto_name, g_cfg->message_type_enum ? : "int", g_cfg->proto_name); -} - -/* Call this from your main(). */ -int osmo_gtlv_gen_main(const struct osmo_gtlv_gen_cfg *cfg, int argc, const char **argv) -{ - if (argc < 2) - return 1; - - g_cfg = cfg; - - if (strcmp(argv[1], "h") == 0) - write_h(); - else if (strcmp(argv[1], "c") == 0) - write_c(); - else - return 1; - - clear_seen(); - return 0; -} diff --git a/src/libosmo-pfcp/Makefile.am b/src/libosmo-pfcp/Makefile.am index db81648..eb8c78f 100644 --- a/src/libosmo-pfcp/Makefile.am +++ b/src/libosmo-pfcp/Makefile.am @@ -9,12 +9,14 @@ AM_CFLAGS = \ -Wall \ $(LIBOSMOCORE_CFLAGS) \ + $(LIBOSMOGTLV_CFLAGS) \ $(LIBOSMOVTY_CFLAGS) \ $(COVERAGE_CFLAGS) \ $(NULL)
AM_LDFLAGS = \ $(LIBOSMOCORE_LIBS) \ + $(LIBOSMOGTLV_LIBS) \ $(LIBOSMOVTY_LIBS) \ $(COVERAGE_LDFLAGS) \ $(NULL) @@ -40,10 +42,7 @@ pfcp_ies_auto.c \ $(NULL)
-pfcp_ies_auto.c: $(srcdir)/gen__pfcp_ies_auto.c \ - $(top_srcdir)/src/libosmo-gtlv/gtlv_gen.c \ - $(top_srcdir)/include/osmocom/gtlv/gtlv_gen.h - $(MAKE) -C $(top_builddir)/src/libosmo-gtlv +pfcp_ies_auto.c: $(srcdir)/gen__pfcp_ies_auto.c $(MAKE) gen__pfcp_ies_auto $(builddir)/gen__pfcp_ies_auto c > $(builddir)/pfcp_ies_auto.c
@@ -54,9 +53,3 @@ gen__pfcp_ies_auto_SOURCES = \ gen__pfcp_ies_auto.c \ $(NULL) - -gen__pfcp_ies_auto_LDADD = \ - $(top_builddir)/src/libosmo-gtlv/libosmo-gtlv.a \ - $(LIBOSMOCORE_LIBS) \ - $(COVERAGE_LDFLAGS) \ - $(NULL) diff --git a/tests/Makefile.am b/tests/Makefile.am index 01ef6b4..fad7e6c 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,5 +1,4 @@ SUBDIRS = \ - libosmo-gtlv \ libosmo-pfcp \ $(NULL)
diff --git a/tests/libosmo-gtlv/Makefile.am b/tests/libosmo-gtlv/Makefile.am deleted file mode 100644 index 45d6ec2..0000000 --- a/tests/libosmo-gtlv/Makefile.am +++ /dev/null @@ -1,49 +0,0 @@ -SUBDIRS = \ - test_gtlv_gen \ - test_tliv \ - $(NULL) - -AM_CPPFLAGS = \ - $(all_includes) \ - -I$(top_srcdir)/include \ - $(NULL) - -AM_CFLAGS = \ - -Wall \ - $(LIBOSMOCORE_CFLAGS) \ - $(NULL) - -noinst_PROGRAMS = \ - gtlv_test \ - gtlv_dec_enc_test \ - $(NULL) - -EXTRA_DIST = \ - gtlv_test.ok \ - gtlv_dec_enc_test.ok \ - $(NULL) - -gtlv_test_SOURCES = \ - gtlv_test.c \ - $(NULL) - -gtlv_test_LDADD = \ - $(top_builddir)/src/libosmo-gtlv/libosmo-gtlv.a \ - $(LIBOSMOCORE_LIBS) \ - $(NULL) - -gtlv_dec_enc_test_SOURCES = \ - gtlv_dec_enc_test.c \ - $(NULL) - -gtlv_dec_enc_test_LDADD = \ - $(top_builddir)/src/libosmo-gtlv/libosmo-gtlv.a \ - $(LIBOSMOCORE_LIBS) \ - $(NULL) - -.PHONY: update_exp -update_exp: - $(builddir)/gtlv_test >$(srcdir)/gtlv_test.ok - $(builddir)/gtlv_dec_enc_test >$(srcdir)/gtlv_dec_enc_test.ok - $(MAKE) -C test_gtlv_gen update_exp - $(MAKE) -C test_tliv update_exp diff --git a/tests/libosmo-gtlv/gtlv_dec_enc_test.c b/tests/libosmo-gtlv/gtlv_dec_enc_test.c deleted file mode 100644 index e02a2e5..0000000 --- a/tests/libosmo-gtlv/gtlv_dec_enc_test.c +++ /dev/null @@ -1,422 +0,0 @@ -/* - * (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 <assert.h> - -#include <osmocom/core/application.h> -#include <osmocom/core/utils.h> -#include <osmocom/core/msgb.h> - -#include <osmocom/gtlv/gtlv_dec_enc.h> - -void *ctx; - -enum tags { - TAG_FOO = 1, - TAG_BAR, - TAG_BAZ, - TAG_REPEAT_INT, - TAG_REPEAT_STRUCT, - TAG_NEST, -}; - -const struct value_string tag_names[] = { - { TAG_FOO, "FOO" }, - { TAG_BAR, "BAR" }, - { TAG_BAZ, "BAZ" }, - { TAG_REPEAT_INT, "REPEAT_INT" }, - { TAG_REPEAT_STRUCT, "REPEAT_STRUCT" }, - { TAG_NEST, "NEST" }, - {} -}; - -struct bar { - char str[23]; -}; - -struct baz { - int v_int; - bool v_bool; -}; - -enum repeat_enum { - R_A, - R_B, - R_C, -}; - -const struct value_string repeat_enum_names[] = { - OSMO_VALUE_STRING(R_A), - OSMO_VALUE_STRING(R_B), - OSMO_VALUE_STRING(R_C), - {} -}; - -struct repeat { - int v_int; - bool v_bool; - enum repeat_enum v_enum; -}; - -struct nested_inner_msg { - int foo; - struct bar bar; - struct baz baz; -}; - -struct decoded_msg { - int foo; - struct bar bar; - - bool baz_present; - struct baz baz; - - unsigned int repeat_int_count; - int repeat_int[32]; - - unsigned int repeat_struct_count; - struct repeat repeat_struct[32]; - - bool nest_present; - struct nested_inner_msg nest; -}; - -int dec_u16(void *decoded_struct, void *decode_to, const struct osmo_gtlv_load *gtlv) -{ - int *foo = decode_to; - if (gtlv->len != 2) - return -EINVAL; - *foo = osmo_load16be(gtlv->val); - return 0; -} - -int enc_u16(struct osmo_gtlv_put *gtlv, const void *decoded_struct, const void *encode_from) -{ - const int *foo = encode_from; - if (*foo > INT16_MAX) - return -EINVAL; - msgb_put_u16(gtlv->dst, *foo); - return 0; -} - -int enc_to_str_u16(char *buf, size_t buflen, const void *encode_from) -{ - const int *foo = encode_from; - return snprintf(buf, buflen, "%d", *foo); -} - -int dec_bar(void *decoded_struct, void *decode_to, const struct osmo_gtlv_load *gtlv) -{ - struct bar *bar = decode_to; - if (gtlv->len > sizeof(bar->str) - 1) - return -EINVAL; - osmo_strlcpy(bar->str, (const char *)gtlv->val, OSMO_MIN(gtlv->len + 1, sizeof(bar->str))); - return 0; -} - -int enc_bar(struct osmo_gtlv_put *gtlv, const void *decoded_struct, const void *encode_from) -{ - const struct bar *bar = encode_from; - int len = strnlen(bar->str, sizeof(bar->str)); - memcpy(msgb_put(gtlv->dst, len), bar, len); - return 0; -} - -int enc_to_str_bar(char *buf, size_t buflen, const void *encode_from) -{ - const struct bar *bar = encode_from; - return osmo_quote_str_buf3(buf, buflen, bar->str, -1); -} - -int dec_baz(void *decoded_struct, void *decode_to, const struct osmo_gtlv_load *gtlv) -{ - struct baz *baz = decode_to; - uint16_t l; - if (gtlv->len != 2) - return -EINVAL; - l = osmo_load16be(gtlv->val); - baz->v_int = l & 0x7fff; - baz->v_bool = (l & 0x8000) ? true : false; - return 0; -} - -int enc_baz(struct osmo_gtlv_put *gtlv, const void *decoded_struct, const void *encode_from) -{ - const struct baz *baz = encode_from; - if (baz->v_int > 0x7fff) - return -EINVAL; - msgb_put_u16(gtlv->dst, (baz->v_bool ? 0x8000 : 0) + (baz->v_int & 0x7fff)); - return 0; -} - -int enc_to_str_baz(char *buf, size_t buflen, const void *encode_from) -{ - const struct baz *baz = encode_from; - return snprintf(buf, buflen, "{%d,%s}", baz->v_int, baz->v_bool ? "true" : "false"); -} - -int dec_repeat_struct(void *decoded_struct, void *decode_to, const struct osmo_gtlv_load *gtlv) -{ - struct repeat *repeat_struct = decode_to; - if (gtlv->len != 3) - return -EINVAL; - repeat_struct->v_int = osmo_load16be(gtlv->val); - repeat_struct->v_bool = gtlv->val[2] & 0x80; - repeat_struct->v_enum = gtlv->val[2] & 0x7f; - return 0; -} - -int enc_repeat_struct(struct osmo_gtlv_put *gtlv, const void *decoded_struct, const void *encode_from) -{ - const struct repeat *repeat_struct = encode_from; - msgb_put_u16(gtlv->dst, repeat_struct->v_int); - msgb_put_u8(gtlv->dst, (repeat_struct->v_bool ? 0x80 : 0) + (repeat_struct->v_enum & 0x7f)); - return 0; -} - -int enc_to_str_repeat_struct(char *buf, size_t buflen, const void *encode_from) -{ - const struct repeat *repeat_struct = encode_from; - return snprintf(buf, buflen, "{%d,%s,%s}", repeat_struct->v_int, repeat_struct->v_bool ? "true" : "false", - get_value_string(repeat_enum_names, repeat_struct->v_enum)); -} - -struct osmo_gtlv_coding nested_inner_msg_ies[] = { - { - .ti = { TAG_FOO }, - .dec_func = dec_u16, - .enc_func = enc_u16, - .enc_to_str_func = enc_to_str_u16, - .memb_ofs = offsetof(struct nested_inner_msg, foo), - }, - { - .ti = { TAG_BAR }, - .dec_func = dec_bar, - .enc_func = enc_bar, - .enc_to_str_func = enc_to_str_bar, - .memb_ofs = offsetof(struct nested_inner_msg, bar), - }, - { - .ti = { TAG_BAZ }, - .dec_func = dec_baz, - .enc_func = enc_baz, - .enc_to_str_func = enc_to_str_baz, - .memb_ofs = offsetof(struct nested_inner_msg, baz), - }, - {} -}; - -struct osmo_gtlv_coding msg_ie_coding[] = { - { - .ti = { TAG_FOO }, - .dec_func = dec_u16, - .enc_func = enc_u16, - .enc_to_str_func = enc_to_str_u16, - .memb_ofs = offsetof(struct decoded_msg, foo), - }, - { - .ti = { TAG_BAR }, - .dec_func = dec_bar, - .enc_func = enc_bar, - .enc_to_str_func = enc_to_str_bar, - .memb_ofs = offsetof(struct decoded_msg, bar), - }, - { - .ti = { TAG_BAZ }, - .dec_func = dec_baz, - .enc_func = enc_baz, - .enc_to_str_func = enc_to_str_baz, - .memb_ofs = offsetof(struct decoded_msg, baz), - .has_presence_flag = true, - .presence_flag_ofs = offsetof(struct decoded_msg, baz_present), - }, - { - .ti = { TAG_REPEAT_INT }, - .dec_func = dec_u16, - .enc_func = enc_u16, - .enc_to_str_func = enc_to_str_u16, - .memb_ofs = offsetof(struct decoded_msg, repeat_int), - .memb_array_pitch = OSMO_MEMB_ARRAY_PITCH(struct decoded_msg, repeat_int), - .has_count = true, - .count_ofs = offsetof(struct decoded_msg, repeat_int_count), - .count_max = ARRAY_SIZE(((struct decoded_msg *)0)->repeat_int), - }, - { - .ti = { TAG_REPEAT_STRUCT }, - .dec_func = dec_repeat_struct, - .enc_func = enc_repeat_struct, - .enc_to_str_func = enc_to_str_repeat_struct, - .memb_ofs = offsetof(struct decoded_msg, repeat_struct), - .memb_array_pitch = OSMO_MEMB_ARRAY_PITCH(struct decoded_msg, repeat_struct), - .has_count = true, - .count_ofs = offsetof(struct decoded_msg, repeat_struct_count), - .count_max = ARRAY_SIZE(((struct decoded_msg *)0)->repeat_struct), - }, - { - .ti = { TAG_NEST }, - .memb_ofs = offsetof(struct decoded_msg, nest), - .nested_ies = nested_inner_msg_ies, - .has_presence_flag = true, - .presence_flag_ofs = offsetof(struct decoded_msg, nest_present), - }, - {} -}; - -char *decoded_msg_to_str(const struct decoded_msg *m) -{ - return osmo_gtlvs_encode_to_str_c(ctx, m, 0, msg_ie_coding, tag_names); -} - - -const struct decoded_msg enc_dec_tests[] = { - { - .foo = 23, - .bar = { "twentythree" }, - }, - { - .foo = 23, - .bar = { "twentythree" }, - - .baz_present = true, - .baz = { - .v_int = 2323, - .v_bool = true, - }, - }, - { - .foo = 23, - .bar = { "twentythree" }, - - .baz_present = true, - .baz = { - .v_int = 2323, - .v_bool = true, - }, - - .repeat_int_count = 3, - .repeat_int = { 1, 2, 0x7fff }, - }, - { - .foo = 23, - .bar = { "twentythree" }, - - .baz_present = true, - .baz = { - .v_int = 2323, - .v_bool = true, - }, - - .repeat_int_count = 3, - .repeat_int = { 1, 2, 0x7fff }, - - .repeat_struct_count = 2, - .repeat_struct = { - { - .v_int = 1001, - .v_bool = true, - .v_enum = R_A, - }, - { - .v_int = 1002, - .v_bool = false, - .v_enum = R_B, - }, - }, - - .nest_present = true, - .nest = { - .foo = 42, - .bar = { "fortytwo" }, - .baz = { - .v_int = 4242, - .v_bool = false, - }, - }, - }, -}; - -static int verify_err_cb_data; - -void err_cb(void *data, void *decoded_struct, const char *file, int line, const char *fmt, ...) -{ - assert(data == &verify_err_cb_data); - va_list args; - va_start(args, fmt); - //printf("ERR: %s:%d ", file, line); - printf("ERR: "); - vprintf(fmt, args); - va_end(args); -} - -void test_enc_dec(const char *label, const struct osmo_gtlv_cfg *cfg, bool ordered) -{ - int i; - for (i = 0; i < ARRAY_SIZE(enc_dec_tests); i++) { - int rc; - const struct decoded_msg *orig = &enc_dec_tests[i]; - struct decoded_msg parsed = {}; - struct osmo_gtlv_load load; - struct osmo_gtlv_put put; - - printf("\n=== start %s %s[%d]\n", label, __func__, i); - printf("encoded: %s\n", decoded_msg_to_str(orig)); - - put = (struct osmo_gtlv_put){ - .cfg = cfg, - .dst = msgb_alloc(1024, __func__), - }; - rc = osmo_gtlvs_encode(&put, (void *)orig, 0, msg_ie_coding, err_cb, &verify_err_cb_data, tag_names); - printf("osmo_gtlvs_encode() rc = %d\n", rc); - printf("%s.\n", osmo_hexdump(put.dst->data, put.dst->len)); - - load = (struct osmo_gtlv_load){ - .cfg = cfg, - .src = { put.dst->data, put.dst->len }, - }; - rc = osmo_gtlvs_decode(&parsed, 0, &load, ordered, msg_ie_coding, err_cb, &verify_err_cb_data, tag_names); - printf("osmo_gtlvs_decode() rc = %d\n", rc); - printf("decoded: %s\n", decoded_msg_to_str(&parsed)); - if (strcmp(decoded_msg_to_str(orig), decoded_msg_to_str(&parsed))) { - printf(" ERROR: parsed != orig\n"); - exit(1); - } - printf("=== end %s %s[%d]\n", label, __func__, i); - } -} - -int main() -{ - ctx = talloc_named_const(NULL, 0, "gtlv_test"); - msgb_talloc_ctx_init(ctx, 0); - - test_enc_dec("t8l8v ordered", &osmo_t8l8v_cfg, true); - test_enc_dec("t8l8v unordered", &osmo_t8l8v_cfg, false); - - test_enc_dec("t16l16v ordered", &osmo_t16l16v_cfg, true); - test_enc_dec("t16l16v unordered", &osmo_t16l16v_cfg, false); - - talloc_free(ctx); - return 0; -} diff --git a/tests/libosmo-gtlv/gtlv_dec_enc_test.ok b/tests/libosmo-gtlv/gtlv_dec_enc_test.ok deleted file mode 100644 index bd6df52..0000000 --- a/tests/libosmo-gtlv/gtlv_dec_enc_test.ok +++ /dev/null @@ -1,128 +0,0 @@ - -=== start t8l8v ordered test_enc_dec[0] -encoded: 'FOO'=23 'BAR'="twentythree" -osmo_gtlvs_encode() rc = 0 -01 02 00 17 02 0b 74 77 65 6e 74 79 74 68 72 65 65 . -osmo_gtlvs_decode() rc = 0 -decoded: 'FOO'=23 'BAR'="twentythree" -=== end t8l8v ordered test_enc_dec[0] - -=== start t8l8v ordered test_enc_dec[1] -encoded: 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} -osmo_gtlvs_encode() rc = 0 -01 02 00 17 02 0b 74 77 65 6e 74 79 74 68 72 65 65 03 02 89 13 . -osmo_gtlvs_decode() rc = 0 -decoded: 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} -=== end t8l8v ordered test_enc_dec[1] - -=== start t8l8v ordered test_enc_dec[2] -encoded: 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} 'REPEAT_INT'={ 1, 2, 32767 } -osmo_gtlvs_encode() rc = 0 -01 02 00 17 02 0b 74 77 65 6e 74 79 74 68 72 65 65 03 02 89 13 04 02 00 01 04 02 00 02 04 02 7f ff . -osmo_gtlvs_decode() rc = 0 -decoded: 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} 'REPEAT_INT'={ 1, 2, 32767 } -=== end t8l8v ordered test_enc_dec[2] - -=== start t8l8v ordered test_enc_dec[3] -encoded: 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} 'REPEAT_INT'={ 1, 2, 32767 } 'REPEAT_STRUCT'={ {1001,true,R_A}, {1002,false,R_B} } 'NEST'={ 'FOO'=42 'BAR'="fortytwo" 'BAZ'={4242,false} } -osmo_gtlvs_encode() rc = 0 -01 02 00 17 02 0b 74 77 65 6e 74 79 74 68 72 65 65 03 02 89 13 04 02 00 01 04 02 00 02 04 02 7f ff 05 03 03 e9 80 05 03 03 ea 01 06 12 01 02 00 2a 02 08 66 6f 72 74 79 74 77 6f 03 02 10 92 . -osmo_gtlvs_decode() rc = 0 -decoded: 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} 'REPEAT_INT'={ 1, 2, 32767 } 'REPEAT_STRUCT'={ {1001,true,R_A}, {1002,false,R_B} } 'NEST'={ 'FOO'=42 'BAR'="fortytwo" 'BAZ'={4242,false} } -=== end t8l8v ordered test_enc_dec[3] - -=== start t8l8v unordered test_enc_dec[0] -encoded: 'FOO'=23 'BAR'="twentythree" -osmo_gtlvs_encode() rc = 0 -01 02 00 17 02 0b 74 77 65 6e 74 79 74 68 72 65 65 . -osmo_gtlvs_decode() rc = 0 -decoded: 'FOO'=23 'BAR'="twentythree" -=== end t8l8v unordered test_enc_dec[0] - -=== start t8l8v unordered test_enc_dec[1] -encoded: 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} -osmo_gtlvs_encode() rc = 0 -01 02 00 17 02 0b 74 77 65 6e 74 79 74 68 72 65 65 03 02 89 13 . -osmo_gtlvs_decode() rc = 0 -decoded: 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} -=== end t8l8v unordered test_enc_dec[1] - -=== start t8l8v unordered test_enc_dec[2] -encoded: 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} 'REPEAT_INT'={ 1, 2, 32767 } -osmo_gtlvs_encode() rc = 0 -01 02 00 17 02 0b 74 77 65 6e 74 79 74 68 72 65 65 03 02 89 13 04 02 00 01 04 02 00 02 04 02 7f ff . -osmo_gtlvs_decode() rc = 0 -decoded: 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} 'REPEAT_INT'={ 1, 2, 32767 } -=== end t8l8v unordered test_enc_dec[2] - -=== start t8l8v unordered test_enc_dec[3] -encoded: 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} 'REPEAT_INT'={ 1, 2, 32767 } 'REPEAT_STRUCT'={ {1001,true,R_A}, {1002,false,R_B} } 'NEST'={ 'FOO'=42 'BAR'="fortytwo" 'BAZ'={4242,false} } -osmo_gtlvs_encode() rc = 0 -01 02 00 17 02 0b 74 77 65 6e 74 79 74 68 72 65 65 03 02 89 13 04 02 00 01 04 02 00 02 04 02 7f ff 05 03 03 e9 80 05 03 03 ea 01 06 12 01 02 00 2a 02 08 66 6f 72 74 79 74 77 6f 03 02 10 92 . -osmo_gtlvs_decode() rc = 0 -decoded: 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} 'REPEAT_INT'={ 1, 2, 32767 } 'REPEAT_STRUCT'={ {1001,true,R_A}, {1002,false,R_B} } 'NEST'={ 'FOO'=42 'BAR'="fortytwo" 'BAZ'={4242,false} } -=== end t8l8v unordered test_enc_dec[3] - -=== start t16l16v ordered test_enc_dec[0] -encoded: 'FOO'=23 'BAR'="twentythree" -osmo_gtlvs_encode() rc = 0 -00 01 00 02 00 17 00 02 00 0b 74 77 65 6e 74 79 74 68 72 65 65 . -osmo_gtlvs_decode() rc = 0 -decoded: 'FOO'=23 'BAR'="twentythree" -=== end t16l16v ordered test_enc_dec[0] - -=== start t16l16v ordered test_enc_dec[1] -encoded: 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} -osmo_gtlvs_encode() rc = 0 -00 01 00 02 00 17 00 02 00 0b 74 77 65 6e 74 79 74 68 72 65 65 00 03 00 02 89 13 . -osmo_gtlvs_decode() rc = 0 -decoded: 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} -=== end t16l16v ordered test_enc_dec[1] - -=== start t16l16v ordered test_enc_dec[2] -encoded: 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} 'REPEAT_INT'={ 1, 2, 32767 } -osmo_gtlvs_encode() rc = 0 -00 01 00 02 00 17 00 02 00 0b 74 77 65 6e 74 79 74 68 72 65 65 00 03 00 02 89 13 00 04 00 02 00 01 00 04 00 02 00 02 00 04 00 02 7f ff . -osmo_gtlvs_decode() rc = 0 -decoded: 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} 'REPEAT_INT'={ 1, 2, 32767 } -=== end t16l16v ordered test_enc_dec[2] - -=== start t16l16v ordered test_enc_dec[3] -encoded: 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} 'REPEAT_INT'={ 1, 2, 32767 } 'REPEAT_STRUCT'={ {1001,true,R_A}, {1002,false,R_B} } 'NEST'={ 'FOO'=42 'BAR'="fortytwo" 'BAZ'={4242,false} } -osmo_gtlvs_encode() rc = 0 -00 01 00 02 00 17 00 02 00 0b 74 77 65 6e 74 79 74 68 72 65 65 00 03 00 02 89 13 00 04 00 02 00 01 00 04 00 02 00 02 00 04 00 02 7f ff 00 05 00 03 03 e9 80 00 05 00 03 03 ea 01 00 06 00 18 00 01 00 02 00 2a 00 02 00 08 66 6f 72 74 79 74 77 6f 00 03 00 02 10 92 . -osmo_gtlvs_decode() rc = 0 -decoded: 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} 'REPEAT_INT'={ 1, 2, 32767 } 'REPEAT_STRUCT'={ {1001,true,R_A}, {1002,false,R_B} } 'NEST'={ 'FOO'=42 'BAR'="fortytwo" 'BAZ'={4242,false} } -=== end t16l16v ordered test_enc_dec[3] - -=== start t16l16v unordered test_enc_dec[0] -encoded: 'FOO'=23 'BAR'="twentythree" -osmo_gtlvs_encode() rc = 0 -00 01 00 02 00 17 00 02 00 0b 74 77 65 6e 74 79 74 68 72 65 65 . -osmo_gtlvs_decode() rc = 0 -decoded: 'FOO'=23 'BAR'="twentythree" -=== end t16l16v unordered test_enc_dec[0] - -=== start t16l16v unordered test_enc_dec[1] -encoded: 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} -osmo_gtlvs_encode() rc = 0 -00 01 00 02 00 17 00 02 00 0b 74 77 65 6e 74 79 74 68 72 65 65 00 03 00 02 89 13 . -osmo_gtlvs_decode() rc = 0 -decoded: 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} -=== end t16l16v unordered test_enc_dec[1] - -=== start t16l16v unordered test_enc_dec[2] -encoded: 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} 'REPEAT_INT'={ 1, 2, 32767 } -osmo_gtlvs_encode() rc = 0 -00 01 00 02 00 17 00 02 00 0b 74 77 65 6e 74 79 74 68 72 65 65 00 03 00 02 89 13 00 04 00 02 00 01 00 04 00 02 00 02 00 04 00 02 7f ff . -osmo_gtlvs_decode() rc = 0 -decoded: 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} 'REPEAT_INT'={ 1, 2, 32767 } -=== end t16l16v unordered test_enc_dec[2] - -=== start t16l16v unordered test_enc_dec[3] -encoded: 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} 'REPEAT_INT'={ 1, 2, 32767 } 'REPEAT_STRUCT'={ {1001,true,R_A}, {1002,false,R_B} } 'NEST'={ 'FOO'=42 'BAR'="fortytwo" 'BAZ'={4242,false} } -osmo_gtlvs_encode() rc = 0 -00 01 00 02 00 17 00 02 00 0b 74 77 65 6e 74 79 74 68 72 65 65 00 03 00 02 89 13 00 04 00 02 00 01 00 04 00 02 00 02 00 04 00 02 7f ff 00 05 00 03 03 e9 80 00 05 00 03 03 ea 01 00 06 00 18 00 01 00 02 00 2a 00 02 00 08 66 6f 72 74 79 74 77 6f 00 03 00 02 10 92 . -osmo_gtlvs_decode() rc = 0 -decoded: 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} 'REPEAT_INT'={ 1, 2, 32767 } 'REPEAT_STRUCT'={ {1001,true,R_A}, {1002,false,R_B} } 'NEST'={ 'FOO'=42 'BAR'="fortytwo" 'BAZ'={4242,false} } -=== end t16l16v unordered test_enc_dec[3] diff --git a/tests/libosmo-gtlv/gtlv_test.c b/tests/libosmo-gtlv/gtlv_test.c deleted file mode 100644 index 8023699..0000000 --- a/tests/libosmo-gtlv/gtlv_test.c +++ /dev/null @@ -1,629 +0,0 @@ -/* - * (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> - -void *ctx; - -struct ie { - struct osmo_gtlv_tag_inst ti; - const char *val; -}; - -/* write all IEs to a msgb */ -struct msgb *test_tlv_enc(const struct osmo_gtlv_cfg *cfg, const struct ie *ies) -{ - const struct ie *ie; - struct osmo_gtlv_put gtlv = { - .cfg = cfg, - .dst = msgb_alloc(1024, __func__), - }; - - for (ie = ies; ie->val; ie++) { - /* put header without knowing length yet */ - OSMO_ASSERT(osmo_gtlv_put_tli(>lv, &ie->ti, 0) == 0); - /* put value data, as much as desired */ - msgb_put(gtlv.dst, osmo_hexparse(ie->val, gtlv.dst->tail, msgb_tailroom(gtlv.dst))); - /* update header len from amount of written data */ - OSMO_ASSERT(osmo_gtlv_put_update_tl(>lv) == 0); - } - - printf("- encoded: %s.\n", osmo_hexdump(gtlv.dst->data, gtlv.dst->len)); - return gtlv.dst; -} - -/* read all IEs from the msgb, and verify that it matches the given list of IEs */ -void test_tlv_dec(const struct osmo_gtlv_cfg *cfg, const struct ie *ies, struct msgb *msg) -{ - const struct ie *ie; - struct osmo_gtlv_load gtlv = { - .cfg = cfg, - .src = { msg->data, msg->len }, - }; - - printf("- decoding:\n"); - osmo_gtlv_load_start(>lv); - - for (ie = ies; ie->val; ie++) { - int rc = osmo_gtlv_load_next(>lv); - if (rc) { - printf(" ERROR loading TLV structure: osmo_gtlv_load_next() rc = %d\n", rc); - exit(1); - } - /* end of TLV structure? */ - if (!gtlv.val) - break; - printf(" T=%s L=%zu", osmo_gtlv_tag_inst_to_str_c(ctx, >lv.ti, NULL), gtlv.len); - printf(" v=%s\n", osmo_hexdump_nospc(gtlv.val, gtlv.len)); - if (gtlv.ti.tag != ie->ti.tag) { - printf(" ERROR loading TLV structure: expected tag %u, got tag %u\n", ie->ti.tag, gtlv.ti.tag); - exit(1); - } - if (strcmp(ie->val, osmo_hexdump_nospc(gtlv.val, gtlv.len))) { - printf(" ERROR loading TLV structure: expected val %s, got val %s\n", ie->val, - osmo_hexdump_nospc(gtlv.val, gtlv.len)); - exit(1); - } - } -} - -void test_tlv_peek(const struct osmo_gtlv_cfg *cfg, const struct ie *ies, struct msgb *msg) -{ - const struct ie *ie; - struct osmo_gtlv_load gtlv = { - .cfg = cfg, - .src = { msg->data, msg->len }, - }; - - printf("- peeking:\n"); - osmo_gtlv_load_start(>lv); - - ie = ies; - while (1) { - int rc; - struct osmo_gtlv_tag_inst next_tag; - rc = osmo_gtlv_load_peek_tag(>lv, &next_tag); - if (rc == -ENOENT) { - printf(" peek rc=-ENOENT\n"); - } else { - printf(" peek T=%s", osmo_gtlv_tag_inst_to_str_c(ctx, &next_tag, NULL)); - printf("\n"); - } - - if (ie->val && osmo_gtlv_tag_inst_cmp(&next_tag, &ie->ti)) { - printf(" ERROR peeking tag: expected tag %s, got tag %s\n", - osmo_gtlv_tag_inst_to_str_c(ctx, &ie->ti, NULL), - osmo_gtlv_tag_inst_to_str_c(ctx, &next_tag, NULL)); - exit(1); - } - if (!ie->val && rc != -ENOENT) { - printf(" ERROR peeking tag: expected -ENOENT, got rc=%d, tag %s\n", rc, - osmo_gtlv_tag_inst_to_str_c(ctx, &next_tag, NULL)); - exit(1); - } - - if (rc == -ENOENT) - break; - - /* go to the next TLV */ - rc = osmo_gtlv_load_next(>lv); - if (rc) { - printf(" ERROR loading TLV structure: osmo_gtlv_load_next() rc = %d\n", rc); - exit(1); - } - if (ie->val) - ie++; - } -} - -/* Decode TLV in random order, each time searching for a tag in the raw data */ -void test_tlv_dec_by_tag(const struct osmo_gtlv_cfg *cfg, const struct ie *ies, struct msgb *msg) -{ - const struct ie *last_ie; - const struct ie *ie; - int rc; - struct osmo_gtlv_load gtlv = { - .cfg = cfg, - .src = { msg->data, msg->len }, - }; - - printf("- decoding in reverse order:\n"); - - last_ie = ies; - while (last_ie->val) last_ie++; - last_ie--; - - for (ie = last_ie; ie >= ies; ie--) { - /* each time, look from the beginning */ - osmo_gtlv_load_start(>lv); - rc = osmo_gtlv_load_next_by_tag_inst(>lv, &ie->ti); - if (rc) { - printf(" ERROR loading TLV structure: osmo_gtlv_load_next_by_tag_inst(%s) rc = %d\n", - osmo_gtlv_tag_inst_to_str_c(ctx, &ie->ti, NULL), rc); - exit(1); - } - if (!gtlv.val) { - printf(" ERROR loading TLV structure: osmo_gtlv_load_next_by_tag_inst(%s) returned NULL val\n", - osmo_gtlv_tag_inst_to_str_c(ctx, &ie->ti, NULL)); - exit(1); - } - if (osmo_gtlv_tag_inst_cmp(>lv.ti, &ie->ti)) { - printf(" ERROR loading TLV structure: expected tag %s, got tag %s\n", - osmo_gtlv_tag_inst_to_str_c(ctx, &ie->ti, NULL), - osmo_gtlv_tag_inst_to_str_c(ctx, >lv.ti, NULL)); - exit(1); - } - if (strcmp(ie->val, osmo_hexdump_nospc(gtlv.val, gtlv.len))) { - while (1) { - printf(" (mismatch: T=%s L=%zu v=%s, checking for another occurrence of T=%s)\n", - osmo_gtlv_tag_inst_to_str_c(ctx, >lv.ti, NULL), - gtlv.len, - osmo_hexdump_nospc(gtlv.val, gtlv.len), - osmo_gtlv_tag_inst_to_str_c(ctx, >lv.ti, NULL)); - - rc = osmo_gtlv_load_next_by_tag_inst(>lv, &ie->ti); - if (rc || !gtlv.val) { - printf(" ERROR val not found\n"); - exit(1); - } - if (strcmp(ie->val, osmo_hexdump_nospc(gtlv.val, gtlv.len)) == 0) { - break; - } - } - } - printf(" T=%s L=%zu v=%s\n", - osmo_gtlv_tag_inst_to_str_c(ctx, >lv.ti, NULL), - gtlv.len, osmo_hexdump_nospc(gtlv.val, gtlv.len)); - } - - printf("- decoding every second tag:\n"); - - osmo_gtlv_load_start(>lv); - for (ie = ies; ie->val; ie++) { - /* skip one tag */ - ie++; - if (!ie->val) - break; - - rc = osmo_gtlv_load_next_by_tag_inst(>lv, &ie->ti); - if (rc) { - printf(" ERROR loading TLV structure: osmo_gtlv_load_next_by_tag_inst(%s) rc = %d\n", - osmo_gtlv_tag_inst_to_str_c(ctx, &ie->ti, NULL), rc); - exit(1); - } - if (!gtlv.val) { - printf(" ERROR loading TLV structure: osmo_gtlv_load_next_by_tag_inst(%s) returned NULL val\n", - osmo_gtlv_tag_inst_to_str_c(ctx, &ie->ti, NULL)); - exit(1); - } - if (osmo_gtlv_tag_inst_cmp(>lv.ti, &ie->ti)) { - printf(" ERROR loading TLV structure: expected tag %s, got tag %s\n", - osmo_gtlv_tag_inst_to_str_c(ctx, &ie->ti, NULL), - osmo_gtlv_tag_inst_to_str_c(ctx, >lv.ti, NULL)); - exit(1); - } - if (strcmp(ie->val, osmo_hexdump_nospc(gtlv.val, gtlv.len))) { - while (1) { - printf(" (mismatch: T=%s L=%zu v=%s, checking for another occurrence of T=%s)\n", - osmo_gtlv_tag_inst_to_str_c(ctx, >lv.ti, NULL), - gtlv.len, - osmo_hexdump_nospc(gtlv.val, gtlv.len), - osmo_gtlv_tag_inst_to_str_c(ctx, >lv.ti, NULL)); - - rc = osmo_gtlv_load_next_by_tag_inst(>lv, &ie->ti); - if (rc || !gtlv.val) { - printf(" ERROR val not found\n"); - exit(1); - } - if (strcmp(ie->val, osmo_hexdump_nospc(gtlv.val, gtlv.len)) == 0) { - break; - } - } - } - printf(" T=%s L=%zu v=%s\n", - osmo_gtlv_tag_inst_to_str_c(ctx, >lv.ti, NULL), - gtlv.len, osmo_hexdump_nospc(gtlv.val, gtlv.len)); - } - - printf("- enforcing order: without restart, a past tag is not parsed again:\n"); - /* Try to read the first tag, expect that it isn't found because we're already halfway in the message data */ - ie = ies; - rc = osmo_gtlv_load_next_by_tag_inst(>lv, &ie->ti); - printf(" osmo_gtlv_load_next_by_tag_inst(%s) rc=", osmo_gtlv_tag_inst_to_str_c(ctx, &ie->ti, NULL)); - if (rc == -ENOENT) { - printf("-ENOENT\n"); - } else { - printf("%d\n", rc); - printf(" ERROR: expected -ENOENT\n"); - exit(1); - } -} - -void test_tlv(const char *label, struct ie *tests[], size_t tests_len, const struct osmo_gtlv_cfg *cfg) -{ - int i; - for (i = 0; i < tests_len; i++) { - const struct ie *ies = tests[i]; - struct msgb *msg; - printf("\n=== start: %s[%d]\n", label, i); - - msg = test_tlv_enc(cfg, ies); - test_tlv_dec(cfg, ies, msg); - test_tlv_peek(cfg, ies, msg); - test_tlv_dec_by_tag(cfg, ies, msg); - - msgb_free(msg); - - printf("=== end: %s[%d]\n", label, i); - } -} - -struct ie t8l8v_test1[] = { - /* smallest T */ - { {}, "2342" }, - /* largest T */ - { {255}, "2342" }, - - /* smallest V (no V data) */ - { {1}, "" }, - /* largest V, 255 bytes is the largest that an 8bit size length can express. */ - { {123}, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - }, - - /* arbitrary test data */ - { {101}, "11" }, - { {102}, "2222" }, - { {103}, "333333" }, - {} -}; - -struct ie t8l8v_test_multi[] = { - { {42}, "42" }, - { {2}, "0101" }, - { {2}, "2222" }, - { {3}, "11" }, - { {3}, "2222" }, - { {3}, "333333" }, - { {23}, "23" }, - { {42}, "666f72747974776f" }, - { {23}, "7477656e74797468726565" }, - {} -}; - -struct ie *t8l8v_tests[] = { - t8l8v_test1, - t8l8v_test_multi, -}; - -void test_t8l8v() -{ - test_tlv(__func__, t8l8v_tests, ARRAY_SIZE(t8l8v_tests), &osmo_t8l8v_cfg); -} - -struct ie t16l16v_test1[] = { - /* smallest T */ - { {}, "2342" }, - /* largest T */ - { {65535}, "2342" }, - - /* smallest V (no V data) */ - { {1}, "" }, - /* 256 bytes is one more than an 8bit size length can express. */ - { {123}, "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" - }, - - /* arbitrary test data */ - { {1001}, "11" }, - { {1002}, "2222" }, - { {1003}, "333333" }, - {} -}; - -struct ie t16l16v_test_multi[] = { - { {1042}, "42" }, - { {102}, "0101" }, - { {102}, "2222" }, - { {103}, "11" }, - { {103}, "2222" }, - { {103}, "333333" }, - { {1023}, "23" }, - { {1042}, "666f72747974776f" }, - { {1023}, "7477656e74797468726565" }, - {} -}; - -struct ie *t16l16v_tests[] = { - t16l16v_test1, - t16l16v_test_multi, -}; - -void test_t16l16v() -{ - test_tlv(__func__, t16l16v_tests, ARRAY_SIZE(t16l16v_tests), &osmo_t16l16v_cfg); -} - -struct ie txlxv_test1[] = { - /* smallest T */ - { {}, "2342" }, - /* largest T that still fits in one encoded octet (highest bit serves as flag) */ - { {0x7f}, "2342" }, - /* smallest T that needs two octets to be encoded (first octet = 0x80 flag + 0, second octet = 0x1) */ - { {0x80}, "2342" }, - /* largest T that can be encoded in 16bit - one flag bit. */ - { {0x7fff}, "2342" }, - - /* smallest V (no V data) */ - { {1}, "" }, - /* 256 bytes is one more than an 8bit size length can express. */ - { {123}, "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000000000000" - }, - - /* arbitrary test data */ - { {1002}, "2222" }, - { {1003}, "333333" }, - {} -}; - -struct ie txlxv_test_multi[] = { - { {1042}, "42" }, - { {1002}, "0101" }, - { {1002}, "2222" }, - { {103}, "11" }, - { {103}, "2222" }, - { {103}, "333333" }, - { {1023}, "23" }, - { {1042}, "666f72747974776f" }, - { {1023}, "7477656e74797468726565" }, - {} -}; - -struct ie *txlxv_tests[] = { - txlxv_test1, - txlxv_test_multi, -}; - -/* Example of defining a variable TL, where size of T and L depend on the actual tag and length values: load. */ -int txlxv_load_tl(struct osmo_gtlv_load *gtlv, const uint8_t *src_data, size_t src_data_len) -{ - const uint8_t *pos = src_data; - const uint8_t *end = src_data + src_data_len; - if (pos[0] & 0x80) { - if (pos + 2 > end) - return -EINVAL; - gtlv->ti.tag = (((int)pos[1]) << 7) + (pos[0] & 0x7f); - pos += 2; - } else { - gtlv->ti.tag = pos[0]; - pos++; - } - - switch (gtlv->ti.tag) { - case 1002: - /* fixed-length IE */ - gtlv->len = 2; - break; - case 123: - /* 16bit length IE */ - if (pos + 2 > end) - return -EINVAL; - gtlv->len = osmo_load16be(pos); - pos += 2; - break; - default: - /* 8bit length IE */ - if (pos + 1 > end) - return -EINVAL; - gtlv->len = *pos; - pos++; - break; - } - gtlv->val = pos; - return 0; -} - -/* Example of defining a variable TL, where size of T and L depend on the actual tag and length values: store. */ -int txlxv_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) -{ - uint8_t *pos = dst_data; - uint8_t *end = dst_data + dst_data_avail; - unsigned int tag = ti->tag; - if (tag < 0x80) { - if (pos + 1 > end) - return -ENOSPC; - pos[0] = tag; - pos++; - } else { - if (pos + 2 > end) - return -ENOSPC; - pos[0] = 0x80 + (tag & 0x7f); - pos[1] = tag >> 7; - pos += 2; - } - - switch (tag) { - case 1002: - /* fixed-length IE, write no len */ - break; - case 123: - /* 16bit length IE */ - if (len > UINT16_MAX) - return -ERANGE; - if (pos + 2 > end) - return -ENOSPC; - osmo_store16be(len, pos); - pos += 2; - break; - default: - /* 8bit length IE */ - if (len > UINT8_MAX) - return -ERANGE; - if (pos + 1 > end) - return -ENOSPC; - pos[0] = len; - pos++; - break; - } - return pos - dst_data; -} - -const struct osmo_gtlv_cfg txlxv_cfg = { - .tl_min_size = 1, - .load_tl = txlxv_load_tl, - .store_tl = txlxv_store_tl, -}; - -void test_txlxv() -{ - test_tlv(__func__, txlxv_tests, ARRAY_SIZE(txlxv_tests), &txlxv_cfg); -} - -/* 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 5: - case 7: - case 9: - if (src_data_len < 3) - return -ENOSPC; - gtlv->ti.instance_present = true; - gtlv->ti.instance = src_data[2]; - gtlv->val = src_data + 3; - 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; - dst_data[1] = len; - - switch (ti->tag) { - /* All tags that are TLIV go here */ - case 5: - case 7: - case 9: - if (dst_data_avail < 3) - return -ENOSPC; - if (!ti->instance_present) - return -EINVAL; - if (ti->instance > UINT8_MAX) - return -EINVAL; - dst_data[2] = ti->instance; - return 3; - default: - return 2; - } -} - -const struct osmo_gtlv_cfg osmo_tliv_cfg = { - .tl_min_size = 2, - .load_tl = tliv_load_tl, - .store_tl = tliv_store_tl, -}; - -struct ie tliv_test1[] = { - /* TLV */ - { {1}, "0002" }, - /* TLIV */ - { {5, true, 1}, "0017" }, - /* TLIV */ - { {5, true, 2}, "0018" }, - /* TLIV */ - { {5, true, 3}, "0019" }, - /* TLV */ - { {6}, "001a" }, - /* TLIV */ - { {7, true, 1}, "001b" }, - /* TLIV */ - { {9, true, 1}, "001c" }, - {} -}; - -struct ie *tliv_tests[] = { - tliv_test1, -}; - -void test_tliv() -{ - test_tlv(__func__, tliv_tests, ARRAY_SIZE(tliv_tests), &osmo_tliv_cfg); -} - -int main() -{ - ctx = talloc_named_const(NULL, 0, "gtlv_test"); - msgb_talloc_ctx_init(ctx, 0); - - test_t8l8v(); - test_t16l16v(); - test_txlxv(); - test_tliv(); - - talloc_free(ctx); - return 0; -} diff --git a/tests/libosmo-gtlv/gtlv_test.ok b/tests/libosmo-gtlv/gtlv_test.ok deleted file mode 100644 index edc6ff3..0000000 --- a/tests/libosmo-gtlv/gtlv_test.ok +++ /dev/null @@ -1,291 +0,0 @@ - -=== start: test_t8l8v[0] -- encoded: 00 02 23 42 ff 02 23 42 01 00 7b ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 65 01 11 66 02 22 22 67 03 33 33 33 . -- decoding: - T=0 L=2 v=2342 - T=255 L=2 v=2342 - T=1 L=0 v= - T=123 L=255 v=ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - T=101 L=1 v=11 - T=102 L=2 v=2222 - T=103 L=3 v=333333 -- peeking: - peek T=0 - peek T=255 - peek T=1 - peek T=123 - peek T=101 - peek T=102 - peek T=103 - peek rc=-ENOENT -- decoding in reverse order: - T=103 L=3 v=333333 - T=102 L=2 v=2222 - T=101 L=1 v=11 - T=123 L=255 v=ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - T=1 L=0 v= - T=255 L=2 v=2342 - T=0 L=2 v=2342 -- decoding every second tag: - T=255 L=2 v=2342 - T=123 L=255 v=ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - T=102 L=2 v=2222 -- enforcing order: without restart, a past tag is not parsed again: - osmo_gtlv_load_next_by_tag_inst(0) rc=-ENOENT -=== end: test_t8l8v[0] - -=== start: test_t8l8v[1] -- encoded: 2a 01 42 02 02 01 01 02 02 22 22 03 01 11 03 02 22 22 03 03 33 33 33 17 01 23 2a 08 66 6f 72 74 79 74 77 6f 17 0b 74 77 65 6e 74 79 74 68 72 65 65 . -- decoding: - T=42 L=1 v=42 - T=2 L=2 v=0101 - T=2 L=2 v=2222 - T=3 L=1 v=11 - T=3 L=2 v=2222 - T=3 L=3 v=333333 - T=23 L=1 v=23 - T=42 L=8 v=666f72747974776f - T=23 L=11 v=7477656e74797468726565 -- peeking: - peek T=42 - peek T=2 - peek T=2 - peek T=3 - peek T=3 - peek T=3 - peek T=23 - peek T=42 - peek T=23 - peek rc=-ENOENT -- decoding in reverse order: - (mismatch: T=23 L=1 v=23, checking for another occurrence of T=23) - T=23 L=11 v=7477656e74797468726565 - (mismatch: T=42 L=1 v=42, checking for another occurrence of T=42) - T=42 L=8 v=666f72747974776f - T=23 L=1 v=23 - (mismatch: T=3 L=1 v=11, checking for another occurrence of T=3) - (mismatch: T=3 L=2 v=2222, checking for another occurrence of T=3) - T=3 L=3 v=333333 - (mismatch: T=3 L=1 v=11, checking for another occurrence of T=3) - T=3 L=2 v=2222 - T=3 L=1 v=11 - (mismatch: T=2 L=2 v=0101, checking for another occurrence of T=2) - T=2 L=2 v=2222 - T=2 L=2 v=0101 - T=42 L=1 v=42 -- decoding every second tag: - T=2 L=2 v=0101 - T=3 L=1 v=11 - (mismatch: T=3 L=2 v=2222, checking for another occurrence of T=3) - T=3 L=3 v=333333 - T=42 L=8 v=666f72747974776f -- enforcing order: without restart, a past tag is not parsed again: - osmo_gtlv_load_next_by_tag_inst(42) rc=-ENOENT -=== end: test_t8l8v[1] - -=== start: test_t16l16v[0] -- encoded: 00 00 00 02 23 42 ff ff 00 02 23 42 00 01 00 00 00 7b 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 e9 00 01 11 03 ea 00 02 22 22 03 eb 00 03 33 33 33 . -- decoding: - T=0 L=2 v=2342 - T=65535 L=2 v=2342 - T=1 L=0 v= - T=123 L=256 v=00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - T=1001 L=1 v=11 - T=1002 L=2 v=2222 - T=1003 L=3 v=333333 -- peeking: - peek T=0 - peek T=65535 - peek T=1 - peek T=123 - peek T=1001 - peek T=1002 - peek T=1003 - peek rc=-ENOENT -- decoding in reverse order: - T=1003 L=3 v=333333 - T=1002 L=2 v=2222 - T=1001 L=1 v=11 - T=123 L=256 v=00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - T=1 L=0 v= - T=65535 L=2 v=2342 - T=0 L=2 v=2342 -- decoding every second tag: - T=65535 L=2 v=2342 - T=123 L=256 v=00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - T=1002 L=2 v=2222 -- enforcing order: without restart, a past tag is not parsed again: - osmo_gtlv_load_next_by_tag_inst(0) rc=-ENOENT -=== end: test_t16l16v[0] - -=== start: test_t16l16v[1] -- encoded: 04 12 00 01 42 00 66 00 02 01 01 00 66 00 02 22 22 00 67 00 01 11 00 67 00 02 22 22 00 67 00 03 33 33 33 03 ff 00 01 23 04 12 00 08 66 6f 72 74 79 74 77 6f 03 ff 00 0b 74 77 65 6e 74 79 74 68 72 65 65 . -- decoding: - T=1042 L=1 v=42 - T=102 L=2 v=0101 - T=102 L=2 v=2222 - T=103 L=1 v=11 - T=103 L=2 v=2222 - T=103 L=3 v=333333 - T=1023 L=1 v=23 - T=1042 L=8 v=666f72747974776f - T=1023 L=11 v=7477656e74797468726565 -- peeking: - peek T=1042 - peek T=102 - peek T=102 - peek T=103 - peek T=103 - peek T=103 - peek T=1023 - peek T=1042 - peek T=1023 - peek rc=-ENOENT -- decoding in reverse order: - (mismatch: T=1023 L=1 v=23, checking for another occurrence of T=1023) - T=1023 L=11 v=7477656e74797468726565 - (mismatch: T=1042 L=1 v=42, checking for another occurrence of T=1042) - T=1042 L=8 v=666f72747974776f - T=1023 L=1 v=23 - (mismatch: T=103 L=1 v=11, checking for another occurrence of T=103) - (mismatch: T=103 L=2 v=2222, checking for another occurrence of T=103) - T=103 L=3 v=333333 - (mismatch: T=103 L=1 v=11, checking for another occurrence of T=103) - T=103 L=2 v=2222 - T=103 L=1 v=11 - (mismatch: T=102 L=2 v=0101, checking for another occurrence of T=102) - T=102 L=2 v=2222 - T=102 L=2 v=0101 - T=1042 L=1 v=42 -- decoding every second tag: - T=102 L=2 v=0101 - T=103 L=1 v=11 - (mismatch: T=103 L=2 v=2222, checking for another occurrence of T=103) - T=103 L=3 v=333333 - T=1042 L=8 v=666f72747974776f -- enforcing order: without restart, a past tag is not parsed again: - osmo_gtlv_load_next_by_tag_inst(1042) rc=-ENOENT -=== end: test_t16l16v[1] - -=== start: test_txlxv[0] -- encoded: 00 02 23 42 7f 02 23 42 80 01 02 23 42 ff ff 02 23 42 01 00 7b 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ea 07 22 22 eb 07 03 33 33 33 . -- decoding: - T=0 L=2 v=2342 - T=127 L=2 v=2342 - T=128 L=2 v=2342 - T=32767 L=2 v=2342 - T=1 L=0 v= - T=123 L=256 v=00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - T=1002 L=2 v=2222 - T=1003 L=3 v=333333 -- peeking: - peek T=0 - peek T=127 - peek T=128 - peek T=32767 - peek T=1 - peek T=123 - peek T=1002 - peek T=1003 - peek rc=-ENOENT -- decoding in reverse order: - T=1003 L=3 v=333333 - T=1002 L=2 v=2222 - T=123 L=256 v=00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - T=1 L=0 v= - T=32767 L=2 v=2342 - T=128 L=2 v=2342 - T=127 L=2 v=2342 - T=0 L=2 v=2342 -- decoding every second tag: - T=127 L=2 v=2342 - T=32767 L=2 v=2342 - T=123 L=256 v=00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - T=1003 L=3 v=333333 -- enforcing order: without restart, a past tag is not parsed again: - osmo_gtlv_load_next_by_tag_inst(0) rc=-ENOENT -=== end: test_txlxv[0] - -=== start: test_txlxv[1] -- encoded: 92 08 01 42 ea 07 01 01 ea 07 22 22 67 01 11 67 02 22 22 67 03 33 33 33 ff 07 01 23 92 08 08 66 6f 72 74 79 74 77 6f ff 07 0b 74 77 65 6e 74 79 74 68 72 65 65 . -- decoding: - T=1042 L=1 v=42 - T=1002 L=2 v=0101 - T=1002 L=2 v=2222 - T=103 L=1 v=11 - T=103 L=2 v=2222 - T=103 L=3 v=333333 - T=1023 L=1 v=23 - T=1042 L=8 v=666f72747974776f - T=1023 L=11 v=7477656e74797468726565 -- peeking: - peek T=1042 - peek T=1002 - peek T=1002 - peek T=103 - peek T=103 - peek T=103 - peek T=1023 - peek T=1042 - peek T=1023 - peek rc=-ENOENT -- decoding in reverse order: - (mismatch: T=1023 L=1 v=23, checking for another occurrence of T=1023) - T=1023 L=11 v=7477656e74797468726565 - (mismatch: T=1042 L=1 v=42, checking for another occurrence of T=1042) - T=1042 L=8 v=666f72747974776f - T=1023 L=1 v=23 - (mismatch: T=103 L=1 v=11, checking for another occurrence of T=103) - (mismatch: T=103 L=2 v=2222, checking for another occurrence of T=103) - T=103 L=3 v=333333 - (mismatch: T=103 L=1 v=11, checking for another occurrence of T=103) - T=103 L=2 v=2222 - T=103 L=1 v=11 - (mismatch: T=1002 L=2 v=0101, checking for another occurrence of T=1002) - T=1002 L=2 v=2222 - T=1002 L=2 v=0101 - T=1042 L=1 v=42 -- decoding every second tag: - T=1002 L=2 v=0101 - T=103 L=1 v=11 - (mismatch: T=103 L=2 v=2222, checking for another occurrence of T=103) - T=103 L=3 v=333333 - T=1042 L=8 v=666f72747974776f -- enforcing order: without restart, a past tag is not parsed again: - osmo_gtlv_load_next_by_tag_inst(1042) rc=-ENOENT -=== end: test_txlxv[1] - -=== start: test_tliv[0] -- encoded: 01 02 00 02 05 02 01 00 17 05 02 02 00 18 05 02 03 00 19 06 02 00 1a 07 02 01 00 1b 09 02 01 00 1c . -- decoding: - T=1 L=2 v=0002 - T=5[1] L=2 v=0017 - T=5[2] L=2 v=0018 - T=5[3] L=2 v=0019 - T=6 L=2 v=001a - T=7[1] L=2 v=001b - T=9[1] L=2 v=001c -- peeking: - peek T=1 - peek T=5[1] - peek T=5[2] - peek T=5[3] - peek T=6 - peek T=7[1] - peek T=9[1] - peek rc=-ENOENT -- decoding in reverse order: - T=9[1] L=2 v=001c - T=7[1] L=2 v=001b - T=6 L=2 v=001a - T=5[3] L=2 v=0019 - T=5[2] L=2 v=0018 - T=5[1] L=2 v=0017 - T=1 L=2 v=0002 -- decoding every second tag: - T=5[1] L=2 v=0017 - T=5[3] L=2 v=0019 - T=7[1] L=2 v=001b -- enforcing order: without restart, a past tag is not parsed again: - osmo_gtlv_load_next_by_tag_inst(1) rc=-ENOENT -=== end: test_tliv[0] diff --git a/tests/libosmo-gtlv/test_gtlv_gen/Makefile.am b/tests/libosmo-gtlv/test_gtlv_gen/Makefile.am deleted file mode 100644 index 0d27292..0000000 --- a/tests/libosmo-gtlv/test_gtlv_gen/Makefile.am +++ /dev/null @@ -1,60 +0,0 @@ -AM_CPPFLAGS = \ - $(all_includes) \ - -I$(top_srcdir)/include \ - -I$(bulddir) \ - $(NULL) - -AM_CFLAGS = \ - -Wall \ - $(LIBOSMOCORE_CFLAGS) \ - $(NULL) - -noinst_PROGRAMS = \ - gen__myproto_ies_auto \ - gtlv_gen_test \ - $(NULL) - -EXTRA_DIST = \ - myproto_ies_custom.h \ - gtlv_gen_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 - -gtlv_gen_test_SOURCES = \ - gtlv_gen_test.c \ - myproto_ies_custom.c \ - myproto_ies_auto.c \ - $(NULL) - -gtlv_gen_test_LDADD = \ - $(top_builddir)/src/libosmo-gtlv/libosmo-gtlv.a \ - $(LIBOSMOCORE_LIBS) \ - $(NULL) - -.PHONY: update_exp -update_exp: - $(builddir)/gtlv_gen_test >$(srcdir)/gtlv_gen_test.ok diff --git a/tests/libosmo-gtlv/test_gtlv_gen/gen__myproto_ies_auto.c b/tests/libosmo-gtlv/test_gtlv_gen/gen__myproto_ies_auto.c deleted file mode 100644 index 75d657d..0000000 --- a/tests/libosmo-gtlv/test_gtlv_gen/gen__myproto_ies_auto.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * (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 ALL_FROM_NAME osmo_gtlv_gen_ie_auto - -/* An IE where the type is not a 'struct myproto_ie_${name}'. */ -static const struct osmo_gtlv_gen_ie number = { - .decoded_type = "int", /* add 'int foo;' to the struct */ - .dec_enc = "u16", /* use myproto_dec_u16() and myproto_enc_u16() for the TLV value part */ - .spec_ref = "an int coded as uint16_t", -}; - -static const struct osmo_gtlv_gen_ie_o ies_in_moo_nest[] = { - /* Mandatory member xxx.foo of the type defined in 'number' above. */ - M(number, "foo"), - /* Mandatory member xxx.bar of type 'struct myproto_ie_bar', using myproto_ie_dec_bar(), myproto_ie_enc_bar(), - * myproto_ie_enc_to_str_bar(), all defined in myproto_ies_custom.h/c. */ - M(ALL_FROM_NAME, "bar"), - M(ALL_FROM_NAME, "baz"), - {} -}; - -static const struct osmo_gtlv_gen_ie huge_number = { - .decoded_type = "uint64_t", - .dec_enc = "u64", -}; - -static const struct osmo_gtlv_gen_ie moo_nest = { - .tag_name = "moo_nest", - .nested_ies = ies_in_moo_nest, -}; - -static const struct osmo_gtlv_gen_ie_o ies_in_goo_nest[] = { - O(huge_number, "val"), - M(moo_nest, "nest"), - {} -}; - -static const struct osmo_gtlv_gen_ie goo_nest = { - .tag_name = "goo_nest", - .nested_ies = ies_in_goo_nest, -}; - -static const struct osmo_gtlv_gen_ie_o ies_in_moo_msg[] = { - M(number, "foo"), - M(ALL_FROM_NAME, "bar"), - O(ALL_FROM_NAME, "baz"), - O_MULTI(32, number, "repeat_int"), - O_MULTI(32, ALL_FROM_NAME, "repeat_struct"), - O(moo_nest, "nest"), - {} -}; - -static const struct osmo_gtlv_gen_ie_o ies_in_goo_msg[] = { - M(number, "foo"), - O(ALL_FROM_NAME, "bar"), - O_MULTI(8, goo_nest, "nest"), - {} -}; - -static const struct osmo_gtlv_gen_msg msg_defs[] = { - { "moo", ies_in_moo_msg }, - { "goo", ies_in_goo_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_gtlv_gen/gtlv_gen_test.c b/tests/libosmo-gtlv/test_gtlv_gen/gtlv_gen_test.c deleted file mode 100644 index ef5372c..0000000 --- a/tests/libosmo-gtlv/test_gtlv_gen/gtlv_gen_test.c +++ /dev/null @@ -1,261 +0,0 @@ -/* - * (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(>lv, (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, >lv, ordered, msg->type, err_cb, NULL, myproto_iei_names); -} - -void *ctx; - -struct myproto_msg tests[] = { - { - MYPROTO_MSGT_MOO, - { - .moo = { - .foo = 23, - .bar = { "twentythree" }, - }, - }, - }, - { - MYPROTO_MSGT_MOO, - { - .moo = { - .foo = 23, - .bar = { "twentythree" }, - - .baz_present = true, - .baz = { - .v_int = 2323, - .v_bool = true, - }, - }, - }, - }, - { - MYPROTO_MSGT_MOO, - { - .moo = { - .foo = 23, - .bar = { "twentythree" }, - - .baz_present = true, - .baz = { - .v_int = 2323, - .v_bool = true, - }, - - .repeat_int_count = 3, - .repeat_int = { 1, 2, 0x7fff }, - }, - }, - }, - { - MYPROTO_MSGT_MOO, - { - .moo = { - .foo = 23, - .bar = { "twentythree" }, - - .baz_present = true, - .baz = { - .v_int = 2323, - .v_bool = true, - }, - - .repeat_int_count = 3, - .repeat_int = { 1, 2, 0x7fff }, - - .repeat_struct_count = 2, - .repeat_struct = { - { - .v_int = 1001, - .v_bool = true, - .v_enum = R_A, - }, - { - .v_int = 1002, - .v_bool = false, - .v_enum = R_B, - }, - }, - - .nest_present = true, - .nest = { - .foo = 42, - .bar = { "fortytwo" }, - .baz = { - .v_int = 4242, - .v_bool = false, - }, - }, - }, - }, - }, - { - MYPROTO_MSGT_GOO, - { - .goo = { - .foo = 17, - - .bar_present = true, - .bar = { "gooei" }, - - .nest_count = 2, - .nest = { - { - .val_present = true, - .val = 0x0123456789abcdef, - .nest = { - .foo = 11, - .bar = { "eleven" }, - .baz = { - .v_int = 1111, - .v_bool = true, - }, - }, - }, - { - .val_present = false, - .nest = { - .foo = 12, - .bar = { "twelve" }, - .baz = { - .v_int = 1212, - .v_bool = false, - }, - }, - }, - }, - }, - }, - }, -}; - -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); - } -} - -int main() -{ - ctx = talloc_named_const(NULL, 0, "test_gen_tlv"); - msgb_talloc_ctx_init(ctx, 0); - - test_enc_dec("t8l8v ordered", &osmo_t8l8v_cfg, true); - test_enc_dec("t8l8v unordered", &osmo_t8l8v_cfg, false); - - test_enc_dec("t16l16v ordered", &osmo_t16l16v_cfg, true); - test_enc_dec("t16l16v unordered", &osmo_t16l16v_cfg, false); - - talloc_free(ctx); - return 0; -} diff --git a/tests/libosmo-gtlv/test_gtlv_gen/gtlv_gen_test.ok b/tests/libosmo-gtlv/test_gtlv_gen/gtlv_gen_test.ok deleted file mode 100644 index e178831..0000000 --- a/tests/libosmo-gtlv/test_gtlv_gen/gtlv_gen_test.ok +++ /dev/null @@ -1,160 +0,0 @@ - -=== start t8l8v ordered test_enc_dec[0] -encoded: MOO={ 'FOO'=23 'BAR'="twentythree" } -myproto_msg_enc() rc = 0 -01 01 02 00 17 02 0b 74 77 65 6e 74 79 74 68 72 65 65 . -myproto_msg_dec() rc = 0 -decoded: MOO={ 'FOO'=23 'BAR'="twentythree" } -=== end t8l8v ordered test_enc_dec[0] - -=== start t8l8v ordered test_enc_dec[1] -encoded: MOO={ 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} } -myproto_msg_enc() rc = 0 -01 01 02 00 17 02 0b 74 77 65 6e 74 79 74 68 72 65 65 03 02 89 13 . -myproto_msg_dec() rc = 0 -decoded: MOO={ 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} } -=== end t8l8v ordered test_enc_dec[1] - -=== start t8l8v ordered test_enc_dec[2] -encoded: MOO={ 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} 'REPEAT_INT'={ 1, 2, 32767 } } -myproto_msg_enc() rc = 0 -01 01 02 00 17 02 0b 74 77 65 6e 74 79 74 68 72 65 65 03 02 89 13 04 02 00 01 04 02 00 02 04 02 7f ff . -myproto_msg_dec() rc = 0 -decoded: MOO={ 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} 'REPEAT_INT'={ 1, 2, 32767 } } -=== end t8l8v ordered test_enc_dec[2] - -=== start t8l8v ordered test_enc_dec[3] -encoded: MOO={ 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} 'REPEAT_INT'={ 1, 2, 32767 } 'REPEAT_STRUCT'={ {1001,true,R_A}, {1002,false,R_B} } 'MOO_NEST'={ 'FOO'=42 'BAR'="fortytwo" 'BAZ'={4242,false} } } -myproto_msg_enc() rc = 0 -01 01 02 00 17 02 0b 74 77 65 6e 74 79 74 68 72 65 65 03 02 89 13 04 02 00 01 04 02 00 02 04 02 7f ff 05 03 03 e9 80 05 03 03 ea 01 06 12 01 02 00 2a 02 08 66 6f 72 74 79 74 77 6f 03 02 10 92 . -myproto_msg_dec() rc = 0 -decoded: MOO={ 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} 'REPEAT_INT'={ 1, 2, 32767 } 'REPEAT_STRUCT'={ {1001,true,R_A}, {1002,false,R_B} } 'MOO_NEST'={ 'FOO'=42 'BAR'="fortytwo" 'BAZ'={4242,false} } } -=== end t8l8v ordered test_enc_dec[3] - -=== start t8l8v ordered test_enc_dec[4] -encoded: GOO={ 'FOO'=17 'BAR'="gooei" 'GOO_NEST'={ { 'VAL'=0x123456789abcdef 'MOO_NEST'={ 'FOO'=11 'BAR'="eleven" 'BAZ'={1111,true} } }, { 'MOO_NEST'={ 'FOO'=12 'BAR'="twelve" 'BAZ'={1212,false} } } } } -myproto_msg_enc() rc = 0 -07 01 02 00 11 02 05 67 6f 6f 65 69 08 1c 07 08 01 23 45 67 89 ab cd ef 06 10 01 02 00 0b 02 06 65 6c 65 76 65 6e 03 02 84 57 08 12 06 10 01 02 00 0c 02 06 74 77 65 6c 76 65 03 02 04 bc . -myproto_msg_dec() rc = 0 -decoded: GOO={ 'FOO'=17 'BAR'="gooei" 'GOO_NEST'={ { 'VAL'=0x123456789abcdef 'MOO_NEST'={ 'FOO'=11 'BAR'="eleven" 'BAZ'={1111,true} } }, { 'MOO_NEST'={ 'FOO'=12 'BAR'="twelve" 'BAZ'={1212,false} } } } } -=== end t8l8v ordered test_enc_dec[4] - -=== start t8l8v unordered test_enc_dec[0] -encoded: MOO={ 'FOO'=23 'BAR'="twentythree" } -myproto_msg_enc() rc = 0 -01 01 02 00 17 02 0b 74 77 65 6e 74 79 74 68 72 65 65 . -myproto_msg_dec() rc = 0 -decoded: MOO={ 'FOO'=23 'BAR'="twentythree" } -=== end t8l8v unordered test_enc_dec[0] - -=== start t8l8v unordered test_enc_dec[1] -encoded: MOO={ 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} } -myproto_msg_enc() rc = 0 -01 01 02 00 17 02 0b 74 77 65 6e 74 79 74 68 72 65 65 03 02 89 13 . -myproto_msg_dec() rc = 0 -decoded: MOO={ 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} } -=== end t8l8v unordered test_enc_dec[1] - -=== start t8l8v unordered test_enc_dec[2] -encoded: MOO={ 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} 'REPEAT_INT'={ 1, 2, 32767 } } -myproto_msg_enc() rc = 0 -01 01 02 00 17 02 0b 74 77 65 6e 74 79 74 68 72 65 65 03 02 89 13 04 02 00 01 04 02 00 02 04 02 7f ff . -myproto_msg_dec() rc = 0 -decoded: MOO={ 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} 'REPEAT_INT'={ 1, 2, 32767 } } -=== end t8l8v unordered test_enc_dec[2] - -=== start t8l8v unordered test_enc_dec[3] -encoded: MOO={ 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} 'REPEAT_INT'={ 1, 2, 32767 } 'REPEAT_STRUCT'={ {1001,true,R_A}, {1002,false,R_B} } 'MOO_NEST'={ 'FOO'=42 'BAR'="fortytwo" 'BAZ'={4242,false} } } -myproto_msg_enc() rc = 0 -01 01 02 00 17 02 0b 74 77 65 6e 74 79 74 68 72 65 65 03 02 89 13 04 02 00 01 04 02 00 02 04 02 7f ff 05 03 03 e9 80 05 03 03 ea 01 06 12 01 02 00 2a 02 08 66 6f 72 74 79 74 77 6f 03 02 10 92 . -myproto_msg_dec() rc = 0 -decoded: MOO={ 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} 'REPEAT_INT'={ 1, 2, 32767 } 'REPEAT_STRUCT'={ {1001,true,R_A}, {1002,false,R_B} } 'MOO_NEST'={ 'FOO'=42 'BAR'="fortytwo" 'BAZ'={4242,false} } } -=== end t8l8v unordered test_enc_dec[3] - -=== start t8l8v unordered test_enc_dec[4] -encoded: GOO={ 'FOO'=17 'BAR'="gooei" 'GOO_NEST'={ { 'VAL'=0x123456789abcdef 'MOO_NEST'={ 'FOO'=11 'BAR'="eleven" 'BAZ'={1111,true} } }, { 'MOO_NEST'={ 'FOO'=12 'BAR'="twelve" 'BAZ'={1212,false} } } } } -myproto_msg_enc() rc = 0 -07 01 02 00 11 02 05 67 6f 6f 65 69 08 1c 07 08 01 23 45 67 89 ab cd ef 06 10 01 02 00 0b 02 06 65 6c 65 76 65 6e 03 02 84 57 08 12 06 10 01 02 00 0c 02 06 74 77 65 6c 76 65 03 02 04 bc . -myproto_msg_dec() rc = 0 -decoded: GOO={ 'FOO'=17 'BAR'="gooei" 'GOO_NEST'={ { 'VAL'=0x123456789abcdef 'MOO_NEST'={ 'FOO'=11 'BAR'="eleven" 'BAZ'={1111,true} } }, { 'MOO_NEST'={ 'FOO'=12 'BAR'="twelve" 'BAZ'={1212,false} } } } } -=== end t8l8v unordered test_enc_dec[4] - -=== start t16l16v ordered test_enc_dec[0] -encoded: MOO={ 'FOO'=23 'BAR'="twentythree" } -myproto_msg_enc() rc = 0 -01 00 01 00 02 00 17 00 02 00 0b 74 77 65 6e 74 79 74 68 72 65 65 . -myproto_msg_dec() rc = 0 -decoded: MOO={ 'FOO'=23 'BAR'="twentythree" } -=== end t16l16v ordered test_enc_dec[0] - -=== start t16l16v ordered test_enc_dec[1] -encoded: MOO={ 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} } -myproto_msg_enc() rc = 0 -01 00 01 00 02 00 17 00 02 00 0b 74 77 65 6e 74 79 74 68 72 65 65 00 03 00 02 89 13 . -myproto_msg_dec() rc = 0 -decoded: MOO={ 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} } -=== end t16l16v ordered test_enc_dec[1] - -=== start t16l16v ordered test_enc_dec[2] -encoded: MOO={ 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} 'REPEAT_INT'={ 1, 2, 32767 } } -myproto_msg_enc() rc = 0 -01 00 01 00 02 00 17 00 02 00 0b 74 77 65 6e 74 79 74 68 72 65 65 00 03 00 02 89 13 00 04 00 02 00 01 00 04 00 02 00 02 00 04 00 02 7f ff . -myproto_msg_dec() rc = 0 -decoded: MOO={ 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} 'REPEAT_INT'={ 1, 2, 32767 } } -=== end t16l16v ordered test_enc_dec[2] - -=== start t16l16v ordered test_enc_dec[3] -encoded: MOO={ 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} 'REPEAT_INT'={ 1, 2, 32767 } 'REPEAT_STRUCT'={ {1001,true,R_A}, {1002,false,R_B} } 'MOO_NEST'={ 'FOO'=42 'BAR'="fortytwo" 'BAZ'={4242,false} } } -myproto_msg_enc() rc = 0 -01 00 01 00 02 00 17 00 02 00 0b 74 77 65 6e 74 79 74 68 72 65 65 00 03 00 02 89 13 00 04 00 02 00 01 00 04 00 02 00 02 00 04 00 02 7f ff 00 05 00 03 03 e9 80 00 05 00 03 03 ea 01 00 06 00 18 00 01 00 02 00 2a 00 02 00 08 66 6f 72 74 79 74 77 6f 00 03 00 02 10 92 . -myproto_msg_dec() rc = 0 -decoded: MOO={ 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} 'REPEAT_INT'={ 1, 2, 32767 } 'REPEAT_STRUCT'={ {1001,true,R_A}, {1002,false,R_B} } 'MOO_NEST'={ 'FOO'=42 'BAR'="fortytwo" 'BAZ'={4242,false} } } -=== end t16l16v ordered test_enc_dec[3] - -=== start t16l16v ordered test_enc_dec[4] -encoded: GOO={ 'FOO'=17 'BAR'="gooei" 'GOO_NEST'={ { 'VAL'=0x123456789abcdef 'MOO_NEST'={ 'FOO'=11 'BAR'="eleven" 'BAZ'={1111,true} } }, { 'MOO_NEST'={ 'FOO'=12 'BAR'="twelve" 'BAZ'={1212,false} } } } } -myproto_msg_enc() rc = 0 -07 00 01 00 02 00 11 00 02 00 05 67 6f 6f 65 69 00 08 00 26 00 07 00 08 01 23 45 67 89 ab cd ef 00 06 00 16 00 01 00 02 00 0b 00 02 00 06 65 6c 65 76 65 6e 00 03 00 02 84 57 00 08 00 1a 00 06 00 16 00 01 00 02 00 0c 00 02 00 06 74 77 65 6c 76 65 00 03 00 02 04 bc . -myproto_msg_dec() rc = 0 -decoded: GOO={ 'FOO'=17 'BAR'="gooei" 'GOO_NEST'={ { 'VAL'=0x123456789abcdef 'MOO_NEST'={ 'FOO'=11 'BAR'="eleven" 'BAZ'={1111,true} } }, { 'MOO_NEST'={ 'FOO'=12 'BAR'="twelve" 'BAZ'={1212,false} } } } } -=== end t16l16v ordered test_enc_dec[4] - -=== start t16l16v unordered test_enc_dec[0] -encoded: MOO={ 'FOO'=23 'BAR'="twentythree" } -myproto_msg_enc() rc = 0 -01 00 01 00 02 00 17 00 02 00 0b 74 77 65 6e 74 79 74 68 72 65 65 . -myproto_msg_dec() rc = 0 -decoded: MOO={ 'FOO'=23 'BAR'="twentythree" } -=== end t16l16v unordered test_enc_dec[0] - -=== start t16l16v unordered test_enc_dec[1] -encoded: MOO={ 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} } -myproto_msg_enc() rc = 0 -01 00 01 00 02 00 17 00 02 00 0b 74 77 65 6e 74 79 74 68 72 65 65 00 03 00 02 89 13 . -myproto_msg_dec() rc = 0 -decoded: MOO={ 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} } -=== end t16l16v unordered test_enc_dec[1] - -=== start t16l16v unordered test_enc_dec[2] -encoded: MOO={ 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} 'REPEAT_INT'={ 1, 2, 32767 } } -myproto_msg_enc() rc = 0 -01 00 01 00 02 00 17 00 02 00 0b 74 77 65 6e 74 79 74 68 72 65 65 00 03 00 02 89 13 00 04 00 02 00 01 00 04 00 02 00 02 00 04 00 02 7f ff . -myproto_msg_dec() rc = 0 -decoded: MOO={ 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} 'REPEAT_INT'={ 1, 2, 32767 } } -=== end t16l16v unordered test_enc_dec[2] - -=== start t16l16v unordered test_enc_dec[3] -encoded: MOO={ 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} 'REPEAT_INT'={ 1, 2, 32767 } 'REPEAT_STRUCT'={ {1001,true,R_A}, {1002,false,R_B} } 'MOO_NEST'={ 'FOO'=42 'BAR'="fortytwo" 'BAZ'={4242,false} } } -myproto_msg_enc() rc = 0 -01 00 01 00 02 00 17 00 02 00 0b 74 77 65 6e 74 79 74 68 72 65 65 00 03 00 02 89 13 00 04 00 02 00 01 00 04 00 02 00 02 00 04 00 02 7f ff 00 05 00 03 03 e9 80 00 05 00 03 03 ea 01 00 06 00 18 00 01 00 02 00 2a 00 02 00 08 66 6f 72 74 79 74 77 6f 00 03 00 02 10 92 . -myproto_msg_dec() rc = 0 -decoded: MOO={ 'FOO'=23 'BAR'="twentythree" 'BAZ'={2323,true} 'REPEAT_INT'={ 1, 2, 32767 } 'REPEAT_STRUCT'={ {1001,true,R_A}, {1002,false,R_B} } 'MOO_NEST'={ 'FOO'=42 'BAR'="fortytwo" 'BAZ'={4242,false} } } -=== end t16l16v unordered test_enc_dec[3] - -=== start t16l16v unordered test_enc_dec[4] -encoded: GOO={ 'FOO'=17 'BAR'="gooei" 'GOO_NEST'={ { 'VAL'=0x123456789abcdef 'MOO_NEST'={ 'FOO'=11 'BAR'="eleven" 'BAZ'={1111,true} } }, { 'MOO_NEST'={ 'FOO'=12 'BAR'="twelve" 'BAZ'={1212,false} } } } } -myproto_msg_enc() rc = 0 -07 00 01 00 02 00 11 00 02 00 05 67 6f 6f 65 69 00 08 00 26 00 07 00 08 01 23 45 67 89 ab cd ef 00 06 00 16 00 01 00 02 00 0b 00 02 00 06 65 6c 65 76 65 6e 00 03 00 02 84 57 00 08 00 1a 00 06 00 16 00 01 00 02 00 0c 00 02 00 06 74 77 65 6c 76 65 00 03 00 02 04 bc . -myproto_msg_dec() rc = 0 -decoded: GOO={ 'FOO'=17 'BAR'="gooei" 'GOO_NEST'={ { 'VAL'=0x123456789abcdef 'MOO_NEST'={ 'FOO'=11 'BAR'="eleven" 'BAZ'={1111,true} } }, { 'MOO_NEST'={ 'FOO'=12 'BAR'="twelve" 'BAZ'={1212,false} } } } } -=== end t16l16v unordered test_enc_dec[4] diff --git a/tests/libosmo-gtlv/test_gtlv_gen/myproto_ies_custom.c b/tests/libosmo-gtlv/test_gtlv_gen/myproto_ies_custom.c deleted file mode 100644 index 8548165..0000000 --- a/tests/libosmo-gtlv/test_gtlv_gen/myproto_ies_custom.c +++ /dev/null @@ -1,180 +0,0 @@ -/* 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_u16(void *decoded_struct, void *decode_to, const struct osmo_gtlv_load *gtlv) -{ - int *foo = decode_to; - if (gtlv->len != 2) - return -EINVAL; - *foo = osmo_load16be(gtlv->val); - return 0; -} - -int myproto_enc_u16(struct osmo_gtlv_put *gtlv, void *decoded_struct, void *encode_from) -{ - int *foo = encode_from; - if (*foo > INT16_MAX) - return -EINVAL; - msgb_put_u16(gtlv->dst, *foo); - return 0; -} - -int myproto_enc_to_str_u16(char *buf, size_t buflen, void *encode_from) -{ - int *foo = encode_from; - return snprintf(buf, buflen, "%d", *foo); -} - -int myproto_dec_u64(void *decoded_struct, void *decode_to, const struct osmo_gtlv_load *gtlv) -{ - uint64_t *val = decode_to; - if (gtlv->len != sizeof(uint64_t)) - return -EINVAL; - *val = osmo_load64be(gtlv->val); - return 0; -} - -int myproto_enc_u64(struct osmo_gtlv_put *gtlv, void *decoded_struct, void *encode_from) -{ - uint64_t *val = encode_from; - osmo_store64be(*val, msgb_put(gtlv->dst, sizeof(*val))); - return 0; -} - -int myproto_enc_to_str_u64(char *buf, size_t buflen, void *encode_from) -{ - uint64_t *val = encode_from; - return snprintf(buf, buflen, "0x%"PRIx64, *val); -} - -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 > sizeof(bar->str) - 1) - return -EINVAL; - osmo_strlcpy(bar->str, (const char *)gtlv->val, OSMO_MIN(gtlv->len + 1, sizeof(bar->str))); - return 0; -} - -int myproto_enc_bar(struct osmo_gtlv_put *gtlv, void *decoded_struct, void *encode_from) -{ - struct myproto_ie_bar *bar = encode_from; - int len = strnlen(bar->str, sizeof(bar->str)); - memcpy(msgb_put(gtlv->dst, len), bar, len); - return 0; -} - -int myproto_enc_to_str_bar(char *buf, size_t buflen, void *encode_from) -{ - struct myproto_ie_bar *bar = encode_from; - return osmo_quote_str_buf3(buf, buflen, bar->str, -1); -} - -int myproto_dec_baz(void *decoded_struct, void *decode_to, const struct osmo_gtlv_load *gtlv) -{ - struct myproto_ie_baz *baz = decode_to; - uint16_t l; - if (gtlv->len != 2) - return -EINVAL; - l = osmo_load16be(gtlv->val); - baz->v_int = l & 0x7fff; - baz->v_bool = (l & 0x8000) ? true : false; - return 0; -} - -int myproto_enc_baz(struct osmo_gtlv_put *gtlv, void *decoded_struct, void *encode_from) -{ - struct myproto_ie_baz *baz = encode_from; - if (baz->v_int > 0x7fff) - return -EINVAL; - msgb_put_u16(gtlv->dst, (baz->v_bool ? 0x8000 : 0) + (baz->v_int & 0x7fff)); - return 0; -} - -int myproto_enc_to_str_baz(char *buf, size_t buflen, void *encode_from) -{ - struct myproto_ie_baz *baz = encode_from; - return snprintf(buf, buflen, "{%d,%s}", baz->v_int, baz->v_bool ? "true" : "false"); -} - -int myproto_dec_repeat_struct(void *decoded_struct, void *decode_to, const struct osmo_gtlv_load *gtlv) -{ - struct myproto_ie_repeat_struct *repeat_struct = decode_to; - if (gtlv->len != 3) - return -EINVAL; - repeat_struct->v_int = osmo_load16be(gtlv->val); - repeat_struct->v_bool = gtlv->val[2] & 0x80; - repeat_struct->v_enum = gtlv->val[2] & 0x7f; - return 0; -} - -int myproto_enc_repeat_struct(struct osmo_gtlv_put *gtlv, void *decoded_struct, void *encode_from) -{ - struct myproto_ie_repeat_struct *repeat_struct = encode_from; - msgb_put_u16(gtlv->dst, repeat_struct->v_int); - msgb_put_u8(gtlv->dst, (repeat_struct->v_bool ? 0x80 : 0) + (repeat_struct->v_enum & 0x7f)); - return 0; -} - -int myproto_enc_to_str_repeat_struct(char *buf, size_t buflen, void *encode_from) -{ - struct myproto_ie_repeat_struct *repeat_struct = encode_from; - return snprintf(buf, buflen, "{%d,%s,%s}", - repeat_struct->v_int, repeat_struct->v_bool ? "true" : "false", - get_value_string(myproto_repeat_enum_names, repeat_struct->v_enum)); -} - -const struct value_string myproto_msg_type_names[] = { - { MYPROTO_MSGT_MOO, "MOO" }, - { MYPROTO_MSGT_GOO, "GOO" }, - {} -}; - -const struct value_string myproto_iei_names[] = { - { MYPROTO_IEI_FOO, "FOO" }, - { MYPROTO_IEI_BAR, "BAR" }, - { MYPROTO_IEI_BAZ, "BAZ" }, - { MYPROTO_IEI_REPEAT_INT, "REPEAT_INT" }, - { MYPROTO_IEI_REPEAT_STRUCT, "REPEAT_STRUCT" }, - { MYPROTO_IEI_MOO_NEST, "MOO_NEST" }, - { MYPROTO_IEI_VAL, "VAL" }, - { MYPROTO_IEI_GOO_NEST, "GOO_NEST" }, - {} -}; - -const struct value_string myproto_repeat_enum_names[] = { - OSMO_VALUE_STRING(R_A), - OSMO_VALUE_STRING(R_B), - OSMO_VALUE_STRING(R_C), - {} -}; diff --git a/tests/libosmo-gtlv/test_gtlv_gen/myproto_ies_custom.h b/tests/libosmo-gtlv/test_gtlv_gen/myproto_ies_custom.h deleted file mode 100644 index 56039af..0000000 --- a/tests/libosmo-gtlv/test_gtlv_gen/myproto_ies_custom.h +++ /dev/null @@ -1,70 +0,0 @@ -/* 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, - MYPROTO_MSGT_GOO = 7, -}; - -extern const struct value_string myproto_msg_type_names[]; - -enum myproto_iei { - MYPROTO_IEI_FOO = 1, - MYPROTO_IEI_BAR, - MYPROTO_IEI_BAZ, - MYPROTO_IEI_REPEAT_INT, - MYPROTO_IEI_REPEAT_STRUCT, - MYPROTO_IEI_MOO_NEST, - MYPROTO_IEI_VAL, - MYPROTO_IEI_GOO_NEST, -}; - -extern const struct value_string myproto_iei_names[]; - -struct myproto_ie_bar { - char str[23]; -}; - -struct myproto_ie_baz { - int v_int; - bool v_bool; -}; - -enum myproto_repeat_enum { - R_A, - R_B, - R_C, -}; - -extern const struct value_string myproto_repeat_enum_names[]; - -struct myproto_ie_repeat_struct { - int v_int; - bool v_bool; - enum myproto_repeat_enum v_enum; -}; diff --git a/tests/libosmo-gtlv/test_tliv/Makefile.am b/tests/libosmo-gtlv/test_tliv/Makefile.am deleted file mode 100644 index eb95e12..0000000 --- a/tests/libosmo-gtlv/test_tliv/Makefile.am +++ /dev/null @@ -1,60 +0,0 @@ -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 deleted file mode 100644 index 21e70d9..0000000 --- a/tests/libosmo-gtlv/test_tliv/gen__myproto_ies_auto.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * (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 deleted file mode 100644 index 54164ce..0000000 --- a/tests/libosmo-gtlv/test_tliv/myproto_ies_custom.c +++ /dev/null @@ -1,68 +0,0 @@ -/* 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 deleted file mode 100644 index 64e06ff..0000000 --- a/tests/libosmo-gtlv/test_tliv/myproto_ies_custom.h +++ /dev/null @@ -1,50 +0,0 @@ -/* 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 deleted file mode 100644 index fd4e310..0000000 --- a/tests/libosmo-gtlv/test_tliv/tliv_test.c +++ /dev/null @@ -1,217 +0,0 @@ -/* - * (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(>lv, (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, >lv, 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 deleted file mode 100644 index 184ffa6..0000000 --- a/tests/libosmo-gtlv/test_tliv/tliv_test.ok +++ /dev/null @@ -1,32 +0,0 @@ - -=== 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] diff --git a/tests/libosmo-pfcp/Makefile.am b/tests/libosmo-pfcp/Makefile.am index fda143f..eba3aa4 100644 --- a/tests/libosmo-pfcp/Makefile.am +++ b/tests/libosmo-pfcp/Makefile.am @@ -7,6 +7,7 @@ AM_CFLAGS = \ -Wall \ $(LIBOSMOCORE_CFLAGS) \ + $(LIBOSMOGTLV_CFLAGS) \ $(NULL)
noinst_PROGRAMS = \ @@ -23,8 +24,8 @@
pfcp_test_LDADD = \ $(top_builddir)/src/libosmo-pfcp/libosmo-pfcp.a \ - $(top_builddir)/src/libosmo-gtlv/libosmo-gtlv.a \ $(LIBOSMOCORE_LIBS) \ + $(LIBOSMOGTLV_LIBS) \ $(NULL)
.PHONY: update_exp diff --git a/tests/testsuite.at b/tests/testsuite.at index a365f0e..352fba9 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -1,30 +1,6 @@ AT_INIT AT_BANNER([Regression tests.])
-AT_SETUP([gtlv]) -AT_KEYWORDS([gtlv]) -cat $abs_srcdir/libosmo-gtlv/gtlv_test.ok > expout -AT_CHECK([$abs_top_builddir/tests/libosmo-gtlv/gtlv_test], [], [expout], [ignore]) -AT_CLEANUP - -AT_SETUP([gtlv_dec_enc]) -AT_KEYWORDS([gtlv_dec_enc]) -cat $abs_srcdir/libosmo-gtlv/gtlv_dec_enc_test.ok > expout -AT_CHECK([$abs_top_builddir/tests/libosmo-gtlv/gtlv_dec_enc_test], [], [expout], [ignore]) -AT_CLEANUP - -AT_SETUP([gtlv_gen]) -AT_KEYWORDS([gtlv_gen]) -cat $abs_srcdir/libosmo-gtlv/test_gtlv_gen/gtlv_gen_test.ok > expout -AT_CHECK([$abs_top_builddir/tests/libosmo-gtlv/test_gtlv_gen/gtlv_gen_test], [], [expout], [ignore]) -AT_CLEANUP - -AT_SETUP([tliv]) -AT_KEYWORDS([tliv]) -cat $abs_srcdir/libosmo-gtlv/test_tliv/tliv_test.ok > expout -AT_CHECK([$abs_top_builddir/tests/libosmo-gtlv/test_tliv/tliv_test], [], [expout], [ignore]) -AT_CLEANUP - AT_SETUP([pfcp]) AT_KEYWORDS([pfcp]) cat $abs_srcdir/libosmo-pfcp/pfcp_test.ok > expout