diff options
Diffstat (limited to 'include/osmocom/gtlv')
-rw-r--r-- | include/osmocom/gtlv/gtlv.h | 28 | ||||
-rw-r--r-- | include/osmocom/gtlv/gtlv_dec_enc.h | 4 | ||||
-rw-r--r-- | include/osmocom/gtlv/gtlv_gen.h | 12 |
3 files changed, 37 insertions, 7 deletions
diff --git a/include/osmocom/gtlv/gtlv.h b/include/osmocom/gtlv/gtlv.h index 7acf558..d800f71 100644 --- a/include/osmocom/gtlv/gtlv.h +++ b/include/osmocom/gtlv/gtlv.h @@ -25,10 +25,25 @@ #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, @@ -49,6 +64,7 @@ struct osmo_gtlv_cfg { /*! 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. @@ -68,12 +84,14 @@ struct osmo_gtlv_cfg { * \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, unsigned int tag, size_t len, struct osmo_gtlv_put *gtlv); + 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. */ @@ -97,7 +115,7 @@ struct osmo_gtlv_load { } src; /*! Return value from last invocation of osmo_gtlv_load_next*(): tag value of parsed IE. */ - unsigned int tag; + 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. */ @@ -114,8 +132,9 @@ static inline void osmo_gtlv_load_start(struct osmo_gtlv_load *gtlv) } int osmo_gtlv_load_next(struct osmo_gtlv_load *gtlv); -int osmo_gtlv_load_peek_tag(const 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 { @@ -128,10 +147,11 @@ struct osmo_gtlv_put { /* msgb to append new TL to */ struct msgb *dst; /* What was the last TL written and where are its TL and V */ - unsigned int last_tag; + 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 index b861129..132239f 100644 --- a/include/osmocom/gtlv/gtlv_dec_enc.h +++ b/include/osmocom/gtlv/gtlv_dec_enc.h @@ -78,8 +78,8 @@ enum osmo_gtlv_coding_nested_ies_ordered { * 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 value */ - unsigned int tag; + /*! 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. */ diff --git a/include/osmocom/gtlv/gtlv_gen.h b/include/osmocom/gtlv/gtlv_gen.h index a2f088b..71cec92 100644 --- a/include/osmocom/gtlv/gtlv_gen.h +++ b/include/osmocom/gtlv/gtlv_gen.h @@ -37,6 +37,10 @@ struct osmo_gtlv_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; @@ -81,6 +85,10 @@ struct osmo_gtlv_gen_ie_o { /*! 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*/ @@ -96,7 +104,9 @@ struct osmo_gtlv_gen_ie { * 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. "MYPROTO_IEI_FOO". If NULL, take "MYPROTO_IEI_"+upper(name) instead. */ + /*! 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(), |